io_uring/net: limit inline multishot retries
[platform/kernel/linux-starfive.git] / kernel / watch_queue.c
index e91cb4c..778b405 100644 (file)
@@ -42,7 +42,7 @@ MODULE_AUTHOR("Red Hat, Inc.");
 static inline bool lock_wqueue(struct watch_queue *wqueue)
 {
        spin_lock_bh(&wqueue->lock);
-       if (unlikely(wqueue->defunct)) {
+       if (unlikely(!wqueue->pipe)) {
                spin_unlock_bh(&wqueue->lock);
                return false;
        }
@@ -104,9 +104,6 @@ static bool post_one_notification(struct watch_queue *wqueue,
        unsigned int head, tail, mask, note, offset, len;
        bool done = false;
 
-       if (!pipe)
-               return false;
-
        spin_lock_irq(&pipe->rd_wait.lock);
 
        mask = pipe->ring_size - 1;
@@ -334,7 +331,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,
            filter.__reserved != 0)
                return -EINVAL;
 
-       tf = memdup_user(_filter->filters, filter.nr_filters * sizeof(*tf));
+       tf = memdup_array_user(_filter->filters, filter.nr_filters, sizeof(*tf));
        if (IS_ERR(tf))
                return PTR_ERR(tf);
 
@@ -603,8 +600,11 @@ void watch_queue_clear(struct watch_queue *wqueue)
        rcu_read_lock();
        spin_lock_bh(&wqueue->lock);
 
-       /* Prevent new notifications from being stored. */
-       wqueue->defunct = true;
+       /*
+        * This pipe can be freed by callers like free_pipe_info().
+        * Removing this reference also prevents new notifications.
+        */
+       wqueue->pipe = NULL;
 
        while (!hlist_empty(&wqueue->watches)) {
                watch = hlist_entry(wqueue->watches.first, struct watch, queue_node);