Skip to content

Commit 450d2f6

Browse files
committed
Merge tag 'nfs-for-6.15-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: - NFS: Fix a couple of missed handlers for the ENETDOWN and ENETUNREACH transport errors - NFS: Handle Oopsable failure of nfs_get_lock_context in the unlock path - NFSv4: Fix a race in nfs_local_open_fh() - NFSv4/pNFS: Fix a couple of layout segment leaks in layoutreturn - NFSv4/pNFS Avoid sharing pNFS DS connections between net namespaces since IP addresses are not guaranteed to refer to the same nodes - NFS: Don't flush file data while holding multiple directory locks in nfs_rename() * tag 'nfs-for-6.15-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFS: Avoid flushing data while holding directory locks in nfs_rename() NFS/pnfs: Fix the error path in pnfs_layoutreturn_retry_later_locked() NFSv4/pnfs: Reset the layout state after a layoutreturn NFS/localio: Fix a race in nfs_local_open_fh() nfs: nfs3acl: drop useless assignment in nfs3_get_acl() nfs: direct: drop useless initializer in nfs_direct_write_completion() nfs: move the nfs4_data_server_cache into struct nfs_net nfs: don't share pNFS DS connections between net namespaces nfs: handle failure of nfs_get_lock_context in unlock path pNFS/flexfiles: Record the RPC errors in the I/O tracepoints NFSv4/pnfs: Layoutreturn on close must handle fatal networking errors NFSv4: Handle fatal ENETDOWN and ENETUNREACH errors
2 parents 83a8965 + dcd21b6 commit 450d2f6

File tree

15 files changed

+143
-62
lines changed

15 files changed

+143
-62
lines changed

fs/nfs/client.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,8 @@ struct nfs_server *nfs_create_server(struct fs_context *fc)
11051105
if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
11061106
server->namelen = NFS2_MAXNAMLEN;
11071107
}
1108+
/* Linux 'subtree_check' borkenness mandates this setting */
1109+
server->fh_expire_type = NFS_FH_VOL_RENAME;
11081110

11091111
if (!(fattr->valid & NFS_ATTR_FATTR)) {
11101112
error = ctx->nfs_mod->rpc_ops->getattr(server, ctx->mntfh,
@@ -1199,6 +1201,10 @@ void nfs_clients_init(struct net *net)
11991201
INIT_LIST_HEAD(&nn->nfs_volume_list);
12001202
#if IS_ENABLED(CONFIG_NFS_V4)
12011203
idr_init(&nn->cb_ident_idr);
1204+
#endif
1205+
#if IS_ENABLED(CONFIG_NFS_V4_1)
1206+
INIT_LIST_HEAD(&nn->nfs4_data_server_cache);
1207+
spin_lock_init(&nn->nfs4_data_server_lock);
12021208
#endif
12031209
spin_lock_init(&nn->nfs_client_lock);
12041210
nn->boot_time = ktime_get_real();
@@ -1216,6 +1222,9 @@ void nfs_clients_exit(struct net *net)
12161222
nfs_cleanup_cb_ident_idr(net);
12171223
WARN_ON_ONCE(!list_empty(&nn->nfs_client_list));
12181224
WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list));
1225+
#if IS_ENABLED(CONFIG_NFS_V4_1)
1226+
WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache));
1227+
#endif
12191228
}
12201229

12211230
#ifdef CONFIG_PROC_FS

fs/nfs/dir.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,18 @@ nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data)
26762676
unblock_revalidate(new_dentry);
26772677
}
26782678

