2014-10-31 20:53:53

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v3 0/3] NFSD: Add ALLOCATE and DEALLOCATE support

From: Anna Schumaker <[email protected]>

These patches add server support for the ALLOCATE and DEALLOCATE operations
part of NFS v4.2.

Changes in v3:
- Add back the do_fallocate() -> vfs_fallocate() patch
- Do Christoph's suggested cleanups to nfsd4_vfs_fallocate()

These patches and the corresponding client changes are available in the
[fallocate] branch of:

git://git.linux-nfs.org/projects/anna/linux-nfs.git


Questions? Comments? Thoughts?

Anna


Anna Schumaker (3):
VFS: Rename do_fallocate() to vfs_fallocate()
nfsd: Add ALLOCATE support
nfsd: Add DEALLOCATE support

drivers/staging/android/ashmem.c | 2 +-
fs/ioctl.c | 2 +-
fs/nfsd/nfs4proc.c | 51 ++++++++++++++++++++++++++++++++++++++++
fs/nfsd/nfs4xdr.c | 21 +++++++++++++++--
fs/nfsd/vfs.c | 20 ++++++++++++++++
fs/nfsd/vfs.h | 2 ++
fs/nfsd/xdr4.h | 9 +++++++
fs/open.c | 5 ++--
include/linux/fs.h | 2 +-
mm/madvise.c | 2 +-
10 files changed, 108 insertions(+), 8 deletions(-)

--
2.1.3



2014-10-31 20:53:53

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v3 2/3] nfsd: Add ALLOCATE support

From: Anna Schumaker <[email protected]>

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 <[email protected]>
---
fs/nfsd/nfs4proc.c | 36 ++++++++++++++++++++++++++++++++++++
fs/nfsd/nfs4xdr.c | 19 ++++++++++++++++++-
fs/nfsd/vfs.c | 20 ++++++++++++++++++++
fs/nfsd/vfs.h | 2 ++
fs/nfsd/xdr4.h | 8 ++++++++
5 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index cdeb3cf..57bfcad 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1014,6 +1014,36 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
}

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)
{
@@ -1926,6 +1956,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",
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index eeea7a9..a60cff8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1514,6 +1514,23 @@ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, str
}

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)
{
DECODE_HEAD;
@@ -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,
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 989129e..9d29631 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -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,25 @@ __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;
+
+ 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);
+
+ if (error == -ENODEV)
+ return nfserr_inval;
+ return nfserrno(error);
+}
#endif /* defined(CONFIG_NFSD_V4) */

#ifdef CONFIG_NFSD_V3
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index c2ff3f1..7ffdb14 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -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,
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 5720e94..eeaa0d0 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -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;
--
2.1.3


2014-10-31 20:53:53

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v3 3/3] nfsd: Add DEALLOCATE support

From: Anna Schumaker <[email protected]>

DEALLOCATE only returns a status value, meaning we can use the noop()
xdr encoder to reply to the client.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfsd/nfs4proc.c | 15 +++++++++++++++
fs/nfsd/nfs4xdr.c | 2 +-
fs/nfsd/xdr4.h | 1 +
3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 57bfcad..b3a9d0d 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -33,6 +33,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/file.h>
+#include <linux/falloc.h>
#include <linux/slab.h>

#include "idmap.h"
@@ -1044,6 +1045,14 @@ nfsd4_allocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
}

