Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Andreas Gruenbacher and committed by
Trond Myklebust
b7fa0554 a257cdd0

+601 -6
+11
fs/Kconfig
··· 1268 1268 depends on INET 1269 1269 select LOCKD 1270 1270 select SUNRPC 1271 + select NFS_ACL_SUPPORT if NFS_V3_ACL 1271 1272 help 1272 1273 If you are connected to some other (usually local) Unix computer 1273 1274 (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing ··· 1310 1309 3 of the NFS protocol. 1311 1310 1312 1311 If unsure, say Y. 1312 + 1313 + config NFS_V3_ACL 1314 + bool "Provide client support for the NFSv3 ACL protocol extension" 1315 + depends on NFS_V3 1316 + help 1317 + Implement the NFSv3 ACL protocol extension for manipulating POSIX 1318 + Access Control Lists. The server should also be compiled with 1319 + the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option. 1320 + 1321 + If unsure, say N. 1313 1322 1314 1323 config NFS_V4 1315 1324 bool "Provide NFSv4 client support (EXPERIMENTAL)"
+1
fs/nfs/Makefile
··· 8 8 proc.o read.o symlink.o unlink.o write.o 9 9 nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o 10 10 nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o 11 + nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o 11 12 nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ 12 13 delegation.o idmap.o \ 13 14 callback.o callback_xdr.o callback_proc.o
+21
fs/nfs/dir.c
··· 75 75 .setattr = nfs_setattr, 76 76 }; 77 77 78 + #ifdef CONFIG_NFS_V3 79 + struct inode_operations nfs3_dir_inode_operations = { 80 + .create = nfs_create, 81 + .lookup = nfs_lookup, 82 + .link = nfs_link, 83 + .unlink = nfs_unlink, 84 + .symlink = nfs_symlink, 85 + .mkdir = nfs_mkdir, 86 + .rmdir = nfs_rmdir, 87 + .mknod = nfs_mknod, 88 + .rename = nfs_rename, 89 + .permission = nfs_permission, 90 + .getattr = nfs_getattr, 91 + .setattr = nfs_setattr, 92 + .listxattr = nfs3_listxattr, 93 + .getxattr = nfs3_getxattr, 94 + .setxattr = nfs3_setxattr, 95 + .removexattr = nfs3_removexattr, 96 + }; 97 + #endif /* CONFIG_NFS_V3 */ 98 + 78 99 #ifdef CONFIG_NFS_V4 79 100 80 101 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
+12
fs/nfs/file.c
··· 71 71 .setattr = nfs_setattr, 72 72 }; 73 73 74 + #ifdef CONFIG_NFS_V3 75 + struct inode_operations nfs3_file_inode_operations = { 76 + .permission = nfs_permission, 77 + .getattr = nfs_getattr, 78 + .setattr = nfs_setattr, 79 + .listxattr = nfs3_listxattr, 80 + .getxattr = nfs3_getxattr, 81 + .setxattr = nfs3_setxattr, 82 + .removexattr = nfs3_removexattr, 83 + }; 84 + #endif /* CONFIG_NFS_v3 */ 85 + 74 86 /* Hack for future NFS swap support */ 75 87 #ifndef IS_SWAPFILE 76 88 # define IS_SWAPFILE(inode) (0)
+33 -3
fs/nfs/inode.c
··· 108 108 .pipe_dir_name = "/nfs", 109 109 }; 110 110 111 + #ifdef CONFIG_NFS_V3_ACL 112 + static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; 113 + static struct rpc_version * nfsacl_version[] = { 114 + [3] = &nfsacl_version3, 115 + }; 116 + 117 + struct rpc_program nfsacl_program = { 118 + .name = "nfsacl", 119 + .number = NFS_ACL_PROGRAM, 120 + .nrvers = sizeof(nfsacl_version) / sizeof(nfsacl_version[0]), 121 + .version = nfsacl_version, 122 + .stats = &nfsacl_rpcstat, 123 + }; 124 + #endif /* CONFIG_NFS_V3_ACL */ 125 + 111 126 static inline unsigned long 112 127 nfs_fattr_to_ino_t(struct nfs_fattr *fattr) 113 128 { ··· 178 163 struct rpc_clnt *rpc = NFS_SB(sb)->client; 179 164 180 165 /* -EIO all pending I/O */ 166 + if (!IS_ERR(rpc)) 167 + rpc_killall_tasks(rpc); 168 + rpc = NFS_SB(sb)->client_acl; 181 169 if (!IS_ERR(rpc)) 182 170 rpc_killall_tasks(rpc); 183 171 } ··· 479 461 atomic_inc(&server->client->cl_count); 480 462 server->client_sys = server->client; 481 463 } 482 - 483 464 if (server->flags & NFS_MOUNT_VER3) { 465 + #ifdef CONFIG_NFS_V3_ACL 466 + if (!(server->flags & NFS_MOUNT_NOACL)) { 467 + server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); 468 + /* No errors! Assume that Sun nfsacls are supported */ 469 + if (!IS_ERR(server->client_acl)) 470 + server->caps |= NFS_CAP_ACLS; 471 + } 472 + #else 473 + server->flags &= ~NFS_MOUNT_NOACL; 474 + #endif /* CONFIG_NFS_V3_ACL */ 484 475 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) 485 476 server->namelen = NFS3_MAXNAMLEN; 486 477 sb->s_time_gran = 1; ··· 573 546 { NFS_MOUNT_NOCTO, ",nocto", "" }, 574 547 { NFS_MOUNT_NOAC, ",noac", "" }, 575 548 { NFS_MOUNT_NONLM, ",nolock", ",lock" }, 549 + { NFS_MOUNT_NOACL, ",noacl", "" }, 576 550 { 0, NULL, NULL } 577 551 }; 578 552 struct proc_nfs_info *nfs_infop; ··· 1480 1452 memset(server, 0, sizeof(struct nfs_server)); 1481 1453 /* Zero out the NFS state stuff */ 1482 1454 init_nfsv4_state(server); 1483 - server->client = server->client_sys = ERR_PTR(-EINVAL); 1455 + server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); 1484 1456 1485 1457 root = &server->fh; 1486 1458 if (data->flags & NFS_MOUNT_VER3) ··· 1541 1513 rpc_shutdown_client(server->client); 1542 1514 if (!IS_ERR(server->client_sys)) 1543 1515 rpc_shutdown_client(server->client_sys); 1516 + if (!IS_ERR(server->client_acl)) 1517 + rpc_shutdown_client(server->client_acl); 1544 1518 1545 1519 if (!(server->flags & NFS_MOUNT_NONLM)) 1546 1520 lockd_down(); /* release rpc.lockd */ ··· 1824 1794 memset(server, 0, sizeof(struct nfs_server)); 1825 1795 /* Zero out the NFS state stuff */ 1826 1796 init_nfsv4_state(server); 1827 - server->client = server->client_sys = ERR_PTR(-EINVAL); 1797 + server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); 1828 1798 1829 1799 p = nfs_copy_user_string(NULL, &data->hostname, 256); 1830 1800 if (IS_ERR(p))
+303
fs/nfs/nfs3acl.c
··· 1 + #include <linux/fs.h> 2 + #include <linux/nfs.h> 3 + #include <linux/nfs3.h> 4 + #include <linux/nfs_fs.h> 5 + #include <linux/xattr_acl.h> 6 + #include <linux/nfsacl.h> 7 + 8 + #define NFSDBG_FACILITY NFSDBG_PROC 9 + 10 + ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size) 11 + { 12 + struct inode *inode = dentry->d_inode; 13 + struct posix_acl *acl; 14 + int pos=0, len=0; 15 + 16 + # define output(s) do { \ 17 + if (pos + sizeof(s) <= size) { \ 18 + memcpy(buffer + pos, s, sizeof(s)); \ 19 + pos += sizeof(s); \ 20 + } \ 21 + len += sizeof(s); \ 22 + } while(0) 23 + 24 + acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS); 25 + if (IS_ERR(acl)) 26 + return PTR_ERR(acl); 27 + if (acl) { 28 + output("system.posix_acl_access"); 29 + posix_acl_release(acl); 30 + } 31 + 32 + if (S_ISDIR(inode->i_mode)) { 33 + acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT); 34 + if (IS_ERR(acl)) 35 + return PTR_ERR(acl); 36 + if (acl) { 37 + output("system.posix_acl_default"); 38 + posix_acl_release(acl); 39 + } 40 + } 41 + 42 + # undef output 43 + 44 + if (!buffer || len <= size) 45 + return len; 46 + return -ERANGE; 47 + } 48 + 49 + ssize_t nfs3_getxattr(struct dentry *dentry, const char *name, 50 + void *buffer, size_t size) 51 + { 52 + struct inode *inode = dentry->d_inode; 53 + struct posix_acl *acl; 54 + int type, error = 0; 55 + 56 + if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) 57 + type = ACL_TYPE_ACCESS; 58 + else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) 59 + type = ACL_TYPE_DEFAULT; 60 + else 61 + return -EOPNOTSUPP; 62 + 63 + acl = nfs3_proc_getacl(inode, type); 64 + if (IS_ERR(acl)) 65 + return PTR_ERR(acl); 66 + else if (acl) { 67 + if (type == ACL_TYPE_ACCESS && acl->a_count == 0) 68 + error = -ENODATA; 69 + else 70 + error = posix_acl_to_xattr(acl, buffer, size); 71 + posix_acl_release(acl); 72 + } else 73 + error = -ENODATA; 74 + 75 + return error; 76 + } 77 + 78 + int nfs3_setxattr(struct dentry *dentry, const char *name, 79 + const void *value, size_t size, int flags) 80 + { 81 + struct inode *inode = dentry->d_inode; 82 + struct posix_acl *acl; 83 + int type, error; 84 + 85 + if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) 86 + type = ACL_TYPE_ACCESS; 87 + else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) 88 + type = ACL_TYPE_DEFAULT; 89 + else 90 + return -EOPNOTSUPP; 91 + 92 + acl = posix_acl_from_xattr(value, size); 93 + if (IS_ERR(acl)) 94 + return PTR_ERR(acl); 95 + error = nfs3_proc_setacl(inode, type, acl); 96 + posix_acl_release(acl); 97 + 98 + return error; 99 + } 100 + 101 + int nfs3_removexattr(struct dentry *dentry, const char *name) 102 + { 103 + struct inode *inode = dentry->d_inode; 104 + int type; 105 + 106 + if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) 107 + type = ACL_TYPE_ACCESS; 108 + else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) 109 + type = ACL_TYPE_DEFAULT; 110 + else 111 + return -EOPNOTSUPP; 112 + 113 + return nfs3_proc_setacl(inode, type, NULL); 114 + } 115 + 116 + struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) 117 + { 118 + struct nfs_server *server = NFS_SERVER(inode); 119 + struct nfs_fattr fattr; 120 + struct page *pages[NFSACL_MAXPAGES] = { }; 121 + struct nfs3_getaclargs args = { 122 + .fh = NFS_FH(inode), 123 + /* The xdr layer may allocate pages here. */ 124 + .pages = pages, 125 + }; 126 + struct nfs3_getaclres res = { 127 + .fattr = &fattr, 128 + }; 129 + struct posix_acl *acl = NULL; 130 + int status, count; 131 + 132 + if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 133 + return ERR_PTR(-EOPNOTSUPP); 134 + 135 + switch (type) { 136 + case ACL_TYPE_ACCESS: 137 + args.mask = NFS_ACLCNT|NFS_ACL; 138 + break; 139 + 140 + case ACL_TYPE_DEFAULT: 141 + if (!S_ISDIR(inode->i_mode)) 142 + return NULL; 143 + args.mask = NFS_DFACLCNT|NFS_DFACL; 144 + break; 145 + 146 + default: 147 + return ERR_PTR(-EINVAL); 148 + } 149 + 150 + dprintk("NFS call getacl\n"); 151 + status = rpc_call(server->client_acl, ACLPROC3_GETACL, 152 + &args, &res, 0); 153 + dprintk("NFS reply getacl: %d\n", status); 154 + 155 + /* pages may have been allocated at the xdr layer. */ 156 + for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++) 157 + __free_page(args.pages[count]); 158 + 159 + switch (status) { 160 + case 0: 161 + status = nfs_refresh_inode(inode, &fattr); 162 + break; 163 + case -EPFNOSUPPORT: 164 + case -EPROTONOSUPPORT: 165 + dprintk("NFS_V3_ACL extension not supported; disabling\n"); 166 + server->caps &= ~NFS_CAP_ACLS; 167 + case -ENOTSUPP: 168 + status = -EOPNOTSUPP; 169 + default: 170 + goto getout; 171 + } 172 + if ((args.mask & res.mask) != args.mask) { 173 + status = -EIO; 174 + goto getout; 175 + } 176 + 177 + if (res.acl_access != NULL) { 178 + if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) { 179 + posix_acl_release(res.acl_access); 180 + res.acl_access = NULL; 181 + } 182 + } 183 + 184 + switch(type) { 185 + case ACL_TYPE_ACCESS: 186 + acl = res.acl_access; 187 + res.acl_access = NULL; 188 + break; 189 + 190 + case ACL_TYPE_DEFAULT: 191 + acl = res.acl_default; 192 + res.acl_default = NULL; 193 + } 194 + 195 + getout: 196 + posix_acl_release(res.acl_access); 197 + posix_acl_release(res.acl_default); 198 + 199 + if (status != 0) { 200 + posix_acl_release(acl); 201 + acl = ERR_PTR(status); 202 + } 203 + return acl; 204 + } 205 + 206 + static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, 207 + struct posix_acl *dfacl) 208 + { 209 + struct nfs_server *server = NFS_SERVER(inode); 210 + struct nfs_fattr fattr; 211 + struct page *pages[NFSACL_MAXPAGES] = { }; 212 + struct nfs3_setaclargs args = { 213 + .inode = inode, 214 + .mask = NFS_ACL, 215 + .acl_access = acl, 216 + .pages = pages, 217 + }; 218 + int status, count; 219 + 220 + status = -EOPNOTSUPP; 221 + if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 222 + goto out; 223 + 224 + /* We are doing this here, because XDR marshalling can only 225 + return -ENOMEM. */ 226 + status = -ENOSPC; 227 + if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES) 228 + goto out; 229 + if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES) 230 + goto out; 231 + if (S_ISDIR(inode->i_mode)) { 232 + args.mask |= NFS_DFACL; 233 + args.acl_default = dfacl; 234 + } 235 + 236 + dprintk("NFS call setacl\n"); 237 + nfs_begin_data_update(inode); 238 + status = rpc_call(server->client_acl, ACLPROC3_SETACL, 239 + &args, &fattr, 0); 240 + NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS; 241 + nfs_end_data_update(inode); 242 + dprintk("NFS reply setacl: %d\n", status); 243 + 244 + /* pages may have been allocated at the xdr layer. */ 245 + for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++) 246 + __free_page(args.pages[count]); 247 + 248 + switch (status) { 249 + case 0: 250 + status = nfs_refresh_inode(inode, &fattr); 251 + break; 252 + case -EPFNOSUPPORT: 253 + case -EPROTONOSUPPORT: 254 + dprintk("NFS_V3_ACL SETACL RPC not supported" 255 + "(will not retry)\n"); 256 + server->caps &= ~NFS_CAP_ACLS; 257 + case -ENOTSUPP: 258 + status = -EOPNOTSUPP; 259 + } 260 + out: 261 + return status; 262 + } 263 + 264 + int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl) 265 + { 266 + struct posix_acl *alloc = NULL, *dfacl = NULL; 267 + int status; 268 + 269 + if (S_ISDIR(inode->i_mode)) { 270 + switch(type) { 271 + case ACL_TYPE_ACCESS: 272 + alloc = dfacl = nfs3_proc_getacl(inode, 273 + ACL_TYPE_DEFAULT); 274 + if (IS_ERR(alloc)) 275 + goto fail; 276 + break; 277 + 278 + case ACL_TYPE_DEFAULT: 279 + dfacl = acl; 280 + alloc = acl = nfs3_proc_getacl(inode, 281 + ACL_TYPE_ACCESS); 282 + if (IS_ERR(alloc)) 283 + goto fail; 284 + break; 285 + 286 + default: 287 + return -EINVAL; 288 + } 289 + } else if (type != ACL_TYPE_ACCESS) 290 + return -EINVAL; 291 + 292 + if (acl == NULL) { 293 + alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); 294 + if (IS_ERR(alloc)) 295 + goto fail; 296 + } 297 + status = nfs3_proc_setacls(inode, acl, dfacl); 298 + posix_acl_release(alloc); 299 + return status; 300 + 301 + fail: 302 + return PTR_ERR(alloc); 303 + }
+4 -3
fs/nfs/nfs3proc.c
··· 17 17 #include <linux/nfs_page.h> 18 18 #include <linux/lockd/bind.h> 19 19 #include <linux/smp_lock.h> 20 + #include <linux/nfs_mount.h> 20 21 21 22 #define NFSDBG_FACILITY NFSDBG_PROC 22 23 ··· 46 45 nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags) 47 46 { 48 47 struct rpc_message msg = { 49 - .rpc_proc = &nfs3_procedures[proc], 48 + .rpc_proc = &clnt->cl_procinfo[proc], 50 49 .rpc_argp = argp, 51 50 .rpc_resp = resp, 52 51 }; ··· 826 825 struct nfs_rpc_ops nfs_v3_clientops = { 827 826 .version = 3, /* protocol version */ 828 827 .dentry_ops = &nfs_dentry_operations, 829 - .dir_inode_ops = &nfs_dir_inode_operations, 830 - .file_inode_ops = &nfs_file_inode_operations, 828 + .dir_inode_ops = &nfs3_dir_inode_operations, 829 + .file_inode_ops = &nfs3_file_inode_operations, 831 830 .getroot = nfs3_proc_get_root, 832 831 .getattr = nfs3_proc_getattr, 833 832 .setattr = nfs3_proc_setattr,
+147
fs/nfs/nfs3xdr.c
··· 21 21 #include <linux/nfs.h> 22 22 #include <linux/nfs3.h> 23 23 #include <linux/nfs_fs.h> 24 + #include <linux/nfsacl.h> 24 25 25 26 #define NFSDBG_FACILITY NFSDBG_XDR 26 27 ··· 79 78 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12) 80 79 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) 81 80 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) 81 + 82 + #define ACL3_getaclargs_sz (NFS3_fh_sz+1) 83 + #define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3)) 84 + #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3)) 85 + #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) 82 86 83 87 /* 84 88 * Map file type to S_IFMT bits ··· 633 627 return 0; 634 628 } 635 629 630 + #ifdef CONFIG_NFS_V3_ACL 631 + /* 632 + * Encode GETACL arguments 633 + */ 634 + static int 635 + nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p, 636 + struct nfs3_getaclargs *args) 637 + { 638 + struct rpc_auth *auth = req->rq_task->tk_auth; 639 + unsigned int replen; 640 + 641 + p = xdr_encode_fhandle(p, args->fh); 642 + *p++ = htonl(args->mask); 643 + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 644 + 645 + if (args->mask & (NFS_ACL | NFS_DFACL)) { 646 + /* Inline the page array */ 647 + replen = (RPC_REPHDRSIZE + auth->au_rslack + 648 + ACL3_getaclres_sz) << 2; 649 + xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, 650 + NFSACL_MAXPAGES << PAGE_SHIFT); 651 + } 652 + return 0; 653 + } 654 + 655 + /* 656 + * Encode SETACL arguments 657 + */ 658 + static int 659 + nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p, 660 + struct nfs3_setaclargs *args) 661 + { 662 + struct xdr_buf *buf = &req->rq_snd_buf; 663 + unsigned int base, len_in_head, len = nfsacl_size( 664 + (args->mask & NFS_ACL) ? args->acl_access : NULL, 665 + (args->mask & NFS_DFACL) ? args->acl_default : NULL); 666 + int count, err; 667 + 668 + p = xdr_encode_fhandle(p, NFS_FH(args->inode)); 669 + *p++ = htonl(args->mask); 670 + base = (char *)p - (char *)buf->head->iov_base; 671 + /* put as much of the acls into head as possible. */ 672 + len_in_head = min_t(unsigned int, buf->head->iov_len - base, len); 673 + len -= len_in_head; 674 + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + len_in_head); 675 + 676 + for (count = 0; (count << PAGE_SHIFT) < len; count++) { 677 + args->pages[count] = alloc_page(GFP_KERNEL); 678 + if (!args->pages[count]) { 679 + while (count) 680 + __free_page(args->pages[--count]); 681 + return -ENOMEM; 682 + } 683 + } 684 + xdr_encode_pages(buf, args->pages, 0, len); 685 + 686 + err = nfsacl_encode(buf, base, args->inode, 687 + (args->mask & NFS_ACL) ? 688 + args->acl_access : NULL, 1, 0); 689 + if (err > 0) 690 + err = nfsacl_encode(buf, base + err, args->inode, 691 + (args->mask & NFS_DFACL) ? 692 + args->acl_default : NULL, 1, 693 + NFS_ACL_DEFAULT); 694 + return (err > 0) ? 0 : err; 695 + } 696 + #endif /* CONFIG_NFS_V3_ACL */ 697 + 636 698 /* 637 699 * NFS XDR decode functions 638 700 */ ··· 1052 978 return 0; 1053 979 } 1054 980 981 + #ifdef CONFIG_NFS_V3_ACL 982 + /* 983 + * Decode GETACL reply 984 + */ 985 + static int 986 + nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p, 987 + struct nfs3_getaclres *res) 988 + { 989 + struct xdr_buf *buf = &req->rq_rcv_buf; 990 + int status = ntohl(*p++); 991 + struct posix_acl **acl; 992 + unsigned int *aclcnt; 993 + int err, base; 994 + 995 + if (status != 0) 996 + return -nfs_stat_to_errno(status); 997 + p = xdr_decode_post_op_attr(p, res->fattr); 998 + res->mask = ntohl(*p++); 999 + if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 1000 + return -EINVAL; 1001 + base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base; 1002 + 1003 + acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL; 1004 + aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL; 1005 + err = nfsacl_decode(buf, base, aclcnt, acl); 1006 + 1007 + acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL; 1008 + aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL; 1009 + if (err > 0) 1010 + err = nfsacl_decode(buf, base + err, aclcnt, acl); 1011 + return (err > 0) ? 0 : err; 1012 + } 1013 + 1014 + /* 1015 + * Decode setacl reply. 1016 + */ 1017 + static int 1018 + nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) 1019 + { 1020 + int status = ntohl(*p++); 1021 + 1022 + if (status) 1023 + return -nfs_stat_to_errno(status); 1024 + xdr_decode_post_op_attr(p, fattr); 1025 + return 0; 1026 + } 1027 + #endif /* CONFIG_NFS_V3_ACL */ 1028 + 1055 1029 #ifndef MAX 1056 1030 # define MAX(a, b) (((a) > (b))? (a) : (b)) 1057 1031 #endif ··· 1143 1021 .procs = nfs3_procedures 1144 1022 }; 1145 1023 1024 + #ifdef CONFIG_NFS_V3_ACL 1025 + static struct rpc_procinfo nfs3_acl_procedures[] = { 1026 + [ACLPROC3_GETACL] = { 1027 + .p_proc = ACLPROC3_GETACL, 1028 + .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs, 1029 + .p_decode = (kxdrproc_t) nfs3_xdr_getaclres, 1030 + .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2, 1031 + .p_timer = 1, 1032 + }, 1033 + [ACLPROC3_SETACL] = { 1034 + .p_proc = ACLPROC3_SETACL, 1035 + .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs, 1036 + .p_decode = (kxdrproc_t) nfs3_xdr_setaclres, 1037 + .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2, 1038 + .p_timer = 0, 1039 + }, 1040 + }; 1041 + 1042 + struct rpc_version nfsacl_version3 = { 1043 + .number = 3, 1044 + .nrprocs = sizeof(nfs3_acl_procedures)/ 1045 + sizeof(nfs3_acl_procedures[0]), 1046 + .procs = nfs3_acl_procedures, 1047 + }; 1048 + #endif /* CONFIG_NFS_V3_ACL */
+9
fs/nfs/nfsroot.c
··· 124 124 Opt_soft, Opt_hard, Opt_intr, 125 125 Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, 126 126 Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp, 127 + Opt_acl, Opt_noacl, 127 128 /* Error token */ 128 129 Opt_err 129 130 }; ··· 159 158 {Opt_udp, "udp"}, 160 159 {Opt_tcp, "proto=tcp"}, 161 160 {Opt_tcp, "tcp"}, 161 + {Opt_acl, "acl"}, 162 + {Opt_noacl, "noacl"}, 162 163 {Opt_err, NULL} 163 164 164 165 }; ··· 268 265 break; 269 266 case Opt_tcp: 270 267 nfs_data.flags |= NFS_MOUNT_TCP; 268 + break; 269 + case Opt_acl: 270 + nfs_data.flags &= ~NFS_MOUNT_NOACL; 271 + break; 272 + case Opt_noacl: 273 + nfs_data.flags |= NFS_MOUNT_NOACL; 271 274 break; 272 275 default : 273 276 return 0;
+31
include/linux/nfs_fs.h
··· 301 301 * linux/fs/nfs/file.c 302 302 */ 303 303 extern struct inode_operations nfs_file_inode_operations; 304 + #ifdef CONFIG_NFS_V3 305 + extern struct inode_operations nfs3_file_inode_operations; 306 + #endif /* CONFIG_NFS_V3 */ 304 307 extern struct file_operations nfs_file_operations; 305 308 extern struct address_space_operations nfs_file_aops; 306 309 ··· 319 316 } 320 317 321 318 /* 319 + * linux/fs/nfs/xattr.c 320 + */ 321 + #ifdef CONFIG_NFS_V3_ACL 322 + extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t); 323 + extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t); 324 + extern int nfs3_setxattr(struct dentry *, const char *, 325 + const void *, size_t, int); 326 + extern int nfs3_removexattr (struct dentry *, const char *name); 327 + #else 328 + # define nfs3_listxattr NULL 329 + # define nfs3_getxattr NULL 330 + # define nfs3_setxattr NULL 331 + # define nfs3_removexattr NULL 332 + #endif 333 + 334 + /* 322 335 * linux/fs/nfs/direct.c 323 336 */ 324 337 extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t, ··· 348 329 * linux/fs/nfs/dir.c 349 330 */ 350 331 extern struct inode_operations nfs_dir_inode_operations; 332 + #ifdef CONFIG_NFS_V3 333 + extern struct inode_operations nfs3_dir_inode_operations; 334 + #endif /* CONFIG_NFS_V3 */ 351 335 extern struct file_operations nfs_dir_operations; 352 336 extern struct dentry_operations nfs_dentry_operations; 353 337 ··· 470 448 } 471 449 472 450 extern void nfs_readdata_release(struct rpc_task *task); 451 + 452 + /* 453 + * linux/fs/nfs3proc.c 454 + */ 455 + #ifdef CONFIG_NFS_V3_ACL 456 + extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type); 457 + extern int nfs3_proc_setacl(struct inode *inode, int type, 458 + struct posix_acl *acl); 459 + #endif /* CONFIG_NFS_V3_ACL */ 473 460 474 461 /* 475 462 * linux/fs/mount_clnt.c
+1
include/linux/nfs_fs_sb.h
··· 10 10 struct nfs_server { 11 11 struct rpc_clnt * client; /* RPC client handle */ 12 12 struct rpc_clnt * client_sys; /* 2nd handle for FSINFO */ 13 + struct rpc_clnt * client_acl; /* ACL RPC client handle */ 13 14 struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ 14 15 struct backing_dev_info backing_dev_info; 15 16 int flags; /* various flags */
+1
include/linux/nfs_mount.h
··· 58 58 #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ 59 59 #define NFS_MOUNT_NONLM 0x0200 /* 3 */ 60 60 #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ 61 + #define NFS_MOUNT_NOACL 0x0800 /* 4 */ 61 62 #define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */ 62 63 #define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */ 63 64 #define NFS_MOUNT_FLAGMASK 0xFFFF
+27
include/linux/nfs_xdr.h
··· 2 2 #define _LINUX_NFS_XDR_H 3 3 4 4 #include <linux/sunrpc/xprt.h> 5 + #include <linux/nfsacl.h> 5 6 6 7 struct nfs4_fsid { 7 8 __u64 major; ··· 369 368 struct page ** pages; 370 369 }; 371 370 371 + struct nfs3_getaclargs { 372 + struct nfs_fh * fh; 373 + int mask; 374 + struct page ** pages; 375 + }; 376 + 377 + struct nfs3_setaclargs { 378 + struct inode * inode; 379 + int mask; 380 + struct posix_acl * acl_access; 381 + struct posix_acl * acl_default; 382 + struct page ** pages; 383 + }; 384 + 372 385 struct nfs_diropok { 373 386 struct nfs_fh * fh; 374 387 struct nfs_fattr * fattr; ··· 504 489 struct nfs_fattr * dir_attr; 505 490 __u32 * verf; 506 491 int plus; 492 + }; 493 + 494 + struct nfs3_getaclres { 495 + struct nfs_fattr * fattr; 496 + int mask; 497 + unsigned int acl_access_count; 498 + unsigned int acl_default_count; 499 + struct posix_acl * acl_access; 500 + struct posix_acl * acl_default; 507 501 }; 508 502 509 503 #ifdef CONFIG_NFS_V4 ··· 771 747 extern struct rpc_version nfs_version2; 772 748 extern struct rpc_version nfs_version3; 773 749 extern struct rpc_version nfs_version4; 750 + 751 + extern struct rpc_version nfsacl_version3; 752 + extern struct rpc_program nfsacl_program; 774 753 775 754 #endif