2679+
static bool nfs_rename_is_unsafe_cross_dir(struct dentry *old_dentry,
2680+
struct dentry *new_dentry)
2681+
{
2682+
struct nfs_server *server = NFS_SB(old_dentry->d_sb);
2683+
2684+
if (old_dentry->d_parent != new_dentry->d_parent)
2685+
return false;
2686+
if (server->fh_expire_type & NFS_FH_RENAME_UNSAFE)
2687+
return !(server->fh_expire_type & NFS_FH_NOEXPIRE_WITH_OPEN);
2688+
return true;
2689+
}
2690+
26792691
/*
26802692
* RENAME
26812693
* FIXME: Some nfsds, like the Linux user space nfsd, may generate a
@@ -2763,7 +2775,8 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
27632775

27642776
}
27652777

2766-
if (S_ISREG(old_inode->i_mode))
2778+
if (S_ISREG(old_inode->i_mode) &&
2779+
nfs_rename_is_unsafe_cross_dir(old_dentry, new_dentry))
27672780
nfs_sync_inode(old_inode);
27682781
task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry,
27692782
must_unblock ? nfs_unblock_rename : NULL);

fs/nfs/direct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,6 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
757757
{
758758
struct nfs_direct_req *dreq = hdr->dreq;
759759
struct nfs_commit_info cinfo;
760-
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
761760
struct inode *inode = dreq->inode;
762761
int flags = NFS_ODIRECT_DONE;
763762

@@ -786,6 +785,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
786785
spin_unlock(&inode->i_lock);
787786

788787
while (!list_empty(&hdr->pages)) {
788+
struct nfs_page *req;
789789

790790
req = nfs_list_entry(hdr->pages.next);
791791
nfs_list_remove_request(req);

fs/nfs/filelayout/filelayoutdev.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
7676
struct page *scratch;
7777
struct list_head dsaddrs;
7878
struct nfs4_pnfs_ds_addr *da;
79+
struct net *net = server->nfs_client->cl_net;
7980

8081
/* set up xdr stream */
8182
scratch = alloc_page(gfp_flags);
@@ -159,8 +160,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
159160

160161
mp_count = be32_to_cpup(p); /* multipath count */
161162
for (j = 0; j < mp_count; j++) {
162-
da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net,
163-
&stream, gfp_flags);
163+
da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags);
164164
if (da)
165165
list_add_tail(&da->da_node, &dsaddrs);
166166
}
@@ -170,7 +170,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
170170
goto out_err_free_deviceid;
171171
}
172172

173-
dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
173+
dsaddr->ds_list[i] = nfs4_pnfs_ds_add(net, &dsaddrs, gfp_flags);
174174
if (!dsaddr->ds_list[i])
175175
goto out_err_drain_dsaddrs;
176176
trace_fl_getdevinfo(server, &pdev->dev_id, dsaddr->ds_list[i]->ds_remotestr);

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
13291329
hdr->args.offset, hdr->args.count,
13301330
&hdr->res.op_status, OP_READ,
13311331
task->tk_status);
1332-
trace_ff_layout_read_error(hdr);
1332+
trace_ff_layout_read_error(hdr, task->tk_status);
13331333
}
13341334

13351335
err = ff_layout_async_handle_error(task, hdr->args.context->state,
@@ -1502,7 +1502,7 @@ static int ff_layout_write_done_cb(struct rpc_task *task,
15021502
hdr->args.offset, hdr->args.count,
15031503
&hdr->res.op_status, OP_WRITE,
15041504
task->tk_status);
1505-
trace_ff_layout_write_error(hdr);
1505+
trace_ff_layout_write_error(hdr, task->tk_status);
15061506
}
15071507

15081508
err = ff_layout_async_handle_error(task, hdr->args.context->state,
@@ -1551,7 +1551,7 @@ static int ff_layout_commit_done_cb(struct rpc_task *task,
15511551
data->args.offset, data->args.count,
15521552
&data->res.op_status, OP_COMMIT,
15531553
task->tk_status);
1554-
trace_ff_layout_commit_error(data);
1554+
trace_ff_layout_commit_error(data, task->tk_status);
15551555
}
15561556

15571557
err = ff_layout_async_handle_error(task, NULL, data->ds_clp,

fs/nfs/flexfilelayout/flexfilelayoutdev.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
4949
struct nfs4_pnfs_ds_addr *da;
5050
struct nfs4_ff_layout_ds *new_ds = NULL;
5151
struct nfs4_ff_ds_version *ds_versions = NULL;
52+
struct net *net = server->nfs_client->cl_net;
5253
u32 mp_count;
5354
u32 version_count;
5455
__be32 *p;
@@ -80,8 +81,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
8081

8182
for (i = 0; i < mp_count; i++) {
8283
/* multipath ds */
83-
da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net,
84-
&stream, gfp_flags);
84+
da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags);
8585
if (da)
8686
list_add_tail(&da->da_node, &dsaddrs);
8787
}
@@ -149,7 +149,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
149149
new_ds->ds_versions = ds_versions;
150150
new_ds->ds_versions_cnt = version_count;
151151

