locks: convert posix locks to file_lock_context
authorJeff Layton <jlayton@primarydata.com>
Fri, 16 Jan 2015 20:05:55 +0000 (15:05 -0500)
committerJeff Layton <jeff.layton@primarydata.com>
Fri, 16 Jan 2015 21:08:16 +0000 (16:08 -0500)
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Acked-by: Christoph Hellwig <hch@lst.de>
fs/ceph/locks.c
fs/cifs/file.c
fs/lockd/svcsubs.c
fs/locks.c
fs/nfs/delegation.c
fs/nfs/nfs4state.c
fs/nfs/pagelist.c
fs/nfs/write.c
fs/nfsd/nfs4state.c
fs/read_write.c
include/linux/fs.h

index 917656ea8dcf8a0bcaf9209d41ae77aec1d0346e..19beeed832337838fd72b8c0e67e28cd5227ed76 100644 (file)
@@ -253,18 +253,15 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
        *fcntl_count = 0;
        *flock_count = 0;
 
-       spin_lock(&inode->i_lock);
-       for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
-               if (lock->fl_flags & FL_POSIX)
-                       ++(*fcntl_count);
-       }
-
        ctx = inode->i_flctx;
        if (ctx) {
+               spin_lock(&inode->i_lock);
+               list_for_each_entry(lock, &ctx->flc_posix, fl_list)
+                       ++(*fcntl_count);
                list_for_each_entry(lock, &ctx->flc_flock, fl_list)
                        ++(*flock_count);
+               spin_unlock(&inode->i_lock);
        }
-       spin_unlock(&inode->i_lock);
        dout("counted %d flock locks and %d fcntl locks",
             *flock_count, *fcntl_count);
 }
@@ -279,7 +276,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
                                int num_fcntl_locks, int num_flock_locks)
 {
        struct file_lock *lock;
-       struct file_lock_context *ctx;
+       struct file_lock_context *ctx = inode->i_flctx;
        int err = 0;
        int seen_fcntl = 0;
        int seen_flock = 0;
@@ -288,34 +285,31 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
        dout("encoding %d flock and %d fcntl locks", num_flock_locks,
             num_fcntl_locks);
 
+       if (!ctx)
+               return 0;
+
        spin_lock(&inode->i_lock);
-       for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
-               if (lock->fl_flags & FL_POSIX) {
-                       ++seen_fcntl;
-                       if (seen_fcntl > num_fcntl_locks) {
-                               err = -ENOSPC;
-                               goto fail;
-                       }
-                       err = lock_to_ceph_filelock(lock, &flocks[l]);
-                       if (err)
-                               goto fail;
-                       ++l;
+       list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
+               ++seen_fcntl;
+               if (seen_fcntl > num_fcntl_locks) {
+                       err = -ENOSPC;
+                       goto fail;
                }
+               err = lock_to_ceph_filelock(lock, &flocks[l]);
+               if (err)
+                       goto fail;
+               ++l;
        }
-
-       ctx = inode->i_flctx;
-       if (ctx) {
-               list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
-                       ++seen_flock;
-                       if (seen_flock > num_flock_locks) {
-                               err = -ENOSPC;
-                               goto fail;
-                       }
-                       err = lock_to_ceph_filelock(lock, &flocks[l]);
-                       if (err)
-                               goto fail;
-                       ++l;
+       list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
+               ++seen_flock;
+               if (seen_flock > num_flock_locks) {
+                       err = -ENOSPC;
+                       goto fail;
                }
+               err = lock_to_ceph_filelock(lock, &flocks[l]);
+               if (err)
+                       goto fail;
+               ++l;
        }
 fail:
        spin_unlock(&inode->i_lock);
index 96b7e9b7706dc58b767863fdeadf3cadfb4e5324..ea78f6f81ce299532939c28bb4e2b031b10a687e 100644 (file)
@@ -1109,11 +1109,6 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
        return rc;
 }
 
