Skip to content

Commit c360699

Browse files
J. Bruce Fieldssmb49
authored andcommitted
nfs: block notification on fs with its own ->lock
BugLink: https://bugs.launchpad.net/bugs/2065435 [ Upstream commit 40595cd ] NFSv4.1 supports an optional lock notification feature which notifies the client when a lock comes available. (Normally NFSv4 clients just poll for locks if necessary.) To make that work, we need to request a blocking lock from the filesystem. We turned that off for NFS in commit f657f8e ("nfs: don't atempt blocking locks on nfs reexports") [sic] because it actually blocks the nfsd thread while waiting for the lock. Thanks to Vasily Averin for pointing out that NFS isn't the only filesystem with that problem. Any filesystem that leaves ->lock NULL will use posix_lock_file(), which does the right thing. Simplest is just to assume that any filesystem that defines its own ->lock is not safe to request a blocking lock from. So, this patch mostly reverts commit f657f8e ("nfs: don't atempt blocking locks on nfs reexports") [sic] and commit b840be2 ("lockd: don't attempt blocking locks on nfs reexports"), and instead uses a check of ->lock (Vasily's suggestion) to decide whether to support blocking lock notifications on a given filesystem. Also add a little documentation. Perhaps someday we could add back an export flag later to allow filesystems with "good" ->lock methods to support blocking lock notifications. Reported-by: Vasily Averin <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]> [ cel: Description rewritten to address checkpatch nits ] [ cel: Fixed warning when SUNRPC debugging is disabled ] [ cel: Fixed NULL check ] Signed-off-by: Chuck Lever <[email protected]> Reviewed-by: Vasily Averin <[email protected]> Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Manuel Diewald <[email protected]> Signed-off-by: Roxana Nicolescu <[email protected]>
1 parent 416964d commit c360699

File tree

5 files changed

+24
-13
lines changed

5 files changed

+24
-13
lines changed

fs/lockd/svclock.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,10 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
470470
struct nlm_host *host, struct nlm_lock *lock, int wait,
471471
struct nlm_cookie *cookie, int reclaim)
472472
{
473-
struct nlm_block *block = NULL;
473+
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
474474
struct inode *inode = nlmsvc_file_inode(file);
475+
#endif
476+
struct nlm_block *block = NULL;
475477
int error;
476478
int mode;
477479
int async_block = 0;
@@ -484,7 +486,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
484486
(long long)lock->fl.fl_end,
485487
wait);
486488

487-
if (inode->i_sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS) {
489+
if (nlmsvc_file_file(file)->f_op->lock) {
488490
async_block = wait;
489491
wait = 0;
490492
}

fs/nfs/export.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,5 +180,5 @@ const struct export_operations nfs_export_ops = {
180180
.fetch_iversion = nfs_fetch_iversion,
181181
.flags = EXPORT_OP_NOWCC|EXPORT_OP_NOSUBTREECHK|
182182
EXPORT_OP_CLOSE_BEFORE_UNLINK|EXPORT_OP_REMOTE_FS|
183-
EXPORT_OP_NOATOMIC_ATTR|EXPORT_OP_SYNC_LOCKS,
183+
EXPORT_OP_NOATOMIC_ATTR,
184184
};

fs/nfsd/nfs4state.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6874,7 +6874,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
68746874
struct nfsd4_blocked_lock *nbl = NULL;
68756875
struct file_lock *file_lock = NULL;
68766876
struct file_lock *conflock = NULL;
6877-
struct super_block *sb;
68786877
__be32 status = 0;
68796878
int lkflg;
68806879
int err;
@@ -6896,7 +6895,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
68966895
dprintk("NFSD: nfsd4_lock: permission denied!\n");
68976896
return status;
68986897
}
6899-
sb = cstate->current_fh.fh_dentry->d_sb;
69006898

69016899
if (lock->lk_is_new) {
69026900
if (nfsd4_has_session(cstate))
@@ -6948,8 +6946,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
69486946
fp = lock_stp->st_stid.sc_file;
69496947
switch (lock->lk_type) {
69506948
case NFS4_READW_LT:
6951-
if (nfsd4_has_session(cstate) &&
6952-
!(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
6949+
if (nfsd4_has_session(cstate))
69536950
fl_flags |= FL_SLEEP;
69546951
fallthrough;
69556952
case NFS4_READ_LT:
@@ -6961,8 +6958,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
69616958
fl_type = F_RDLCK;
69626959
break;
69636960
case NFS4_WRITEW_LT:
6964-
if (nfsd4_has_session(cstate) &&
6965-
!(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
6961+
if (nfsd4_has_session(cstate))
69666962
fl_flags |= FL_SLEEP;
69676963
fallthrough;
69686964
case NFS4_WRITE_LT:
@@ -6983,6 +6979,16 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
69836979
goto out;
69846980
}
69856981

6982+
/*
6983+
* Most filesystems with their own ->lock operations will block
6984+
* the nfsd thread waiting to acquire the lock. That leads to
6985+
* deadlocks (we don't want every nfsd thread tied up waiting
6986+
* for file locks), so don't attempt blocking lock notifications
6987+
* on those filesystems:
6988+
*/
6989+
if (nf->nf_file->f_op->lock)
6990+
fl_flags &= ~FL_SLEEP;
6991+
69866992
nbl = find_or_allocate_block(lock_sop, &fp->fi_fhandle, nn);
69876993
if (!nbl) {
69886994
dprintk("NFSD: %s: unable to allocate block!\n", __func__);

include/linux/exportfs.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,6 @@ struct export_operations {
221221
#define EXPORT_OP_NOATOMIC_ATTR (0x10) /* Filesystem cannot supply
222222
atomic attribute updates
223223
*/
224-
#define EXPORT_OP_SYNC_LOCKS (0x20) /* Filesystem can't do
225-
asychronous blocking locks */
226224
unsigned long flags;
227225
};
228226

include/linux/lockd/lockd.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,15 @@ void nlmsvc_invalidate_all(void);
303303
int nlmsvc_unlock_all_by_sb(struct super_block *sb);
304304
int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr);
305305

306+
static inline struct file *nlmsvc_file_file(struct nlm_file *file)
307+
{
308+
return file->f_file[O_RDONLY] ?
309+
file->f_file[O_RDONLY] : file->f_file[O_WRONLY];
310+
}
311+
306312
static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
307313
{
308-
return locks_inode(file->f_file[O_RDONLY] ?
309-
file->f_file[O_RDONLY] : file->f_file[O_WRONLY]);
314+
return locks_inode(nlmsvc_file_file(file));
310315
}
311316

312317
static inline int __nlm_privileged_request4(const struct sockaddr *sap)

0 commit comments

Comments
 (0)