static __be32
+nfsd4_deallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_fallocate *fallocate)
+{
+ return nfsd4_fallocate(rqstp, cstate, fallocate,
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE);
+}
+
+static __be32
nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_seek *seek)
{
@@ -1962,6 +1971,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
.op_name = "OP_ALLOCATE",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
},
+ [OP_DEALLOCATE] = {
+ .op_func = (nfsd4op_func)nfsd4_deallocate,
+ .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
+ .op_name = "OP_DEALLOCATE",
+ .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
+ },
[OP_SEEK] = {
.op_func = (nfsd4op_func)nfsd4_seek,
.op_name = "OP_SEEK",
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a60cff8..0622d4f 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1624,7 +1624,7 @@ static nfsd4_dec nfsd4_dec_ops[] = {
[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,
+ [OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate,
[OP_IO_ADVISE] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_LAYOUTERROR] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp,
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index eeaa0d0..90a5925 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -494,6 +494,7 @@ struct nfsd4_op {

/* NFSv4.2 */
struct nfsd4_fallocate allocate;
+ struct nfsd4_fallocate deallocate;
struct nfsd4_seek seek;
} u;
struct nfs4_replay * replay;
--
2.1.3


2014-10-31 20:53:53

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v3 1/3] VFS: Rename do_fallocate() to vfs_fallocate()

From: Anna Schumaker <[email protected]>

This function needs to be exported so it can be used by the NFSD module
when responding to the new ALLOCATE and DEALLOCATE operations in NFS
v4.2. Christoph Hellwig suggested renaming the function to stay
consistent with how other vfs functions are named.

Signed-off-by: Anna Schumaker <[email protected]>
---
drivers/staging/android/ashmem.c | 2 +-
fs/ioctl.c | 2 +-
fs/open.c | 5 +++--
include/linux/fs.h | 2 +-
mm/madvise.c | 2 +-
5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index ad4f579..27eecfe 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -446,7 +446,7 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
loff_t start = range->pgstart * PAGE_SIZE;
loff_t end = (range->pgend + 1) * PAGE_SIZE;

- do_fallocate(range->asma->file,
+ vfs_fallocate(range->asma->file,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
start, end - start);
range->purged = ASHMEM_WAS_PURGED;
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 8ac3fad..0bd61421 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -443,7 +443,7 @@ int ioctl_preallocate(struct file *filp, void __user *argp)
return -EINVAL;
}

- return do_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
+ return vfs_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
}

static int file_ioctl(struct file *filp, unsigned int cmd,
diff --git a/fs/open.c b/fs/open.c
index de92c13..192c429 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -222,7 +222,7 @@ SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length)
#endif /* BITS_PER_LONG == 32 */


-int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
{
struct inode *inode = file_inode(file);
long ret;
@@ -298,6 +298,7 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
sb_end_write(inode->i_sb);
return ret;
}
+EXPORT_SYMBOL_GPL(vfs_fallocate);

SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
{
@@ -305,7 +306,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
int error = -EBADF;

if (f.file) {
- error = do_fallocate(f.file, mode, offset, len);
+ error = vfs_fallocate(f.file, mode, offset, len);
fdput(f);
}
return error;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4e41a4a..fee9914 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2057,7 +2057,7 @@ struct filename {
extern long vfs_truncate(struct path *, loff_t);
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
struct file *filp);
-extern int do_fallocate(struct file *file, int mode, loff_t offset,
+extern int vfs_fallocate(struct file *file, int mode, loff_t offset,
loff_t len);
extern long do_sys_open(int dfd, const char __user *filename, int flags,
umode_t mode);
diff --git a/mm/madvise.c b/mm/madvise.c
index 0938b30..a271adc 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -326,7 +326,7 @@ static long madvise_remove(struct vm_area_struct *vma,
*/
get_file(f);
up_read(&current->mm->mmap_sem);
- error = do_fallocate(f,
+ error = vfs_fallocate(f,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
offset, end - start);
fput(f);
--
2.1.3


2014-11-06 20:11:34

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH v3 2/3] nfsd: Add ALLOCATE support

On 11/06/2014 03:08 PM, J. Bruce Fields wrote:
> On Fri, Oct 31, 2014 at 04:53:45PM -0400, [email protected] wrote:
>> From: Anna Schumaker <[email protected]>
>>
>> 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 <[email protected]>
>> ---
>> fs/nfsd/nfs4proc.c | 36 ++++++++++++++++++++++++++++++++++++
>> fs/nfsd/nfs4xdr.c | 19 ++++++++++++++++++-
>> fs/nfsd/vfs.c | 20 ++++++++++++++++++++
>> fs/nfsd/vfs.h | 2 ++
>> fs/nfsd/xdr4.h | 8 ++++++++
>> 5 files changed, 84 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
>> index cdeb3cf..57bfcad 100644
>> --- a/fs/nfsd/nfs4proc.c
>> +++ b/fs/nfsd/nfs4proc.c
>> @@ -1014,6 +1014,36 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>> }
>>
>> 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)
>> {
>> @@ -1926,6 +1956,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",
>> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
>> index eeea7a9..a60cff8 100644
>> --- a/fs/nfsd/nfs4xdr.c
>> +++ b/fs/nfsd/nfs4xdr.c
>> @@ -1514,6 +1514,23 @@ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, str
>> }
>>
>> 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)
>> {
>> DECODE_HEAD;
>> @@ -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,
>> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
>> index 989129e..9d29631 100644
>> --- a/fs/nfsd/vfs.c
>> +++ b/fs/nfsd/vfs.c
>> @@ -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,25 @@ __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;
>> +
>> + 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);
>> +
>> + if (error == -ENODEV)
>> + return nfserr_inval;
>
> If I'm reading the code right, this is the case where we try to
> fallocate on something other than a regular file?
>
> Actually the vfs code has a note syaing filesystems may allow fallocate
> on directories. Do we? There's nothing explicit in the spec that I can
> see but I don't think it'd make sense.
>
> So how about replacing this by an explicit check for the type before the
> fallocate call?

Sure thing! I should probably check that on both client and server side.

Anna
>
> (And also add a note to the spec requiring NFS4ERR_INVAL on anything not
> a regular file.)
>
> Otherwise these patches look fine.
>
> --b.
>
>> + return nfserrno(error);
>> +}
>> #endif /* defined(CONFIG_NFSD_V4) */
>>
>> #ifdef CONFIG_NFSD_V3
>> diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
>> index c2ff3f1..7ffdb14 100644
>> --- a/fs/nfsd/vfs.h
>> +++ b/fs/nfsd/vfs.h
>> @@ -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,
>> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
>> index 5720e94..eeaa0d0 100644
>> --- a/fs/nfsd/xdr4.h
>> +++ b/fs/nfsd/xdr4.h
>> @@ -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;
>> --
>> 2.1.3
>>


