diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2005-06-22 13:16:27 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-06-22 16:07:24 -0400 |
commit | b7fa0554cf1ba6d6895cd0a5b02989a26e0bc704 (patch) | |
tree | 83eb405f3ff78c17695999df38c99484e3aee01f /fs/nfs/nfs3xdr.c | |
parent | a257cdd0e2179630d3201c32ba14d7fcb3c3a055 (diff) |
[PATCH] NFS: Add support for NFSv3 ACLs
This adds acl support fo nfs clients via the NFSACL protocol extension, by
implementing the getxattr, listxattr, setxattr, and removexattr iops for the
system.posix_acl_access and system.posix_acl_default attributes. This patch
implements a dumb version that uses no caching (and thus adds some overhead).
(Another patch in this patchset adds caching as well.)
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Acked-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs3xdr.c')
-rw-r--r-- | fs/nfs/nfs3xdr.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index a3593d47e5ab..a4437fb177f0 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/nfs.h> | 21 | #include <linux/nfs.h> |
22 | #include <linux/nfs3.h> | 22 | #include <linux/nfs3.h> |
23 | #include <linux/nfs_fs.h> | 23 | #include <linux/nfs_fs.h> |
24 | #include <linux/nfsacl.h> | ||
24 | 25 | ||
25 | #define NFSDBG_FACILITY NFSDBG_XDR | 26 | #define NFSDBG_FACILITY NFSDBG_XDR |
26 | 27 | ||
@@ -79,6 +80,11 @@ extern int nfs_stat_to_errno(int); | |||
79 | #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) | 80 | #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) |
80 | #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) | 81 | #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) |
81 | 82 | ||
83 | #define ACL3_getaclargs_sz (NFS3_fh_sz+1) | ||
84 | #define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3)) | ||
85 | #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3)) | ||
86 | #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) | ||
87 | |||
82 | /* | 88 | /* |
83 | * Map file type to S_IFMT bits | 89 | * Map file type to S_IFMT bits |
84 | */ | 90 | */ |
@@ -627,6 +633,74 @@ nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) | |||
627 | return 0; | 633 | return 0; |
628 | } | 634 | } |
629 | 635 | ||
636 | #ifdef CONFIG_NFS_V3_ACL | ||
637 | /* | ||
638 | * Encode GETACL arguments | ||
639 | */ | ||
640 | static int | ||
641 | nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p, | ||
642 | struct nfs3_getaclargs *args) | ||
643 | { | ||
644 | struct rpc_auth *auth = req->rq_task->tk_auth; | ||
645 | unsigned int replen; | ||
646 | |||
647 | p = xdr_encode_fhandle(p, args->fh); | ||
648 | *p++ = htonl(args->mask); | ||
649 | req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); | ||
650 | |||
651 | if (args->mask & (NFS_ACL | NFS_DFACL)) { | ||
652 | /* Inline the page array */ | ||
653 | replen = (RPC_REPHDRSIZE + auth->au_rslack + | ||
654 | ACL3_getaclres_sz) << 2; | ||
655 | xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, | ||
656 | NFSACL_MAXPAGES << PAGE_SHIFT); | ||
657 | } | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | * Encode SETACL arguments | ||
663 | */ | ||
664 | static int | ||
665 | nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p, | ||
666 | struct nfs3_setaclargs *args) | ||
667 | { | ||
668 | struct xdr_buf *buf = &req->rq_snd_buf; | ||
669 | unsigned int base, len_in_head, len = nfsacl_size( | ||
670 | (args->mask & NFS_ACL) ? args->acl_access : NULL, | ||
671 | (args->mask & NFS_DFACL) ? args->acl_default : NULL); | ||
672 | int count, err; | ||
673 | |||
674 | p = xdr_encode_fhandle(p, NFS_FH(args->inode)); | ||
675 | *p++ = htonl(args->mask); | ||
676 | base = (char *)p - (char *)buf->head->iov_base; | ||
677 | /* put as much of the acls into head as possible. */ | ||
678 | len_in_head = min_t(unsigned int, buf->head->iov_len - base, len); | ||
679 | len -= len_in_head; | ||
680 | req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + len_in_head); | ||
681 | |||
682 | for (count = 0; (count << PAGE_SHIFT) < len; count++) { | ||
683 | args->pages[count] = alloc_page(GFP_KERNEL); | ||
684 | if (!args->pages[count]) { | ||
685 | while (count) | ||
686 | __free_page(args->pages[--count]); | ||
687 | return -ENOMEM; | ||
688 | } | ||
689 | } | ||
690 | xdr_encode_pages(buf, args->pages, 0, len); | ||
691 | |||
692 | err = nfsacl_encode(buf, base, args->inode, | ||
693 | (args->mask & NFS_ACL) ? | ||
694 | args->acl_access : NULL, 1, 0); | ||
695 | if (err > 0) | ||
696 | err = nfsacl_encode(buf, base + err, args->inode, | ||
697 | (args->mask & NFS_DFACL) ? | ||
698 | args->acl_default : NULL, 1, | ||
699 | NFS_ACL_DEFAULT); | ||
700 | return (err > 0) ? 0 : err; | ||
701 | } | ||
702 | #endif /* CONFIG_NFS_V3_ACL */ | ||
703 | |||
630 | /* | 704 | /* |
631 | * NFS XDR decode functions | 705 | * NFS XDR decode functions |
632 | */ | 706 | */ |
@@ -978,6 +1052,54 @@ nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) | |||
978 | return 0; | 1052 | return 0; |
979 | } | 1053 | } |
980 | 1054 | ||
1055 | #ifdef CONFIG_NFS_V3_ACL | ||
1056 | /* | ||
1057 | * Decode GETACL reply | ||
1058 | */ | ||
1059 | static int | ||
1060 | nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p, | ||
1061 | struct nfs3_getaclres *res) | ||
1062 | { | ||
1063 | struct xdr_buf *buf = &req->rq_rcv_buf; | ||
1064 | int status = ntohl(*p++); | ||
1065 | struct posix_acl **acl; | ||
1066 | unsigned int *aclcnt; | ||
1067 | int err, base; | ||
1068 | |||
1069 | if (status != 0) | ||
1070 | return -nfs_stat_to_errno(status); | ||
1071 | p = xdr_decode_post_op_attr(p, res->fattr); | ||
1072 | res->mask = ntohl(*p++); | ||
1073 | if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) | ||
1074 | return -EINVAL; | ||
1075 | base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base; | ||
1076 | |||
1077 | acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL; | ||
1078 | aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL; | ||
1079 | err = nfsacl_decode(buf, base, aclcnt, acl); | ||
1080 | |||
1081 | acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL; | ||
1082 | aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL; | ||
1083 | if (err > 0) | ||
1084 | err = nfsacl_decode(buf, base + err, aclcnt, acl); | ||
1085 | return (err > 0) ? 0 : err; | ||
1086 | } | ||
1087 | |||
1088 | /* | ||
1089 | * Decode setacl reply. | ||
1090 | */ | ||
1091 | static int | ||
1092 | nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) | ||
1093 | { | ||
1094 | int status = ntohl(*p++); | ||
1095 | |||
1096 | if (status) | ||
1097 | return -nfs_stat_to_errno(status); | ||
1098 | xdr_decode_post_op_attr(p, fattr); | ||
1099 | return 0; | ||
1100 | } | ||
1101 | #endif /* CONFIG_NFS_V3_ACL */ | ||
1102 | |||
981 | #ifndef MAX | 1103 | #ifndef MAX |
982 | # define MAX(a, b) (((a) > (b))? (a) : (b)) | 1104 | # define MAX(a, b) (((a) > (b))? (a) : (b)) |
983 | #endif | 1105 | #endif |
@@ -1021,3 +1143,28 @@ struct rpc_version nfs_version3 = { | |||
1021 | .procs = nfs3_procedures | 1143 | .procs = nfs3_procedures |
1022 | }; | 1144 | }; |
1023 | 1145 | ||
1146 | #ifdef CONFIG_NFS_V3_ACL | ||
1147 | static struct rpc_procinfo nfs3_acl_procedures[] = { | ||
1148 | [ACLPROC3_GETACL] = { | ||
1149 | .p_proc = ACLPROC3_GETACL, | ||
1150 | .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs, | ||
1151 | .p_decode = (kxdrproc_t) nfs3_xdr_getaclres, | ||
1152 | .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2, | ||
1153 | .p_timer = 1, | ||
1154 | }, | ||
1155 | [ACLPROC3_SETACL] = { | ||
1156 | .p_proc = ACLPROC3_SETACL, | ||
1157 | .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs, | ||
1158 | .p_decode = (kxdrproc_t) nfs3_xdr_setaclres, | ||
1159 | .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2, | ||
1160 | .p_timer = 0, | ||
1161 | }, | ||
1162 | }; | ||
1163 | |||
1164 | struct rpc_version nfsacl_version3 = { | ||
1165 | .number = 3, | ||
1166 | .nrprocs = sizeof(nfs3_acl_procedures)/ | ||
1167 | sizeof(nfs3_acl_procedures[0]), | ||
1168 | .procs = nfs3_acl_procedures, | ||
1169 | }; | ||
1170 | #endif /* CONFIG_NFS_V3_ACL */ | ||