Skip to content

Commit c8ebd43

Browse files
committed
Merge tag 'nfsd-6.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd fixes from Chuck Lever: "A set of NFSD fixes that arrived just a bit late for the 6.19 merge window. Regression fix: - Avoid unnecessarily breaking a timestamp delegation Stable fixes: - Fix a crasher in nlm4svc_proc_test() - Fix nfsd_file reference leak during write delegation - Fix error flow in client_states_open()" * tag 'nfsd-6.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: nfsd: Drop the client reference in client_states_open() nfsd: use ATTR_DELEG in nfsd4_finalize_deleg_timestamps() nfsd: fix nfsd_file reference leak in nfsd4_add_rdaccess_to_wrdeleg() lockd: fix vfs_test_lock() calls
2 parents dbf8fe8 + 1f941b2 commit c8ebd43

5 files changed

Lines changed: 38 additions & 24 deletions

File tree

fs/lockd/svc4proc.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
9797
struct nlm_args *argp = rqstp->rq_argp;
9898
struct nlm_host *host;
9999
struct nlm_file *file;
100-
struct nlm_lockowner *test_owner;
101100
__be32 rc = rpc_success;
102101

103102
dprintk("lockd: TEST4 called\n");
@@ -107,7 +106,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
107106
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
108107
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
109108

110-
test_owner = argp->lock.fl.c.flc_owner;
111109
/* Now check for conflicting locks */
112110
resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock,
113111
&resp->lock);
@@ -116,7 +114,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
116114
else
117115
dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
118116

119-
nlmsvc_put_lockowner(test_owner);
117+
nlmsvc_release_lockowner(&argp->lock);
120118
nlmsvc_release_host(host);
121119
nlm_release_file(file);
122120
return rc;

fs/lockd/svclock.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
633633
}
634634

635635
mode = lock_to_openmode(&lock->fl);
636-
error = vfs_test_lock(file->f_file[mode], &lock->fl);
636+
locks_init_lock(&conflock->fl);
637+
/* vfs_test_lock only uses start, end, and owner, but tests flc_file */
638+
conflock->fl.c.flc_file = lock->fl.c.flc_file;
639+
conflock->fl.fl_start = lock->fl.fl_start;
640+
conflock->fl.fl_end = lock->fl.fl_end;
641+
conflock->fl.c.flc_owner = lock->fl.c.flc_owner;
642+
error = vfs_test_lock(file->f_file[mode], &conflock->fl);
637643
if (error) {
638644
/* We can't currently deal with deferred test requests */
639645
if (error == FILE_LOCK_DEFERRED)
@@ -643,22 +649,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
643649
goto out;
644650
}
645651

646-
if (lock->fl.c.flc_type == F_UNLCK) {
652+
if (conflock->fl.c.flc_type == F_UNLCK) {
647653
ret = nlm_granted;
648654
goto out;
649655
}
650656

651657
dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
652-
lock->fl.c.flc_type, (long long)lock->fl.fl_start,
653-
(long long)lock->fl.fl_end);
658+
conflock->fl.c.flc_type, (long long)conflock->fl.fl_start,
659+
(long long)conflock->fl.fl_end);
654660
conflock->caller = "somehost"; /* FIXME */
655661
conflock->len = strlen(conflock->caller);
656662
conflock->oh.len = 0; /* don't return OH info */
657-
conflock->svid = lock->fl.c.flc_pid;
658-
conflock->fl.c.flc_type = lock->fl.c.flc_type;
659-
conflock->fl.fl_start = lock->fl.fl_start;
660-
conflock->fl.fl_end = lock->fl.fl_end;
661-
locks_release_private(&lock->fl);
663+
conflock->svid = conflock->fl.c.flc_pid;
664+
locks_release_private(&conflock->fl);
662665

663666
ret = nlm_lck_denied;
664667
out:

fs/lockd/svcproc.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
117117
struct nlm_args *argp = rqstp->rq_argp;
118118
struct nlm_host *host;
119119
struct nlm_file *file;
120-
struct nlm_lockowner *test_owner;
121120
__be32 rc = rpc_success;
122121

