Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 505d5c11 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'nfs-for-4.13-2' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client bugfixes from Anna Schumaker:
 "Stable bugfix:
   - Fix error reporting regression

  Bugfixes:
   - Fix setting filelayout ds address race
   - Fix subtle access bug when using ACLs
   - Fix setting mnt3_counts array size
   - Fix a couple of pNFS commit races"

* tag 'nfs-for-4.13-2' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFS/filelayout: Fix racy setting of fl->dsaddr in filelayout_check_deviceid()
  NFS: Be more careful about mapping file permissions
  NFS: Store the raw NFS access mask in the inode's access cache
  NFSv3: Convert nfs3_proc_access() to use nfs_access_set_mask()
  NFS: Refactor NFS access to kernel access mask calculation
  net/sunrpc/xprt_sock: fix regression in connection error reporting.
  nfs: count correct array for mnt3_counts array size
  Revert commit 722f0b89 ("pNFS: Don't send COMMITs to the DSes if...")
  pNFS/flexfiles: Handle expired layout segments in ff_layout_initiate_commit()
  NFS: Fix another COMMIT race in pNFS
  NFS: Fix a COMMIT race in pNFS
  mount: copy the port field into the cloned nfs_server structure.
  NFS: Don't run wake_up_bit() when nobody is waiting...
  nfs: add export operations
parents 99313414 1ebf9801
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -820,6 +820,7 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour
	target->caps = source->caps;
	target->options = source->options;
	target->auth_info = source->auth_info;
	target->port = source->port;
}
EXPORT_SYMBOL_GPL(nfs_server_copy_userdata);

+37 −10
Original line number Diff line number Diff line
@@ -2372,16 +2372,40 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
}
EXPORT_SYMBOL_GPL(nfs_access_add_cache);

#define NFS_MAY_READ (NFS4_ACCESS_READ)
#define NFS_MAY_WRITE (NFS4_ACCESS_MODIFY | \
		NFS4_ACCESS_EXTEND | \
		NFS4_ACCESS_DELETE)
#define NFS_FILE_MAY_WRITE (NFS4_ACCESS_MODIFY | \
		NFS4_ACCESS_EXTEND)
#define NFS_DIR_MAY_WRITE NFS_MAY_WRITE
#define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP)
#define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE)
static int
nfs_access_calc_mask(u32 access_result, umode_t umode)
{
	int mask = 0;

	if (access_result & NFS_MAY_READ)
		mask |= MAY_READ;
	if (S_ISDIR(umode)) {
		if ((access_result & NFS_DIR_MAY_WRITE) == NFS_DIR_MAY_WRITE)
			mask |= MAY_WRITE;
		if ((access_result & NFS_MAY_LOOKUP) == NFS_MAY_LOOKUP)
			mask |= MAY_EXEC;
	} else if (S_ISREG(umode)) {
		if ((access_result & NFS_FILE_MAY_WRITE) == NFS_FILE_MAY_WRITE)
			mask |= MAY_WRITE;
		if ((access_result & NFS_MAY_EXECUTE) == NFS_MAY_EXECUTE)
			mask |= MAY_EXEC;
	} else if (access_result & NFS_MAY_WRITE)
			mask |= MAY_WRITE;
	return mask;
}

void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result)
{
	entry->mask = 0;
	if (access_result & NFS4_ACCESS_READ)
		entry->mask |= MAY_READ;
	if (access_result &
	    (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
		entry->mask |= MAY_WRITE;
	if (access_result & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
		entry->mask |= MAY_EXEC;
	entry->mask = access_result;
}
EXPORT_SYMBOL_GPL(nfs_access_set_mask);

@@ -2389,6 +2413,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
{
	struct nfs_access_entry cache;
	bool may_block = (mask & MAY_NOT_BLOCK) == 0;
	int cache_mask;
	int status;

	trace_nfs_access_enter(inode);
@@ -2404,7 +2429,8 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
		goto out;

	/* Be clever: ask server to check for all possible rights */
	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
	cache.mask = NFS_MAY_LOOKUP | NFS_MAY_EXECUTE
		     | NFS_MAY_WRITE | NFS_MAY_READ;
	cache.cred = cred;
	cache.jiffies = jiffies;
	status = NFS_PROTO(inode)->access(inode, &cache);
@@ -2418,7 +2444,8 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
	}
	nfs_access_add_cache(inode, &cache);
out_cached:
	if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0)
	cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode);
	if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0)
		status = -EACCES;
out:
	trace_nfs_access_exit(inode, status);
+11 −2
Original line number Diff line number Diff line
@@ -542,6 +542,10 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
	struct nfs4_file_layout_dsaddr *dsaddr;
	int status = -EINVAL;

	/* Is the deviceid already set? If so, we're good. */
	if (fl->dsaddr != NULL)
		return 0;

	/* find and reference the deviceid */
	d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
			lo->plh_lc_cred, gfp_flags);
@@ -553,8 +557,6 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
	if (filelayout_test_devid_unavailable(&dsaddr->id_node))
		goto out_put;

	fl->dsaddr = dsaddr;

	if (fl->first_stripe_index >= dsaddr->stripe_count) {
		dprintk("%s Bad first_stripe_index %u\n",
				__func__, fl->first_stripe_index);
@@ -570,6 +572,13 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
		goto out_put;
	}
	status = 0;

	/*
	 * Atomic compare and xchange to ensure we don't scribble
	 * over a non-NULL pointer.
	 */
	if (cmpxchg(&fl->dsaddr, NULL, dsaddr) != NULL)
		goto out_put;
out:
	return status;
out_put:
+4 −0
Original line number Diff line number Diff line
@@ -1842,6 +1842,10 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how)
	int vers, ret;
	struct nfs_fh *fh;

	if (!lseg || !(pnfs_is_valid_lseg(lseg) ||
	    test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags)))
		goto out_err;

	idx = calc_ds_index_from_commit(lseg, data->ds_commit_index);
	ds = nfs4_ff_layout_prepare_ds(lseg, idx, true);
	if (!ds)
+1 −1
Original line number Diff line number Diff line
@@ -512,7 +512,7 @@ static const struct rpc_version mnt_version1 = {
	.counts		= mnt_counts,
};

static unsigned int mnt3_counts[ARRAY_SIZE(mnt_procedures)];
static unsigned int mnt3_counts[ARRAY_SIZE(mnt3_procedures)];
static const struct rpc_version mnt_version3 = {
	.number		= 3,
	.nrprocs	= ARRAY_SIZE(mnt3_procedures),
Loading