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

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
...@@ -134,6 +134,16 @@ config NFSD_FLEXFILELAYOUT ...@@ -134,6 +134,16 @@ config NFSD_FLEXFILELAYOUT
If unsure, say N. 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 config NFSD_V4_SECURITY_LABEL
bool "Provide Security Label support for NFSv4 server" bool "Provide Security Label support for NFSv4 server"
depends on NFSD_V4 && SECURITY depends on NFSD_V4 && SECURITY
......
...@@ -504,12 +504,20 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -504,12 +504,20 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
union nfsd4_op_u *u) union nfsd4_op_u *u)
{ {
struct nfsd4_putfh *putfh = &u->putfh; struct nfsd4_putfh *putfh = &u->putfh;
__be32 ret;
fh_put(&cstate->current_fh); fh_put(&cstate->current_fh);
cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
putfh->pf_fhlen); 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 static __be32
...@@ -1957,6 +1965,45 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp, ...@@ -1957,6 +1965,45 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp,
- rqstp->rq_auth_slack; - 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. * COMPOUND call.
*/ */
...@@ -2005,6 +2052,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) ...@@ -2005,6 +2052,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
resp->opcnt = 1; resp->opcnt = 1;
goto encode_op; goto encode_op;
} }
check_if_stalefh_allowed(args);
trace_nfsd_compound(rqstp, args->opcnt); trace_nfsd_compound(rqstp, args->opcnt);
while (!status && resp->opcnt < args->opcnt) { while (!status && resp->opcnt < args->opcnt) {
...@@ -2020,13 +2068,14 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) ...@@ -2020,13 +2068,14 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
op->status = nfsd4_open_omfg(rqstp, cstate, op); op->status = nfsd4_open_omfg(rqstp, cstate, op);
goto encode_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)) { if (!(op->opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
op->status = nfserr_nofilehandle; op->status = nfserr_nofilehandle;
goto encode_op; 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->opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
op->status = nfserr_moved; op->status = nfserr_moved;
goto encode_op; goto encode_op;
......
...@@ -35,7 +35,7 @@ typedef struct svc_fh { ...@@ -35,7 +35,7 @@ typedef struct svc_fh {
bool fh_locked; /* inode locked by us */ bool fh_locked; /* inode locked by us */
bool fh_want_write; /* remount protection taken */ bool fh_want_write; /* remount protection taken */
int fh_flags; /* FH flags */
#ifdef CONFIG_NFSD_V3 #ifdef CONFIG_NFSD_V3
bool fh_post_saved; /* post-op attrs saved */ bool fh_post_saved; /* post-op attrs saved */
bool fh_pre_saved; /* pre-op attrs saved */ bool fh_pre_saved; /* pre-op attrs saved */
...@@ -56,6 +56,9 @@ typedef struct svc_fh { ...@@ -56,6 +56,9 @@ typedef struct svc_fh {
#endif /* CONFIG_NFSD_V3 */ #endif /* CONFIG_NFSD_V3 */
} svc_fh; } 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 { enum nfsd_fsid {
FSID_DEV = 0, FSID_DEV = 0,
......
...@@ -221,6 +221,7 @@ struct nfsd4_lookup { ...@@ -221,6 +221,7 @@ struct nfsd4_lookup {
struct nfsd4_putfh { struct nfsd4_putfh {
u32 pf_fhlen; /* request */ u32 pf_fhlen; /* request */
char *pf_fhval; /* request */ char *pf_fhval; /* request */
bool no_verify; /* represents foreigh fh */
}; };
struct nfsd4_open { struct nfsd4_open {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment