Commit b9e8638e authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by J. Bruce Fields
Browse files

NFSD: allow inter server COPY to have a STALE source server fh



The inter server to server COPY source server filehandle
is a foreign filehandle as the COPY is sent to the destination
server.

Signed-off-by: default avatarOlga Kornievskaia <kolga@netapp.com>
parent 51100d2b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -134,6 +134,16 @@ config NFSD_FLEXFILELAYOUT

	  If unsure, say N.

config NFSD_V4_2_INTER_SSC
	bool "NFSv4.2 inter server to server COPY"
	depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2
	help
	  This option enables support for NFSv4.2 inter server to
	  server copy where the destination server calls the NFSv4.2
	  client to read the data to copy from the source server.

	  If unsure, say N.

config NFSD_V4_SECURITY_LABEL
	bool "Provide Security Label support for NFSv4 server"
	depends on NFSD_V4 && SECURITY
+53 −4
Original line number Diff line number Diff line
@@ -504,12 +504,20 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	    union nfsd4_op_u *u)
{
	struct nfsd4_putfh *putfh = &u->putfh;
	__be32 ret;

	fh_put(&cstate->current_fh);
	cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
	memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
	       putfh->pf_fhlen);
	return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
	ret = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
#ifdef CONFIG_NFSD_V4_2_INTER_SSC
	if (ret == nfserr_stale && putfh->no_verify) {
		SET_FH_FLAG(&cstate->current_fh, NFSD4_FH_FOREIGN);
		ret = 0;
	}
#endif
	return ret;
}

static __be32
@@ -1957,6 +1965,45 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp,
		- rqstp->rq_auth_slack;
}

#ifdef CONFIG_NFSD_V4_2_INTER_SSC
static void
check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
{
	struct nfsd4_op	*op, *current_op = NULL, *saved_op = NULL;
	struct nfsd4_copy *copy;
	struct nfsd4_putfh *putfh;
	int i;

	/* traverse all operation and if it's a COPY compound, mark the
	 * source filehandle to skip verification
	 */
	for (i = 0; i < args->opcnt; i++) {
		op = &args->ops[i];
		if (op->opnum == OP_PUTFH)
			current_op = op;
		else if (op->opnum == OP_SAVEFH)
			saved_op = current_op;
		else if (op->opnum == OP_RESTOREFH)
			current_op = saved_op;
		else if (op->opnum == OP_COPY) {
			copy = (struct nfsd4_copy *)&op->u;
			if (!saved_op) {
				op->status = nfserr_nofilehandle;
				return;
			}
			putfh = (struct nfsd4_putfh *)&saved_op->u;
			if (!copy->cp_intra)
				putfh->no_verify = true;
		}
	}
}
#else
static void
check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
{
}
#endif

/*
 * COMPOUND call.
 */
@@ -2005,6 +2052,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
		resp->opcnt = 1;
		goto encode_op;
	}
	check_if_stalefh_allowed(args);

	trace_nfsd_compound(rqstp, args->opcnt);
	while (!status && resp->opcnt < args->opcnt) {
@@ -2020,13 +2068,14 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
				op->status = nfsd4_open_omfg(rqstp, cstate, op);
			goto encode_op;
		}

		if (!current_fh->fh_dentry) {
		if (!current_fh->fh_dentry &&
				!HAS_FH_FLAG(current_fh, NFSD4_FH_FOREIGN)) {
			if (!(op->opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
				op->status = nfserr_nofilehandle;
				goto encode_op;
			}
		} else if (current_fh->fh_export->ex_fslocs.migrated &&
		} else if (current_fh->fh_export &&
			   current_fh->fh_export->ex_fslocs.migrated &&
			  !(op->opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
			op->status = nfserr_moved;
			goto encode_op;
+4 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ typedef struct svc_fh {

	bool			fh_locked;	/* inode locked by us */
	bool			fh_want_write;	/* remount protection taken */

	int			fh_flags;	/* FH flags */
#ifdef CONFIG_NFSD_V3
	bool			fh_post_saved;	/* post-op attrs saved */
	bool			fh_pre_saved;	/* pre-op attrs saved */
@@ -56,6 +56,9 @@ typedef struct svc_fh {
#endif /* CONFIG_NFSD_V3 */

} svc_fh;
#define NFSD4_FH_FOREIGN (1<<0)
#define SET_FH_FLAG(c, f) ((c)->fh_flags |= (f))
#define HAS_FH_FLAG(c, f) ((c)->fh_flags & (f))

enum nfsd_fsid {
	FSID_DEV = 0,
+1 −0
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ struct nfsd4_lookup {
struct nfsd4_putfh {
	u32		pf_fhlen;           /* request */
	char		*pf_fhval;          /* request */
	bool		no_verify;	    /* represents foreigh fh */
};

struct nfsd4_open {