diff options
author | Jeff Layton <jlayton@primarydata.com> | 2015-01-16 15:05:55 -0500 |
---|---|---|
committer | Jeff Layton <jeff.layton@primarydata.com> | 2015-01-16 15:09:25 -0500 |
commit | 5263e31e452fb84138b9bee061d5c06c0f359fea (patch) | |
tree | 68726ce860d2c824f605e6ec3f2adc9187d6dc86 /fs/locks.c | |
parent | c362781cadd37858c3d8f5d18b1e9957d4671298 (diff) |
locks: move flock locks to file_lock_context
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Acked-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/fs/locks.c b/fs/locks.c index 526d5fca67c8..055df53f19de 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -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 @@ -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. */ @@ -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 inode * inode = file_inode(filp); + 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) @@ -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; } @@ -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; @@ -954,7 +969,7 @@ find_conflict: 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; @@ -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) |