Loading fs/ceph/locks.c +16 −7 Original line number Diff line number Diff line Loading @@ -239,14 +239,16 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl) return err; } /** * Must be called with lock_flocks() already held. Fills in the passed * counter variables, so you can prepare pagelist metadata before calling * ceph_encode_locks. /* * Fills in the passed counter variables, so you can prepare pagelist metadata * before calling ceph_encode_locks. * * FIXME: add counters to struct file_lock_context so we don't need to do this? */ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count) { struct file_lock *lock; struct file_lock_context *ctx; *fcntl_count = 0; *flock_count = 0; Loading @@ -255,7 +257,11 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count) for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_POSIX) ++(*fcntl_count); else if (lock->fl_flags & FL_FLOCK) } ctx = inode->i_flctx; if (ctx) { list_for_each_entry(lock, &ctx->flc_flock, fl_list) ++(*flock_count); } spin_unlock(&inode->i_lock); Loading @@ -273,6 +279,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; int err = 0; int seen_fcntl = 0; int seen_flock = 0; Loading @@ -295,8 +302,10 @@ int ceph_encode_locks_to_buffer(struct inode *inode, ++l; } } for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_FLOCK) { 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; Loading fs/locks.c +35 −19 Original line number Diff line number Diff line Loading @@ -694,6 +694,14 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) locks_insert_global_locks(fl); } static void locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before) { fl->fl_nspid = get_pid(task_tgid(current)); list_add_tail(&fl->fl_list, before); locks_insert_global_locks(fl); } /** * locks_delete_lock - Delete a lock and then free it. * @thisfl_p: pointer that points to the fl_next field of the previous Loading Loading @@ -739,6 +747,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p, locks_free_lock(fl); } static void locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose) { locks_delete_global_locks(fl); if (fl->fl_nspid) { put_pid(fl->fl_nspid); fl->fl_nspid = NULL; } locks_wake_up_blocks(fl); list_move(&fl->fl_list, dispose); } /* Determine if lock sys_fl blocks lock caller_fl. Common functionality * checks for shared/exclusive status of overlapping locks. */ Loading Loading @@ -888,12 +908,17 @@ static int posix_locks_deadlock(struct file_lock *caller_fl, static int flock_lock_file(struct file *filp, struct file_lock *request) { struct file_lock *new_fl = NULL; struct file_lock **before; struct file_lock *fl; struct file_lock_context *ctx; struct inode *inode = file_inode(filp); int error = 0; int found = 0; bool found = false; LIST_HEAD(dispose); ctx = locks_get_lock_context(inode); if (!ctx) return -ENOMEM; if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { new_fl = locks_alloc_lock(); if (!new_fl) Loading @@ -904,18 +929,13 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) if (request->fl_flags & FL_ACCESS) goto find_conflict; for_each_lock(inode, before) { struct file_lock *fl = *before; if (IS_POSIX(fl)) break; if (IS_LEASE(fl)) continue; list_for_each_entry(fl, &ctx->flc_flock, fl_list) { if (filp != fl->fl_file) continue; if (request->fl_type == fl->fl_type) goto out; found = 1; locks_delete_lock(before, &dispose); found = true; locks_delete_lock_ctx(fl, &dispose); break; } Loading @@ -936,12 +956,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) } find_conflict: for_each_lock(inode, before) { struct file_lock *fl = *before; if (IS_POSIX(fl)) break; if (IS_LEASE(fl)) continue; list_for_each_entry(fl, &ctx->flc_flock, fl_list) { if (!flock_locks_conflict(request, fl)) continue; error = -EAGAIN; Loading @@ -954,7 +969,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) if (request->fl_flags & FL_ACCESS) goto out; locks_copy_lock(new_fl, request); locks_insert_lock(before, new_fl); locks_insert_lock_ctx(new_fl, &ctx->flc_flock); new_fl = NULL; error = 0; Loading Loading @@ -2412,8 +2427,9 @@ locks_remove_flock(struct file *filp) .fl_type = F_UNLCK, .fl_end = OFFSET_MAX, }; struct file_lock_context *flctx = file_inode(filp)->i_flctx; if (!file_inode(filp)->i_flock) if (!flctx || list_empty(&flctx->flc_flock)) return; if (filp->f_op->flock) Loading fs/nfs/delegation.c +17 −2 Original line number Diff line number Diff line Loading @@ -85,15 +85,16 @@ 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; int status = 0; if (inode->i_flock == NULL) if (inode->i_flock == NULL && inode->i_flctx == NULL) goto out; /* Protect inode->i_flock using the i_lock */ spin_lock(&inode->i_lock); for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) if (!(fl->fl_flags & (FL_POSIX))) continue; if (nfs_file_open_context(fl->fl_file) != ctx) continue; Loading @@ -103,6 +104,20 @@ 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); } } spin_unlock(&inode->i_lock); out: return status; Loading fs/nfs/nfs4state.c +40 −2 Original line number Diff line number Diff line Loading @@ -1366,8 +1366,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ struct nfs_inode *nfsi = NFS_I(inode); struct file_lock *fl; int status = 0; struct file_lock_context *flctx = inode->i_flctx; if (inode->i_flock == NULL) if (inode->i_flock == NULL && flctx == NULL) return 0; /* Guard against delegation returns and new lock/unlock calls */ Loading @@ -1375,7 +1376,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ /* 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|FL_FLOCK))) if (!(fl->fl_flags & FL_POSIX)) continue; if (nfs_file_open_context(fl->fl_file)->state != state) continue; Loading Loading @@ -1408,6 +1409,43 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ } spin_lock(&inode->i_lock); } if (!flctx) goto out_unlock; list_for_each_entry(fl, &flctx->flc_flock, fl_list) { 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: pr_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); } out_unlock: spin_unlock(&inode->i_lock); out: up_write(&nfsi->rwsem); Loading fs/nfs/pagelist.c +6 −0 Original line number Diff line number Diff line Loading @@ -826,6 +826,7 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev, struct nfs_pageio_descriptor *pgio) { size_t size; struct file_lock_context *flctx; if (prev) { if (!nfs_match_open_context(req->wb_context, prev->wb_context)) Loading @@ -834,6 +835,11 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev, !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) && !nfs_match_lock_context(req->wb_lock_context, prev->wb_lock_context)) return false; if (req_offset(req) != req_offset(prev) + prev->wb_bytes) return false; if (req->wb_page == prev->wb_page) { Loading Loading
fs/ceph/locks.c +16 −7 Original line number Diff line number Diff line Loading @@ -239,14 +239,16 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl) return err; } /** * Must be called with lock_flocks() already held. Fills in the passed * counter variables, so you can prepare pagelist metadata before calling * ceph_encode_locks. /* * Fills in the passed counter variables, so you can prepare pagelist metadata * before calling ceph_encode_locks. * * FIXME: add counters to struct file_lock_context so we don't need to do this? */ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count) { struct file_lock *lock; struct file_lock_context *ctx; *fcntl_count = 0; *flock_count = 0; Loading @@ -255,7 +257,11 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count) for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_POSIX) ++(*fcntl_count); else if (lock->fl_flags & FL_FLOCK) } ctx = inode->i_flctx; if (ctx) { list_for_each_entry(lock, &ctx->flc_flock, fl_list) ++(*flock_count); } spin_unlock(&inode->i_lock); Loading @@ -273,6 +279,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; int err = 0; int seen_fcntl = 0; int seen_flock = 0; Loading @@ -295,8 +302,10 @@ int ceph_encode_locks_to_buffer(struct inode *inode, ++l; } } for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_FLOCK) { 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; Loading
fs/locks.c +35 −19 Original line number Diff line number Diff line Loading @@ -694,6 +694,14 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) locks_insert_global_locks(fl); } static void locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before) { fl->fl_nspid = get_pid(task_tgid(current)); list_add_tail(&fl->fl_list, before); locks_insert_global_locks(fl); } /** * locks_delete_lock - Delete a lock and then free it. * @thisfl_p: pointer that points to the fl_next field of the previous Loading Loading @@ -739,6 +747,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p, locks_free_lock(fl); } static void locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose) { locks_delete_global_locks(fl); if (fl->fl_nspid) { put_pid(fl->fl_nspid); fl->fl_nspid = NULL; } locks_wake_up_blocks(fl); list_move(&fl->fl_list, dispose); } /* Determine if lock sys_fl blocks lock caller_fl. Common functionality * checks for shared/exclusive status of overlapping locks. */ Loading Loading @@ -888,12 +908,17 @@ static int posix_locks_deadlock(struct file_lock *caller_fl, static int flock_lock_file(struct file *filp, struct file_lock *request) { struct file_lock *new_fl = NULL; struct file_lock **before; struct file_lock *fl; struct file_lock_context *ctx; struct inode *inode = file_inode(filp); int error = 0; int found = 0; bool found = false; LIST_HEAD(dispose); ctx = locks_get_lock_context(inode); if (!ctx) return -ENOMEM; if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { new_fl = locks_alloc_lock(); if (!new_fl) Loading @@ -904,18 +929,13 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) if (request->fl_flags & FL_ACCESS) goto find_conflict; for_each_lock(inode, before) { struct file_lock *fl = *before; if (IS_POSIX(fl)) break; if (IS_LEASE(fl)) continue; list_for_each_entry(fl, &ctx->flc_flock, fl_list) { if (filp != fl->fl_file) continue; if (request->fl_type == fl->fl_type) goto out; found = 1; locks_delete_lock(before, &dispose); found = true; locks_delete_lock_ctx(fl, &dispose); break; } Loading @@ -936,12 +956,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) } find_conflict: for_each_lock(inode, before) { struct file_lock *fl = *before; if (IS_POSIX(fl)) break; if (IS_LEASE(fl)) continue; list_for_each_entry(fl, &ctx->flc_flock, fl_list) { if (!flock_locks_conflict(request, fl)) continue; error = -EAGAIN; Loading @@ -954,7 +969,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) if (request->fl_flags & FL_ACCESS) goto out; locks_copy_lock(new_fl, request); locks_insert_lock(before, new_fl); locks_insert_lock_ctx(new_fl, &ctx->flc_flock); new_fl = NULL; error = 0; Loading Loading @@ -2412,8 +2427,9 @@ locks_remove_flock(struct file *filp) .fl_type = F_UNLCK, .fl_end = OFFSET_MAX, }; struct file_lock_context *flctx = file_inode(filp)->i_flctx; if (!file_inode(filp)->i_flock) if (!flctx || list_empty(&flctx->flc_flock)) return; if (filp->f_op->flock) Loading
fs/nfs/delegation.c +17 −2 Original line number Diff line number Diff line Loading @@ -85,15 +85,16 @@ 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; int status = 0; if (inode->i_flock == NULL) if (inode->i_flock == NULL && inode->i_flctx == NULL) goto out; /* Protect inode->i_flock using the i_lock */ spin_lock(&inode->i_lock); for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) if (!(fl->fl_flags & (FL_POSIX))) continue; if (nfs_file_open_context(fl->fl_file) != ctx) continue; Loading @@ -103,6 +104,20 @@ 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); } } spin_unlock(&inode->i_lock); out: return status; Loading
fs/nfs/nfs4state.c +40 −2 Original line number Diff line number Diff line Loading @@ -1366,8 +1366,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ struct nfs_inode *nfsi = NFS_I(inode); struct file_lock *fl; int status = 0; struct file_lock_context *flctx = inode->i_flctx; if (inode->i_flock == NULL) if (inode->i_flock == NULL && flctx == NULL) return 0; /* Guard against delegation returns and new lock/unlock calls */ Loading @@ -1375,7 +1376,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ /* 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|FL_FLOCK))) if (!(fl->fl_flags & FL_POSIX)) continue; if (nfs_file_open_context(fl->fl_file)->state != state) continue; Loading Loading @@ -1408,6 +1409,43 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ } spin_lock(&inode->i_lock); } if (!flctx) goto out_unlock; list_for_each_entry(fl, &flctx->flc_flock, fl_list) { 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: pr_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); } out_unlock: spin_unlock(&inode->i_lock); out: up_write(&nfsi->rwsem); Loading
fs/nfs/pagelist.c +6 −0 Original line number Diff line number Diff line Loading @@ -826,6 +826,7 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev, struct nfs_pageio_descriptor *pgio) { size_t size; struct file_lock_context *flctx; if (prev) { if (!nfs_match_open_context(req->wb_context, prev->wb_context)) Loading @@ -834,6 +835,11 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev, !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) && !nfs_match_lock_context(req->wb_lock_context, prev->wb_lock_context)) return false; if (req_offset(req) != req_offset(prev) + prev->wb_bytes) return false; if (req->wb_page == prev->wb_page) { Loading