Loading fs/nfsd/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -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 Loading fs/nfsd/nfs4proc.c +53 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. */ Loading Loading @@ -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) { Loading @@ -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; Loading fs/nfsd/nfsfh.h +4 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading @@ -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, Loading fs/nfsd/xdr4.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading
fs/nfsd/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
fs/nfsd/nfs4proc.c +53 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. */ Loading Loading @@ -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) { Loading @@ -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; Loading
fs/nfsd/nfsfh.h +4 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading @@ -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, Loading
fs/nfsd/xdr4.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading