]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
nfsd: Add ALLOCATE support
authorAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 7 Nov 2014 19:44:26 +0000 (14:44 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 7 Nov 2014 21:19:49 +0000 (16:19 -0500)
The ALLOCATE operation is used to preallocate space in a file.  I can do
this by using vfs_fallocate() to do the actual preallocation.

ALLOCATE only returns a status indicator, so we don't need to write a
special encode() function.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4xdr.c
fs/nfsd/vfs.c
fs/nfsd/vfs.h
fs/nfsd/xdr4.h

index 0beb023f25ace63a8b4ec270eb69bdbaa3e19cbe..a261f1800922f54ff29a7d6f1e127008997a3bcc 100644 (file)
@@ -1013,6 +1013,36 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        return status;
 }
 
+static __be32
+nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+               struct nfsd4_fallocate *fallocate, int flags)
+{
+       __be32 status = nfserr_notsupp;
+       struct file *file;
+
+       status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate,
+                                           &fallocate->falloc_stateid,
+                                           WR_STATE, &file);
+       if (status != nfs_ok) {
+               dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
+               return status;
+       }
+
+       status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file,
+                                    fallocate->falloc_offset,
+                                    fallocate->falloc_length,
+                                    flags);
+       fput(file);
+       return status;
+}
+
+static __be32
+nfsd4_allocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+              struct nfsd4_fallocate *fallocate)
+{
+       return nfsd4_fallocate(rqstp, cstate, fallocate, 0);
+}
+
 static __be32
 nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                struct nfsd4_seek *seek)
@@ -1929,6 +1959,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
        },
 
        /* NFSv4.2 operations */
+       [OP_ALLOCATE] = {
+               .op_func = (nfsd4op_func)nfsd4_allocate,
+               .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
+               .op_name = "OP_ALLOCATE",
+               .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
+       },
        [OP_SEEK] = {
                .op_func = (nfsd4op_func)nfsd4_seek,
                .op_name = "OP_SEEK",
index eeea7a90eb873d6d4d8b606ddf2584a1c3a9f85c..a60cff86fc28d57baa9468bf1d90ca6522c09817 100644 (file)
@@ -1513,6 +1513,23 @@ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, str
        DECODE_TAIL;
 }
 
+static __be32
+nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
+                      struct nfsd4_fallocate *fallocate)
+{
+       DECODE_HEAD;
+
+       status = nfsd4_decode_stateid(argp, &fallocate->falloc_stateid);
+       if (status)
+               return status;
+
+       READ_BUF(16);
+       p = xdr_decode_hyper(p, &fallocate->falloc_offset);
+       xdr_decode_hyper(p, &fallocate->falloc_length);
+
+       DECODE_TAIL;
+}
+
 static __be32
 nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
 {
@@ -1604,7 +1621,7 @@ static nfsd4_dec nfsd4_dec_ops[] = {
        [OP_RECLAIM_COMPLETE]   = (nfsd4_dec)nfsd4_decode_reclaim_complete,
 
        /* new operations for NFSv4.2 */
-       [OP_ALLOCATE]           = (nfsd4_dec)nfsd4_decode_notsupp,
+       [OP_ALLOCATE]           = (nfsd4_dec)nfsd4_decode_fallocate,
        [OP_COPY]               = (nfsd4_dec)nfsd4_decode_notsupp,
        [OP_COPY_NOTIFY]        = (nfsd4_dec)nfsd4_decode_notsupp,
        [OP_DEALLOCATE]         = (nfsd4_dec)nfsd4_decode_notsupp,
index d16076bd9a7a2cb9177fd941924337f66e57be61..f1999619d516138ff84cbeb907c2d12d3fa447e1 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/splice.h>
+#include <linux/falloc.h>
 #include <linux/fcntl.h>
 #include <linux/namei.h>
 #include <linux/delay.h>
@@ -533,6 +534,26 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
 }
 #endif
 
+__be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                          struct file *file, loff_t offset, loff_t len,
+                          int flags)
+{
+       __be32 err;
+       int error;
+
+       if (!S_ISREG(file_inode(file)->i_mode))
+               return nfserr_inval;
+
+       err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, NFSD_MAY_WRITE);
+       if (err)
+               return err;
+
+       error = vfs_fallocate(file, flags, offset, len);
+       if (!error)
+               error = commit_metadata(fhp);
+
+       return nfserrno(error);
+}
 #endif /* defined(CONFIG_NFSD_V4) */
 
 #ifdef CONFIG_NFSD_V3
index c2ff3f14e5f6146fc4d0ea72f063d32e615921e4..7ffdb144e4867b804cefaa528601dc263bd6310c 100644 (file)
@@ -54,6 +54,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *);
 #ifdef CONFIG_NFSD_V4
 __be32          nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
                    struct xdr_netobj *);
+__be32         nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
+                                   struct file *, loff_t, loff_t, int);
 #endif /* CONFIG_NFSD_V4 */
 __be32         nfsd_create(struct svc_rqst *, struct svc_fh *,
                                char *name, int len, struct iattr *attrs,
index 5720e9457f3324a29dbdd68551a8a129a6e3db6e..eeaa0d0c4f794148fc76bd2bcd32124940204886 100644 (file)
@@ -428,6 +428,13 @@ struct nfsd4_reclaim_complete {
        u32 rca_one_fs;
 };
 
+struct nfsd4_fallocate {
+       /* request */
+       stateid_t       falloc_stateid;
+       loff_t          falloc_offset;
+       u64             falloc_length;
+};
+
 struct nfsd4_seek {
        /* request */
        stateid_t       seek_stateid;
@@ -486,6 +493,7 @@ struct nfsd4_op {
                struct nfsd4_free_stateid       free_stateid;
 
                /* NFSv4.2 */
+               struct nfsd4_fallocate          allocate;
                struct nfsd4_seek               seek;
        } u;
        struct nfs4_replay *                    replay;