123122
dprintk("lockd: TEST called\n");
@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
127126
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
128127
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
129128

130-
test_owner = argp->lock.fl.c.flc_owner;
131-
132129
/* Now check for conflicting locks */
133130
resp->status = cast_status(nlmsvc_testlock(rqstp, file, host,
134131
&argp->lock, &resp->lock));
@@ -138,7 +135,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
138135
dprintk("lockd: TEST status %d vers %d\n",
139136
ntohl(resp->status), rqstp->rq_vers);
140137

141-
nlmsvc_put_lockowner(test_owner);
138+
nlmsvc_release_lockowner(&argp->lock);
142139
nlmsvc_release_host(host);
143140
nlm_release_file(file);
144141
return rc;

fs/locks.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,13 +2236,21 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
22362236
/**
22372237
* vfs_test_lock - test file byte range lock
22382238
* @filp: The file to test lock for
2239-
* @fl: The lock to test; also used to hold result
2239+
* @fl: The byte-range in the file to test; also used to hold result
22402240
*
2241+
* On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end)
2242+
* in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks
2243+
* should be ignored. c.flc_type and c.flc_flags are ignored.
2244+
* Both fl_lmops and fl_ops in @fl must be NULL.
22412245
* Returns -ERRNO on failure. Indicates presence of conflicting lock by
2242-
* setting conf->fl_type to something other than F_UNLCK.
2246+
* setting fl->fl_type to something other than F_UNLCK.
2247+
*
2248+
* If vfs_test_lock() does find a lock and return it, the caller must
2249+
* use locks_free_lock() or locks_release_private() on the returned lock.
22432250
*/
22442251
int vfs_test_lock(struct file *filp, struct file_lock *fl)
22452252
{
2253+
WARN_ON_ONCE(fl->fl_ops || fl->fl_lmops);
22462254
WARN_ON_ONCE(filp != fl->c.flc_file);
22472255
if (filp->f_op->lock)
22482256
return filp->f_op->lock(filp, F_GETLK, fl);

fs/nfsd/nfs4state.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,13 +1218,15 @@ static void put_deleg_file(struct nfs4_file *fp)
12181218

12191219
if (nf)
12201220
nfsd_file_put(nf);
1221-
if (rnf)
1221+
if (rnf) {
1222+
nfsd_file_put(rnf);
12221223
nfs4_file_put_access(fp, NFS4_SHARE_ACCESS_READ);
1224+
}
12231225
}
12241226

12251227
static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct file *f)
12261228
{
1227-
struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME };
1229+
struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME | ATTR_DELEG };
12281230
struct inode *inode = file_inode(f);
12291231
int ret;
12301232

@@ -3097,8 +3099,10 @@ static int client_states_open(struct inode *inode, struct file *file)
30973099
return -ENXIO;
30983100

30993101
ret = seq_open(file, &states_seq_ops);
3100-
if (ret)
3102+
if (ret) {
3103+
drop_client(clp);
31013104
return ret;
3105+
}
31023106
s = file->private_data;
31033107
s->private = clp;
31043108
return 0;
@@ -6231,10 +6235,14 @@ nfsd4_add_rdaccess_to_wrdeleg(struct svc_rqst *rqstp, struct nfsd4_open *open,
62316235
fp = stp->st_stid.sc_file;
62326236
spin_lock(&fp->fi_lock);
62336237
__nfs4_file_get_access(fp, NFS4_SHARE_ACCESS_READ);
6234-
fp = stp->st_stid.sc_file;
6235-
fp->fi_fds[O_RDONLY] = nf;
6236-
fp->fi_rdeleg_file = nf;
6238+
if (!fp->fi_fds[O_RDONLY]) {
6239+
fp->fi_fds[O_RDONLY] = nf;
6240+
nf = NULL;
6241+
}
6242+
fp->fi_rdeleg_file = nfsd_file_get(fp->fi_fds[O_RDONLY]);
62376243
spin_unlock(&fp->fi_lock);
6244+
if (nf)
6245+
nfsd_file_put(nf);
62386246
}
62396247
return true;
62406248
}

0 commit comments

Comments
 (0)