-/* copied from fs/locks.c with a name change */
-#define cifs_for_each_lock(inode, lockp) \
-       for (lockp = &inode->i_flock; *lockp != NULL; \
-            lockp = &(*lockp)->fl_next)
-
 struct lock_to_push {
        struct list_head llist;
        __u64 offset;
@@ -1128,8 +1123,9 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
 {
        struct inode *inode = cfile->dentry->d_inode;
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-       struct file_lock *flock, **before;
-       unsigned int count = 0, i = 0;
+       struct file_lock *flock;
+       struct file_lock_context *flctx = inode->i_flctx;
+       unsigned int count = 0, i;
        int rc = 0, xid, type;
        struct list_head locks_to_send, *el;
        struct lock_to_push *lck, *tmp;
@@ -1137,10 +1133,12 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
 
        xid = get_xid();
 
+       if (!flctx)
+               goto out;
+
        spin_lock(&inode->i_lock);
-       cifs_for_each_lock(inode, before) {
-               if ((*before)->fl_flags & FL_POSIX)
-                       count++;
+       list_for_each(el, &flctx->flc_posix) {
+               count++;
        }
        spin_unlock(&inode->i_lock);
 
@@ -1151,7 +1149,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
         * added to the list while we are holding cinode->lock_sem that
         * protects locking operations of this inode.
         */
-       for (; i < count; i++) {
+       for (i = 0; i < count; i++) {
                lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
                if (!lck) {
                        rc = -ENOMEM;
@@ -1162,10 +1160,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
 
        el = locks_to_send.next;
        spin_lock(&inode->i_lock);
-       cifs_for_each_lock(inode, before) {
-               flock = *before;
-               if ((flock->fl_flags & FL_POSIX) == 0)
-                       continue;
+       list_for_each_entry(flock, &flctx->flc_posix, fl_list) {
                if (el == &locks_to_send) {
                        /*
                         * The list ended. We don't have enough allocated
@@ -1185,7 +1180,6 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
                lck->length = length;
                lck->type = type;
                lck->offset = flock->fl_start;
-               el = el->next;
        }
        spin_unlock(&inode->i_lock);
 
index d12ff4e2dbe792e175eaacf0a67286d1a3815a13..5300bb53835f57326944eca4f6bbd26216058494 100644 (file)
@@ -164,12 +164,15 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
 {
        struct inode     *inode = nlmsvc_file_inode(file);
        struct file_lock *fl;
+       struct file_lock_context *flctx = inode->i_flctx;
        struct nlm_host  *lockhost;
 
+       if (!flctx || list_empty_careful(&flctx->flc_posix))
+               return 0;
 again:
        file->f_locks = 0;
        spin_lock(&inode->i_lock);
-       for (fl = inode->i_flock; fl; fl = fl->fl_next) {
+       list_for_each_entry(fl, &flctx->flc_posix, fl_list) {
                if (fl->fl_lmops != &nlmsvc_lock_operations)
                        continue;
 
@@ -223,18 +226,21 @@ nlm_file_inuse(struct nlm_file *file)
 {
        struct inode     *inode = nlmsvc_file_inode(file);
        struct file_lock *fl;
+       struct file_lock_context *flctx = inode->i_flctx;
 
        if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares)
                return 1;
 
-       spin_lock(&inode->i_lock);
-       for (fl = inode->i_flock; fl; fl = fl->fl_next) {
-               if (fl->fl_lmops == &nlmsvc_lock_operations) {
-                       spin_unlock(&inode->i_lock);
-                       return 1;
+       if (flctx && !list_empty_careful(&flctx->flc_posix)) {
+               spin_lock(&inode->i_lock);
+               list_for_each_entry(fl, &flctx->flc_posix, fl_list) {
+                       if (fl->fl_lmops == &nlmsvc_lock_operations) {
+                               spin_unlock(&inode->i_lock);
+                               return 1;
+                       }
                }
+               spin_unlock(&inode->i_lock);
        }
-       spin_unlock(&inode->i_lock);
        file->f_locks = 0;
        return 0;
 }
index 055df53f19de7476bf6bdff8501faffd0664d937..e50bb4d9e757c91d9da2488ed30c71d034dc39e4 100644 (file)
@@ -157,9 +157,6 @@ static int target_leasetype(struct file_lock *fl)
 int leases_enable = 1;
 int lease_break_time = 45;
 
-#define for_each_lock(inode, lockp) \
-       for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
-
 /*
  * The global file_lock_list is only used for displaying /proc/locks, so we
  * keep a list on each CPU, with each list protected by its own spinlock via
@@ -218,6 +215,7 @@ locks_get_lock_context(struct inode *inode)
                goto out;
 
        INIT_LIST_HEAD(&new->flc_flock);
+       INIT_LIST_HEAD(&new->flc_posix);
 
        /*
         * Assign the pointer if it's not already assigned. If it is, then
@@ -241,6 +239,7 @@ locks_free_lock_context(struct file_lock_context *ctx)
 {
        if (ctx) {
                WARN_ON_ONCE(!list_empty(&ctx->flc_flock));
+               WARN_ON_ONCE(!list_empty(&ctx->flc_posix));
                kmem_cache_free(flctx_cache, ctx);
        }
 }
@@ -809,21 +808,26 @@ void
 posix_test_lock(struct file *filp, struct file_lock *fl)
 {
        struct file_lock *cfl;
+       struct file_lock_context *ctx;
        struct inode *inode = file_inode(filp);
 
+       ctx = inode->i_flctx;
+       if (!ctx || list_empty_careful(&ctx->flc_posix)) {
+               fl->fl_type = F_UNLCK;
+               return;
+       }
+
        spin_lock(&inode->i_lock);
-       for (cfl = file_inode(filp)->i_flock; cfl; cfl = cfl->fl_next) {
-               if (!IS_POSIX(cfl))
-                       continue;
-               if (posix_locks_conflict(fl, cfl))
-                       break;
+       list_for_each_entry(cfl, &ctx->flc_posix, fl_list) {
+               if (posix_locks_conflict(fl, cfl)) {
+                       locks_copy_conflock(fl, cfl);
+                       if (cfl->fl_nspid)
+                               fl->fl_pid = pid_vnr(cfl->fl_nspid);
+                       goto out;
+               }
        }
-       if (cfl) {
-               locks_copy_conflock(fl, cfl);
-               if (cfl->fl_nspid)
-                       fl->fl_pid = pid_vnr(cfl->fl_nspid);
-       } else
-               fl->fl_type = F_UNLCK;
+       fl->fl_type = F_UNLCK;
+out:
        spin_unlock(&inode->i_lock);
        return;
 }
@@ -983,16 +987,20 @@ out:
 
 static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
 {
-       struct file_lock *fl;
+       struct file_lock *fl, *tmp;
        struct file_lock *new_fl = NULL;
        struct file_lock *new_fl2 = NULL;
        struct file_lock *left = NULL;
        struct file_lock *right = NULL;
-       struct file_lock **before;
+       struct file_lock_context *ctx;
        int error;
        bool added = false;
        LIST_HEAD(dispose);
 
+       ctx = locks_get_lock_context(inode);
+       if (!ctx)
+               return -ENOMEM;
+
        /*
         * We may need two file_lock structures for this operation,
         * so we get them in advance to avoid races.
@@ -1013,8 +1021,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
         * blocker's list of waiters and the global blocked_hash.
         */
        if (request->fl_type != F_UNLCK) {
-               for_each_lock(inode, before) {
-                       fl = *before;
+               list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
                        if (!IS_POSIX(fl))
                                continue;
                        if (!posix_locks_conflict(request, fl))
@@ -1044,29 +1051,25 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
        if (request->fl_flags & FL_ACCESS)
                goto out;
 
-       /*
-        * Find the first old lock with the same owner as the new lock.
-        */
-       
-       before = &inode->i_flock;
-
-       /* First skip locks owned by other processes.  */
-       while ((fl = *before) && (!IS_POSIX(fl) ||
-                                 !posix_same_owner(request, fl))) {
-               before = &fl->fl_next;
+       /* Find the first old lock with the same owner as the new lock */
+       list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
+               if (posix_same_owner(request, fl))
+                       break;
        }
 
        /* Process locks with this owner. */
-       while ((fl = *before) && posix_same_owner(request, fl)) {
-               /* Detect adjacent or overlapping regions (if same lock type)
-                */
+       list_for_each_entry_safe_from(fl, tmp, &ctx->flc_posix, fl_list) {
+               if (!posix_same_owner(request, fl))
+                       break;
+
+               /* Detect adjacent or overlapping regions (if same lock type) */
                if (request->fl_type == fl->fl_type) {
                        /* In all comparisons of start vs end, use
                         * "start - 1" rather than "end + 1". If end
                         * is OFFSET_MAX, end + 1 will become negative.
                         */
                        if (fl->fl_end < request->fl_start - 1)
-                               goto next_lock;
+                               continue;
                        /* If the next lock in the list has entirely bigger
                         * addresses than the new one, insert the lock here.
                         */
@@ -1087,18 +1090,17 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                        else
                                request->fl_end = fl->fl_end;
                        if (added) {
-                               locks_delete_lock(before, &dispose);
+                               locks_delete_lock_ctx(fl, &dispose);
                                continue;
                        }
                        request = fl;
                        added = true;
-               }
-               else {
+               } else {
                        /* Processing for different lock types is a bit
                         * more complex.
                         */
                        if (fl->fl_end < request->fl_start)
-                               goto next_lock;
+                               continue;
                        if (fl->fl_start > request->fl_end)
                                break;
                        if (request->fl_type == F_UNLCK)
@@ -1117,7 +1119,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                                 * one (This may happen several times).
                                 */
                                if (added) {
-                                       locks_delete_lock(before, &dispose);
+                                       locks_delete_lock_ctx(fl, &dispose);
                                        continue;
                                }
                                /*
@@ -1133,15 +1135,11 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                                locks_copy_lock(new_fl, request);
                                request = new_fl;
                                new_fl = NULL;
-                               locks_delete_lock(before, &dispose);
-                               locks_insert_lock(before, request);
+                               locks_insert_lock_ctx(request, &fl->fl_list);
+                               locks_delete_lock_ctx(fl, &dispose);
                                added = true;
                        }
                }
-               /* Go on to next lock.
-                */
-       next_lock:
-               before = &fl->fl_next;
        }
 
        /*
@@ -1166,7 +1164,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                        goto out;
                }
                locks_copy_lock(new_fl, request);
-               locks_insert_lock(before, new_fl);
+               locks_insert_lock_ctx(new_fl, &fl->fl_list);
                new_fl = NULL;
        }
        if (right) {
@@ -1177,7 +1175,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
                        left = new_fl2;
                        new_fl2 = NULL;
                        locks_copy_lock(left, right);
-                       locks_insert_lock(before, left);
+                       locks_insert_lock_ctx(left, &fl->fl_list);
                }
                right->fl_start = request->fl_end + 1;
                locks_wake_up_blocks(right);
@@ -1257,22 +1255,29 @@ EXPORT_SYMBOL(posix_lock_file_wait);
  */
 int locks_mandatory_locked(struct file *file)
 {
+       int ret;
        struct inode *inode = file_inode(file);
+       struct file_lock_context *ctx;
        struct file_lock *fl;
 
+       ctx = inode->i_flctx;
+       if (!ctx || list_empty_careful(&ctx->flc_posix))
+               return 0;
+
        /*
         * Search the lock list for this inode for any POSIX locks.
         */
        spin_lock(&inode->i_lock);
-       for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
-               if (!IS_POSIX(fl))
-                       continue;
+       ret = 0;
+       list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
                if (fl->fl_owner != current->files &&
-                   fl->fl_owner != file)
+                   fl->fl_owner != file) {
+                       ret = -EAGAIN;
                        break;
+               }
        }
        spin_unlock(&inode->i_lock);
-       return fl ? -EAGAIN : 0;
+       return ret;
 }
 
 /**
@@ -2389,13 +2394,14 @@ out:
 void locks_remove_posix(struct file *filp, fl_owner_t owner)
 {
        struct file_lock lock;
+       struct file_lock_context *ctx = file_inode(filp)->i_flctx;
 
        /*
         * If there are no locks held on this file, we don't need to call
         * posix_lock_file().  Another process could be setting a lock on this
         * file at the same time, but we wouldn't remove that lock anyway.
         */
-       if (!file_inode(filp)->i_flock)
+       if (!ctx || list_empty(&ctx->flc_posix))
                return;
 
        lock.fl_type = F_UNLCK;
index 9f9f67b17e2b017a703a2bbd5452eff0ebc411b5..3fb1caa3874d6c8b056be429800e86c69de39f8c 100644 (file)
@@ -85,17 +85,17 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
 {
        struct inode *inode = state->inode;
        struct file_lock *fl;
-       struct file_lock_context *flctx;
+       struct file_lock_context *flctx = inode->i_flctx;
+       struct list_head *list;
        int status = 0;
 
-       if (inode->i_flock == NULL && inode->i_flctx == NULL)
+       if (flctx == NULL)
                goto out;
 
-       /* Protect inode->i_flock using the i_lock */
+       list = &flctx->flc_posix;
        spin_lock(&inode->i_lock);
-       for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
-               if (!(fl->fl_flags & (FL_POSIX)))
-                       continue;
+restart:
+       list_for_each_entry(fl, list, fl_list) {
                if (nfs_file_open_context(fl->fl_file) != ctx)
                        continue;
                spin_unlock(&inode->i_lock);
@@ -104,19 +104,9 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
                        goto out;
                spin_lock(&inode->i_lock);
        }
-
-       flctx = inode->i_flctx;
-       if (flctx) {
-               list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
-                       if (nfs_file_open_context(fl->fl_file) != ctx)
-                               continue;
-                       spin_unlock(&inode->i_lock);
-                       status = nfs4_lock_delegation_recall(fl, state,
-                                                               stateid);
-                       if (status < 0)
-                               goto out;
-                       spin_lock(&inode->i_lock);
-               }
+       if (list == &flctx->flc_posix) {
+               list = &flctx->flc_flock;
+               goto restart;
        }
        spin_unlock(&inode->i_lock);
 out:
index 65c404bf61aef145e9d6a3c809d96cb5692d71f3..6084c267f3a0d046be45533b3528232eb3cca43a 100644 (file)
@@ -1367,53 +1367,18 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
        struct file_lock *fl;
        int status = 0;
        struct file_lock_context *flctx = inode->i_flctx;
+       struct list_head *list;
 
-       if (inode->i_flock == NULL && flctx == NULL)
+       if (flctx == NULL)
                return 0;
 
+       list = &flctx->flc_posix;
+
        /* Guard against delegation returns and new lock/unlock calls */
        down_write(&nfsi->rwsem);
-       /* Protect inode->i_flock using the BKL */
        spin_lock(&inode->i_lock);
-       for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
-               if (!(fl->fl_flags & FL_POSIX))
-                       continue;
-               if (nfs_file_open_context(fl->fl_file)->state != state)
-                       continue;
-               spin_unlock(&inode->i_lock);
-               status = ops->recover_lock(state, fl);
-               switch (status) {
-                       case 0:
-                               break;
-                       case -ESTALE:
-                       case -NFS4ERR_ADMIN_REVOKED:
-                       case -NFS4ERR_STALE_STATEID:
-                       case -NFS4ERR_BAD_STATEID:
-                       case -NFS4ERR_EXPIRED:
-                       case -NFS4ERR_NO_GRACE:
-                       case -NFS4ERR_STALE_CLIENTID:
-                       case -NFS4ERR_BADSESSION:
-                       case -NFS4ERR_BADSLOT:
-                       case -NFS4ERR_BAD_HIGH_SLOT:
-                       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
-                               goto out;
-                       default:
-                               printk(KERN_ERR "NFS: %s: unhandled error %d\n",
-                                        __func__, status);
-                       case -ENOMEM:
-                       case -NFS4ERR_DENIED:
-                       case -NFS4ERR_RECLAIM_BAD:
-                       case -NFS4ERR_RECLAIM_CONFLICT:
-                               /* kill_proc(fl->fl_pid, SIGLOST, 1); */
-                               status = 0;
-               }
-               spin_lock(&inode->i_lock);
-       }
-
-       if (!flctx)
-               goto out_unlock;
-
-       list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
+restart:
+       list_for_each_entry(fl, list, fl_list) {
                if (nfs_file_open_context(fl->fl_file)->state != state)
                        continue;
                spin_unlock(&inode->i_lock);
@@ -1445,7 +1410,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
                }
                spin_lock(&inode->i_lock);
        }
-out_unlock:
+       if (list == &flctx->flc_posix) {
+               list = &flctx->flc_flock;
+               goto restart;
+       }
        spin_unlock(&inode->i_lock);
 out:
        up_write(&nfsi->rwsem);
index a3b62e15b4440f635f3b89b49559c39dabafdabc..29c7f33c9cf1b666b88fee7dc1ed2882fdb76825 100644 (file)
@@ -831,12 +831,10 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
        if (prev) {
                if (!nfs_match_open_context(req->wb_context, prev->wb_context))
                        return false;
-               if (req->wb_context->dentry->d_inode->i_flock != NULL &&
-                   !nfs_match_lock_context(req->wb_lock_context,
-                                           prev->wb_lock_context))
-                       return false;
                flctx = req->wb_context->dentry->d_inode->i_flctx;
-               if (flctx != NULL && !list_empty_careful(&flctx->flc_flock) &&
+               if (flctx != NULL &&
+                   !(list_empty_careful(&flctx->flc_posix) &&
+                     list_empty_careful(&flctx->flc_flock)) &&
                    !nfs_match_lock_context(req->wb_lock_context,
                                            prev->wb_lock_context))
                        return false;
index e072aeb34195d9017d8969a4512fef37865985a7..784c13485b3fb143fc4d42f02021729d7102229b 100644 (file)
@@ -1091,6 +1091,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
 {
        struct nfs_open_context *ctx = nfs_file_open_context(file);
        struct nfs_lock_context *l_ctx;
+       struct file_lock_context *flctx = file_inode(file)->i_flctx;
        struct nfs_page *req;
        int do_flush, status;
        /*
@@ -1109,12 +1110,9 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
                do_flush = req->wb_page != page || req->wb_context != ctx;
                /* for now, flush if more than 1 request in page_group */
                do_flush |= req->wb_this_page != req;
-               if (l_ctx && ctx->dentry->d_inode->i_flock != NULL) {
-                       do_flush |= l_ctx->lockowner.l_owner != current->files
-                               || l_ctx->lockowner.l_pid != current->tgid;
-               }
-               if (l_ctx && ctx->dentry->d_inode->i_flctx &&
-                   !list_empty_careful(&ctx->dentry->d_inode->i_flctx->flc_flock)) {
+               if (l_ctx && flctx &&
+                   !(list_empty_careful(&flctx->flc_posix) &&
+                     list_empty_careful(&flctx->flc_flock))) {
                        do_flush |= l_ctx->lockowner.l_owner != current->files
                                || l_ctx->lockowner.l_pid != current->tgid;
                }
@@ -1202,26 +1200,24 @@ static int nfs_can_extend_write(struct file *file, struct page *page, struct ino
                return 0;
        if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
                return 1;
-       if (!inode->i_flock && !flctx)
+       if (!flctx || (list_empty_careful(&flctx->flc_flock) &&
+                      list_empty_careful(&flctx->flc_posix)))
                return 0;
 
        /* Check to see if there are whole file write locks */
-       spin_lock(&inode->i_lock);
        ret = 0;
-
-       fl = inode->i_flock;
-       if (fl && is_whole_file_wrlock(fl)) {
-               ret = 1;
-               goto out;
-       }
-
-       if (!list_empty(&flctx->flc_flock)) {
+       spin_lock(&inode->i_lock);
+       if (!list_empty(&flctx->flc_posix)) {
+               fl = list_first_entry(&flctx->flc_posix, struct file_lock,
+                                       fl_list);
+               if (is_whole_file_wrlock(fl))
+                       ret = 1;
+       } else if (!list_empty(&flctx->flc_flock)) {
                fl = list_first_entry(&flctx->flc_flock, struct file_lock,
                                        fl_list);
                if (fl->fl_type == F_WRLCK)
                        ret = 1;
        }
-out:
        spin_unlock(&inode->i_lock);
        return ret;
 }
index c06a1ba80d73e5fd2cd6c68f61210e8be9518993..fad821991369f9b0c4990c6fb53641780cafc5d9 100644 (file)
@@ -5556,10 +5556,11 @@ out_nfserr:
 static bool
 check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
 {
-       struct file_lock **flpp;
+       struct file_lock *fl;
        int status = false;
        struct file *filp = find_any_file(fp);
        struct inode *inode;
+       struct file_lock_context *flctx;
 
        if (!filp) {
                /* Any valid lock stateid should have some sort of access */
@@ -5568,15 +5569,18 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
        }
 
        inode = file_inode(filp);
+       flctx = inode->i_flctx;
 
-       spin_lock(&inode->i_lock);
-       for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
-               if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
-                       status = true;
-                       break;
+       if (flctx && !list_empty_careful(&flctx->flc_posix)) {
+               spin_lock(&inode->i_lock);
+               list_for_each_entry(fl, &flctx->flc_posix, fl_list) {
+                       if (fl->fl_owner == (fl_owner_t)lowner) {
+                               status = true;
+                               break;
+                       }
                }
+               spin_unlock(&inode->i_lock);
        }
-       spin_unlock(&inode->i_lock);
        fput(filp);
        return status;
 }
index c0805c93b6fa18d34b9b579d5c470af2a5a66b1b..4060691e78f78ab734986a1347c1d81d117c4b90 100644 (file)
@@ -358,7 +358,7 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t
                        return retval;
        }
 
-       if (unlikely(inode->i_flock && mandatory_lock(inode))) {
+       if (unlikely(inode->i_flctx && mandatory_lock(inode))) {
                retval = locks_mandatory_area(
                        read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
                        inode, file, pos, count);
index dec0d38b05de4f7745243df429128aae948a20c7..571f113588e9882f3d43a31b6335c7d82bc49ca9 100644 (file)
@@ -968,6 +968,7 @@ struct file_lock {
 
 struct file_lock_context {
        struct list_head        flc_flock;
+       struct list_head        flc_posix;
 };
 
 /* The following constant reflects the upper bound of the file/locking space */
@@ -1971,7 +1972,7 @@ static inline int locks_verify_truncate(struct inode *inode,
                                    struct file *filp,
                                    loff_t size)
 {
-       if (inode->i_flock && mandatory_lock(inode))
+       if (inode->i_flctx && mandatory_lock(inode))
                return locks_mandatory_area(
                        FLOCK_VERIFY_WRITE, inode, filp,
                        size < inode->i_size ? size : inode->i_size,