Loading fs/ceph/locks.c +26 −32 Original line number Diff line number Diff line Loading @@ -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); } dout("counted %d flock locks and %d fcntl locks", *flock_count, *fcntl_count); } Loading @@ -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; Loading @@ -288,9 +285,11 @@ 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) { list_for_each_entry(lock, &ctx->flc_flock, fl_list) { ++seen_fcntl; if (seen_fcntl > num_fcntl_locks) { err = -ENOSPC; Loading @@ -301,10 +300,6 @@ int ceph_encode_locks_to_buffer(struct inode *inode, 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) { Loading @@ -316,7 +311,6 @@ int ceph_encode_locks_to_buffer(struct inode *inode, goto fail; ++l; } } fail: spin_unlock(&inode->i_lock); return err; Loading fs/cifs/file.c +10 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -1137,9 +1133,11 @@ 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) list_for_each(el, &flctx->flc_posix) { count++; } spin_unlock(&inode->i_lock); Loading @@ -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; Loading @@ -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 Loading @@ -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); Loading fs/lockd/svcsubs.c +13 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; if (flctx && !list_empty_careful(&flctx->flc_posix)) { 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) { spin_unlock(&inode->i_lock); return 1; } } spin_unlock(&inode->i_lock); } file->f_locks = 0; return 0; } Loading fs/locks.c +57 −51 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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); } } Loading Loading @@ -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); 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; ctx = inode->i_flctx; if (!ctx || list_empty_careful(&ctx->flc_posix)) { fl->fl_type = F_UNLCK; return; } if (cfl) { spin_lock(&inode->i_lock); 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); } else goto out; } } fl->fl_type = F_UNLCK; out: spin_unlock(&inode->i_lock); return; } Loading Loading @@ -983,16 +987,20 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) 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. Loading @@ -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)) Loading Loading @@ -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. */ Loading @@ -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) Loading @@ -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; } /* Loading @@ -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; } /* Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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; } /** Loading Loading @@ -2389,13 +2394,14 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, 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; Loading fs/nfs/delegation.c +9 −19 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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: Loading Loading
fs/ceph/locks.c +26 −32 Original line number Diff line number Diff line Loading @@ -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); } dout("counted %d flock locks and %d fcntl locks", *flock_count, *fcntl_count); } Loading @@ -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; Loading @@ -288,9 +285,11 @@ 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) { list_for_each_entry(lock, &ctx->flc_flock, fl_list) { ++seen_fcntl; if (seen_fcntl > num_fcntl_locks) { err = -ENOSPC; Loading @@ -301,10 +300,6 @@ int ceph_encode_locks_to_buffer(struct inode *inode, 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) { Loading @@ -316,7 +311,6 @@ int ceph_encode_locks_to_buffer(struct inode *inode, goto fail; ++l; } } fail: spin_unlock(&inode->i_lock); return err; Loading
fs/cifs/file.c +10 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -1137,9 +1133,11 @@ 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) list_for_each(el, &flctx->flc_posix) { count++; } spin_unlock(&inode->i_lock); Loading @@ -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; Loading @@ -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 Loading @@ -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); Loading
fs/lockd/svcsubs.c +13 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; if (flctx && !list_empty_careful(&flctx->flc_posix)) { 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) { spin_unlock(&inode->i_lock); return 1; } } spin_unlock(&inode->i_lock); } file->f_locks = 0; return 0; } Loading
fs/locks.c +57 −51 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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); } } Loading Loading @@ -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); 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; ctx = inode->i_flctx; if (!ctx || list_empty_careful(&ctx->flc_posix)) { fl->fl_type = F_UNLCK; return; } if (cfl) { spin_lock(&inode->i_lock); 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); } else goto out; } } fl->fl_type = F_UNLCK; out: spin_unlock(&inode->i_lock); return; } Loading Loading @@ -983,16 +987,20 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) 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. Loading @@ -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)) Loading Loading @@ -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. */ Loading @@ -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) Loading @@ -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; } /* Loading @@ -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; } /* Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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; } /** Loading Loading @@ -2389,13 +2394,14 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, 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; Loading
fs/nfs/delegation.c +9 −19 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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: Loading