Commit f74e3ea3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client fixes from Anna Schumaker:
 "Stable Fix:
   - Fix a pNFS hang in nfs4_evict_inode()

  Fixes:
   - Force update of suid/sgid bits after an NFS v4.2 ALLOCATE op
   - Fix a potential oops in nfs_inode_remove_request()
   - Check the validity of the layout pointer in ff_layout_mirror_prepare_stats()
   - Fix incorrectly marking the pNFS MDS with USE_PNFS_DS in some cases"

* tag 'nfs-for-6.6-4' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFSv4.1: fixup use EXCHGID4_FLAG_USE_PNFS_DS for DS server
  pNFS/flexfiles: Check the layout validity in ff_layout_mirror_prepare_stats
  pNFS: Fix a hang in nfs4_evict_inode()
  NFS: Fix potential oops in nfs_inode_remove_request()
  nfs42: client needs to strip file mode's suid/sgid bit after ALLOCATE op
parents 0e97fd29 379e4adf
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -2520,9 +2520,9 @@ ff_layout_mirror_prepare_stats(struct pnfs_layout_hdr *lo,
	return i;
}

static int
ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
static int ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
{
	struct pnfs_layout_hdr *lo;
	struct nfs4_flexfile_layout *ff_layout;
	const int dev_count = PNFS_LAYOUTSTATS_MAXDEV;

@@ -2533,11 +2533,14 @@ ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
		return -ENOMEM;

	spin_lock(&args->inode->i_lock);
	ff_layout = FF_LAYOUT_FROM_HDR(NFS_I(args->inode)->layout);
	args->num_dev = ff_layout_mirror_prepare_stats(&ff_layout->generic_hdr,
						       &args->devinfo[0],
						       dev_count,
	lo = NFS_I(args->inode)->layout;
	if (lo && pnfs_layout_is_valid(lo)) {
		ff_layout = FF_LAYOUT_FROM_HDR(lo);
		args->num_dev = ff_layout_mirror_prepare_stats(
			&ff_layout->generic_hdr, &args->devinfo[0], dev_count,
			NFS4_FF_OP_LAYOUTSTATS);
	} else
		args->num_dev = 0;
	spin_unlock(&args->inode->i_lock);
	if (!args->num_dev) {
		kfree(args->devinfo);
+2 −1
Original line number Diff line number Diff line
@@ -81,7 +81,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
	if (status == 0) {
		if (nfs_should_remove_suid(inode)) {
			spin_lock(&inode->i_lock);
			nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
			nfs_set_cache_invalid(inode,
				NFS_INO_REVAL_FORCED | NFS_INO_INVALID_MODE);
			spin_unlock(&inode->i_lock);
		}
		status = nfs_post_op_update_inode_force_wcc(inode,
+0 −2
Original line number Diff line number Diff line
@@ -8870,8 +8870,6 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cre
	/* Save the EXCHANGE_ID verifier session trunk tests */
	memcpy(clp->cl_confirm.data, argp->verifier.data,
	       sizeof(clp->cl_confirm.data));
	if (resp->flags & EXCHGID4_FLAG_USE_PNFS_DS)
		set_bit(NFS_CS_DS, &clp->cl_flags);
out:
	trace_nfs4_exchange_id(clp, status);
	rpc_put_task(task);
+23 −10
Original line number Diff line number Diff line
@@ -2634,31 +2634,44 @@ pnfs_should_return_unused_layout(struct pnfs_layout_hdr *lo,
	return mode == 0;
}

static int
pnfs_layout_return_unused_byserver(struct nfs_server *server, void *data)
static int pnfs_layout_return_unused_byserver(struct nfs_server *server,
					      void *data)
{
	const struct pnfs_layout_range *range = data;
	const struct cred *cred;
	struct pnfs_layout_hdr *lo;
	struct inode *inode;
	nfs4_stateid stateid;
	enum pnfs_iomode iomode;

restart:
	rcu_read_lock();
	list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
		if (!pnfs_layout_can_be_returned(lo) ||
		inode = lo->plh_inode;
		if (!inode || !pnfs_layout_can_be_returned(lo) ||
		    test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags))
			continue;
		inode = lo->plh_inode;
		spin_lock(&inode->i_lock);
		if (!pnfs_should_return_unused_layout(lo, range)) {
		if (!lo->plh_inode ||
		    !pnfs_should_return_unused_layout(lo, range)) {
			spin_unlock(&inode->i_lock);
			continue;
		}
		pnfs_get_layout_hdr(lo);
		pnfs_set_plh_return_info(lo, range->iomode, 0);
		if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs,
						    range, 0) != 0 ||
		    !pnfs_prepare_layoutreturn(lo, &stateid, &cred, &iomode)) {
			spin_unlock(&inode->i_lock);
		inode = pnfs_grab_inode_layout_hdr(lo);
		if (!inode)
			continue;
			rcu_read_unlock();
		pnfs_mark_layout_for_return(inode, range);
		iput(inode);
			pnfs_put_layout_hdr(lo);
			cond_resched();
			goto restart;
		}
		spin_unlock(&inode->i_lock);
		rcu_read_unlock();
		pnfs_send_layoutreturn(lo, &stateid, &cred, iomode, false);
		pnfs_put_layout_hdr(lo);
		cond_resched();
		goto restart;
	}
+3 −1
Original line number Diff line number Diff line
@@ -788,6 +788,8 @@ static void nfs_inode_add_request(struct nfs_page *req)
 */
static void nfs_inode_remove_request(struct nfs_page *req)
{
	struct nfs_inode *nfsi = NFS_I(nfs_page_to_inode(req));

	if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) {
		struct folio *folio = nfs_page_to_folio(req->wb_head);
		struct address_space *mapping = folio_file_mapping(folio);
@@ -802,7 +804,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
	}

	if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
		atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests);
		atomic_long_dec(&nfsi->nrequests);
		nfs_release_request(req);
	}
}