152-
new_ds->ds = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
152+
new_ds->ds = nfs4_pnfs_ds_add(net, &dsaddrs, gfp_flags);
153153
if (!new_ds->ds)
154154
goto out_err_drain_dsaddrs;
155155

fs/nfs/localio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
278278
new = __nfs_local_open_fh(clp, cred, fh, nfl, mode);
279279
if (IS_ERR(new))
280280
return NULL;
281+
rcu_read_lock();
281282
/* try to swap in the pointer */
282283
spin_lock(&clp->cl_uuid.lock);
283284
nf = rcu_dereference_protected(*pnf, 1);
@@ -287,7 +288,6 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
287288
rcu_assign_pointer(*pnf, nf);
288289
}
289290
spin_unlock(&clp->cl_uuid.lock);
290-
rcu_read_lock();
291291
}
292292
nf = nfs_local_file_get(nf);
293293
rcu_read_unlock();

fs/nfs/netns.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ struct nfs_net {
3131
unsigned short nfs_callback_tcpport;
3232
unsigned short nfs_callback_tcpport6;
3333
int cb_users[NFS4_MAX_MINOR_VERSION + 1];
34-
#endif
34+
#endif /* CONFIG_NFS_V4 */
35+
#if IS_ENABLED(CONFIG_NFS_V4_1)
36+
struct list_head nfs4_data_server_cache;
37+
spinlock_t nfs4_data_server_lock;
38+
#endif /* CONFIG_NFS_V4_1 */
3539
struct nfs_netns_client *nfs_client;
3640
spinlock_t nfs_client_lock;
3741
ktime_t boot_time;

fs/nfs/nfs3acl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type, bool rcu)
104104

105105
switch (status) {
106106
case 0:
107-
status = nfs_refresh_inode(inode, res.fattr);
107+
nfs_refresh_inode(inode, res.fattr);
108108
break;
109109
case -EPFNOSUPPORT:
110110
case -EPROTONOSUPPORT:

fs/nfs/nfs4proc.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,15 @@ nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server,
671671
struct nfs_client *clp = server->nfs_client;
672672
int ret;
673673

674+
if ((task->tk_rpc_status == -ENETDOWN ||
675+
task->tk_rpc_status == -ENETUNREACH) &&
676+
task->tk_flags & RPC_TASK_NETUNREACH_FATAL) {
677+
exception->delay = 0;
678+
exception->recovering = 0;
679+
exception->retry = 0;
680+
return -EIO;
681+
}
682+
674683
ret = nfs4_do_handle_exception(server, errorcode, exception);
675684
if (exception->delay) {
676685
int ret2 = nfs4_exception_should_retrans(server, exception);
@@ -7074,18 +7083,25 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
70747083
struct nfs4_unlockdata *p;
70757084
struct nfs4_state *state = lsp->ls_state;
70767085
struct inode *inode = state->inode;
7086+
struct nfs_lock_context *l_ctx;
70777087

70787088
p = kzalloc(sizeof(*p), GFP_KERNEL);
70797089
if (p == NULL)
70807090
return NULL;
7091+
l_ctx = nfs_get_lock_context(ctx);
7092+
if (!IS_ERR(l_ctx)) {
7093+
p->l_ctx = l_ctx;
7094+
} else {
7095+
kfree(p);
7096+
return NULL;
7097+
}
70817098
p->arg.fh = NFS_FH(inode);
70827099
p->arg.fl = &p->fl;
70837100
p->arg.seqid = seqid;
70847101
p->res.seqid = seqid;
70857102
p->lsp = lsp;
70867103
/* Ensure we don't close file until we're done freeing locks! */
70877104
p->ctx = get_nfs_open_context(ctx);
7088-
p->l_ctx = nfs_get_lock_context(ctx);
70897105
locks_init_lock(&p->fl);
70907106
locks_copy_lock(&p->fl, fl);
70917107
p->server = NFS_SERVER(inode);

0 commit comments

Comments
 (0)