locks: move flock locks to file_lock_context
[linux-2.6-block.git] / fs / locks.c
index 526d5fca67c8f46be67b181b2b6ff8c6d36a3dbc..055df53f19de7476bf6bdff8501faffd0664d937 100644 (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)