diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-11 13:21:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-11 13:21:34 -0400 |
commit | ef4a48c513211d842c55e84f7a1c31884b91dcf7 (patch) | |
tree | 997ecc4d359a7307d6c0e55ab057fe9f9c2b888e /fs | |
parent | 90d0c376f5ee1927327b267faf15bf970476f09e (diff) | |
parent | 1b2b32dcdb3df28dd103033c73cac2417fa05845 (diff) |
Merge tag 'locks-v3.18-1' of git://git.samba.org/jlayton/linux
Pull file locking related changes from Jeff Layton:
"This release is a little more busy for file locking changes than the
last:
- a set of patches from Kinglong Mee to fix the lockowner handling in
knfsd
- a pile of cleanups to the internal file lease API. This should get
us a bit closer to allowing for setlease methods that can block.
There are some dependencies between mine and Bruce's trees this cycle,
and I based my tree on top of the requisite patches in Bruce's tree"
* tag 'locks-v3.18-1' of git://git.samba.org/jlayton/linux: (26 commits)
locks: fix fcntl_setlease/getlease return when !CONFIG_FILE_LOCKING
locks: flock_make_lock should return a struct file_lock (or PTR_ERR)
locks: set fl_owner for leases to filp instead of current->files
locks: give lm_break a return value
locks: __break_lease cleanup in preparation of allowing direct removal of leases
locks: remove i_have_this_lease check from __break_lease
locks: move freeing of leases outside of i_lock
locks: move i_lock acquisition into generic_*_lease handlers
locks: define a lm_setup handler for leases
locks: plumb a "priv" pointer into the setlease routines
nfsd: don't keep a pointer to the lease in nfs4_file
locks: clean up vfs_setlease kerneldoc comments
locks: generic_delete_lease doesn't need a file_lock at all
nfsd: fix potential lease memory leak in nfs4_setlease
locks: close potential race in lease_get_mtime
security: make security_file_set_fowner, f_setown and __f_setown void return
locks: consolidate "nolease" routines
locks: remove lock_may_read and lock_may_write
lockd: rip out deferred lock handling from testlock codepath
NFSD: Get reference of lockowner when coping file_lock
...
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsfs.c | 7 | ||||
-rw-r--r-- | fs/dlm/plock.c | 8 | ||||
-rw-r--r-- | fs/fcntl.c | 21 | ||||
-rw-r--r-- | fs/gfs2/file.c | 22 | ||||
-rw-r--r-- | fs/libfs.c | 18 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 68 | ||||
-rw-r--r-- | fs/locks.c | 444 | ||||
-rw-r--r-- | fs/nfs/file.c | 13 | ||||
-rw-r--r-- | fs/nfs/internal.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4file.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 104 | ||||
-rw-r--r-- | fs/nfsd/state.h | 1 | ||||
-rw-r--r-- | fs/notify/dnotify/dnotify.c | 8 |
13 files changed, 300 insertions, 417 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 889b98455750..9d7996e8e793 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -813,7 +813,8 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) | |||
813 | return generic_file_llseek(file, offset, whence); | 813 | return generic_file_llseek(file, offset, whence); |
814 | } | 814 | } |
815 | 815 | ||
816 | static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | 816 | static int |
817 | cifs_setlease(struct file *file, long arg, struct file_lock **lease, void **priv) | ||
817 | { | 818 | { |
818 | /* | 819 | /* |
819 | * Note that this is called by vfs setlease with i_lock held to | 820 | * Note that this is called by vfs setlease with i_lock held to |
@@ -829,7 +830,7 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | |||
829 | if (arg == F_UNLCK || | 830 | if (arg == F_UNLCK || |
830 | ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) || | 831 | ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) || |
831 | ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode)))) | 832 | ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode)))) |
832 | return generic_setlease(file, arg, lease); | 833 | return generic_setlease(file, arg, lease, priv); |
833 | else if (tlink_tcon(cfile->tlink)->local_lease && | 834 | else if (tlink_tcon(cfile->tlink)->local_lease && |
834 | !CIFS_CACHE_READ(CIFS_I(inode))) | 835 | !CIFS_CACHE_READ(CIFS_I(inode))) |
835 | /* | 836 | /* |
@@ -840,7 +841,7 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | |||
840 | * knows that the file won't be changed on the server by anyone | 841 | * knows that the file won't be changed on the server by anyone |
841 | * else. | 842 | * else. |
842 | */ | 843 | */ |
843 | return generic_setlease(file, arg, lease); | 844 | return generic_setlease(file, arg, lease, priv); |
844 | else | 845 | else |
845 | return -EAGAIN; | 846 | return -EAGAIN; |
846 | } | 847 | } |
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index f704458ea5f5..e0ab3a93eeff 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c | |||
@@ -30,7 +30,7 @@ struct plock_op { | |||
30 | 30 | ||
31 | struct plock_xop { | 31 | struct plock_xop { |
32 | struct plock_op xop; | 32 | struct plock_op xop; |
33 | void *callback; | 33 | int (*callback)(struct file_lock *fl, int result); |
34 | void *fl; | 34 | void *fl; |
35 | void *file; | 35 | void *file; |
36 | struct file_lock flc; | 36 | struct file_lock flc; |
@@ -190,7 +190,7 @@ static int dlm_plock_callback(struct plock_op *op) | |||
190 | struct file *file; | 190 | struct file *file; |
191 | struct file_lock *fl; | 191 | struct file_lock *fl; |
192 | struct file_lock *flc; | 192 | struct file_lock *flc; |
193 | int (*notify)(void *, void *, int) = NULL; | 193 | int (*notify)(struct file_lock *fl, int result) = NULL; |
194 | struct plock_xop *xop = (struct plock_xop *)op; | 194 | struct plock_xop *xop = (struct plock_xop *)op; |
195 | int rv = 0; | 195 | int rv = 0; |
196 | 196 | ||
@@ -209,7 +209,7 @@ static int dlm_plock_callback(struct plock_op *op) | |||
209 | notify = xop->callback; | 209 | notify = xop->callback; |
210 | 210 | ||
211 | if (op->info.rv) { | 211 | if (op->info.rv) { |
212 | notify(fl, NULL, op->info.rv); | 212 | notify(fl, op->info.rv); |
213 | goto out; | 213 | goto out; |
214 | } | 214 | } |
215 | 215 | ||
@@ -228,7 +228,7 @@ static int dlm_plock_callback(struct plock_op *op) | |||
228 | (unsigned long long)op->info.number, file, fl); | 228 | (unsigned long long)op->info.number, file, fl); |
229 | } | 229 | } |
230 | 230 | ||
231 | rv = notify(fl, NULL, 0); | 231 | rv = notify(fl, 0); |
232 | if (rv) { | 232 | if (rv) { |
233 | /* XXX: We need to cancel the fs lock here: */ | 233 | /* XXX: We need to cancel the fs lock here: */ |
234 | log_print("dlm_plock_callback: lock granted after lock request " | 234 | log_print("dlm_plock_callback: lock granted after lock request " |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 22d1c3df61ac..99d440a4a6ba 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -98,26 +98,19 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, | |||
98 | write_unlock_irq(&filp->f_owner.lock); | 98 | write_unlock_irq(&filp->f_owner.lock); |
99 | } | 99 | } |
100 | 100 | ||
101 | int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, | 101 | void __f_setown(struct file *filp, struct pid *pid, enum pid_type type, |
102 | int force) | 102 | int force) |
103 | { | 103 | { |
104 | int err; | 104 | security_file_set_fowner(filp); |
105 | |||
106 | err = security_file_set_fowner(filp); | ||
107 | if (err) | ||
108 | return err; | ||
109 | |||
110 | f_modown(filp, pid, type, force); | 105 | f_modown(filp, pid, type, force); |
111 | return 0; | ||
112 | } | 106 | } |
113 | EXPORT_SYMBOL(__f_setown); | 107 | EXPORT_SYMBOL(__f_setown); |
114 | 108 | ||
115 | int f_setown(struct file *filp, unsigned long arg, int force) | 109 | void f_setown(struct file *filp, unsigned long arg, int force) |
116 | { | 110 | { |
117 | enum pid_type type; | 111 | enum pid_type type; |
118 | struct pid *pid; | 112 | struct pid *pid; |
119 | int who = arg; | 113 | int who = arg; |
120 | int result; | ||
121 | type = PIDTYPE_PID; | 114 | type = PIDTYPE_PID; |
122 | if (who < 0) { | 115 | if (who < 0) { |
123 | type = PIDTYPE_PGID; | 116 | type = PIDTYPE_PGID; |
@@ -125,9 +118,8 @@ int f_setown(struct file *filp, unsigned long arg, int force) | |||
125 | } | 118 | } |
126 | rcu_read_lock(); | 119 | rcu_read_lock(); |
127 | pid = find_vpid(who); | 120 | pid = find_vpid(who); |
128 | result = __f_setown(filp, pid, type, force); | 121 | __f_setown(filp, pid, type, force); |
129 | rcu_read_unlock(); | 122 | rcu_read_unlock(); |
130 | return result; | ||
131 | } | 123 | } |
132 | EXPORT_SYMBOL(f_setown); | 124 | EXPORT_SYMBOL(f_setown); |
133 | 125 | ||
@@ -181,7 +173,7 @@ static int f_setown_ex(struct file *filp, unsigned long arg) | |||
181 | if (owner.pid && !pid) | 173 | if (owner.pid && !pid) |
182 | ret = -ESRCH; | 174 | ret = -ESRCH; |
183 | else | 175 | else |
184 | ret = __f_setown(filp, pid, type, 1); | 176 | __f_setown(filp, pid, type, 1); |
185 | rcu_read_unlock(); | 177 | rcu_read_unlock(); |
186 | 178 | ||
187 | return ret; | 179 | return ret; |
@@ -302,7 +294,8 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
302 | force_successful_syscall_return(); | 294 | force_successful_syscall_return(); |
303 | break; | 295 | break; |
304 | case F_SETOWN: | 296 | case F_SETOWN: |
305 | err = f_setown(filp, arg, 1); | 297 | f_setown(filp, arg, 1); |
298 | err = 0; | ||
306 | break; | 299 | break; |
307 | case F_GETOWN_EX: | 300 | case F_GETOWN_EX: |
308 | err = f_getown_ex(filp, arg); | 301 | err = f_getown_ex(filp, arg); |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 7f4ed3daa38c..80dd44dca028 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -914,26 +914,6 @@ out_uninit: | |||
914 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM | 914 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM |
915 | 915 | ||
916 | /** | 916 | /** |
917 | * gfs2_setlease - acquire/release a file lease | ||
918 | * @file: the file pointer | ||
919 | * @arg: lease type | ||
920 | * @fl: file lock | ||
921 | * | ||
922 | * We don't currently have a way to enforce a lease across the whole | ||
923 | * cluster; until we do, disable leases (by just returning -EINVAL), | ||
924 | * unless the administrator has requested purely local locking. | ||
925 | * | ||
926 | * Locking: called under i_lock | ||
927 | * | ||
928 | * Returns: errno | ||
929 | */ | ||
930 | |||
931 | static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl) | ||
932 | { | ||
933 | return -EINVAL; | ||
934 | } | ||
935 | |||
936 | /** | ||
937 | * gfs2_lock - acquire/release a posix lock on a file | 917 | * gfs2_lock - acquire/release a posix lock on a file |
938 | * @file: the file pointer | 918 | * @file: the file pointer |
939 | * @cmd: either modify or retrieve lock state, possibly wait | 919 | * @cmd: either modify or retrieve lock state, possibly wait |
@@ -1078,7 +1058,7 @@ const struct file_operations gfs2_file_fops = { | |||
1078 | .flock = gfs2_flock, | 1058 | .flock = gfs2_flock, |
1079 | .splice_read = generic_file_splice_read, | 1059 | .splice_read = generic_file_splice_read, |
1080 | .splice_write = iter_file_splice_write, | 1060 | .splice_write = iter_file_splice_write, |
1081 | .setlease = gfs2_setlease, | 1061 | .setlease = simple_nosetlease, |
1082 | .fallocate = gfs2_fallocate, | 1062 | .fallocate = gfs2_fallocate, |
1083 | }; | 1063 | }; |
1084 | 1064 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index 88e3e00e2eca..171d2846f2a3 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -1075,3 +1075,21 @@ struct inode *alloc_anon_inode(struct super_block *s) | |||
1075 | return inode; | 1075 | return inode; |
1076 | } | 1076 | } |
1077 | EXPORT_SYMBOL(alloc_anon_inode); | 1077 | EXPORT_SYMBOL(alloc_anon_inode); |
1078 | |||
1079 | /** | ||
1080 | * simple_nosetlease - generic helper for prohibiting leases | ||
1081 | * @filp: file pointer | ||
1082 | * @arg: type of lease to obtain | ||
1083 | * @flp: new lease supplied for insertion | ||
1084 | * @priv: private data for lm_setup operation | ||
1085 | * | ||
1086 | * Generic helper for filesystems that do not wish to allow leases to be set. | ||
1087 | * All arguments are ignored and it just returns -EINVAL. | ||
1088 | */ | ||
1089 | int | ||
1090 | simple_nosetlease(struct file *filp, long arg, struct file_lock **flp, | ||
1091 | void **priv) | ||
1092 | { | ||
1093 | return -EINVAL; | ||
1094 | } | ||
1095 | EXPORT_SYMBOL(simple_nosetlease); | ||
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index ab798a88ec1d..13db95f54176 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -245,7 +245,6 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host, | |||
245 | block->b_daemon = rqstp->rq_server; | 245 | block->b_daemon = rqstp->rq_server; |
246 | block->b_host = host; | 246 | block->b_host = host; |
247 | block->b_file = file; | 247 | block->b_file = file; |
248 | block->b_fl = NULL; | ||
249 | file->f_count++; | 248 | file->f_count++; |
250 | 249 | ||
251 | /* Add to file's list of blocks */ | 250 | /* Add to file's list of blocks */ |
@@ -295,7 +294,6 @@ static void nlmsvc_free_block(struct kref *kref) | |||
295 | nlmsvc_freegrantargs(block->b_call); | 294 | nlmsvc_freegrantargs(block->b_call); |
296 | nlmsvc_release_call(block->b_call); | 295 | nlmsvc_release_call(block->b_call); |
297 | nlm_release_file(block->b_file); | 296 | nlm_release_file(block->b_file); |
298 | kfree(block->b_fl); | ||
299 | kfree(block); | 297 | kfree(block); |
300 | } | 298 | } |
301 | 299 | ||
@@ -508,7 +506,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
508 | struct nlm_host *host, struct nlm_lock *lock, | 506 | struct nlm_host *host, struct nlm_lock *lock, |
509 | struct nlm_lock *conflock, struct nlm_cookie *cookie) | 507 | struct nlm_lock *conflock, struct nlm_cookie *cookie) |
510 | { | 508 | { |
511 | struct nlm_block *block = NULL; | ||
512 | int error; | 509 | int error; |
513 | __be32 ret; | 510 | __be32 ret; |
514 | 511 | ||
@@ -519,63 +516,26 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
519 | (long long)lock->fl.fl_start, | 516 | (long long)lock->fl.fl_start, |
520 | (long long)lock->fl.fl_end); | 517 | (long long)lock->fl.fl_end); |
521 | 518 | ||
522 | /* Get existing block (in case client is busy-waiting) */ | ||
523 | block = nlmsvc_lookup_block(file, lock); | ||
524 | |||
525 | if (block == NULL) { | ||
526 | struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL); | ||
527 | |||
528 | if (conf == NULL) | ||
529 | return nlm_granted; | ||
530 | block = nlmsvc_create_block(rqstp, host, file, lock, cookie); | ||
531 | if (block == NULL) { | ||
532 | kfree(conf); | ||
533 | return nlm_granted; | ||
534 | } | ||
535 | block->b_fl = conf; | ||
536 | } | ||
537 | if (block->b_flags & B_QUEUED) { | ||
538 | dprintk("lockd: nlmsvc_testlock deferred block %p flags %d fl %p\n", | ||
539 | block, block->b_flags, block->b_fl); | ||
540 | if (block->b_flags & B_TIMED_OUT) { | ||
541 | nlmsvc_unlink_block(block); | ||
542 | ret = nlm_lck_denied; | ||
543 | goto out; | ||
544 | } | ||
545 | if (block->b_flags & B_GOT_CALLBACK) { | ||
546 | nlmsvc_unlink_block(block); | ||
547 | if (block->b_fl != NULL | ||
548 | && block->b_fl->fl_type != F_UNLCK) { | ||
549 | lock->fl = *block->b_fl; | ||
550 | goto conf_lock; | ||
551 | } else { | ||
552 | ret = nlm_granted; | ||
553 | goto out; | ||
554 | } | ||
555 | } | ||
556 | ret = nlm_drop_reply; | ||
557 | goto out; | ||
558 | } | ||
559 | |||
560 | if (locks_in_grace(SVC_NET(rqstp))) { | 519 | if (locks_in_grace(SVC_NET(rqstp))) { |
561 | ret = nlm_lck_denied_grace_period; | 520 | ret = nlm_lck_denied_grace_period; |
562 | goto out; | 521 | goto out; |
563 | } | 522 | } |
523 | |||
564 | error = vfs_test_lock(file->f_file, &lock->fl); | 524 | error = vfs_test_lock(file->f_file, &lock->fl); |
565 | if (error == FILE_LOCK_DEFERRED) { | ||
566 | ret = nlmsvc_defer_lock_rqst(rqstp, block); | ||
567 | goto out; | ||
568 | } | ||
569 | if (error) { | 525 | if (error) { |
526 | /* We can't currently deal with deferred test requests */ | ||
527 | if (error == FILE_LOCK_DEFERRED) | ||
528 | WARN_ON_ONCE(1); | ||
529 | |||
570 | ret = nlm_lck_denied_nolocks; | 530 | ret = nlm_lck_denied_nolocks; |
571 | goto out; | 531 | goto out; |
572 | } | 532 | } |
533 | |||
573 | if (lock->fl.fl_type == F_UNLCK) { | 534 | if (lock->fl.fl_type == F_UNLCK) { |
574 | ret = nlm_granted; | 535 | ret = nlm_granted; |
575 | goto out; | 536 | goto out; |
576 | } | 537 | } |
577 | 538 | ||
578 | conf_lock: | ||
579 | dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", | 539 | dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", |
580 | lock->fl.fl_type, (long long)lock->fl.fl_start, | 540 | lock->fl.fl_type, (long long)lock->fl.fl_start, |
581 | (long long)lock->fl.fl_end); | 541 | (long long)lock->fl.fl_end); |
@@ -586,10 +546,9 @@ conf_lock: | |||
586 | conflock->fl.fl_type = lock->fl.fl_type; | 546 | conflock->fl.fl_type = lock->fl.fl_type; |
587 | conflock->fl.fl_start = lock->fl.fl_start; | 547 | conflock->fl.fl_start = lock->fl.fl_start; |
588 | conflock->fl.fl_end = lock->fl.fl_end; | 548 | conflock->fl.fl_end = lock->fl.fl_end; |
549 | locks_release_private(&lock->fl); | ||
589 | ret = nlm_lck_denied; | 550 | ret = nlm_lck_denied; |
590 | out: | 551 | out: |
591 | if (block) | ||
592 | nlmsvc_release_block(block); | ||
593 | return ret; | 552 | return ret; |
594 | } | 553 | } |
595 | 554 | ||
@@ -660,29 +619,22 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *l | |||
660 | * This is a callback from the filesystem for VFS file lock requests. | 619 | * This is a callback from the filesystem for VFS file lock requests. |
661 | * It will be used if lm_grant is defined and the filesystem can not | 620 | * It will be used if lm_grant is defined and the filesystem can not |
662 | * respond to the request immediately. | 621 | * respond to the request immediately. |
663 | * For GETLK request it will copy the reply to the nlm_block. | ||
664 | * For SETLK or SETLKW request it will get the local posix lock. | 622 | * For SETLK or SETLKW request it will get the local posix lock. |
665 | * In all cases it will move the block to the head of nlm_blocked q where | 623 | * In all cases it will move the block to the head of nlm_blocked q where |
666 | * nlmsvc_retry_blocked() can send back a reply for SETLKW or revisit the | 624 | * nlmsvc_retry_blocked() can send back a reply for SETLKW or revisit the |
667 | * deferred rpc for GETLK and SETLK. | 625 | * deferred rpc for GETLK and SETLK. |
668 | */ | 626 | */ |
669 | static void | 627 | static void |
670 | nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf, | 628 | nlmsvc_update_deferred_block(struct nlm_block *block, int result) |
671 | int result) | ||
672 | { | 629 | { |
673 | block->b_flags |= B_GOT_CALLBACK; | 630 | block->b_flags |= B_GOT_CALLBACK; |
674 | if (result == 0) | 631 | if (result == 0) |
675 | block->b_granted = 1; | 632 | block->b_granted = 1; |
676 | else | 633 | else |
677 | block->b_flags |= B_TIMED_OUT; | 634 | block->b_flags |= B_TIMED_OUT; |
678 | if (conf) { | ||
679 | if (block->b_fl) | ||
680 | __locks_copy_lock(block->b_fl, conf); | ||
681 | } | ||
682 | } | 635 | } |
683 | 636 | ||
684 | static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf, | 637 | static int nlmsvc_grant_deferred(struct file_lock *fl, int result) |
685 | int result) | ||
686 | { | 638 | { |
687 | struct nlm_block *block; | 639 | struct nlm_block *block; |
688 | int rc = -ENOENT; | 640 | int rc = -ENOENT; |
@@ -697,7 +649,7 @@ static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf, | |||
697 | rc = -ENOLCK; | 649 | rc = -ENOLCK; |
698 | break; | 650 | break; |
699 | } | 651 | } |
700 | nlmsvc_update_deferred_block(block, conf, result); | 652 | nlmsvc_update_deferred_block(block, result); |
701 | } else if (result == 0) | 653 | } else if (result == 0) |
702 | block->b_granted = 1; | 654 | block->b_granted = 1; |
703 | 655 | ||
diff --git a/fs/locks.c b/fs/locks.c index bb08857f90b5..735b8d3fa78c 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -230,8 +230,12 @@ void locks_release_private(struct file_lock *fl) | |||
230 | fl->fl_ops->fl_release_private(fl); | 230 | fl->fl_ops->fl_release_private(fl); |
231 | fl->fl_ops = NULL; | 231 | fl->fl_ops = NULL; |
232 | } | 232 | } |
233 | fl->fl_lmops = NULL; | ||
234 | 233 | ||
234 | if (fl->fl_lmops) { | ||
235 | if (fl->fl_lmops->lm_put_owner) | ||
236 | fl->fl_lmops->lm_put_owner(fl); | ||
237 | fl->fl_lmops = NULL; | ||
238 | } | ||
235 | } | 239 | } |
236 | EXPORT_SYMBOL_GPL(locks_release_private); | 240 | EXPORT_SYMBOL_GPL(locks_release_private); |
237 | 241 | ||
@@ -267,21 +271,10 @@ void locks_init_lock(struct file_lock *fl) | |||
267 | 271 | ||
268 | EXPORT_SYMBOL(locks_init_lock); | 272 | EXPORT_SYMBOL(locks_init_lock); |
269 | 273 | ||
270 | static void locks_copy_private(struct file_lock *new, struct file_lock *fl) | ||
271 | { | ||
272 | if (fl->fl_ops) { | ||
273 | if (fl->fl_ops->fl_copy_lock) | ||
274 | fl->fl_ops->fl_copy_lock(new, fl); | ||
275 | new->fl_ops = fl->fl_ops; | ||
276 | } | ||
277 | if (fl->fl_lmops) | ||
278 | new->fl_lmops = fl->fl_lmops; | ||
279 | } | ||
280 | |||
281 | /* | 274 | /* |
282 | * Initialize a new lock from an existing file_lock structure. | 275 | * Initialize a new lock from an existing file_lock structure. |
283 | */ | 276 | */ |
284 | void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl) | 277 | void locks_copy_conflock(struct file_lock *new, struct file_lock *fl) |
285 | { | 278 | { |
286 | new->fl_owner = fl->fl_owner; | 279 | new->fl_owner = fl->fl_owner; |
287 | new->fl_pid = fl->fl_pid; | 280 | new->fl_pid = fl->fl_pid; |
@@ -290,22 +283,30 @@ void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl) | |||
290 | new->fl_type = fl->fl_type; | 283 | new->fl_type = fl->fl_type; |
291 | new->fl_start = fl->fl_start; | 284 | new->fl_start = fl->fl_start; |
292 | new->fl_end = fl->fl_end; | 285 | new->fl_end = fl->fl_end; |
286 | new->fl_lmops = fl->fl_lmops; | ||
293 | new->fl_ops = NULL; | 287 | new->fl_ops = NULL; |
294 | 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 | } | ||
295 | } | 293 | } |
296 | EXPORT_SYMBOL(__locks_copy_lock); | 294 | EXPORT_SYMBOL(locks_copy_conflock); |
297 | 295 | ||
298 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) | 296 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) |
299 | { | 297 | { |
300 | /* "new" must be a freshly-initialized lock */ | 298 | /* "new" must be a freshly-initialized lock */ |
301 | WARN_ON_ONCE(new->fl_ops); | 299 | WARN_ON_ONCE(new->fl_ops); |
302 | 300 | ||
303 | __locks_copy_lock(new, fl); | 301 | locks_copy_conflock(new, fl); |
302 | |||
304 | new->fl_file = fl->fl_file; | 303 | new->fl_file = fl->fl_file; |
305 | new->fl_ops = fl->fl_ops; | 304 | new->fl_ops = fl->fl_ops; |
306 | new->fl_lmops = fl->fl_lmops; | ||
307 | 305 | ||
308 | 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 | } | ||
309 | } | 310 | } |
310 | 311 | ||
311 | EXPORT_SYMBOL(locks_copy_lock); | 312 | EXPORT_SYMBOL(locks_copy_lock); |
@@ -325,17 +326,18 @@ static inline int flock_translate_cmd(int cmd) { | |||
325 | } | 326 | } |
326 | 327 | ||
327 | /* Fill in a file_lock structure with an appropriate FLOCK lock. */ | 328 | /* Fill in a file_lock structure with an appropriate FLOCK lock. */ |
328 | static int flock_make_lock(struct file *filp, struct file_lock **lock, | 329 | static struct file_lock * |
329 | unsigned int cmd) | 330 | flock_make_lock(struct file *filp, unsigned int cmd) |
330 | { | 331 | { |
331 | struct file_lock *fl; | 332 | struct file_lock *fl; |
332 | int type = flock_translate_cmd(cmd); | 333 | int type = flock_translate_cmd(cmd); |
334 | |||
333 | if (type < 0) | 335 | if (type < 0) |
334 | return type; | 336 | return ERR_PTR(type); |
335 | 337 | ||
336 | fl = locks_alloc_lock(); | 338 | fl = locks_alloc_lock(); |
337 | if (fl == NULL) | 339 | if (fl == NULL) |
338 | return -ENOMEM; | 340 | return ERR_PTR(-ENOMEM); |
339 | 341 | ||
340 | fl->fl_file = filp; | 342 | fl->fl_file = filp; |
341 | fl->fl_owner = filp; | 343 | fl->fl_owner = filp; |
@@ -344,8 +346,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock, | |||
344 | fl->fl_type = type; | 346 | fl->fl_type = type; |
345 | fl->fl_end = OFFSET_MAX; | 347 | fl->fl_end = OFFSET_MAX; |
346 | 348 | ||
347 | *lock = fl; | 349 | return fl; |
348 | return 0; | ||
349 | } | 350 | } |
350 | 351 | ||
351 | static int assign_type(struct file_lock *fl, long type) | 352 | static int assign_type(struct file_lock *fl, long type) |
@@ -426,14 +427,34 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, | |||
426 | } | 427 | } |
427 | 428 | ||
428 | /* default lease lock manager operations */ | 429 | /* default lease lock manager operations */ |
429 | static void lease_break_callback(struct file_lock *fl) | 430 | static bool |
431 | lease_break_callback(struct file_lock *fl) | ||
430 | { | 432 | { |
431 | kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); | 433 | kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); |
434 | return false; | ||
435 | } | ||
436 | |||
437 | static void | ||
438 | lease_setup(struct file_lock *fl, void **priv) | ||
439 | { | ||
440 | struct file *filp = fl->fl_file; | ||
441 | struct fasync_struct *fa = *priv; | ||
442 | |||
443 | /* | ||
444 | * fasync_insert_entry() returns the old entry if any. If there was no | ||
445 | * old entry, then it used "priv" and inserted it into the fasync list. | ||
446 | * Clear the pointer to indicate that it shouldn't be freed. | ||
447 | */ | ||
448 | if (!fasync_insert_entry(fa->fa_fd, filp, &fl->fl_fasync, fa)) | ||
449 | *priv = NULL; | ||
450 | |||
451 | __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); | ||
432 | } | 452 | } |
433 | 453 | ||
434 | static const struct lock_manager_operations lease_manager_ops = { | 454 | static const struct lock_manager_operations lease_manager_ops = { |
435 | .lm_break = lease_break_callback, | 455 | .lm_break = lease_break_callback, |
436 | .lm_change = lease_modify, | 456 | .lm_change = lease_modify, |
457 | .lm_setup = lease_setup, | ||
437 | }; | 458 | }; |
438 | 459 | ||
439 | /* | 460 | /* |
@@ -444,7 +465,7 @@ static int lease_init(struct file *filp, long type, struct file_lock *fl) | |||
444 | if (assign_type(fl, type) != 0) | 465 | if (assign_type(fl, type) != 0) |
445 | return -EINVAL; | 466 | return -EINVAL; |
446 | 467 | ||
447 | fl->fl_owner = current->files; | 468 | fl->fl_owner = filp; |
448 | fl->fl_pid = current->tgid; | 469 | fl->fl_pid = current->tgid; |
449 | 470 | ||
450 | fl->fl_file = filp; | 471 | fl->fl_file = filp; |
@@ -735,7 +756,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl) | |||
735 | break; | 756 | break; |
736 | } | 757 | } |
737 | if (cfl) { | 758 | if (cfl) { |
738 | __locks_copy_lock(fl, cfl); | 759 | locks_copy_conflock(fl, cfl); |
739 | if (cfl->fl_nspid) | 760 | if (cfl->fl_nspid) |
740 | fl->fl_pid = pid_vnr(cfl->fl_nspid); | 761 | fl->fl_pid = pid_vnr(cfl->fl_nspid); |
741 | } else | 762 | } else |
@@ -941,7 +962,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
941 | if (!posix_locks_conflict(request, fl)) | 962 | if (!posix_locks_conflict(request, fl)) |
942 | continue; | 963 | continue; |
943 | if (conflock) | 964 | if (conflock) |
944 | __locks_copy_lock(conflock, fl); | 965 | locks_copy_conflock(conflock, fl); |
945 | error = -EAGAIN; | 966 | error = -EAGAIN; |
946 | if (!(request->fl_flags & FL_SLEEP)) | 967 | if (!(request->fl_flags & FL_SLEEP)) |
947 | goto out; | 968 | goto out; |
@@ -1273,7 +1294,7 @@ static void lease_clear_pending(struct file_lock *fl, int arg) | |||
1273 | } | 1294 | } |
1274 | 1295 | ||
1275 | /* We already had a lease on this file; just change its type */ | 1296 | /* We already had a lease on this file; just change its type */ |
1276 | int lease_modify(struct file_lock **before, int arg) | 1297 | int lease_modify(struct file_lock **before, int arg, struct list_head *dispose) |
1277 | { | 1298 | { |
1278 | struct file_lock *fl = *before; | 1299 | struct file_lock *fl = *before; |
1279 | int error = assign_type(fl, arg); | 1300 | int error = assign_type(fl, arg); |
@@ -1292,11 +1313,10 @@ int lease_modify(struct file_lock **before, int arg) | |||
1292 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); | 1313 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); |
1293 | fl->fl_fasync = NULL; | 1314 | fl->fl_fasync = NULL; |
1294 | } | 1315 | } |
1295 | locks_delete_lock(before, NULL); | 1316 | locks_delete_lock(before, dispose); |
1296 | } | 1317 | } |
1297 | return 0; | 1318 | return 0; |
1298 | } | 1319 | } |
1299 | |||
1300 | EXPORT_SYMBOL(lease_modify); | 1320 | EXPORT_SYMBOL(lease_modify); |
1301 | 1321 | ||
1302 | static bool past_time(unsigned long then) | 1322 | static bool past_time(unsigned long then) |
@@ -1307,18 +1327,20 @@ static bool past_time(unsigned long then) | |||
1307 | return time_after(jiffies, then); | 1327 | return time_after(jiffies, then); |
1308 | } | 1328 | } |
1309 | 1329 | ||
1310 | static void time_out_leases(struct inode *inode) | 1330 | static void time_out_leases(struct inode *inode, struct list_head *dispose) |
1311 | { | 1331 | { |
1312 | struct file_lock **before; | 1332 | struct file_lock **before; |
1313 | struct file_lock *fl; | 1333 | struct file_lock *fl; |
1314 | 1334 | ||
1335 | lockdep_assert_held(&inode->i_lock); | ||
1336 | |||
1315 | before = &inode->i_flock; | 1337 | before = &inode->i_flock; |
1316 | while ((fl = *before) && IS_LEASE(fl) && lease_breaking(fl)) { | 1338 | while ((fl = *before) && IS_LEASE(fl) && lease_breaking(fl)) { |
1317 | trace_time_out_leases(inode, fl); | 1339 | trace_time_out_leases(inode, fl); |
1318 | if (past_time(fl->fl_downgrade_time)) | 1340 | if (past_time(fl->fl_downgrade_time)) |
1319 | lease_modify(before, F_RDLCK); | 1341 | lease_modify(before, F_RDLCK, dispose); |
1320 | if (past_time(fl->fl_break_time)) | 1342 | if (past_time(fl->fl_break_time)) |
1321 | lease_modify(before, F_UNLCK); | 1343 | lease_modify(before, F_UNLCK, dispose); |
1322 | if (fl == *before) /* lease_modify may have freed fl */ | 1344 | if (fl == *before) /* lease_modify may have freed fl */ |
1323 | before = &fl->fl_next; | 1345 | before = &fl->fl_next; |
1324 | } | 1346 | } |
@@ -1331,6 +1353,20 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker) | |||
1331 | return locks_conflict(breaker, lease); | 1353 | return locks_conflict(breaker, lease); |
1332 | } | 1354 | } |
1333 | 1355 | ||
1356 | static bool | ||
1357 | any_leases_conflict(struct inode *inode, struct file_lock *breaker) | ||
1358 | { | ||
1359 | struct file_lock *fl; | ||
1360 | |||
1361 | lockdep_assert_held(&inode->i_lock); | ||
1362 | |||
1363 | for (fl = inode->i_flock ; fl && IS_LEASE(fl); fl = fl->fl_next) { | ||
1364 | if (leases_conflict(fl, breaker)) | ||
1365 | return true; | ||
1366 | } | ||
1367 | return false; | ||
1368 | } | ||
1369 | |||
1334 | /** | 1370 | /** |
1335 | * __break_lease - revoke all outstanding leases on file | 1371 | * __break_lease - revoke all outstanding leases on file |
1336 | * @inode: the inode of the file to return | 1372 | * @inode: the inode of the file to return |
@@ -1347,12 +1383,11 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker) | |||
1347 | int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) | 1383 | int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) |
1348 | { | 1384 | { |
1349 | int error = 0; | 1385 | int error = 0; |
1350 | struct file_lock *new_fl, *flock; | 1386 | struct file_lock *new_fl; |
1351 | struct file_lock *fl; | 1387 | struct file_lock *fl, **before; |
1352 | unsigned long break_time; | 1388 | unsigned long break_time; |
1353 | int i_have_this_lease = 0; | ||
1354 | bool lease_conflict = false; | ||
1355 | int want_write = (mode & O_ACCMODE) != O_RDONLY; | 1389 | int want_write = (mode & O_ACCMODE) != O_RDONLY; |
1390 | LIST_HEAD(dispose); | ||
1356 | 1391 | ||
1357 | new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK); | 1392 | new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK); |
1358 | if (IS_ERR(new_fl)) | 1393 | if (IS_ERR(new_fl)) |
@@ -1361,20 +1396,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) | |||
1361 | 1396 | ||
1362 | spin_lock(&inode->i_lock); | 1397 | spin_lock(&inode->i_lock); |
1363 | 1398 | ||
1364 | time_out_leases(inode); | 1399 | time_out_leases(inode, &dispose); |
1365 | |||
1366 | flock = inode->i_flock; | ||
1367 | if ((flock == NULL) || !IS_LEASE(flock)) | ||
1368 | goto out; | ||
1369 | 1400 | ||
1370 | for (fl = flock; fl && IS_LEASE(fl); fl = fl->fl_next) { | 1401 | if (!any_leases_conflict(inode, new_fl)) |
1371 | if (leases_conflict(fl, new_fl)) { | ||
1372 | lease_conflict = true; | ||
1373 | if (fl->fl_owner == current->files) | ||
1374 | i_have_this_lease = 1; | ||
1375 | } | ||
1376 | } | ||
1377 | if (!lease_conflict) | ||
1378 | goto out; | 1402 | goto out; |
1379 | 1403 | ||
1380 | break_time = 0; | 1404 | break_time = 0; |
@@ -1384,7 +1408,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) | |||
1384 | break_time++; /* so that 0 means no break time */ | 1408 | break_time++; /* so that 0 means no break time */ |
1385 | } | 1409 | } |
1386 | 1410 | ||
1387 | for (fl = flock; fl && IS_LEASE(fl); fl = fl->fl_next) { | 1411 | for (before = &inode->i_flock; |
1412 | ((fl = *before) != NULL) && IS_LEASE(fl); | ||
1413 | before = &fl->fl_next) { | ||
1388 | if (!leases_conflict(fl, new_fl)) | 1414 | if (!leases_conflict(fl, new_fl)) |
1389 | continue; | 1415 | continue; |
1390 | if (want_write) { | 1416 | if (want_write) { |
@@ -1393,51 +1419,56 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) | |||
1393 | fl->fl_flags |= FL_UNLOCK_PENDING; | 1419 | fl->fl_flags |= FL_UNLOCK_PENDING; |
1394 | fl->fl_break_time = break_time; | 1420 | fl->fl_break_time = break_time; |
1395 | } else { | 1421 | } else { |
1396 | if (lease_breaking(flock)) | 1422 | if (lease_breaking(inode->i_flock)) |
1397 | continue; | 1423 | continue; |
1398 | fl->fl_flags |= FL_DOWNGRADE_PENDING; | 1424 | fl->fl_flags |= FL_DOWNGRADE_PENDING; |
1399 | fl->fl_downgrade_time = break_time; | 1425 | fl->fl_downgrade_time = break_time; |
1400 | } | 1426 | } |
1401 | fl->fl_lmops->lm_break(fl); | 1427 | if (fl->fl_lmops->lm_break(fl)) |
1428 | locks_delete_lock(before, &dispose); | ||
1402 | } | 1429 | } |
1403 | 1430 | ||
1404 | if (i_have_this_lease || (mode & O_NONBLOCK)) { | 1431 | fl = inode->i_flock; |
1432 | if (!fl || !IS_LEASE(fl)) | ||
1433 | goto out; | ||
1434 | |||
1435 | if (mode & O_NONBLOCK) { | ||
1405 | trace_break_lease_noblock(inode, new_fl); | 1436 | trace_break_lease_noblock(inode, new_fl); |
1406 | error = -EWOULDBLOCK; | 1437 | error = -EWOULDBLOCK; |
1407 | goto out; | 1438 | goto out; |
1408 | } | 1439 | } |
1409 | 1440 | ||
1410 | restart: | 1441 | restart: |
1411 | break_time = flock->fl_break_time; | 1442 | break_time = inode->i_flock->fl_break_time; |
1412 | if (break_time != 0) | 1443 | if (break_time != 0) |
1413 | break_time -= jiffies; | 1444 | break_time -= jiffies; |
1414 | if (break_time == 0) | 1445 | if (break_time == 0) |
1415 | break_time++; | 1446 | break_time++; |
1416 | locks_insert_block(flock, new_fl); | 1447 | locks_insert_block(inode->i_flock, new_fl); |
1417 | trace_break_lease_block(inode, new_fl); | 1448 | trace_break_lease_block(inode, new_fl); |
1418 | spin_unlock(&inode->i_lock); | 1449 | spin_unlock(&inode->i_lock); |
1450 | locks_dispose_list(&dispose); | ||
1419 | error = wait_event_interruptible_timeout(new_fl->fl_wait, | 1451 | error = wait_event_interruptible_timeout(new_fl->fl_wait, |
1420 | !new_fl->fl_next, break_time); | 1452 | !new_fl->fl_next, break_time); |
1421 | spin_lock(&inode->i_lock); | 1453 | spin_lock(&inode->i_lock); |
1422 | trace_break_lease_unblock(inode, new_fl); | 1454 | trace_break_lease_unblock(inode, new_fl); |
1423 | locks_delete_block(new_fl); | 1455 | locks_delete_block(new_fl); |
1424 | if (error >= 0) { | 1456 | if (error >= 0) { |
1425 | if (error == 0) | ||
1426 | time_out_leases(inode); | ||
1427 | /* | 1457 | /* |
1428 | * Wait for the next conflicting lease that has not been | 1458 | * Wait for the next conflicting lease that has not been |
1429 | * broken yet | 1459 | * broken yet |
1430 | */ | 1460 | */ |
1431 | for (flock = inode->i_flock; flock && IS_LEASE(flock); | 1461 | if (error == 0) |
1432 | flock = flock->fl_next) { | 1462 | time_out_leases(inode, &dispose); |
1433 | if (leases_conflict(new_fl, flock)) | 1463 | if (any_leases_conflict(inode, new_fl)) |
1434 | goto restart; | 1464 | goto restart; |
1435 | } | 1465 | |
1436 | error = 0; | 1466 | error = 0; |
1437 | } | 1467 | } |
1438 | 1468 | ||
1439 | out: | 1469 | out: |
1440 | spin_unlock(&inode->i_lock); | 1470 | spin_unlock(&inode->i_lock); |
1471 | locks_dispose_list(&dispose); | ||
1441 | locks_free_lock(new_fl); | 1472 | locks_free_lock(new_fl); |
1442 | return error; | 1473 | return error; |
1443 | } | 1474 | } |
@@ -1455,8 +1486,18 @@ EXPORT_SYMBOL(__break_lease); | |||
1455 | */ | 1486 | */ |
1456 | void lease_get_mtime(struct inode *inode, struct timespec *time) | 1487 | void lease_get_mtime(struct inode *inode, struct timespec *time) |
1457 | { | 1488 | { |
1458 | struct file_lock *flock = inode->i_flock; | 1489 | bool has_lease = false; |
1459 | if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK)) | 1490 | struct file_lock *flock; |
1491 | |||
1492 | if (inode->i_flock) { | ||
1493 | spin_lock(&inode->i_lock); | ||
1494 | flock = inode->i_flock; | ||
1495 | if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK)) | ||
1496 | has_lease = true; | ||
1497 | spin_unlock(&inode->i_lock); | ||
1498 | } | ||
1499 | |||
1500 | if (has_lease) | ||
1460 | *time = current_fs_time(inode->i_sb); | 1501 | *time = current_fs_time(inode->i_sb); |
1461 | else | 1502 | else |
1462 | *time = inode->i_mtime; | 1503 | *time = inode->i_mtime; |
@@ -1492,9 +1533,10 @@ int fcntl_getlease(struct file *filp) | |||
1492 | struct file_lock *fl; | 1533 | struct file_lock *fl; |
1493 | struct inode *inode = file_inode(filp); | 1534 | struct inode *inode = file_inode(filp); |
1494 | int type = F_UNLCK; | 1535 | int type = F_UNLCK; |
1536 | LIST_HEAD(dispose); | ||
1495 | 1537 | ||
1496 | spin_lock(&inode->i_lock); | 1538 | spin_lock(&inode->i_lock); |
1497 | time_out_leases(file_inode(filp)); | 1539 | time_out_leases(file_inode(filp), &dispose); |
1498 | for (fl = file_inode(filp)->i_flock; fl && IS_LEASE(fl); | 1540 | for (fl = file_inode(filp)->i_flock; fl && IS_LEASE(fl); |
1499 | fl = fl->fl_next) { | 1541 | fl = fl->fl_next) { |
1500 | if (fl->fl_file == filp) { | 1542 | if (fl->fl_file == filp) { |
@@ -1503,6 +1545,7 @@ int fcntl_getlease(struct file *filp) | |||
1503 | } | 1545 | } |
1504 | } | 1546 | } |
1505 | spin_unlock(&inode->i_lock); | 1547 | spin_unlock(&inode->i_lock); |
1548 | locks_dispose_list(&dispose); | ||
1506 | return type; | 1549 | return type; |
1507 | } | 1550 | } |
1508 | 1551 | ||
@@ -1532,13 +1575,15 @@ check_conflicting_open(const struct dentry *dentry, const long arg) | |||
1532 | return ret; | 1575 | return ret; |
1533 | } | 1576 | } |
1534 | 1577 | ||
1535 | static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp) | 1578 | static int |
1579 | generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv) | ||
1536 | { | 1580 | { |
1537 | struct file_lock *fl, **before, **my_before = NULL, *lease; | 1581 | struct file_lock *fl, **before, **my_before = NULL, *lease; |
1538 | struct dentry *dentry = filp->f_path.dentry; | 1582 | struct dentry *dentry = filp->f_path.dentry; |
1539 | struct inode *inode = dentry->d_inode; | 1583 | struct inode *inode = dentry->d_inode; |
1540 | bool is_deleg = (*flp)->fl_flags & FL_DELEG; | 1584 | bool is_deleg = (*flp)->fl_flags & FL_DELEG; |
1541 | int error; | 1585 | int error; |
1586 | LIST_HEAD(dispose); | ||
1542 | 1587 | ||
1543 | lease = *flp; | 1588 | lease = *flp; |
1544 | trace_generic_add_lease(inode, lease); | 1589 | trace_generic_add_lease(inode, lease); |
@@ -1561,6 +1606,8 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp | |||
1561 | return -EINVAL; | 1606 | return -EINVAL; |
1562 | } | 1607 | } |
1563 | 1608 | ||
1609 | spin_lock(&inode->i_lock); | ||
1610 | time_out_leases(inode, &dispose); | ||
1564 | error = check_conflicting_open(dentry, arg); | 1611 | error = check_conflicting_open(dentry, arg); |
1565 | if (error) | 1612 | if (error) |
1566 | goto out; | 1613 | goto out; |
@@ -1596,10 +1643,11 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp | |||
1596 | } | 1643 | } |
1597 | 1644 | ||
1598 | if (my_before != NULL) { | 1645 | if (my_before != NULL) { |
1599 | error = lease->fl_lmops->lm_change(my_before, arg); | 1646 | lease = *my_before; |
1600 | if (!error) | 1647 | error = lease->fl_lmops->lm_change(my_before, arg, &dispose); |
1601 | *flp = *my_before; | 1648 | if (error) |
1602 | goto out; | 1649 | goto out; |
1650 | goto out_setup; | ||
1603 | } | 1651 | } |
1604 | 1652 | ||
1605 | error = -EINVAL; | 1653 | error = -EINVAL; |
@@ -1619,43 +1667,61 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp | |||
1619 | smp_mb(); | 1667 | smp_mb(); |
1620 | error = check_conflicting_open(dentry, arg); | 1668 | error = check_conflicting_open(dentry, arg); |
1621 | if (error) | 1669 | if (error) |
1622 | locks_unlink_lock(before); | 1670 | goto out_unlink; |
1671 | |||
1672 | out_setup: | ||
1673 | if (lease->fl_lmops->lm_setup) | ||
1674 | lease->fl_lmops->lm_setup(lease, priv); | ||
1623 | out: | 1675 | out: |
1676 | spin_unlock(&inode->i_lock); | ||
1677 | locks_dispose_list(&dispose); | ||
1624 | if (is_deleg) | 1678 | if (is_deleg) |
1625 | mutex_unlock(&inode->i_mutex); | 1679 | mutex_unlock(&inode->i_mutex); |
1680 | if (!error && !my_before) | ||
1681 | *flp = NULL; | ||
1626 | return error; | 1682 | return error; |
1683 | out_unlink: | ||
1684 | locks_unlink_lock(before); | ||
1685 | goto out; | ||
1627 | } | 1686 | } |
1628 | 1687 | ||
1629 | static int generic_delete_lease(struct file *filp, struct file_lock **flp) | 1688 | static int generic_delete_lease(struct file *filp) |
1630 | { | 1689 | { |
1690 | int error = -EAGAIN; | ||
1631 | struct file_lock *fl, **before; | 1691 | struct file_lock *fl, **before; |
1632 | struct dentry *dentry = filp->f_path.dentry; | 1692 | struct dentry *dentry = filp->f_path.dentry; |
1633 | struct inode *inode = dentry->d_inode; | 1693 | struct inode *inode = dentry->d_inode; |
1694 | LIST_HEAD(dispose); | ||
1634 | 1695 | ||
1635 | trace_generic_delete_lease(inode, *flp); | 1696 | spin_lock(&inode->i_lock); |
1636 | 1697 | time_out_leases(inode, &dispose); | |
1637 | for (before = &inode->i_flock; | 1698 | for (before = &inode->i_flock; |
1638 | ((fl = *before) != NULL) && IS_LEASE(fl); | 1699 | ((fl = *before) != NULL) && IS_LEASE(fl); |
1639 | before = &fl->fl_next) { | 1700 | before = &fl->fl_next) { |
1640 | if (fl->fl_file != filp) | 1701 | if (fl->fl_file == filp) |
1641 | continue; | 1702 | break; |
1642 | return (*flp)->fl_lmops->lm_change(before, F_UNLCK); | ||
1643 | } | 1703 | } |
1644 | return -EAGAIN; | 1704 | trace_generic_delete_lease(inode, fl); |
1705 | if (fl) | ||
1706 | error = fl->fl_lmops->lm_change(before, F_UNLCK, &dispose); | ||
1707 | spin_unlock(&inode->i_lock); | ||
1708 | locks_dispose_list(&dispose); | ||
1709 | return error; | ||
1645 | } | 1710 | } |
1646 | 1711 | ||
1647 | /** | 1712 | /** |
1648 | * generic_setlease - sets a lease on an open file | 1713 | * generic_setlease - sets a lease on an open file |
1649 | * @filp: file pointer | 1714 | * @filp: file pointer |
1650 | * @arg: type of lease to obtain | 1715 | * @arg: type of lease to obtain |
1651 | * @flp: input - file_lock to use, output - file_lock inserted | 1716 | * @flp: input - file_lock to use, output - file_lock inserted |
1717 | * @priv: private data for lm_setup (may be NULL if lm_setup | ||
1718 | * doesn't require it) | ||
1652 | * | 1719 | * |
1653 | * The (input) flp->fl_lmops->lm_break function is required | 1720 | * The (input) flp->fl_lmops->lm_break function is required |
1654 | * by break_lease(). | 1721 | * by break_lease(). |
1655 | * | ||
1656 | * Called with inode->i_lock held. | ||
1657 | */ | 1722 | */ |
1658 | int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | 1723 | int generic_setlease(struct file *filp, long arg, struct file_lock **flp, |
1724 | void **priv) | ||
1659 | { | 1725 | { |
1660 | struct dentry *dentry = filp->f_path.dentry; | 1726 | struct dentry *dentry = filp->f_path.dentry; |
1661 | struct inode *inode = dentry->d_inode; | 1727 | struct inode *inode = dentry->d_inode; |
@@ -1669,83 +1735,52 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
1669 | if (error) | 1735 | if (error) |
1670 | return error; | 1736 | return error; |
1671 | 1737 | ||
1672 | time_out_leases(inode); | ||
1673 | |||
1674 | BUG_ON(!(*flp)->fl_lmops->lm_break); | ||
1675 | |||
1676 | switch (arg) { | 1738 | switch (arg) { |
1677 | case F_UNLCK: | 1739 | case F_UNLCK: |
1678 | return generic_delete_lease(filp, flp); | 1740 | return generic_delete_lease(filp); |
1679 | case F_RDLCK: | 1741 | case F_RDLCK: |
1680 | case F_WRLCK: | 1742 | case F_WRLCK: |
1681 | return generic_add_lease(filp, arg, flp); | 1743 | if (!(*flp)->fl_lmops->lm_break) { |
1744 | WARN_ON_ONCE(1); | ||
1745 | return -ENOLCK; | ||
1746 | } | ||
1747 | return generic_add_lease(filp, arg, flp, priv); | ||
1682 | default: | 1748 | default: |
1683 | return -EINVAL; | 1749 | return -EINVAL; |
1684 | } | 1750 | } |
1685 | } | 1751 | } |
1686 | EXPORT_SYMBOL(generic_setlease); | 1752 | EXPORT_SYMBOL(generic_setlease); |
1687 | 1753 | ||
1688 | static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease) | ||
1689 | { | ||
1690 | if (filp->f_op->setlease) | ||
1691 | return filp->f_op->setlease(filp, arg, lease); | ||
1692 | else | ||
1693 | return generic_setlease(filp, arg, lease); | ||
1694 | } | ||
1695 | |||
1696 | /** | 1754 | /** |
1697 | * vfs_setlease - sets a lease on an open file | 1755 | * vfs_setlease - sets a lease on an open file |
1698 | * @filp: file pointer | 1756 | * @filp: file pointer |
1699 | * @arg: type of lease to obtain | 1757 | * @arg: type of lease to obtain |
1700 | * @lease: file_lock to use | 1758 | * @lease: file_lock to use when adding a lease |
1701 | * | 1759 | * @priv: private info for lm_setup when adding a lease (may be |
1702 | * Call this to establish a lease on the file. | 1760 | * NULL if lm_setup doesn't require it) |
1703 | * The (*lease)->fl_lmops->lm_break operation must be set; if not, | 1761 | * |
1704 | * break_lease will oops! | 1762 | * Call this to establish a lease on the file. The "lease" argument is not |
1705 | * | 1763 | * used for F_UNLCK requests and may be NULL. For commands that set or alter |
1706 | * This will call the filesystem's setlease file method, if | 1764 | * an existing lease, the (*lease)->fl_lmops->lm_break operation must be set; |
1707 | * defined. Note that there is no getlease method; instead, the | 1765 | * if not, this function will return -ENOLCK (and generate a scary-looking |
1708 | * filesystem setlease method should call back to setlease() to | 1766 | * stack trace). |
1709 | * add a lease to the inode's lease list, where fcntl_getlease() can | 1767 | * |
1710 | * find it. Since fcntl_getlease() only reports whether the current | 1768 | * The "priv" pointer is passed directly to the lm_setup function as-is. It |
1711 | * task holds a lease, a cluster filesystem need only do this for | 1769 | * may be NULL if the lm_setup operation doesn't require it. |
1712 | * leases held by processes on this node. | ||
1713 | * | ||
1714 | * There is also no break_lease method; filesystems that | ||
1715 | * handle their own leases should break leases themselves from the | ||
1716 | * filesystem's open, create, and (on truncate) setattr methods. | ||
1717 | * | ||
1718 | * Warning: the only current setlease methods exist only to disable | ||
1719 | * leases in certain cases. More vfs changes may be required to | ||
1720 | * allow a full filesystem lease implementation. | ||
1721 | */ | 1770 | */ |
1722 | 1771 | int | |
1723 | int vfs_setlease(struct file *filp, long arg, struct file_lock **lease) | 1772 | vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv) |
1724 | { | 1773 | { |
1725 | struct inode *inode = file_inode(filp); | 1774 | if (filp->f_op->setlease) |
1726 | int error; | 1775 | return filp->f_op->setlease(filp, arg, lease, priv); |
1727 | 1776 | else | |
1728 | spin_lock(&inode->i_lock); | 1777 | return generic_setlease(filp, arg, lease, priv); |
1729 | error = __vfs_setlease(filp, arg, lease); | ||
1730 | spin_unlock(&inode->i_lock); | ||
1731 | |||
1732 | return error; | ||
1733 | } | 1778 | } |
1734 | EXPORT_SYMBOL_GPL(vfs_setlease); | 1779 | EXPORT_SYMBOL_GPL(vfs_setlease); |
1735 | 1780 | ||
1736 | static int do_fcntl_delete_lease(struct file *filp) | ||
1737 | { | ||
1738 | struct file_lock fl, *flp = &fl; | ||
1739 | |||
1740 | lease_init(filp, F_UNLCK, flp); | ||
1741 | |||
1742 | return vfs_setlease(filp, F_UNLCK, &flp); | ||
1743 | } | ||
1744 | |||
1745 | static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | 1781 | static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) |
1746 | { | 1782 | { |
1747 | struct file_lock *fl, *ret; | 1783 | struct file_lock *fl; |
1748 | struct inode *inode = file_inode(filp); | ||
1749 | struct fasync_struct *new; | 1784 | struct fasync_struct *new; |
1750 | int error; | 1785 | int error; |
1751 | 1786 | ||
@@ -1758,26 +1793,9 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | |||
1758 | locks_free_lock(fl); | 1793 | locks_free_lock(fl); |
1759 | return -ENOMEM; | 1794 | return -ENOMEM; |
1760 | } | 1795 | } |
1761 | ret = fl; | 1796 | new->fa_fd = fd; |
1762 | spin_lock(&inode->i_lock); | ||
1763 | error = __vfs_setlease(filp, arg, &ret); | ||
1764 | if (error) | ||
1765 | goto out_unlock; | ||
1766 | if (ret == fl) | ||
1767 | fl = NULL; | ||
1768 | |||
1769 | /* | ||
1770 | * fasync_insert_entry() returns the old entry if any. | ||
1771 | * If there was no old entry, then it used 'new' and | ||
1772 | * inserted it into the fasync list. Clear new so that | ||
1773 | * we don't release it here. | ||
1774 | */ | ||
1775 | if (!fasync_insert_entry(fd, filp, &ret->fl_fasync, new)) | ||
1776 | new = NULL; | ||
1777 | 1797 | ||
1778 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); | 1798 | error = vfs_setlease(filp, arg, &fl, (void **)&new); |
1779 | out_unlock: | ||
1780 | spin_unlock(&inode->i_lock); | ||
1781 | if (fl) | 1799 | if (fl) |
1782 | locks_free_lock(fl); | 1800 | locks_free_lock(fl); |
1783 | if (new) | 1801 | if (new) |
@@ -1798,7 +1816,7 @@ out_unlock: | |||
1798 | int fcntl_setlease(unsigned int fd, struct file *filp, long arg) | 1816 | int fcntl_setlease(unsigned int fd, struct file *filp, long arg) |
1799 | { | 1817 | { |
1800 | if (arg == F_UNLCK) | 1818 | if (arg == F_UNLCK) |
1801 | return do_fcntl_delete_lease(filp); | 1819 | return vfs_setlease(filp, F_UNLCK, NULL, NULL); |
1802 | return do_fcntl_add_lease(fd, filp, arg); | 1820 | return do_fcntl_add_lease(fd, filp, arg); |
1803 | } | 1821 | } |
1804 | 1822 | ||
@@ -1867,9 +1885,12 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) | |||
1867 | !(f.file->f_mode & (FMODE_READ|FMODE_WRITE))) | 1885 | !(f.file->f_mode & (FMODE_READ|FMODE_WRITE))) |
1868 | goto out_putf; | 1886 | goto out_putf; |
1869 | 1887 | ||
1870 | error = flock_make_lock(f.file, &lock, cmd); | 1888 | lock = flock_make_lock(f.file, cmd); |
1871 | if (error) | 1889 | if (IS_ERR(lock)) { |
1890 | error = PTR_ERR(lock); | ||
1872 | goto out_putf; | 1891 | goto out_putf; |
1892 | } | ||
1893 | |||
1873 | if (can_sleep) | 1894 | if (can_sleep) |
1874 | lock->fl_flags |= FL_SLEEP; | 1895 | lock->fl_flags |= FL_SLEEP; |
1875 | 1896 | ||
@@ -1981,11 +2002,13 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l) | |||
1981 | if (file_lock.fl_type != F_UNLCK) { | 2002 | if (file_lock.fl_type != F_UNLCK) { |
1982 | error = posix_lock_to_flock(&flock, &file_lock); | 2003 | error = posix_lock_to_flock(&flock, &file_lock); |
1983 | if (error) | 2004 | if (error) |
1984 | goto out; | 2005 | goto rel_priv; |
1985 | } | 2006 | } |
1986 | error = -EFAULT; | 2007 | error = -EFAULT; |
1987 | if (!copy_to_user(l, &flock, sizeof(flock))) | 2008 | if (!copy_to_user(l, &flock, sizeof(flock))) |
1988 | error = 0; | 2009 | error = 0; |
2010 | rel_priv: | ||
2011 | locks_release_private(&file_lock); | ||
1989 | out: | 2012 | out: |
1990 | return error; | 2013 | return error; |
1991 | } | 2014 | } |
@@ -2206,7 +2229,8 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) | |||
2206 | error = -EFAULT; | 2229 | error = -EFAULT; |
2207 | if (!copy_to_user(l, &flock, sizeof(flock))) | 2230 | if (!copy_to_user(l, &flock, sizeof(flock))) |
2208 | error = 0; | 2231 | error = 0; |
2209 | 2232 | ||
2233 | locks_release_private(&file_lock); | ||
2210 | out: | 2234 | out: |
2211 | return error; | 2235 | return error; |
2212 | } | 2236 | } |
@@ -2369,7 +2393,7 @@ void locks_remove_file(struct file *filp) | |||
2369 | while ((fl = *before) != NULL) { | 2393 | while ((fl = *before) != NULL) { |
2370 | if (fl->fl_file == filp) { | 2394 | if (fl->fl_file == filp) { |
2371 | if (IS_LEASE(fl)) { | 2395 | if (IS_LEASE(fl)) { |
2372 | lease_modify(before, F_UNLCK); | 2396 | lease_modify(before, F_UNLCK, &dispose); |
2373 | continue; | 2397 | continue; |
2374 | } | 2398 | } |
2375 | 2399 | ||
@@ -2593,86 +2617,6 @@ static int __init proc_locks_init(void) | |||
2593 | module_init(proc_locks_init); | 2617 | module_init(proc_locks_init); |
2594 | #endif | 2618 | #endif |
2595 | 2619 | ||
2596 | /** | ||
2597 | * lock_may_read - checks that the region is free of locks | ||
2598 | * @inode: the inode that is being read | ||
2599 | * @start: the first byte to read | ||
2600 | * @len: the number of bytes to read | ||
2601 | * | ||
2602 | * Emulates Windows locking requirements. Whole-file | ||
2603 | * mandatory locks (share modes) can prohibit a read and | ||
2604 | * byte-range POSIX locks can prohibit a read if they overlap. | ||
2605 | * | ||
2606 | * N.B. this function is only ever called | ||
2607 | * from knfsd and ownership of locks is never checked. | ||
2608 | */ | ||
2609 | int lock_may_read(struct inode *inode, loff_t start, unsigned long len) | ||
2610 | { | ||
2611 | struct file_lock *fl; | ||
2612 | int result = 1; | ||
2613 | |||
2614 | spin_lock(&inode->i_lock); | ||
2615 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | ||
2616 | if (IS_POSIX(fl)) { | ||
2617 | if (fl->fl_type == F_RDLCK) | ||
2618 | continue; | ||
2619 | if ((fl->fl_end < start) || (fl->fl_start > (start + len))) | ||
2620 | continue; | ||
2621 | } else if (IS_FLOCK(fl)) { | ||
2622 | if (!(fl->fl_type & LOCK_MAND)) | ||
2623 | continue; | ||
2624 | if (fl->fl_type & LOCK_READ) | ||
2625 | continue; | ||
2626 | } else | ||
2627 | continue; | ||
2628 | result = 0; | ||
2629 | break; | ||
2630 | } | ||
2631 | spin_unlock(&inode->i_lock); | ||
2632 | return result; | ||
2633 | } | ||
2634 | |||
2635 | EXPORT_SYMBOL(lock_may_read); | ||
2636 | |||
2637 | /** | ||
2638 | * lock_may_write - checks that the region is free of locks | ||
2639 | * @inode: the inode that is being written | ||
2640 | * @start: the first byte to write | ||
2641 | * @len: the number of bytes to write | ||
2642 | * | ||
2643 | * Emulates Windows locking requirements. Whole-file | ||
2644 | * mandatory locks (share modes) can prohibit a write and | ||
2645 | * byte-range POSIX locks can prohibit a write if they overlap. | ||
2646 | * | ||
2647 | * N.B. this function is only ever called | ||
2648 | * from knfsd and ownership of locks is never checked. | ||
2649 | */ | ||
2650 | int lock_may_write(struct inode *inode, loff_t start, unsigned long len) | ||
2651 | { | ||
2652 | struct file_lock *fl; | ||
2653 | int result = 1; | ||
2654 | |||
2655 | spin_lock(&inode->i_lock); | ||
2656 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | ||
2657 | if (IS_POSIX(fl)) { | ||
2658 | if ((fl->fl_end < start) || (fl->fl_start > (start + len))) | ||
2659 | continue; | ||
2660 | } else if (IS_FLOCK(fl)) { | ||
2661 | if (!(fl->fl_type & LOCK_MAND)) | ||
2662 | continue; | ||
2663 | if (fl->fl_type & LOCK_WRITE) | ||
2664 | continue; | ||
2665 | } else | ||
2666 | continue; | ||
2667 | result = 0; | ||
2668 | break; | ||
2669 | } | ||
2670 | spin_unlock(&inode->i_lock); | ||
2671 | return result; | ||
2672 | } | ||
2673 | |||
2674 | EXPORT_SYMBOL(lock_may_write); | ||
2675 | |||
2676 | static int __init filelock_init(void) | 2620 | static int __init filelock_init(void) |
2677 | { | 2621 | { |
2678 | int i; | 2622 | int i; |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 6920127c5eb7..4ea92ce0537f 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -919,17 +919,6 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
919 | } | 919 | } |
920 | EXPORT_SYMBOL_GPL(nfs_flock); | 920 | EXPORT_SYMBOL_GPL(nfs_flock); |
921 | 921 | ||
922 | /* | ||
923 | * There is no protocol support for leases, so we have no way to implement | ||
924 | * them correctly in the face of opens by other clients. | ||
925 | */ | ||
926 | int nfs_setlease(struct file *file, long arg, struct file_lock **fl) | ||
927 | { | ||
928 | dprintk("NFS: setlease(%pD2, arg=%ld)\n", file, arg); | ||
929 | return -EINVAL; | ||
930 | } | ||
931 | EXPORT_SYMBOL_GPL(nfs_setlease); | ||
932 | |||
933 | const struct file_operations nfs_file_operations = { | 922 | const struct file_operations nfs_file_operations = { |
934 | .llseek = nfs_file_llseek, | 923 | .llseek = nfs_file_llseek, |
935 | .read = new_sync_read, | 924 | .read = new_sync_read, |
@@ -946,6 +935,6 @@ const struct file_operations nfs_file_operations = { | |||
946 | .splice_read = nfs_file_splice_read, | 935 | .splice_read = nfs_file_splice_read, |
947 | .splice_write = iter_file_splice_write, | 936 | .splice_write = iter_file_splice_write, |
948 | .check_flags = nfs_check_flags, | 937 | .check_flags = nfs_check_flags, |
949 | .setlease = nfs_setlease, | 938 | .setlease = simple_nosetlease, |
950 | }; | 939 | }; |
951 | EXPORT_SYMBOL_GPL(nfs_file_operations); | 940 | EXPORT_SYMBOL_GPL(nfs_file_operations); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 14ae6f20a172..efaa31c70fbe 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -339,7 +339,6 @@ int nfs_file_release(struct inode *, struct file *); | |||
339 | int nfs_lock(struct file *, int, struct file_lock *); | 339 | int nfs_lock(struct file *, int, struct file_lock *); |
340 | int nfs_flock(struct file *, int, struct file_lock *); | 340 | int nfs_flock(struct file *, int, struct file_lock *); |
341 | int nfs_check_flags(int); | 341 | int nfs_check_flags(int); |
342 | int nfs_setlease(struct file *, long, struct file_lock **); | ||
343 | 342 | ||
344 | /* inode.c */ | 343 | /* inode.c */ |
345 | extern struct workqueue_struct *nfsiod_workqueue; | 344 | extern struct workqueue_struct *nfsiod_workqueue; |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index a816f0627a6c..3e987ad9ae25 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
@@ -131,5 +131,5 @@ const struct file_operations nfs4_file_operations = { | |||
131 | .splice_read = nfs_file_splice_read, | 131 | .splice_read = nfs_file_splice_read, |
132 | .splice_write = iter_file_splice_write, | 132 | .splice_write = iter_file_splice_write, |
133 | .check_flags = nfs_check_flags, | 133 | .check_flags = nfs_check_flags, |
134 | .setlease = nfs_setlease, | 134 | .setlease = simple_nosetlease, |
135 | }; | 135 | }; |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 5c0cac173068..e9c3afe4b5d3 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -218,6 +218,13 @@ static void nfsd4_put_session(struct nfsd4_session *ses) | |||
218 | spin_unlock(&nn->client_lock); | 218 | spin_unlock(&nn->client_lock); |
219 | } | 219 | } |
220 | 220 | ||
221 | static inline struct nfs4_stateowner * | ||
222 | nfs4_get_stateowner(struct nfs4_stateowner *sop) | ||
223 | { | ||
224 | atomic_inc(&sop->so_count); | ||
225 | return sop; | ||
226 | } | ||
227 | |||
221 | static int | 228 | static int |
222 | same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner) | 229 | same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner) |
223 | { | 230 | { |
@@ -237,10 +244,8 @@ find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open, | |||
237 | so_strhash) { | 244 | so_strhash) { |
238 | if (!so->so_is_open_owner) | 245 | if (!so->so_is_open_owner) |
239 | continue; | 246 | continue; |
240 | if (same_owner_str(so, &open->op_owner)) { | 247 | if (same_owner_str(so, &open->op_owner)) |
241 | atomic_inc(&so->so_count); | 248 | return openowner(nfs4_get_stateowner(so)); |
242 | return openowner(so); | ||
243 | } | ||
244 | } | 249 | } |
245 | return NULL; | 250 | return NULL; |
246 | } | 251 | } |
@@ -678,18 +683,14 @@ nfs4_put_stid(struct nfs4_stid *s) | |||
678 | static void nfs4_put_deleg_lease(struct nfs4_file *fp) | 683 | static void nfs4_put_deleg_lease(struct nfs4_file *fp) |
679 | { | 684 | { |
680 | struct file *filp = NULL; | 685 | struct file *filp = NULL; |
681 | struct file_lock *fl; | ||
682 | 686 | ||
683 | spin_lock(&fp->fi_lock); | 687 | spin_lock(&fp->fi_lock); |
684 | if (fp->fi_lease && atomic_dec_and_test(&fp->fi_delegees)) { | 688 | if (fp->fi_deleg_file && atomic_dec_and_test(&fp->fi_delegees)) |
685 | swap(filp, fp->fi_deleg_file); | 689 | swap(filp, fp->fi_deleg_file); |
686 | fl = fp->fi_lease; | ||
687 | fp->fi_lease = NULL; | ||
688 | } | ||
689 | spin_unlock(&fp->fi_lock); | 690 | spin_unlock(&fp->fi_lock); |
690 | 691 | ||
691 | if (filp) { | 692 | if (filp) { |
692 | vfs_setlease(filp, F_UNLCK, &fl); | 693 | vfs_setlease(filp, F_UNLCK, NULL, NULL); |
693 | fput(filp); | 694 | fput(filp); |
694 | } | 695 | } |
695 | } | 696 | } |
@@ -1655,7 +1656,7 @@ __destroy_client(struct nfs4_client *clp) | |||
1655 | } | 1656 | } |
1656 | while (!list_empty(&clp->cl_openowners)) { | 1657 | while (!list_empty(&clp->cl_openowners)) { |
1657 | oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); | 1658 | oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); |
1658 | atomic_inc(&oo->oo_owner.so_count); | 1659 | nfs4_get_stateowner(&oo->oo_owner); |
1659 | release_openowner(oo); | 1660 | release_openowner(oo); |
1660 | } | 1661 | } |
1661 | nfsd4_shutdown_callback(clp); | 1662 | nfsd4_shutdown_callback(clp); |
@@ -3067,8 +3068,8 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh) | |||
3067 | INIT_LIST_HEAD(&fp->fi_stateids); | 3068 | INIT_LIST_HEAD(&fp->fi_stateids); |
3068 | INIT_LIST_HEAD(&fp->fi_delegations); | 3069 | INIT_LIST_HEAD(&fp->fi_delegations); |
3069 | fh_copy_shallow(&fp->fi_fhandle, fh); | 3070 | fh_copy_shallow(&fp->fi_fhandle, fh); |
3071 | fp->fi_deleg_file = NULL; | ||
3070 | fp->fi_had_conflict = false; | 3072 | fp->fi_had_conflict = false; |
3071 | fp->fi_lease = NULL; | ||
3072 | fp->fi_share_deny = 0; | 3073 | fp->fi_share_deny = 0; |
3073 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); | 3074 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); |
3074 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); | 3075 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); |
@@ -3136,8 +3137,7 @@ static void nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate, | |||
3136 | { | 3137 | { |
3137 | if (!nfsd4_has_session(cstate)) { | 3138 | if (!nfsd4_has_session(cstate)) { |
3138 | mutex_lock(&so->so_replay.rp_mutex); | 3139 | mutex_lock(&so->so_replay.rp_mutex); |
3139 | cstate->replay_owner = so; | 3140 | cstate->replay_owner = nfs4_get_stateowner(so); |
3140 | atomic_inc(&so->so_count); | ||
3141 | } | 3141 | } |
3142 | } | 3142 | } |
3143 | 3143 | ||
@@ -3236,8 +3236,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | |||
3236 | atomic_inc(&stp->st_stid.sc_count); | 3236 | atomic_inc(&stp->st_stid.sc_count); |
3237 | stp->st_stid.sc_type = NFS4_OPEN_STID; | 3237 | stp->st_stid.sc_type = NFS4_OPEN_STID; |
3238 | INIT_LIST_HEAD(&stp->st_locks); | 3238 | INIT_LIST_HEAD(&stp->st_locks); |
3239 | stp->st_stateowner = &oo->oo_owner; | 3239 | stp->st_stateowner = nfs4_get_stateowner(&oo->oo_owner); |
3240 | atomic_inc(&stp->st_stateowner->so_count); | ||
3241 | get_nfs4_file(fp); | 3240 | get_nfs4_file(fp); |
3242 | stp->st_stid.sc_file = fp; | 3241 | stp->st_stid.sc_file = fp; |
3243 | stp->st_access_bmap = 0; | 3242 | stp->st_access_bmap = 0; |
@@ -3434,18 +3433,20 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp) | |||
3434 | } | 3433 | } |
3435 | 3434 | ||
3436 | /* Called from break_lease() with i_lock held. */ | 3435 | /* Called from break_lease() with i_lock held. */ |
3437 | static void nfsd_break_deleg_cb(struct file_lock *fl) | 3436 | static bool |
3437 | nfsd_break_deleg_cb(struct file_lock *fl) | ||
3438 | { | 3438 | { |
3439 | bool ret = false; | ||
3439 | struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner; | 3440 | struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner; |
3440 | struct nfs4_delegation *dp; | 3441 | struct nfs4_delegation *dp; |
3441 | 3442 | ||
3442 | if (!fp) { | 3443 | if (!fp) { |
3443 | WARN(1, "(%p)->fl_owner NULL\n", fl); | 3444 | WARN(1, "(%p)->fl_owner NULL\n", fl); |
3444 | return; | 3445 | return ret; |
3445 | } | 3446 | } |
3446 | if (fp->fi_had_conflict) { | 3447 | if (fp->fi_had_conflict) { |
3447 | WARN(1, "duplicate break on %p\n", fp); | 3448 | WARN(1, "duplicate break on %p\n", fp); |
3448 | return; | 3449 | return ret; |
3449 | } | 3450 | } |
3450 | /* | 3451 | /* |
3451 | * We don't want the locks code to timeout the lease for us; | 3452 | * We don't want the locks code to timeout the lease for us; |
@@ -3457,24 +3458,23 @@ static void nfsd_break_deleg_cb(struct file_lock *fl) | |||
3457 | spin_lock(&fp->fi_lock); | 3458 | spin_lock(&fp->fi_lock); |
3458 | fp->fi_had_conflict = true; | 3459 | fp->fi_had_conflict = true; |
3459 | /* | 3460 | /* |
3460 | * If there are no delegations on the list, then we can't count on this | 3461 | * If there are no delegations on the list, then return true |
3461 | * lease ever being cleaned up. Set the fl_break_time to jiffies so that | 3462 | * so that the lease code will go ahead and delete it. |
3462 | * time_out_leases will do it ASAP. The fact that fi_had_conflict is now | ||
3463 | * true should keep any new delegations from being hashed. | ||
3464 | */ | 3463 | */ |
3465 | if (list_empty(&fp->fi_delegations)) | 3464 | if (list_empty(&fp->fi_delegations)) |
3466 | fl->fl_break_time = jiffies; | 3465 | ret = true; |
3467 | else | 3466 | else |
3468 | list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) | 3467 | list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) |
3469 | nfsd_break_one_deleg(dp); | 3468 | nfsd_break_one_deleg(dp); |
3470 | spin_unlock(&fp->fi_lock); | 3469 | spin_unlock(&fp->fi_lock); |
3470 | return ret; | ||
3471 | } | 3471 | } |
3472 | 3472 | ||
3473 | static | 3473 | static int |
3474 | int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) | 3474 | nfsd_change_deleg_cb(struct file_lock **onlist, int arg, struct list_head *dispose) |
3475 | { | 3475 | { |
3476 | if (arg & F_UNLCK) | 3476 | if (arg & F_UNLCK) |
3477 | return lease_modify(onlist, arg); | 3477 | return lease_modify(onlist, arg, dispose); |
3478 | else | 3478 | else |
3479 | return -EAGAIN; | 3479 | return -EAGAIN; |
3480 | } | 3480 | } |
@@ -3820,7 +3820,7 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag) | |||
3820 | static int nfs4_setlease(struct nfs4_delegation *dp) | 3820 | static int nfs4_setlease(struct nfs4_delegation *dp) |
3821 | { | 3821 | { |
3822 | struct nfs4_file *fp = dp->dl_stid.sc_file; | 3822 | struct nfs4_file *fp = dp->dl_stid.sc_file; |
3823 | struct file_lock *fl; | 3823 | struct file_lock *fl, *ret; |
3824 | struct file *filp; | 3824 | struct file *filp; |
3825 | int status = 0; | 3825 | int status = 0; |
3826 | 3826 | ||
@@ -3834,11 +3834,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp) | |||
3834 | return -EBADF; | 3834 | return -EBADF; |
3835 | } | 3835 | } |
3836 | fl->fl_file = filp; | 3836 | fl->fl_file = filp; |
3837 | status = vfs_setlease(filp, fl->fl_type, &fl); | 3837 | ret = fl; |
3838 | if (status) { | 3838 | status = vfs_setlease(filp, fl->fl_type, &fl, NULL); |
3839 | if (fl) | ||
3839 | locks_free_lock(fl); | 3840 | locks_free_lock(fl); |
3841 | if (status) | ||
3840 | goto out_fput; | 3842 | goto out_fput; |
3841 | } | ||
3842 | spin_lock(&state_lock); | 3843 | spin_lock(&state_lock); |
3843 | spin_lock(&fp->fi_lock); | 3844 | spin_lock(&fp->fi_lock); |
3844 | /* Did the lease get broken before we took the lock? */ | 3845 | /* Did the lease get broken before we took the lock? */ |
@@ -3846,13 +3847,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp) | |||
3846 | if (fp->fi_had_conflict) | 3847 | if (fp->fi_had_conflict) |
3847 | goto out_unlock; | 3848 | goto out_unlock; |
3848 | /* Race breaker */ | 3849 | /* Race breaker */ |
3849 | if (fp->fi_lease) { | 3850 | if (fp->fi_deleg_file) { |
3850 | status = 0; | 3851 | status = 0; |
3851 | atomic_inc(&fp->fi_delegees); | 3852 | atomic_inc(&fp->fi_delegees); |
3852 | hash_delegation_locked(dp, fp); | 3853 | hash_delegation_locked(dp, fp); |
3853 | goto out_unlock; | 3854 | goto out_unlock; |
3854 | } | 3855 | } |
3855 | fp->fi_lease = fl; | ||
3856 | fp->fi_deleg_file = filp; | 3856 | fp->fi_deleg_file = filp; |
3857 | atomic_set(&fp->fi_delegees, 1); | 3857 | atomic_set(&fp->fi_delegees, 1); |
3858 | hash_delegation_locked(dp, fp); | 3858 | hash_delegation_locked(dp, fp); |
@@ -3885,7 +3885,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, | |||
3885 | spin_lock(&state_lock); | 3885 | spin_lock(&state_lock); |
3886 | spin_lock(&fp->fi_lock); | 3886 | spin_lock(&fp->fi_lock); |
3887 | dp->dl_stid.sc_file = fp; | 3887 | dp->dl_stid.sc_file = fp; |
3888 | if (!fp->fi_lease) { | 3888 | if (!fp->fi_deleg_file) { |
3889 | spin_unlock(&fp->fi_lock); | 3889 | spin_unlock(&fp->fi_lock); |
3890 | spin_unlock(&state_lock); | 3890 | spin_unlock(&state_lock); |
3891 | status = nfs4_setlease(dp); | 3891 | status = nfs4_setlease(dp); |
@@ -4929,9 +4929,25 @@ nfs4_transform_lock_offset(struct file_lock *lock) | |||
4929 | lock->fl_end = OFFSET_MAX; | 4929 | lock->fl_end = OFFSET_MAX; |
4930 | } | 4930 | } |
4931 | 4931 | ||
4932 | /* Hack!: For now, we're defining this just so we can use a pointer to it | 4932 | static void nfsd4_fl_get_owner(struct file_lock *dst, struct file_lock *src) |
4933 | * as a unique cookie to identify our (NFSv4's) posix locks. */ | 4933 | { |
4934 | struct nfs4_lockowner *lo = (struct nfs4_lockowner *)src->fl_owner; | ||
4935 | dst->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lo->lo_owner)); | ||
4936 | } | ||
4937 | |||
4938 | static void nfsd4_fl_put_owner(struct file_lock *fl) | ||
4939 | { | ||
4940 | struct nfs4_lockowner *lo = (struct nfs4_lockowner *)fl->fl_owner; | ||
4941 | |||
4942 | if (lo) { | ||
4943 | nfs4_put_stateowner(&lo->lo_owner); | ||
4944 | fl->fl_owner = NULL; | ||
4945 | } | ||
4946 | } | ||
4947 | |||
4934 | static const struct lock_manager_operations nfsd_posix_mng_ops = { | 4948 | static const struct lock_manager_operations nfsd_posix_mng_ops = { |
4949 | .lm_get_owner = nfsd4_fl_get_owner, | ||
4950 | .lm_put_owner = nfsd4_fl_put_owner, | ||
4935 | }; | 4951 | }; |
4936 | 4952 | ||
4937 | static inline void | 4953 | static inline void |
@@ -4977,10 +4993,8 @@ find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner, | |||
4977 | so_strhash) { | 4993 | so_strhash) { |
4978 | if (so->so_is_open_owner) | 4994 | if (so->so_is_open_owner) |
4979 | continue; | 4995 | continue; |
4980 | if (!same_owner_str(so, owner)) | 4996 | if (same_owner_str(so, owner)) |
4981 | continue; | 4997 | return lockowner(nfs4_get_stateowner(so)); |
4982 | atomic_inc(&so->so_count); | ||
4983 | return lockowner(so); | ||
4984 | } | 4998 | } |
4985 | return NULL; | 4999 | return NULL; |
4986 | } | 5000 | } |
@@ -5059,8 +5073,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, | |||
5059 | 5073 | ||
5060 | atomic_inc(&stp->st_stid.sc_count); | 5074 | atomic_inc(&stp->st_stid.sc_count); |
5061 | stp->st_stid.sc_type = NFS4_LOCK_STID; | 5075 | stp->st_stid.sc_type = NFS4_LOCK_STID; |
5062 | stp->st_stateowner = &lo->lo_owner; | 5076 | stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner); |
5063 | atomic_inc(&lo->lo_owner.so_count); | ||
5064 | get_nfs4_file(fp); | 5077 | get_nfs4_file(fp); |
5065 | stp->st_stid.sc_file = fp; | 5078 | stp->st_stid.sc_file = fp; |
5066 | stp->st_stid.sc_free = nfs4_free_lock_stateid; | 5079 | stp->st_stid.sc_free = nfs4_free_lock_stateid; |
@@ -5299,7 +5312,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5299 | status = nfserr_openmode; | 5312 | status = nfserr_openmode; |
5300 | goto out; | 5313 | goto out; |
5301 | } | 5314 | } |
5302 | file_lock->fl_owner = (fl_owner_t)lock_sop; | 5315 | |
5316 | file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lock_sop->lo_owner)); | ||
5303 | file_lock->fl_pid = current->tgid; | 5317 | file_lock->fl_pid = current->tgid; |
5304 | file_lock->fl_file = filp; | 5318 | file_lock->fl_file = filp; |
5305 | file_lock->fl_flags = FL_POSIX; | 5319 | file_lock->fl_flags = FL_POSIX; |
@@ -5495,7 +5509,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5495 | } | 5509 | } |
5496 | 5510 | ||
5497 | file_lock->fl_type = F_UNLCK; | 5511 | file_lock->fl_type = F_UNLCK; |
5498 | file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); | 5512 | file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(stp->st_stateowner)); |
5499 | file_lock->fl_pid = current->tgid; | 5513 | file_lock->fl_pid = current->tgid; |
5500 | file_lock->fl_file = filp; | 5514 | file_lock->fl_file = filp; |
5501 | file_lock->fl_flags = FL_POSIX; | 5515 | file_lock->fl_flags = FL_POSIX; |
@@ -5602,7 +5616,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
5602 | } | 5616 | } |
5603 | } | 5617 | } |
5604 | 5618 | ||
5605 | atomic_inc(&sop->so_count); | 5619 | nfs4_get_stateowner(sop); |
5606 | break; | 5620 | break; |
5607 | } | 5621 | } |
5608 | spin_unlock(&clp->cl_lock); | 5622 | spin_unlock(&clp->cl_lock); |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 0a47c6a6b301..2712042a66b1 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -486,7 +486,6 @@ struct nfs4_file { | |||
486 | atomic_t fi_access[2]; | 486 | atomic_t fi_access[2]; |
487 | u32 fi_share_deny; | 487 | u32 fi_share_deny; |
488 | struct file *fi_deleg_file; | 488 | struct file *fi_deleg_file; |
489 | struct file_lock *fi_lease; | ||
490 | atomic_t fi_delegees; | 489 | atomic_t fi_delegees; |
491 | struct knfsd_fh fi_fhandle; | 490 | struct knfsd_fh fi_fhandle; |
492 | bool fi_had_conflict; | 491 | bool fi_had_conflict; |
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index abc8cbcfe90e..caaaf9dfe353 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c | |||
@@ -346,13 +346,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) | |||
346 | goto out; | 346 | goto out; |
347 | } | 347 | } |
348 | 348 | ||
349 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); | 349 | __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); |
350 | if (error) { | ||
351 | /* if we added, we must shoot */ | ||
352 | if (dn_mark == new_dn_mark) | ||
353 | destroy = 1; | ||
354 | goto out; | ||
355 | } | ||
356 | 350 | ||
357 | error = attach_dn(dn, dn_mark, id, fd, filp, mask); | 351 | error = attach_dn(dn, dn_mark, id, fd, filp, mask); |
358 | /* !error means that we attached the dn to the dn_mark, so don't free it */ | 352 | /* !error means that we attached the dn to the dn_mark, so don't free it */ |