]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
NFSD: allow inter server COPY to have a STALE source server fh
authorOlga Kornievskaia <olga.kornievskaia@gmail.com>
Mon, 7 Oct 2019 14:56:48 +0000 (10:56 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 9 Dec 2019 16:42:14 +0000 (11:42 -0500)
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>
fs/nfsd/Kconfig
fs/nfsd/nfs4proc.c
fs/nfsd/nfsfh.h
fs/nfsd/xdr4.h

index f2f81561ebb659be4f123d97a084820ade17c220..f368f3215f88fce200a3fbafbd57d56d5757a0c6 100644 (file)
@@ -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
index 8cc9f6e91874c89bad3d926980ce980cc7e8543b..816777c12bc7803a088db3a86d6acdf47f242b98 100644 (file)
@@ -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;
index 755e256a910393bf2b9a6147a63fc0300862b968..b9c75680bc3169d63d56609bf4c9e3af406ed5dc 100644 (file)
@@ -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,
index 0b4fe0795b720f7b9070bf91afa14d4fe8a1cf27..b16f602af8f1b7dc2ee2935b6ebb12e1cc70568a 100644 (file)
@@ -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 {