Commit 450d2f6e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 83a89654 dcd21b60
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1105,6 +1105,8 @@ struct nfs_server *nfs_create_server(struct fs_context *fc)
		if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
			server->namelen = NFS2_MAXNAMLEN;
	}
	/* Linux 'subtree_check' borkenness mandates this setting */
	server->fh_expire_type = NFS_FH_VOL_RENAME;

	if (!(fattr->valid & NFS_ATTR_FATTR)) {
		error = ctx->nfs_mod->rpc_ops->getattr(server, ctx->mntfh,
@@ -1199,6 +1201,10 @@ void nfs_clients_init(struct net *net)
	INIT_LIST_HEAD(&nn->nfs_volume_list);
#if IS_ENABLED(CONFIG_NFS_V4)
	idr_init(&nn->cb_ident_idr);
#endif
#if IS_ENABLED(CONFIG_NFS_V4_1)
	INIT_LIST_HEAD(&nn->nfs4_data_server_cache);
	spin_lock_init(&nn->nfs4_data_server_lock);
#endif
	spin_lock_init(&nn->nfs_client_lock);
	nn->boot_time = ktime_get_real();
@@ -1216,6 +1222,9 @@ void nfs_clients_exit(struct net *net)
	nfs_cleanup_cb_ident_idr(net);
	WARN_ON_ONCE(!list_empty(&nn->nfs_client_list));
	WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list));
#if IS_ENABLED(CONFIG_NFS_V4_1)
	WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache));
#endif
}

#ifdef CONFIG_PROC_FS
+14 −1
Original line number Diff line number Diff line
@@ -2676,6 +2676,18 @@ nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data)
	unblock_revalidate(new_dentry);
}

static bool nfs_rename_is_unsafe_cross_dir(struct dentry *old_dentry,
					   struct dentry *new_dentry)
{
	struct nfs_server *server = NFS_SB(old_dentry->d_sb);

	if (old_dentry->d_parent != new_dentry->d_parent)
		return false;
	if (server->fh_expire_type & NFS_FH_RENAME_UNSAFE)
		return !(server->fh_expire_type & NFS_FH_NOEXPIRE_WITH_OPEN);
	return true;
}

/*
 * RENAME
 * 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,

	}

	if (S_ISREG(old_inode->i_mode))
	if (S_ISREG(old_inode->i_mode) &&
	    nfs_rename_is_unsafe_cross_dir(old_dentry, new_dentry))
		nfs_sync_inode(old_inode);
	task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry,
				must_unblock ? nfs_unblock_rename : NULL);
+1 −1
Original line number Diff line number Diff line
@@ -757,7 +757,6 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
{
	struct nfs_direct_req *dreq = hdr->dreq;
	struct nfs_commit_info cinfo;
	struct nfs_page *req = nfs_list_entry(hdr->pages.next);
	struct inode *inode = dreq->inode;
	int flags = NFS_ODIRECT_DONE;

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

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

		req = nfs_list_entry(hdr->pages.next);
		nfs_list_remove_request(req);
+3 −3
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
	struct page *scratch;
	struct list_head dsaddrs;
	struct nfs4_pnfs_ds_addr *da;
	struct net *net = server->nfs_client->cl_net;

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

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

		dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
		dsaddr->ds_list[i] = nfs4_pnfs_ds_add(net, &dsaddrs, gfp_flags);
		if (!dsaddr->ds_list[i])
			goto out_err_drain_dsaddrs;
		trace_fl_getdevinfo(server, &pdev->dev_id, dsaddr->ds_list[i]->ds_remotestr);
+3 −3
Original line number Diff line number Diff line
@@ -1329,7 +1329,7 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
					    hdr->args.offset, hdr->args.count,
					    &hdr->res.op_status, OP_READ,
					    task->tk_status);
		trace_ff_layout_read_error(hdr);
		trace_ff_layout_read_error(hdr, task->tk_status);
	}

	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,
					    hdr->args.offset, hdr->args.count,
					    &hdr->res.op_status, OP_WRITE,
					    task->tk_status);
		trace_ff_layout_write_error(hdr);
		trace_ff_layout_write_error(hdr, task->tk_status);
	}

	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,
					    data->args.offset, data->args.count,
					    &data->res.op_status, OP_COMMIT,
					    task->tk_status);
		trace_ff_layout_commit_error(data);
		trace_ff_layout_commit_error(data, task->tk_status);
	}

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