Skip to content

Commit 40595cd

Browse files
J. Bruce Fieldschucklever
authored andcommitted
nfs: block notification on fs with its own ->lock
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]>
1 parent cd2e999 commit 40595cd

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
@@ -158,5 +158,5 @@ const struct export_operations nfs_export_ops = {
158158
.fetch_iversion = nfs_fetch_iversion,
159159
.flags = EXPORT_OP_NOWCC|EXPORT_OP_NOSUBTREECHK|
160160
EXPORT_OP_CLOSE_BEFORE_UNLINK|EXPORT_OP_REMOTE_FS|
161-
EXPORT_OP_NOATOMIC_ATTR|EXPORT_OP_SYNC_LOCKS,
161+
EXPORT_OP_NOATOMIC_ATTR,
162162
};

fs/nfsd/nfs4state.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6842,7 +6842,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
68426842
struct nfsd4_blocked_lock *nbl = NULL;
68436843
struct file_lock *file_lock = NULL;
68446844
struct file_lock *conflock = NULL;
6845-
struct super_block *sb;
68466845
__be32 status = 0;
68476846
int lkflg;
68486847
int err;
@@ -6864,7 +6863,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
68646863
dprintk("NFSD: nfsd4_lock: permission denied!\n");
68656864
return status;
68666865
}
6867-
sb = cstate->current_fh.fh_dentry->d_sb;
68686866

68696867
if (lock->lk_is_new) {
68706868
if (nfsd4_has_session(cstate))
@@ -6916,8 +6914,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
69166914
fp = lock_stp->st_stid.sc_file;
69176915
switch (lock->lk_type) {
69186916
case NFS4_READW_LT:
6919-
if (nfsd4_has_session(cstate) &&
6920-
!(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
6917+
if (nfsd4_has_session(cstate))
69216918
fl_flags |= FL_SLEEP;
69226919
fallthrough;
69236920
case NFS4_READ_LT:
@@ -6929,8 +6926,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
69296926
fl_type = F_RDLCK;
69306927
break;
69316928
case NFS4_WRITEW_LT:
6932-
if (nfsd4_has_session(cstate) &&
6933-
!(sb->s_export_op->flags & EXPORT_OP_SYNC_LOCKS))
6929+
if (nfsd4_has_session(cstate))
69346930
fl_flags |= FL_SLEEP;
69356931
fallthrough;
69366932
case NFS4_WRITE_LT:
@@ -6951,6 +6947,16 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
69516947
goto out;
69526948
}
69536949

6950+
/*
6951+
* Most filesystems with their own ->lock operations will block
6952+
* the nfsd thread waiting to acquire the lock. That leads to
6953+
* deadlocks (we don't want every nfsd thread tied up waiting
6954+
* for file locks), so don't attempt blocking lock notifications
6955+
* on those filesystems:
6956+
*/
6957+
if (nf->nf_file->f_op->lock)
6958+
fl_flags &= ~FL_SLEEP;
6959+
69546960
nbl = find_or_allocate_block(lock_sop, &fp->fi_fhandle, nn);
69556961
if (!nbl) {
69566962
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)