diff options
-rw-r--r-- | fs/nfsd/nfs4proc.c | 49 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 36 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 14 | ||||
-rw-r--r-- | include/linux/nfs4.h | 5 |
4 files changed, 102 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 5e0dc528a0e8..cdeb3cfd6f32 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -1013,6 +1013,49 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
1013 | return status; | 1013 | return status; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static __be32 | ||
1017 | nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
1018 | struct nfsd4_seek *seek) | ||
1019 | { | ||
1020 | int whence; | ||
1021 | __be32 status; | ||
1022 | struct file *file; | ||
1023 | |||
1024 | status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate, | ||
1025 | &seek->seek_stateid, | ||
1026 | RD_STATE, &file); | ||
1027 | if (status) { | ||
1028 | dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n"); | ||
1029 | return status; | ||
1030 | } | ||
1031 | |||
1032 | switch (seek->seek_whence) { | ||
1033 | case NFS4_CONTENT_DATA: | ||
1034 | whence = SEEK_DATA; | ||
1035 | break; | ||
1036 | case NFS4_CONTENT_HOLE: | ||
1037 | whence = SEEK_HOLE; | ||
1038 | break; | ||
1039 | default: | ||
1040 | status = nfserr_union_notsupp; | ||
1041 | goto out; | ||
1042 | } | ||
1043 | |||
1044 | /* | ||
1045 | * Note: This call does change file->f_pos, but nothing in NFSD | ||
1046 | * should ever file->f_pos. | ||
1047 | */ | ||
1048 | seek->seek_pos = vfs_llseek(file, seek->seek_offset, whence); | ||
1049 | if (seek->seek_pos < 0) | ||
1050 | status = nfserrno(seek->seek_pos); | ||
1051 | else if (seek->seek_pos >= i_size_read(file_inode(file))) | ||
1052 | seek->seek_eof = true; | ||
1053 | |||
1054 | out: | ||
1055 | fput(file); | ||
1056 | return status; | ||
1057 | } | ||
1058 | |||
1016 | /* This routine never returns NFS_OK! If there are no other errors, it | 1059 | /* This routine never returns NFS_OK! If there are no other errors, it |
1017 | * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the | 1060 | * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the |
1018 | * attributes matched. VERIFY is implemented by mapping NFSERR_SAME | 1061 | * attributes matched. VERIFY is implemented by mapping NFSERR_SAME |
@@ -1881,6 +1924,12 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1881 | .op_get_currentstateid = (stateid_getter)nfsd4_get_freestateid, | 1924 | .op_get_currentstateid = (stateid_getter)nfsd4_get_freestateid, |
1882 | .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, | 1925 | .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, |
1883 | }, | 1926 | }, |
1927 | |||
1928 | /* NFSv4.2 operations */ | ||
1929 | [OP_SEEK] = { | ||
1930 | .op_func = (nfsd4op_func)nfsd4_seek, | ||
1931 | .op_name = "OP_SEEK", | ||
1932 | }, | ||
1884 | }; | 1933 | }; |
1885 | 1934 | ||
1886 | int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1935 | int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op) |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 0311baebd7d3..7ec646380005 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1514,6 +1514,22 @@ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, str | |||
1514 | } | 1514 | } |
1515 | 1515 | ||
1516 | static __be32 | 1516 | static __be32 |
1517 | nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek) | ||
1518 | { | ||
1519 | DECODE_HEAD; | ||
1520 | |||
1521 | status = nfsd4_decode_stateid(argp, &seek->seek_stateid); | ||
1522 | if (status) | ||
1523 | return status; | ||
1524 | |||
1525 | READ_BUF(8 + 4); | ||
1526 | p = xdr_decode_hyper(p, &seek->seek_offset); | ||
1527 | seek->seek_whence = be32_to_cpup(p); | ||
1528 | |||
1529 | DECODE_TAIL; | ||
1530 | } | ||
1531 | |||
1532 | static __be32 | ||
1517 | nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p) | 1533 | nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p) |
1518 | { | 1534 | { |
1519 | return nfs_ok; | 1535 | return nfs_ok; |
@@ -1598,7 +1614,7 @@ static nfsd4_dec nfsd4_dec_ops[] = { | |||
1598 | [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_notsupp, | 1614 | [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_notsupp, |
1599 | [OP_OFFLOAD_STATUS] = (nfsd4_dec)nfsd4_decode_notsupp, | 1615 | [OP_OFFLOAD_STATUS] = (nfsd4_dec)nfsd4_decode_notsupp, |
1600 | [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_notsupp, | 1616 | [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_notsupp, |
1601 | [OP_SEEK] = (nfsd4_dec)nfsd4_decode_notsupp, | 1617 | [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek, |
1602 | [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp, | 1618 | [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp, |
1603 | }; | 1619 | }; |
1604 | 1620 | ||
@@ -3766,6 +3782,22 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3766 | } | 3782 | } |
3767 | 3783 | ||
3768 | static __be32 | 3784 | static __be32 |
3785 | nfsd4_encode_seek(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
3786 | struct nfsd4_seek *seek) | ||
3787 | { | ||
3788 | __be32 *p; | ||
3789 | |||
3790 | if (nfserr) | ||
3791 | return nfserr; | ||
3792 | |||
3793 | p = xdr_reserve_space(&resp->xdr, 4 + 8); | ||
3794 | *p++ = cpu_to_be32(seek->seek_eof); | ||
3795 | p = xdr_encode_hyper(p, seek->seek_pos); | ||
3796 | |||
3797 | return nfserr; | ||
3798 | } | ||
3799 | |||
3800 | static __be32 | ||
3769 | nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) | 3801 | nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) |
3770 | { | 3802 | { |
3771 | return nfserr; | 3803 | return nfserr; |
@@ -3849,7 +3881,7 @@ static nfsd4_enc nfsd4_enc_ops[] = { | |||
3849 | [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop, | 3881 | [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop, |
3850 | [OP_OFFLOAD_STATUS] = (nfsd4_enc)nfsd4_encode_noop, | 3882 | [OP_OFFLOAD_STATUS] = (nfsd4_enc)nfsd4_encode_noop, |
3851 | [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_noop, | 3883 | [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_noop, |
3852 | [OP_SEEK] = (nfsd4_enc)nfsd4_encode_noop, | 3884 | [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek, |
3853 | [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop, | 3885 | [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop, |
3854 | }; | 3886 | }; |
3855 | 3887 | ||
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 465e7799742a..5720e9457f33 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -428,6 +428,17 @@ struct nfsd4_reclaim_complete { | |||
428 | u32 rca_one_fs; | 428 | u32 rca_one_fs; |
429 | }; | 429 | }; |
430 | 430 | ||
431 | struct nfsd4_seek { | ||
432 | /* request */ | ||
433 | stateid_t seek_stateid; | ||
434 | loff_t seek_offset; | ||
435 | u32 seek_whence; | ||
436 | |||
437 | /* response */ | ||
438 | u32 seek_eof; | ||
439 | loff_t seek_pos; | ||
440 | }; | ||
441 | |||
431 | struct nfsd4_op { | 442 | struct nfsd4_op { |
432 | int opnum; | 443 | int opnum; |
433 | __be32 status; | 444 | __be32 status; |
@@ -473,6 +484,9 @@ struct nfsd4_op { | |||
473 | struct nfsd4_reclaim_complete reclaim_complete; | 484 | struct nfsd4_reclaim_complete reclaim_complete; |
474 | struct nfsd4_test_stateid test_stateid; | 485 | struct nfsd4_test_stateid test_stateid; |
475 | struct nfsd4_free_stateid free_stateid; | 486 | struct nfsd4_free_stateid free_stateid; |
487 | |||
488 | /* NFSv4.2 */ | ||
489 | struct nfsd4_seek seek; | ||
476 | } u; | 490 | } u; |
477 | struct nfs4_replay * replay; | 491 | struct nfs4_replay * replay; |
478 | }; | 492 | }; |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index cf38224c4fa0..026b0c042c40 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -550,4 +550,9 @@ struct nfs4_deviceid { | |||
550 | char data[NFS4_DEVICEID4_SIZE]; | 550 | char data[NFS4_DEVICEID4_SIZE]; |
551 | }; | 551 | }; |
552 | 552 | ||
553 | enum data_content4 { | ||
554 | NFS4_CONTENT_DATA = 0, | ||
555 | NFS4_CONTENT_HOLE = 1, | ||
556 | }; | ||
557 | |||
553 | #endif | 558 | #endif |