2014-11-06 20:08:46

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH v3 2/3] nfsd: Add ALLOCATE support

On Fri, Oct 31, 2014 at 04:53:45PM -0400, [email protected] wrote:
> From: Anna Schumaker <[email protected]>
>
> 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 <[email protected]>
> ---
> fs/nfsd/nfs4proc.c | 36 ++++++++++++++++++++++++++++++++++++
> fs/nfsd/nfs4xdr.c | 19 ++++++++++++++++++-
> fs/nfsd/vfs.c | 20 ++++++++++++++++++++
> fs/nfsd/vfs.h | 2 ++
> fs/nfsd/xdr4.h | 8 ++++++++
> 5 files changed, 84 insertions(+), 1 deletion(-)
>
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index cdeb3cf..57bfcad 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -1014,6 +1014,36 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> }
>
> 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)
> {
> @@ -1926,6 +1956,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",
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index eeea7a9..a60cff8 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -1514,6 +1514,23 @@ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, str
> }
>
> 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)
> {
> DECODE_HEAD;
> @@ -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,
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 989129e..9d29631 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -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,25 @@ __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;
> +
> + 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);
> +
> + if (error == -ENODEV)
> + return nfserr_inval;

If I'm reading the code right, this is the case where we try to
fallocate on something other than a regular file?

Actually the vfs code has a note syaing filesystems may allow fallocate
on directories. Do we? There's nothing explicit in the spec that I can
see but I don't think it'd make sense.

So how about replacing this by an explicit check for the type before the
fallocate call?

(And also add a note to the spec requiring NFS4ERR_INVAL on anything not
a regular file.)

Otherwise these patches look fine.

--b.

> + return nfserrno(error);
> +}
> #endif /* defined(CONFIG_NFSD_V4) */
>
> #ifdef CONFIG_NFSD_V3
> diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
> index c2ff3f1..7ffdb14 100644
> --- a/fs/nfsd/vfs.h
> +++ b/fs/nfsd/vfs.h
> @@ -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,
> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> index 5720e94..eeaa0d0 100644
> --- a/fs/nfsd/xdr4.h
> +++ b/fs/nfsd/xdr4.h
> @@ -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;
> --
> 2.1.3
>