Skip to content

Commit

Permalink
NFSD: allow inter server COPY to have a STALE source server fh
Browse files Browse the repository at this point in the history
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: Olga Kornievskaia <kolga@netapp.com>
  • Loading branch information
Olga Kornievskaia authored and J. Bruce Fields committed Dec 9, 2019
1 parent 51100d2 commit b9e8638
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 5 deletions.
10 changes: 10 additions & 0 deletions fs/nfsd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
57 changes: 53 additions & 4 deletions fs/nfsd/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion fs/nfsd/nfsfh.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions fs/nfsd/xdr4.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit b9e8638

Please sign in to comment.