locks: move flock locks to file_lock_context

Signed-off-by: Jeff Layton <[email protected]>
Acked-by: Christoph Hellwig <[email protected]>
This commit is contained in:
Jeff Layton 2015-01-16 15:05:55 -05:00 • committed by Jeff Layton
commit 5263e31e45
6 changed files with 152 additions and 35 deletions

View file

@ -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)