diff options
author | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2014-11-07 14:44:26 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-11-07 16:19:49 -0500 |
commit | 95d871f03cae6b49de040265cf88cbe2a16b9f05 (patch) | |
tree | 911d8bed4226e4e87e1411145c7fe0e275dea545 /fs/nfsd | |
parent | 72c72bdf7bf53353d2d8e055194d27f0128be92b (diff) |
nfsd: Add ALLOCATE support
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>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 36 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 19 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 21 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 2 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 8 |
5 files changed, 85 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 0beb023f25ac..a261f1800922 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, | |||
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static __be32 | 1016 | static __be32 |
1017 | nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
1018 | struct nfsd4_fallocate *fallocate, int flags) | ||
1019 | { | ||
1020 | __be32 status = nfserr_notsupp; | ||
1021 | struct file *file; | ||
1022 | |||
1023 | status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate, | ||
1024 | &fallocate->falloc_stateid, | ||
1025 | WR_STATE, &file); | ||
1026 | if (status != nfs_ok) { | ||
1027 | dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n"); | ||
1028 | return status; | ||
1029 | } | ||
1030 | |||
1031 | status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file, | ||
1032 | fallocate->falloc_offset, | ||
1033 | fallocate->falloc_length, | ||
1034 | flags); | ||
1035 | fput(file); | ||
1036 | return status; | ||
1037 | } | ||
1038 | |||
1039 | static __be32 | ||
1040 | nfsd4_allocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
1041 | struct nfsd4_fallocate *fallocate) | ||
1042 | { | ||
1043 | return nfsd4_fallocate(rqstp, cstate, fallocate, 0); | ||
1044 | } | ||
1045 | |||
1046 | static __be32 | ||
1017 | nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 1047 | nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
1018 | struct nfsd4_seek *seek) | 1048 | struct nfsd4_seek *seek) |
1019 | { | 1049 | { |
@@ -1929,6 +1959,12 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1929 | }, | 1959 | }, |
1930 | 1960 | ||
1931 | /* NFSv4.2 operations */ | 1961 | /* NFSv4.2 operations */ |
1962 | [OP_ALLOCATE] = { | ||
1963 | .op_func = (nfsd4op_func)nfsd4_allocate, | ||
1964 | .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, | ||
1965 | .op_name = "OP_ALLOCATE", | ||
1966 | .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, | ||
1967 | }, | ||
1932 | [OP_SEEK] = { | 1968 | [OP_SEEK] = { |
1933 | .op_func = (nfsd4op_func)nfsd4_seek, | 1969 | .op_func = (nfsd4op_func)nfsd4_seek, |
1934 | .op_name = "OP_SEEK", | 1970 | .op_name = "OP_SEEK", |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index eeea7a90eb87..a60cff86fc28 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 | |||
1514 | } | 1514 | } |
1515 | 1515 | ||
1516 | static __be32 | 1516 | static __be32 |
1517 | nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp, | ||
1518 | struct nfsd4_fallocate *fallocate) | ||
1519 | { | ||
1520 | DECODE_HEAD; | ||
1521 | |||
1522 | status = nfsd4_decode_stateid(argp, &fallocate->falloc_stateid); | ||
1523 | if (status) | ||
1524 | return status; | ||
1525 | |||
1526 | READ_BUF(16); | ||
1527 | p = xdr_decode_hyper(p, &fallocate->falloc_offset); | ||
1528 | xdr_decode_hyper(p, &fallocate->falloc_length); | ||
1529 | |||
1530 | DECODE_TAIL; | ||
1531 | } | ||
1532 | |||
1533 | static __be32 | ||
1517 | nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek) | 1534 | nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek) |
1518 | { | 1535 | { |
1519 | DECODE_HEAD; | 1536 | DECODE_HEAD; |
@@ -1604,7 +1621,7 @@ static nfsd4_dec nfsd4_dec_ops[] = { | |||
1604 | [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, | 1621 | [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, |
1605 | 1622 | ||
1606 | /* new operations for NFSv4.2 */ | 1623 | /* new operations for NFSv4.2 */ |
1607 | [OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_notsupp, | 1624 | [OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate, |
1608 | [OP_COPY] = (nfsd4_dec)nfsd4_decode_notsupp, | 1625 | [OP_COPY] = (nfsd4_dec)nfsd4_decode_notsupp, |
1609 | [OP_COPY_NOTIFY] = (nfsd4_dec)nfsd4_decode_notsupp, | 1626 | [OP_COPY_NOTIFY] = (nfsd4_dec)nfsd4_decode_notsupp, |
1610 | [OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_notsupp, | 1627 | [OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_notsupp, |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index d16076bd9a7a..f1999619d516 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/file.h> | 17 | #include <linux/file.h> |
18 | #include <linux/splice.h> | 18 | #include <linux/splice.h> |
19 | #include <linux/falloc.h> | ||
19 | #include <linux/fcntl.h> | 20 | #include <linux/fcntl.h> |
20 | #include <linux/namei.h> | 21 | #include <linux/namei.h> |
21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
@@ -533,6 +534,26 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
533 | } | 534 | } |
534 | #endif | 535 | #endif |
535 | 536 | ||
537 | __be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp, | ||
538 | struct file *file, loff_t offset, loff_t len, | ||
539 | int flags) | ||
540 | { | ||
541 | __be32 err; | ||
542 | int error; | ||
543 | |||
544 | if (!S_ISREG(file_inode(file)->i_mode)) | ||
545 | return nfserr_inval; | ||
546 | |||
547 | err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, NFSD_MAY_WRITE); | ||
548 | if (err) | ||
549 | return err; | ||
550 | |||
551 | error = vfs_fallocate(file, flags, offset, len); | ||
552 | if (!error) | ||
553 | error = commit_metadata(fhp); | ||
554 | |||
555 | return nfserrno(error); | ||
556 | } | ||
536 | #endif /* defined(CONFIG_NFSD_V4) */ | 557 | #endif /* defined(CONFIG_NFSD_V4) */ |
537 | 558 | ||
538 | #ifdef CONFIG_NFSD_V3 | 559 | #ifdef CONFIG_NFSD_V3 |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index c2ff3f14e5f6..7ffdb144e486 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
@@ -54,6 +54,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *); | |||
54 | #ifdef CONFIG_NFSD_V4 | 54 | #ifdef CONFIG_NFSD_V4 |
55 | __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, | 55 | __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, |
56 | struct xdr_netobj *); | 56 | struct xdr_netobj *); |
57 | __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *, | ||
58 | struct file *, loff_t, loff_t, int); | ||
57 | #endif /* CONFIG_NFSD_V4 */ | 59 | #endif /* CONFIG_NFSD_V4 */ |
58 | __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, | 60 | __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, |
59 | char *name, int len, struct iattr *attrs, | 61 | char *name, int len, struct iattr *attrs, |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 5720e9457f33..eeaa0d0c4f79 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -428,6 +428,13 @@ struct nfsd4_reclaim_complete { | |||
428 | u32 rca_one_fs; | 428 | u32 rca_one_fs; |
429 | }; | 429 | }; |
430 | 430 | ||
431 | struct nfsd4_fallocate { | ||
432 | /* request */ | ||
433 | stateid_t falloc_stateid; | ||
434 | loff_t falloc_offset; | ||
435 | u64 falloc_length; | ||
436 | }; | ||
437 | |||
431 | struct nfsd4_seek { | 438 | struct nfsd4_seek { |
432 | /* request */ | 439 | /* request */ |
433 | stateid_t seek_stateid; | 440 | stateid_t seek_stateid; |
@@ -486,6 +493,7 @@ struct nfsd4_op { | |||
486 | struct nfsd4_free_stateid free_stateid; | 493 | struct nfsd4_free_stateid free_stateid; |
487 | 494 | ||
488 | /* NFSv4.2 */ | 495 | /* NFSv4.2 */ |
496 | struct nfsd4_fallocate allocate; | ||
489 | struct nfsd4_seek seek; | 497 | struct nfsd4_seek seek; |
490 | } u; | 498 | } u; |
491 | struct nfs4_replay * replay; | 499 | struct nfs4_replay * replay; |