]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Fix posix file locking (2/9)
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 23 Aug 2004 07:13:17 +0000 (00:13 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 23 Aug 2004 07:13:17 +0000 (00:13 -0700)
VFS: Enable filesystems and to hook certain functions for copying and
   freeing locks using the new struct file_lock_operations.

VFS: Enable lock managers (i.e. lockd) to hook functions for
   comparing lock ownership using the new struct
   lock_manager_operations.

Signed-off-by: Trond Myklebust <trond.myklebust@fys.uio.no>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/locks.c
include/linux/fs.h

index b0e47577cf08f58e37bc09e54ba81666428189de..4b16affb806205ff875ce09ed8080977ca0d37d3 100644 (file)
@@ -167,6 +167,13 @@ static inline void locks_free_lock(struct file_lock *fl)
        if (!list_empty(&fl->fl_link))
                panic("Attempting to free lock on active lock list");
 
+       if (fl->fl_ops) {
+               if (fl->fl_ops->fl_release_private)
+                       fl->fl_ops->fl_release_private(fl);
+               fl->fl_ops = NULL;
+       }
+       fl->fl_lmops = NULL;
+
        kmem_cache_free(filelock_cache, fl);
 }
 
@@ -186,6 +193,8 @@ void locks_init_lock(struct file_lock *fl)
        fl->fl_notify = NULL;
        fl->fl_insert = NULL;
        fl->fl_remove = NULL;
+       fl->fl_ops = NULL;
+       fl->fl_lmops = NULL;
 }
 
 EXPORT_SYMBOL(locks_init_lock);
@@ -220,7 +229,10 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
        new->fl_notify = fl->fl_notify;
        new->fl_insert = fl->fl_insert;
        new->fl_remove = fl->fl_remove;
-       new->fl_u = fl->fl_u;
+       new->fl_ops = fl->fl_ops;
+       new->fl_lmops = fl->fl_lmops;
+       if (fl->fl_ops && fl->fl_ops->fl_copy_lock)
+               fl->fl_ops->fl_copy_lock(new, fl);
 }
 
 EXPORT_SYMBOL(locks_copy_lock);
@@ -324,6 +336,8 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
        fl->fl_notify = NULL;
        fl->fl_insert = NULL;
        fl->fl_remove = NULL;
+       fl->fl_ops = NULL;
+       fl->fl_lmops = NULL;
 
        return assign_type(fl, l->l_type);
 }
@@ -364,6 +378,8 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
        fl->fl_notify = NULL;
        fl->fl_insert = NULL;
        fl->fl_remove = NULL;
+       fl->fl_ops = NULL;
+       fl->fl_lmops = NULL;
 
        switch (l->l_type) {
        case F_RDLCK:
@@ -400,6 +416,8 @@ static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
        fl->fl_notify = NULL;
        fl->fl_insert = NULL;
        fl->fl_remove = NULL;
+       fl->fl_ops = NULL;
+       fl->fl_lmops = NULL;
 
        *flp = fl;
        return 0;
@@ -419,10 +437,9 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
 static inline int
 posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 {
-       /* FIXME: Replace this sort of thing with struct file_lock_operations */
-       if ((fl1->fl_type | fl2->fl_type) & FL_LOCKD)
-               return fl1->fl_owner == fl2->fl_owner &&
-                       fl1->fl_pid == fl2->fl_pid;
+       if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner)
+               return fl2->fl_lmops == fl1->fl_lmops &&
+                       fl1->fl_lmops->fl_compare_owner(fl1, fl2);
        return fl1->fl_owner == fl2->fl_owner;
 }
 
@@ -1415,7 +1432,6 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
        error = -EFAULT;
        if (!copy_to_user(l, &flock, sizeof(flock)))
                error = 0;
-  
 out:
        return error;
 }
@@ -1665,6 +1681,8 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
        lock.fl_owner = owner;
        lock.fl_pid = current->tgid;
        lock.fl_file = filp;
+       lock.fl_ops = NULL;
+       lock.fl_lmops = NULL;
 
        if (filp->f_op && filp->f_op->lock != NULL) {
                filp->f_op->lock(filp, F_SETLK, &lock);
@@ -1684,6 +1702,8 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
                before = &fl->fl_next;
        }
        unlock_kernel();
+       if (lock.fl_ops && lock.fl_ops->fl_release_private)
+               lock.fl_ops->fl_release_private(&lock);
 }
 
 EXPORT_SYMBOL(locks_remove_posix);
index 9ab017c1403c416747e903ea2576ffeea900e4b5..cc2bbd2fb0c64c369a35779dc232a7125abc4fa4 100644 (file)
@@ -622,6 +622,15 @@ extern spinlock_t files_lock;
  */
 typedef struct files_struct *fl_owner_t;
 
+struct file_lock_operations {
+       void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+       void (*fl_release_private)(struct file_lock *);
+};
+
+struct lock_manager_operations {
+       int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
+};
+
 /* that will die - we need it for nfs_lock_info */
 #include <linux/nfs_fs_i.h>
 
@@ -645,6 +654,8 @@ struct file_lock {
        struct fasync_struct *  fl_fasync; /* for lease break notifications */
        unsigned long fl_break_time;    /* for nonblocking lease breaks */
 
+       struct file_lock_operations *fl_ops;    /* Callbacks for filesystems */
+       struct lock_manager_operations *fl_lmops;       /* Callbacks for lockmanagers */
        union {
                struct nfs_lock_info    nfs_fl;
        } fl_u;