Commit f9308812 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] Fix posix file locking (2/9)

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: default avatarTrond Myklebust <trond.myklebust@fys.uio.no>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 796bcdd1
...@@ -167,6 +167,13 @@ static inline void locks_free_lock(struct file_lock *fl) ...@@ -167,6 +167,13 @@ static inline void locks_free_lock(struct file_lock *fl)
if (!list_empty(&fl->fl_link)) if (!list_empty(&fl->fl_link))
panic("Attempting to free lock on active lock list"); 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); kmem_cache_free(filelock_cache, fl);
} }
...@@ -186,6 +193,8 @@ void locks_init_lock(struct file_lock *fl) ...@@ -186,6 +193,8 @@ void locks_init_lock(struct file_lock *fl)
fl->fl_notify = NULL; fl->fl_notify = NULL;
fl->fl_insert = NULL; fl->fl_insert = NULL;
fl->fl_remove = NULL; fl->fl_remove = NULL;
fl->fl_ops = NULL;
fl->fl_lmops = NULL;
} }
EXPORT_SYMBOL(locks_init_lock); EXPORT_SYMBOL(locks_init_lock);
...@@ -220,7 +229,10 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl) ...@@ -220,7 +229,10 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
new->fl_notify = fl->fl_notify; new->fl_notify = fl->fl_notify;
new->fl_insert = fl->fl_insert; new->fl_insert = fl->fl_insert;
new->fl_remove = fl->fl_remove; 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); EXPORT_SYMBOL(locks_copy_lock);
...@@ -324,6 +336,8 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, ...@@ -324,6 +336,8 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
fl->fl_notify = NULL; fl->fl_notify = NULL;
fl->fl_insert = NULL; fl->fl_insert = NULL;
fl->fl_remove = NULL; fl->fl_remove = NULL;
fl->fl_ops = NULL;
fl->fl_lmops = NULL;
return assign_type(fl, l->l_type); return assign_type(fl, l->l_type);
} }
...@@ -364,6 +378,8 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, ...@@ -364,6 +378,8 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
fl->fl_notify = NULL; fl->fl_notify = NULL;
fl->fl_insert = NULL; fl->fl_insert = NULL;
fl->fl_remove = NULL; fl->fl_remove = NULL;
fl->fl_ops = NULL;
fl->fl_lmops = NULL;
switch (l->l_type) { switch (l->l_type) {
case F_RDLCK: case F_RDLCK:
...@@ -400,6 +416,8 @@ static int lease_alloc(struct file *filp, int type, struct file_lock **flp) ...@@ -400,6 +416,8 @@ static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
fl->fl_notify = NULL; fl->fl_notify = NULL;
fl->fl_insert = NULL; fl->fl_insert = NULL;
fl->fl_remove = NULL; fl->fl_remove = NULL;
fl->fl_ops = NULL;
fl->fl_lmops = NULL;
*flp = fl; *flp = fl;
return 0; return 0;
...@@ -419,10 +437,9 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2) ...@@ -419,10 +437,9 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
static inline int static inline int
posix_same_owner(struct file_lock *fl1, struct file_lock *fl2) 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_lmops && fl1->fl_lmops->fl_compare_owner)
if ((fl1->fl_type | fl2->fl_type) & FL_LOCKD) return fl2->fl_lmops == fl1->fl_lmops &&
return fl1->fl_owner == fl2->fl_owner && fl1->fl_lmops->fl_compare_owner(fl1, fl2);
fl1->fl_pid == fl2->fl_pid;
return fl1->fl_owner == fl2->fl_owner; return fl1->fl_owner == fl2->fl_owner;
} }
...@@ -1415,7 +1432,6 @@ int fcntl_getlk(struct file *filp, struct flock __user *l) ...@@ -1415,7 +1432,6 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
error = -EFAULT; error = -EFAULT;
if (!copy_to_user(l, &flock, sizeof(flock))) if (!copy_to_user(l, &flock, sizeof(flock)))
error = 0; error = 0;
out: out:
return error; return error;
} }
...@@ -1665,6 +1681,8 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) ...@@ -1665,6 +1681,8 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
lock.fl_owner = owner; lock.fl_owner = owner;
lock.fl_pid = current->tgid; lock.fl_pid = current->tgid;
lock.fl_file = filp; lock.fl_file = filp;
lock.fl_ops = NULL;
lock.fl_lmops = NULL;
if (filp->f_op && filp->f_op->lock != NULL) { if (filp->f_op && filp->f_op->lock != NULL) {
filp->f_op->lock(filp, F_SETLK, &lock); filp->f_op->lock(filp, F_SETLK, &lock);
...@@ -1684,6 +1702,8 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) ...@@ -1684,6 +1702,8 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
before = &fl->fl_next; before = &fl->fl_next;
} }
unlock_kernel(); unlock_kernel();
if (lock.fl_ops && lock.fl_ops->fl_release_private)
lock.fl_ops->fl_release_private(&lock);
} }
EXPORT_SYMBOL(locks_remove_posix); EXPORT_SYMBOL(locks_remove_posix);
......
...@@ -622,6 +622,15 @@ extern spinlock_t files_lock; ...@@ -622,6 +622,15 @@ extern spinlock_t files_lock;
*/ */
typedef struct files_struct *fl_owner_t; 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 */ /* that will die - we need it for nfs_lock_info */
#include <linux/nfs_fs_i.h> #include <linux/nfs_fs_i.h>
...@@ -645,6 +654,8 @@ struct file_lock { ...@@ -645,6 +654,8 @@ struct file_lock {
struct fasync_struct * fl_fasync; /* for lease break notifications */ struct fasync_struct * fl_fasync; /* for lease break notifications */
unsigned long fl_break_time; /* for nonblocking lease breaks */ 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 { union {
struct nfs_lock_info nfs_fl; struct nfs_lock_info nfs_fl;
} fl_u; } fl_u;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment