diff options
author | Kinglong Mee <kinglongmee@gmail.com> | 2014-08-22 10:18:43 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@primarydata.com> | 2014-09-09 16:01:09 -0400 |
commit | f328296e27414394f25cebaef4a111a82ce0df32 (patch) | |
tree | 2263381bcef86e21e5d20dbfdd72c1f248382daa | |
parent | 5c97d7b1479982a48cf2129062b880c2555049ac (diff) |
locks: Copy fl_lmops information for conflock in locks_copy_conflock()
Commit d5b9026a67 ([PATCH] knfsd: locks: flag NFSv4-owned locks) using
fl_lmops field in file_lock for checking nfsd4 lockowner.
But, commit 1a747ee0cc (locks: don't call ->copy_lock methods on return
of conflicting locks) causes the fl_lmops of conflock always be NULL.
Also, commit 0996905f93 (lockd: posix_test_lock() should not call
locks_copy_lock()) caused the fl_lmops of conflock always be NULL too.
Make sure copy the private information by fl_copy_lock() in struct
file_lock_operations, merge __locks_copy_lock() to fl_copy_lock().
Jeff advice, "Set fl_lmops on conflocks, but don't set fl_ops.
fl_ops are superfluous, since they are callbacks into the filesystem.
There should be no need to bother the filesystem at all with info
in a conflock. But, lock _ownership_ matters for conflocks and that's
indicated by the fl_lmops. So you really do want to copy the fl_lmops
for conflocks I think."
v5: add missing calling of locks_release_private() in nlmsvc_testlock()
v4: only copy fl_lmops for conflock, don't copy fl_ops
Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
-rw-r--r-- | fs/lockd/svclock.c | 1 | ||||
-rw-r--r-- | fs/locks.c | 36 |
2 files changed, 17 insertions, 20 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 2a6170133c1d..acfa94d5b489 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -586,6 +586,7 @@ conf_lock: | |||
586 | conflock->fl.fl_type = lock->fl.fl_type; | 586 | conflock->fl.fl_type = lock->fl.fl_type; |
587 | conflock->fl.fl_start = lock->fl.fl_start; | 587 | conflock->fl.fl_start = lock->fl.fl_start; |
588 | conflock->fl.fl_end = lock->fl.fl_end; | 588 | conflock->fl.fl_end = lock->fl.fl_end; |
589 | locks_release_private(&lock->fl); | ||
589 | ret = nlm_lck_denied; | 590 | ret = nlm_lck_denied; |
590 | out: | 591 | out: |
591 | if (block) | 592 | if (block) |
diff --git a/fs/locks.c b/fs/locks.c index 5e83f3a99377..c3991dc80137 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -271,21 +271,6 @@ void locks_init_lock(struct file_lock *fl) | |||
271 | 271 | ||
272 | EXPORT_SYMBOL(locks_init_lock); | 272 | EXPORT_SYMBOL(locks_init_lock); |
273 | 273 | ||
274 | static void locks_copy_private(struct file_lock *new, struct file_lock *fl) | ||
275 | { | ||
276 | if (fl->fl_ops) { | ||
277 | if (fl->fl_ops->fl_copy_lock) | ||
278 | fl->fl_ops->fl_copy_lock(new, fl); | ||
279 | new->fl_ops = fl->fl_ops; | ||
280 | } | ||
281 | |||
282 | if (fl->fl_lmops) { | ||
283 | if (fl->fl_lmops->lm_get_owner) | ||
284 | fl->fl_lmops->lm_get_owner(new, fl); | ||
285 | new->fl_lmops = fl->fl_lmops; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | /* | 274 | /* |
290 | * Initialize a new lock from an existing file_lock structure. | 275 | * Initialize a new lock from an existing file_lock structure. |
291 | */ | 276 | */ |
@@ -298,8 +283,13 @@ void locks_copy_conflock(struct file_lock *new, struct file_lock *fl) | |||
298 | new->fl_type = fl->fl_type; | 283 | new->fl_type = fl->fl_type; |
299 | new->fl_start = fl->fl_start; | 284 | new->fl_start = fl->fl_start; |
300 | new->fl_end = fl->fl_end; | 285 | new->fl_end = fl->fl_end; |
286 | new->fl_lmops = fl->fl_lmops; | ||
301 | new->fl_ops = NULL; | 287 | new->fl_ops = NULL; |
302 | new->fl_lmops = NULL; | 288 | |
289 | if (fl->fl_lmops) { | ||
290 | if (fl->fl_lmops->lm_get_owner) | ||
291 | fl->fl_lmops->lm_get_owner(new, fl); | ||
292 | } | ||
303 | } | 293 | } |
304 | EXPORT_SYMBOL(locks_copy_conflock); | 294 | EXPORT_SYMBOL(locks_copy_conflock); |
305 | 295 | ||
@@ -309,11 +299,14 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl) | |||
309 | WARN_ON_ONCE(new->fl_ops); | 299 | WARN_ON_ONCE(new->fl_ops); |
310 | 300 | ||
311 | locks_copy_conflock(new, fl); | 301 | locks_copy_conflock(new, fl); |
302 | |||
312 | new->fl_file = fl->fl_file; | 303 | new->fl_file = fl->fl_file; |
313 | new->fl_ops = fl->fl_ops; | 304 | new->fl_ops = fl->fl_ops; |
314 | new->fl_lmops = fl->fl_lmops; | ||
315 | 305 | ||
316 | locks_copy_private(new, fl); | 306 | if (fl->fl_ops) { |
307 | if (fl->fl_ops->fl_copy_lock) | ||
308 | fl->fl_ops->fl_copy_lock(new, fl); | ||
309 | } | ||
317 | } | 310 | } |
318 | 311 | ||
319 | EXPORT_SYMBOL(locks_copy_lock); | 312 | EXPORT_SYMBOL(locks_copy_lock); |
@@ -1989,11 +1982,13 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l) | |||
1989 | if (file_lock.fl_type != F_UNLCK) { | 1982 | if (file_lock.fl_type != F_UNLCK) { |
1990 | error = posix_lock_to_flock(&flock, &file_lock); | 1983 | error = posix_lock_to_flock(&flock, &file_lock); |
1991 | if (error) | 1984 | if (error) |
1992 | goto out; | 1985 | goto rel_priv; |
1993 | } | 1986 | } |
1994 | error = -EFAULT; | 1987 | error = -EFAULT; |
1995 | if (!copy_to_user(l, &flock, sizeof(flock))) | 1988 | if (!copy_to_user(l, &flock, sizeof(flock))) |
1996 | error = 0; | 1989 | error = 0; |
1990 | rel_priv: | ||
1991 | locks_release_private(&file_lock); | ||
1997 | out: | 1992 | out: |
1998 | return error; | 1993 | return error; |
1999 | } | 1994 | } |
@@ -2214,7 +2209,8 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) | |||
2214 | error = -EFAULT; | 2209 | error = -EFAULT; |
2215 | if (!copy_to_user(l, &flock, sizeof(flock))) | 2210 | if (!copy_to_user(l, &flock, sizeof(flock))) |
2216 | error = 0; | 2211 | error = 0; |
2217 | 2212 | ||
2213 | locks_release_private(&file_lock); | ||
2218 | out: | 2214 | out: |
2219 | return error; | 2215 | return error; |
2220 | } | 2216 | } |