nfsd4: make recall callback an asynchronous rpc
[safe/jmp/linux-2.6] / fs / fcntl.c
index 431bb64..cc8e4de 100644 (file)
@@ -184,6 +184,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
                error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
                if (error < 0)
                        goto out;
+               if (error > 0)
+                       error = 0;
        }
        spin_lock(&filp->f_lock);
        filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
@@ -529,6 +531,12 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap
                if (!new)
                        return -ENOMEM;
        }
+
+       /*
+        * We need to take f_lock first since it's not an IRQ-safe
+        * lock.
+        */
+       spin_lock(&filp->f_lock);
        write_lock_irq(&fasync_lock);
        for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
                if (fa->fa_file == filp) {
@@ -553,14 +561,12 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap
                result = 1;
        }
 out:
-       /* Fix up FASYNC bit while still holding fasync_lock */
-       spin_lock(&filp->f_lock);
        if (on)
                filp->f_flags |= FASYNC;
        else
                filp->f_flags &= ~FASYNC;
-       spin_unlock(&filp->f_lock);
        write_unlock_irq(&fasync_lock);
+       spin_unlock(&filp->f_lock);
        return result;
 }