diff options
50 files changed, 1550 insertions, 542 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 13ca196385f5..b5e80b0af315 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
| @@ -104,6 +104,15 @@ config NFS_V4_1 | |||
| 104 | 104 | ||
| 105 | If unsure, say N. | 105 | If unsure, say N. |
| 106 | 106 | ||
| 107 | config NFS_V4_2 | ||
| 108 | bool "NFS client support for NFSv4.2" | ||
| 109 | depends on NFS_V4_1 | ||
| 110 | help | ||
| 111 | This option enables support for minor version 2 of the NFSv4 protocol | ||
| 112 | in the kernel's NFS client. | ||
| 113 | |||
| 114 | If unsure, say N. | ||
| 115 | |||
| 107 | config PNFS_FILE_LAYOUT | 116 | config PNFS_FILE_LAYOUT |
| 108 | tristate | 117 | tristate |
| 109 | depends on NFS_V4_1 | 118 | depends on NFS_V4_1 |
| @@ -131,6 +140,11 @@ config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN | |||
| 131 | If the NFS client is unchanged from the upstream kernel, this | 140 | If the NFS client is unchanged from the upstream kernel, this |
| 132 | option should be set to the default "kernel.org". | 141 | option should be set to the default "kernel.org". |
| 133 | 142 | ||
| 143 | config NFS_V4_SECURITY_LABEL | ||
| 144 | bool | ||
| 145 | depends on NFS_V4_2 && SECURITY | ||
| 146 | default y | ||
| 147 | |||
| 134 | config ROOT_NFS | 148 | config ROOT_NFS |
| 135 | bool "Root file system on NFS" | 149 | bool "Root file system on NFS" |
| 136 | depends on NFS_FS=y && IP_PNP | 150 | depends on NFS_FS=y && IP_PNP |
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index cce2c057bd2d..e0bb048e9576 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
| @@ -6,8 +6,7 @@ obj-$(CONFIG_NFS_FS) += nfs.o | |||
| 6 | 6 | ||
| 7 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ | 7 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ |
| 8 | direct.o pagelist.o read.o symlink.o unlink.o \ | 8 | direct.o pagelist.o read.o symlink.o unlink.o \ |
| 9 | write.o namespace.o mount_clnt.o \ | 9 | write.o namespace.o mount_clnt.o |
| 10 | dns_resolve.o cache_lib.o | ||
| 11 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o | 10 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o |
| 12 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 11 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
| 13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o | 12 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o |
| @@ -22,7 +21,8 @@ nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o | |||
| 22 | obj-$(CONFIG_NFS_V4) += nfsv4.o | 21 | obj-$(CONFIG_NFS_V4) += nfsv4.o |
| 23 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ | 22 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ |
| 24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ | 23 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ |
| 25 | nfs4namespace.o nfs4getroot.o nfs4client.o | 24 | nfs4namespace.o nfs4getroot.o nfs4client.o dns_resolve.o |
| 25 | nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o | ||
| 26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o | 26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o |
| 27 | nfsv4-$(CONFIG_NFS_V4_1) += nfs4session.o pnfs.o pnfs_dev.o | 27 | nfsv4-$(CONFIG_NFS_V4_1) += nfs4session.o pnfs.o pnfs_dev.o |
| 28 | 28 | ||
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 434b93ec0970..e242bbf72972 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
| @@ -1089,9 +1089,10 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh, | |||
| 1089 | dev->pgbase = 0; | 1089 | dev->pgbase = 0; |
| 1090 | dev->pglen = PAGE_SIZE * max_pages; | 1090 | dev->pglen = PAGE_SIZE * max_pages; |
| 1091 | dev->mincount = 0; | 1091 | dev->mincount = 0; |
| 1092 | dev->maxcount = max_resp_sz - nfs41_maxgetdevinfo_overhead; | ||
| 1092 | 1093 | ||
| 1093 | dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data); | 1094 | dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data); |
| 1094 | rc = nfs4_proc_getdeviceinfo(server, dev); | 1095 | rc = nfs4_proc_getdeviceinfo(server, dev, NULL); |
| 1095 | dprintk("%s getdevice info returns %d\n", __func__, rc); | 1096 | dprintk("%s getdevice info returns %d\n", __func__, rc); |
| 1096 | if (rc) { | 1097 | if (rc) { |
| 1097 | rv = ERR_PTR(rc); | 1098 | rv = ERR_PTR(rc); |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index da6a43d19aa3..67cd73213168 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
| @@ -281,6 +281,7 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct n | |||
| 281 | ret = nfs4_callback_up_net(serv, net); | 281 | ret = nfs4_callback_up_net(serv, net); |
| 282 | break; | 282 | break; |
| 283 | case 1: | 283 | case 1: |
| 284 | case 2: | ||
| 284 | ret = nfs41_callback_up_net(serv, net); | 285 | ret = nfs41_callback_up_net(serv, net); |
| 285 | break; | 286 | break; |
| 286 | default: | 287 | default: |
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index efd54f0a4c46..84326e9fb47a 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
| @@ -32,6 +32,8 @@ enum nfs4_callback_opnum { | |||
| 32 | OP_CB_WANTS_CANCELLED = 12, | 32 | OP_CB_WANTS_CANCELLED = 12, |
| 33 | OP_CB_NOTIFY_LOCK = 13, | 33 | OP_CB_NOTIFY_LOCK = 13, |
| 34 | OP_CB_NOTIFY_DEVICEID = 14, | 34 | OP_CB_NOTIFY_DEVICEID = 14, |
| 35 | /* Callback operations new to NFSv4.2 */ | ||
| 36 | OP_CB_OFFLOAD = 15, | ||
| 35 | OP_CB_ILLEGAL = 10044, | 37 | OP_CB_ILLEGAL = 10044, |
| 36 | }; | 38 | }; |
| 37 | 39 | ||
| @@ -39,6 +41,7 @@ struct cb_process_state { | |||
| 39 | __be32 drc_status; | 41 | __be32 drc_status; |
| 40 | struct nfs_client *clp; | 42 | struct nfs_client *clp; |
| 41 | u32 slotid; | 43 | u32 slotid; |
| 44 | u32 minorversion; | ||
| 42 | struct net *net; | 45 | struct net *net; |
| 43 | }; | 46 | }; |
| 44 | 47 | ||
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 0bc27684ebfa..e6ebc4c38c81 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
| @@ -406,7 +406,8 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args, | |||
| 406 | int i; | 406 | int i; |
| 407 | __be32 status = htonl(NFS4ERR_BADSESSION); | 407 | __be32 status = htonl(NFS4ERR_BADSESSION); |
| 408 | 408 | ||
| 409 | clp = nfs4_find_client_sessionid(cps->net, args->csa_addr, &args->csa_sessionid); | 409 | clp = nfs4_find_client_sessionid(cps->net, args->csa_addr, |
| 410 | &args->csa_sessionid, cps->minorversion); | ||
| 410 | if (clp == NULL) | 411 | if (clp == NULL) |
| 411 | goto out; | 412 | goto out; |
| 412 | 413 | ||
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index a35582c9d444..f4ccfe6521ec 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
| @@ -166,9 +166,9 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound | |||
| 166 | if (unlikely(p == NULL)) | 166 | if (unlikely(p == NULL)) |
| 167 | return htonl(NFS4ERR_RESOURCE); | 167 | return htonl(NFS4ERR_RESOURCE); |
| 168 | hdr->minorversion = ntohl(*p++); | 168 | hdr->minorversion = ntohl(*p++); |
| 169 | /* Check minor version is zero or one. */ | 169 | /* Check for minor version support */ |
| 170 | if (hdr->minorversion <= 1) { | 170 | if (hdr->minorversion <= NFS4_MAX_MINOR_VERSION) { |
| 171 | hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 */ | 171 | hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 and v4.2 */ |
| 172 | } else { | 172 | } else { |
| 173 | pr_warn_ratelimited("NFS: %s: NFSv4 server callback with " | 173 | pr_warn_ratelimited("NFS: %s: NFSv4 server callback with " |
| 174 | "illegal minor version %u!\n", | 174 | "illegal minor version %u!\n", |
| @@ -786,6 +786,26 @@ static void nfs4_cb_free_slot(struct cb_process_state *cps) | |||
| 786 | } | 786 | } |
| 787 | #endif /* CONFIG_NFS_V4_1 */ | 787 | #endif /* CONFIG_NFS_V4_1 */ |
| 788 | 788 | ||
| 789 | #ifdef CONFIG_NFS_V4_2 | ||
| 790 | static __be32 | ||
| 791 | preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op) | ||
| 792 | { | ||
| 793 | __be32 status = preprocess_nfs41_op(nop, op_nr, op); | ||
| 794 | if (status != htonl(NFS4ERR_OP_ILLEGAL)) | ||
| 795 | return status; | ||
| 796 | |||
| 797 | if (op_nr == OP_CB_OFFLOAD) | ||
| 798 | return htonl(NFS4ERR_NOTSUPP); | ||
| 799 | return htonl(NFS4ERR_OP_ILLEGAL); | ||
| 800 | } | ||
| 801 | #else /* CONFIG_NFS_V4_2 */ | ||
| 802 | static __be32 | ||
| 803 | preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op) | ||
| 804 | { | ||
| 805 | return htonl(NFS4ERR_MINOR_VERS_MISMATCH); | ||
| 806 | } | ||
| 807 | #endif /* CONFIG_NFS_V4_2 */ | ||
| 808 | |||
| 789 | static __be32 | 809 | static __be32 |
| 790 | preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) | 810 | preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) |
| 791 | { | 811 | { |
| @@ -801,8 +821,7 @@ preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) | |||
| 801 | return htonl(NFS_OK); | 821 | return htonl(NFS_OK); |
| 802 | } | 822 | } |
| 803 | 823 | ||
| 804 | static __be32 process_op(uint32_t minorversion, int nop, | 824 | static __be32 process_op(int nop, struct svc_rqst *rqstp, |
| 805 | struct svc_rqst *rqstp, | ||
| 806 | struct xdr_stream *xdr_in, void *argp, | 825 | struct xdr_stream *xdr_in, void *argp, |
| 807 | struct xdr_stream *xdr_out, void *resp, | 826 | struct xdr_stream *xdr_out, void *resp, |
| 808 | struct cb_process_state *cps) | 827 | struct cb_process_state *cps) |
| @@ -819,10 +838,22 @@ static __be32 process_op(uint32_t minorversion, int nop, | |||
| 819 | return status; | 838 | return status; |
| 820 | 839 | ||
| 821 | dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", | 840 | dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", |
| 822 | __func__, minorversion, nop, op_nr); | 841 | __func__, cps->minorversion, nop, op_nr); |
| 842 | |||
| 843 | switch (cps->minorversion) { | ||
| 844 | case 0: | ||
| 845 | status = preprocess_nfs4_op(op_nr, &op); | ||
| 846 | break; | ||
| 847 | case 1: | ||
| 848 | status = preprocess_nfs41_op(nop, op_nr, &op); | ||
| 849 | break; | ||
| 850 | case 2: | ||
| 851 | status = preprocess_nfs42_op(nop, op_nr, &op); | ||
| 852 | break; | ||
| 853 | default: | ||
| 854 | status = htonl(NFS4ERR_MINOR_VERS_MISMATCH); | ||
| 855 | } | ||
| 823 | 856 | ||
| 824 | status = minorversion ? preprocess_nfs41_op(nop, op_nr, &op) : | ||
| 825 | preprocess_nfs4_op(op_nr, &op); | ||
| 826 | if (status == htonl(NFS4ERR_OP_ILLEGAL)) | 857 | if (status == htonl(NFS4ERR_OP_ILLEGAL)) |
| 827 | op_nr = OP_CB_ILLEGAL; | 858 | op_nr = OP_CB_ILLEGAL; |
| 828 | if (status) | 859 | if (status) |
| @@ -885,14 +916,15 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
| 885 | return rpc_drop_reply; | 916 | return rpc_drop_reply; |
| 886 | } | 917 | } |
| 887 | 918 | ||
| 919 | cps.minorversion = hdr_arg.minorversion; | ||
| 888 | hdr_res.taglen = hdr_arg.taglen; | 920 | hdr_res.taglen = hdr_arg.taglen; |
| 889 | hdr_res.tag = hdr_arg.tag; | 921 | hdr_res.tag = hdr_arg.tag; |
| 890 | if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) | 922 | if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) |
| 891 | return rpc_system_err; | 923 | return rpc_system_err; |
| 892 | 924 | ||
| 893 | while (status == 0 && nops != hdr_arg.nops) { | 925 | while (status == 0 && nops != hdr_arg.nops) { |
| 894 | status = process_op(hdr_arg.minorversion, nops, rqstp, | 926 | status = process_op(nops, rqstp, &xdr_in, |
| 895 | &xdr_in, argp, &xdr_out, resp, &cps); | 927 | argp, &xdr_out, resp, &cps); |
| 896 | nops++; | 928 | nops++; |
| 897 | } | 929 | } |
| 898 | 930 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index c513b0cc835f..340b1eff0267 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -753,8 +753,6 @@ static int nfs_init_server(struct nfs_server *server, | |||
| 753 | data->timeo, data->retrans); | 753 | data->timeo, data->retrans); |
| 754 | if (data->flags & NFS_MOUNT_NORESVPORT) | 754 | if (data->flags & NFS_MOUNT_NORESVPORT) |
| 755 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); | 755 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); |
| 756 | if (server->options & NFS_OPTION_MIGRATION) | ||
| 757 | set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); | ||
| 758 | 756 | ||
| 759 | /* Allocate or find a client reference we can use */ | 757 | /* Allocate or find a client reference we can use */ |
| 760 | clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX); | 758 | clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX); |
| @@ -1076,7 +1074,7 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info, | |||
| 1076 | } | 1074 | } |
| 1077 | 1075 | ||
| 1078 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1076 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
| 1079 | error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr); | 1077 | error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr, NULL); |
| 1080 | if (error < 0) { | 1078 | if (error < 0) { |
| 1081 | dprintk("nfs_create_server: getattr error = %d\n", -error); | 1079 | dprintk("nfs_create_server: getattr error = %d\n", -error); |
| 1082 | goto error; | 1080 | goto error; |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c933bdfbcb1f..0fac2cb1ea18 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -437,6 +437,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
| 437 | struct dentry *alias; | 437 | struct dentry *alias; |
| 438 | struct inode *dir = parent->d_inode; | 438 | struct inode *dir = parent->d_inode; |
| 439 | struct inode *inode; | 439 | struct inode *inode; |
| 440 | int status; | ||
| 440 | 441 | ||
| 441 | if (filename.name[0] == '.') { | 442 | if (filename.name[0] == '.') { |
| 442 | if (filename.len == 1) | 443 | if (filename.len == 1) |
| @@ -449,7 +450,9 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
| 449 | dentry = d_lookup(parent, &filename); | 450 | dentry = d_lookup(parent, &filename); |
| 450 | if (dentry != NULL) { | 451 | if (dentry != NULL) { |
| 451 | if (nfs_same_file(dentry, entry)) { | 452 | if (nfs_same_file(dentry, entry)) { |
| 452 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | 453 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); |
| 454 | if (!status) | ||
| 455 | nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label); | ||
| 453 | goto out; | 456 | goto out; |
| 454 | } else { | 457 | } else { |
| 455 | if (d_invalidate(dentry) != 0) | 458 | if (d_invalidate(dentry) != 0) |
| @@ -462,7 +465,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
| 462 | if (dentry == NULL) | 465 | if (dentry == NULL) |
| 463 | return; | 466 | return; |
| 464 | 467 | ||
| 465 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | 468 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, entry->label); |
| 466 | if (IS_ERR(inode)) | 469 | if (IS_ERR(inode)) |
| 467 | goto out; | 470 | goto out; |
| 468 | 471 | ||
| @@ -587,10 +590,16 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
| 587 | if (entry.fh == NULL || entry.fattr == NULL) | 590 | if (entry.fh == NULL || entry.fattr == NULL) |
| 588 | goto out; | 591 | goto out; |
| 589 | 592 | ||
| 593 | entry.label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); | ||
| 594 | if (IS_ERR(entry.label)) { | ||
| 595 | status = PTR_ERR(entry.label); | ||
| 596 | goto out; | ||
| 597 | } | ||
| 598 | |||
| 590 | array = nfs_readdir_get_array(page); | 599 | array = nfs_readdir_get_array(page); |
| 591 | if (IS_ERR(array)) { | 600 | if (IS_ERR(array)) { |
| 592 | status = PTR_ERR(array); | 601 | status = PTR_ERR(array); |
| 593 | goto out; | 602 | goto out_label_free; |
| 594 | } | 603 | } |
| 595 | memset(array, 0, sizeof(struct nfs_cache_array)); | 604 | memset(array, 0, sizeof(struct nfs_cache_array)); |
| 596 | array->eof_index = -1; | 605 | array->eof_index = -1; |
| @@ -616,6 +625,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
| 616 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); | 625 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); |
| 617 | out_release_array: | 626 | out_release_array: |
| 618 | nfs_readdir_release_array(page); | 627 | nfs_readdir_release_array(page); |
| 628 | out_label_free: | ||
| 629 | nfs4_label_free(entry.label); | ||
| 619 | out: | 630 | out: |
| 620 | nfs_free_fattr(entry.fattr); | 631 | nfs_free_fattr(entry.fattr); |
| 621 | nfs_free_fhandle(entry.fh); | 632 | nfs_free_fhandle(entry.fh); |
| @@ -1040,6 +1051,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 1040 | struct dentry *parent; | 1051 | struct dentry *parent; |
| 1041 | struct nfs_fh *fhandle = NULL; | 1052 | struct nfs_fh *fhandle = NULL; |
| 1042 | struct nfs_fattr *fattr = NULL; | 1053 | struct nfs_fattr *fattr = NULL; |
| 1054 | struct nfs4_label *label = NULL; | ||
| 1043 | int error; | 1055 | int error; |
| 1044 | 1056 | ||
| 1045 | if (flags & LOOKUP_RCU) | 1057 | if (flags & LOOKUP_RCU) |
| @@ -1082,7 +1094,11 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 1082 | if (fhandle == NULL || fattr == NULL) | 1094 | if (fhandle == NULL || fattr == NULL) |
| 1083 | goto out_error; | 1095 | goto out_error; |
| 1084 | 1096 | ||
| 1085 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1097 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); |
| 1098 | if (IS_ERR(label)) | ||
| 1099 | goto out_error; | ||
| 1100 | |||
| 1101 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | ||
| 1086 | if (error) | 1102 | if (error) |
| 1087 | goto out_bad; | 1103 | goto out_bad; |
| 1088 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1104 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
| @@ -1090,8 +1106,12 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 1090 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) | 1106 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) |
| 1091 | goto out_bad; | 1107 | goto out_bad; |
| 1092 | 1108 | ||
| 1109 | nfs_setsecurity(inode, fattr, label); | ||
| 1110 | |||
| 1093 | nfs_free_fattr(fattr); | 1111 | nfs_free_fattr(fattr); |
| 1094 | nfs_free_fhandle(fhandle); | 1112 | nfs_free_fhandle(fhandle); |
| 1113 | nfs4_label_free(label); | ||
| 1114 | |||
| 1095 | out_set_verifier: | 1115 | out_set_verifier: |
| 1096 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1116 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 1097 | out_valid: | 1117 | out_valid: |
| @@ -1108,6 +1128,7 @@ out_zap_parent: | |||
| 1108 | out_bad: | 1128 | out_bad: |
| 1109 | nfs_free_fattr(fattr); | 1129 | nfs_free_fattr(fattr); |
| 1110 | nfs_free_fhandle(fhandle); | 1130 | nfs_free_fhandle(fhandle); |
| 1131 | nfs4_label_free(label); | ||
| 1111 | nfs_mark_for_revalidate(dir); | 1132 | nfs_mark_for_revalidate(dir); |
| 1112 | if (inode && S_ISDIR(inode->i_mode)) { | 1133 | if (inode && S_ISDIR(inode->i_mode)) { |
| 1113 | /* Purge readdir caches. */ | 1134 | /* Purge readdir caches. */ |
| @@ -1128,6 +1149,7 @@ out_zap_parent: | |||
| 1128 | out_error: | 1149 | out_error: |
| 1129 | nfs_free_fattr(fattr); | 1150 | nfs_free_fattr(fattr); |
| 1130 | nfs_free_fhandle(fhandle); | 1151 | nfs_free_fhandle(fhandle); |
| 1152 | nfs4_label_free(label); | ||
| 1131 | dput(parent); | 1153 | dput(parent); |
| 1132 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", | 1154 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", |
| 1133 | __func__, dentry->d_parent->d_name.name, | 1155 | __func__, dentry->d_parent->d_name.name, |
| @@ -1256,6 +1278,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
| 1256 | struct inode *inode = NULL; | 1278 | struct inode *inode = NULL; |
| 1257 | struct nfs_fh *fhandle = NULL; | 1279 | struct nfs_fh *fhandle = NULL; |
| 1258 | struct nfs_fattr *fattr = NULL; | 1280 | struct nfs_fattr *fattr = NULL; |
| 1281 | struct nfs4_label *label = NULL; | ||
| 1259 | int error; | 1282 | int error; |
| 1260 | 1283 | ||
| 1261 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", | 1284 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", |
| @@ -1282,17 +1305,21 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
| 1282 | if (fhandle == NULL || fattr == NULL) | 1305 | if (fhandle == NULL || fattr == NULL) |
| 1283 | goto out; | 1306 | goto out; |
| 1284 | 1307 | ||
| 1308 | label = nfs4_label_alloc(NFS_SERVER(dir), GFP_NOWAIT); | ||
| 1309 | if (IS_ERR(label)) | ||
| 1310 | goto out; | ||
| 1311 | |||
| 1285 | parent = dentry->d_parent; | 1312 | parent = dentry->d_parent; |
| 1286 | /* Protect against concurrent sillydeletes */ | 1313 | /* Protect against concurrent sillydeletes */ |
| 1287 | nfs_block_sillyrename(parent); | 1314 | nfs_block_sillyrename(parent); |
| 1288 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1315 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
| 1289 | if (error == -ENOENT) | 1316 | if (error == -ENOENT) |
| 1290 | goto no_entry; | 1317 | goto no_entry; |
| 1291 | if (error < 0) { | 1318 | if (error < 0) { |
| 1292 | res = ERR_PTR(error); | 1319 | res = ERR_PTR(error); |
| 1293 | goto out_unblock_sillyrename; | 1320 | goto out_unblock_sillyrename; |
| 1294 | } | 1321 | } |
| 1295 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1322 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
| 1296 | res = ERR_CAST(inode); | 1323 | res = ERR_CAST(inode); |
| 1297 | if (IS_ERR(res)) | 1324 | if (IS_ERR(res)) |
| 1298 | goto out_unblock_sillyrename; | 1325 | goto out_unblock_sillyrename; |
| @@ -1310,6 +1337,7 @@ no_entry: | |||
| 1310 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1337 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 1311 | out_unblock_sillyrename: | 1338 | out_unblock_sillyrename: |
| 1312 | nfs_unblock_sillyrename(parent); | 1339 | nfs_unblock_sillyrename(parent); |
| 1340 | nfs4_label_free(label); | ||
| 1313 | out: | 1341 | out: |
| 1314 | nfs_free_fattr(fattr); | 1342 | nfs_free_fattr(fattr); |
| 1315 | nfs_free_fhandle(fhandle); | 1343 | nfs_free_fhandle(fhandle); |
| @@ -1357,18 +1385,6 @@ static int nfs_finish_open(struct nfs_open_context *ctx, | |||
| 1357 | { | 1385 | { |
| 1358 | int err; | 1386 | int err; |
| 1359 | 1387 | ||
| 1360 | if (ctx->dentry != dentry) { | ||
| 1361 | dput(ctx->dentry); | ||
| 1362 | ctx->dentry = dget(dentry); | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | /* If the open_intent is for execute, we have an extra check to make */ | ||
| 1366 | if (ctx->mode & FMODE_EXEC) { | ||
| 1367 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); | ||
| 1368 | if (err < 0) | ||
| 1369 | goto out; | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | err = finish_open(file, dentry, do_open, opened); | 1388 | err = finish_open(file, dentry, do_open, opened); |
| 1373 | if (err) | 1389 | if (err) |
| 1374 | goto out; | 1390 | goto out; |
| @@ -1427,13 +1443,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
| 1427 | 1443 | ||
| 1428 | nfs_block_sillyrename(dentry->d_parent); | 1444 | nfs_block_sillyrename(dentry->d_parent); |
| 1429 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1445 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
| 1430 | d_drop(dentry); | 1446 | nfs_unblock_sillyrename(dentry->d_parent); |
| 1431 | if (IS_ERR(inode)) { | 1447 | if (IS_ERR(inode)) { |
| 1432 | nfs_unblock_sillyrename(dentry->d_parent); | ||
| 1433 | put_nfs_open_context(ctx); | 1448 | put_nfs_open_context(ctx); |
| 1434 | err = PTR_ERR(inode); | 1449 | err = PTR_ERR(inode); |
| 1435 | switch (err) { | 1450 | switch (err) { |
| 1436 | case -ENOENT: | 1451 | case -ENOENT: |
| 1452 | d_drop(dentry); | ||
| 1437 | d_add(dentry, NULL); | 1453 | d_add(dentry, NULL); |
| 1438 | break; | 1454 | break; |
| 1439 | case -EISDIR: | 1455 | case -EISDIR: |
| @@ -1449,16 +1465,8 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
| 1449 | } | 1465 | } |
| 1450 | goto out; | 1466 | goto out; |
| 1451 | } | 1467 | } |
| 1452 | res = d_add_unique(dentry, inode); | ||
| 1453 | if (res != NULL) | ||
| 1454 | dentry = res; | ||
| 1455 | |||
| 1456 | nfs_unblock_sillyrename(dentry->d_parent); | ||
| 1457 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1458 | |||
| 1459 | err = nfs_finish_open(ctx, dentry, file, open_flags, opened); | ||
| 1460 | 1468 | ||
| 1461 | dput(res); | 1469 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); |
| 1462 | out: | 1470 | out: |
| 1463 | return err; | 1471 | return err; |
| 1464 | 1472 | ||
| @@ -1528,7 +1536,8 @@ no_open: | |||
| 1528 | * Code common to create, mkdir, and mknod. | 1536 | * Code common to create, mkdir, and mknod. |
| 1529 | */ | 1537 | */ |
| 1530 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | 1538 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, |
| 1531 | struct nfs_fattr *fattr) | 1539 | struct nfs_fattr *fattr, |
| 1540 | struct nfs4_label *label) | ||
| 1532 | { | 1541 | { |
| 1533 | struct dentry *parent = dget_parent(dentry); | 1542 | struct dentry *parent = dget_parent(dentry); |
| 1534 | struct inode *dir = parent->d_inode; | 1543 | struct inode *dir = parent->d_inode; |
| @@ -1541,18 +1550,18 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | |||
| 1541 | if (dentry->d_inode) | 1550 | if (dentry->d_inode) |
| 1542 | goto out; | 1551 | goto out; |
| 1543 | if (fhandle->size == 0) { | 1552 | if (fhandle->size == 0) { |
| 1544 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1553 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL); |
| 1545 | if (error) | 1554 | if (error) |
| 1546 | goto out_error; | 1555 | goto out_error; |
| 1547 | } | 1556 | } |
| 1548 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1557 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 1549 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1558 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
| 1550 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 1559 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
| 1551 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); | 1560 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL); |
| 1552 | if (error < 0) | 1561 | if (error < 0) |
| 1553 | goto out_error; | 1562 | goto out_error; |
| 1554 | } | 1563 | } |
| 1555 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1564 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
| 1556 | error = PTR_ERR(inode); | 1565 | error = PTR_ERR(inode); |
| 1557 | if (IS_ERR(inode)) | 1566 | if (IS_ERR(inode)) |
| 1558 | goto out_error; | 1567 | goto out_error; |
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 945527092295..fc0f95ec7358 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c | |||
| @@ -29,7 +29,6 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen, | |||
| 29 | kfree(ip_addr); | 29 | kfree(ip_addr); |
| 30 | return ret; | 30 | return ret; |
| 31 | } | 31 | } |
| 32 | EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); | ||
| 33 | 32 | ||
| 34 | #else | 33 | #else |
| 35 | 34 | ||
| @@ -351,7 +350,6 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, | |||
| 351 | ret = -ESRCH; | 350 | ret = -ESRCH; |
| 352 | return ret; | 351 | return ret; |
| 353 | } | 352 | } |
| 354 | EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); | ||
| 355 | 353 | ||
| 356 | static struct cache_detail nfs_dns_resolve_template = { | 354 | static struct cache_detail nfs_dns_resolve_template = { |
| 357 | .owner = THIS_MODULE, | 355 | .owner = THIS_MODULE, |
| @@ -396,6 +394,21 @@ void nfs_dns_resolver_cache_destroy(struct net *net) | |||
| 396 | cache_destroy_net(nn->nfs_dns_resolve, net); | 394 | cache_destroy_net(nn->nfs_dns_resolve, net); |
| 397 | } | 395 | } |
| 398 | 396 | ||
| 397 | static int nfs4_dns_net_init(struct net *net) | ||
| 398 | { | ||
| 399 | return nfs_dns_resolver_cache_init(net); | ||
| 400 | } | ||
| 401 | |||
| 402 | static void nfs4_dns_net_exit(struct net *net) | ||
| 403 | { | ||
| 404 | nfs_dns_resolver_cache_destroy(net); | ||
| 405 | } | ||
| 406 | |||
| 407 | static struct pernet_operations nfs4_dns_resolver_ops = { | ||
| 408 | .init = nfs4_dns_net_init, | ||
| 409 | .exit = nfs4_dns_net_exit, | ||
| 410 | }; | ||
| 411 | |||
| 399 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | 412 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, |
| 400 | void *ptr) | 413 | void *ptr) |
| 401 | { | 414 | { |
| @@ -432,11 +445,24 @@ static struct notifier_block nfs_dns_resolver_block = { | |||
| 432 | 445 | ||
| 433 | int nfs_dns_resolver_init(void) | 446 | int nfs_dns_resolver_init(void) |
| 434 | { | 447 | { |
| 435 | return rpc_pipefs_notifier_register(&nfs_dns_resolver_block); | 448 | int err; |
| 449 | |||
| 450 | err = register_pernet_subsys(&nfs4_dns_resolver_ops); | ||
| 451 | if (err < 0) | ||
| 452 | goto out; | ||
| 453 | err = rpc_pipefs_notifier_register(&nfs_dns_resolver_block); | ||
| 454 | if (err < 0) | ||
| 455 | goto out1; | ||
| 456 | return 0; | ||
| 457 | out1: | ||
| 458 | unregister_pernet_subsys(&nfs4_dns_resolver_ops); | ||
| 459 | out: | ||
| 460 | return err; | ||
| 436 | } | 461 | } |
| 437 | 462 | ||
| 438 | void nfs_dns_resolver_destroy(void) | 463 | void nfs_dns_resolver_destroy(void) |
| 439 | { | 464 | { |
| 440 | rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block); | 465 | rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block); |
| 466 | unregister_pernet_subsys(&nfs4_dns_resolver_ops); | ||
| 441 | } | 467 | } |
| 442 | #endif | 468 | #endif |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 44efaa8c5f78..66984a9aafaa 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
| @@ -95,7 +95,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, | |||
| 95 | goto out; | 95 | goto out; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr); | 98 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr, NULL); |
| 99 | if (IS_ERR(inode)) { | 99 | if (IS_ERR(inode)) { |
| 100 | dprintk("nfs_get_root: get root inode failed\n"); | 100 | dprintk("nfs_get_root: get root inode failed\n"); |
| 101 | ret = ERR_CAST(inode); | 101 | ret = ERR_CAST(inode); |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index c516da5873fd..c2c4163d5683 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
| @@ -262,29 +262,42 @@ static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen, | |||
| 262 | return desclen; | 262 | return desclen; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | static ssize_t nfs_idmap_request_key(struct key_type *key_type, | 265 | static struct key *nfs_idmap_request_key(const char *name, size_t namelen, |
| 266 | const char *name, size_t namelen, | 266 | const char *type, struct idmap *idmap) |
| 267 | const char *type, void *data, | ||
| 268 | size_t data_size, struct idmap *idmap) | ||
| 269 | { | 267 | { |
| 270 | const struct cred *saved_cred; | ||
| 271 | struct key *rkey; | ||
| 272 | char *desc; | 268 | char *desc; |
| 273 | struct user_key_payload *payload; | 269 | struct key *rkey; |
| 274 | ssize_t ret; | 270 | ssize_t ret; |
| 275 | 271 | ||
| 276 | ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); | 272 | ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); |
| 277 | if (ret <= 0) | 273 | if (ret <= 0) |
| 278 | goto out; | 274 | return ERR_PTR(ret); |
| 275 | |||
| 276 | rkey = request_key(&key_type_id_resolver, desc, ""); | ||
| 277 | if (IS_ERR(rkey)) { | ||
| 278 | mutex_lock(&idmap->idmap_mutex); | ||
| 279 | rkey = request_key_with_auxdata(&key_type_id_resolver_legacy, | ||
| 280 | desc, "", 0, idmap); | ||
| 281 | mutex_unlock(&idmap->idmap_mutex); | ||
| 282 | } | ||
| 283 | |||
| 284 | kfree(desc); | ||
| 285 | return rkey; | ||
| 286 | } | ||
| 287 | |||
| 288 | static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | ||
| 289 | const char *type, void *data, | ||
| 290 | size_t data_size, struct idmap *idmap) | ||
| 291 | { | ||
| 292 | const struct cred *saved_cred; | ||
| 293 | struct key *rkey; | ||
| 294 | struct user_key_payload *payload; | ||
| 295 | ssize_t ret; | ||
| 279 | 296 | ||
| 280 | saved_cred = override_creds(id_resolver_cache); | 297 | saved_cred = override_creds(id_resolver_cache); |
| 281 | if (idmap) | 298 | rkey = nfs_idmap_request_key(name, namelen, type, idmap); |
| 282 | rkey = request_key_with_auxdata(key_type, desc, "", 0, idmap); | ||
| 283 | else | ||
| 284 | rkey = request_key(&key_type_id_resolver, desc, ""); | ||
| 285 | revert_creds(saved_cred); | 299 | revert_creds(saved_cred); |
| 286 | 300 | ||
| 287 | kfree(desc); | ||
| 288 | if (IS_ERR(rkey)) { | 301 | if (IS_ERR(rkey)) { |
| 289 | ret = PTR_ERR(rkey); | 302 | ret = PTR_ERR(rkey); |
| 290 | goto out; | 303 | goto out; |
| @@ -316,23 +329,6 @@ out: | |||
| 316 | return ret; | 329 | return ret; |
| 317 | } | 330 | } |
| 318 | 331 | ||
| 319 | static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | ||
| 320 | const char *type, void *data, | ||
| 321 | size_t data_size, struct idmap *idmap) | ||
| 322 | { | ||
| 323 | ssize_t ret = nfs_idmap_request_key(&key_type_id_resolver, | ||
| 324 | name, namelen, type, data, | ||
| 325 | data_size, NULL); | ||
| 326 | if (ret < 0) { | ||
| 327 | mutex_lock(&idmap->idmap_mutex); | ||
| 328 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, | ||
| 329 | name, namelen, type, data, | ||
| 330 | data_size, idmap); | ||
| 331 | mutex_unlock(&idmap->idmap_mutex); | ||
| 332 | } | ||
| 333 | return ret; | ||
| 334 | } | ||
| 335 | |||
| 336 | /* ID -> Name */ | 332 | /* ID -> Name */ |
| 337 | static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, | 333 | static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, |
| 338 | size_t buflen, struct idmap *idmap) | 334 | size_t buflen, struct idmap *idmap) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index ce727047ee87..c93639e6cf68 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -48,7 +48,6 @@ | |||
| 48 | #include "iostat.h" | 48 | #include "iostat.h" |
| 49 | #include "internal.h" | 49 | #include "internal.h" |
| 50 | #include "fscache.h" | 50 | #include "fscache.h" |
| 51 | #include "dns_resolve.h" | ||
| 52 | #include "pnfs.h" | 51 | #include "pnfs.h" |
| 53 | #include "nfs.h" | 52 | #include "nfs.h" |
| 54 | #include "netns.h" | 53 | #include "netns.h" |
| @@ -162,11 +161,19 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
| 162 | 161 | ||
| 163 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); | 162 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); |
| 164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 163 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
| 165 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | ||
| 166 | nfs_fscache_invalidate(inode); | 164 | nfs_fscache_invalidate(inode); |
| 167 | } else { | 165 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
| 168 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 166 | | NFS_INO_INVALID_LABEL |
| 169 | } | 167 | | NFS_INO_INVALID_DATA |
| 168 | | NFS_INO_INVALID_ACCESS | ||
| 169 | | NFS_INO_INVALID_ACL | ||
| 170 | | NFS_INO_REVAL_PAGECACHE; | ||
| 171 | } else | ||
| 172 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | ||
| 173 | | NFS_INO_INVALID_LABEL | ||
| 174 | | NFS_INO_INVALID_ACCESS | ||
| 175 | | NFS_INO_INVALID_ACL | ||
| 176 | | NFS_INO_REVAL_PAGECACHE; | ||
| 170 | } | 177 | } |
| 171 | 178 | ||
| 172 | void nfs_zap_caches(struct inode *inode) | 179 | void nfs_zap_caches(struct inode *inode) |
| @@ -257,12 +264,72 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
| 257 | return 0; | 264 | return 0; |
| 258 | } | 265 | } |
| 259 | 266 | ||
| 267 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 268 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
| 269 | struct nfs4_label *label) | ||
| 270 | { | ||
| 271 | int error; | ||
| 272 | |||
| 273 | if (label == NULL) | ||
| 274 | return; | ||
| 275 | |||
| 276 | if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL) == 0) | ||
| 277 | return; | ||
| 278 | |||
| 279 | if (NFS_SERVER(inode)->nfs_client->cl_minorversion < 2) | ||
| 280 | return; | ||
| 281 | |||
| 282 | if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) { | ||
| 283 | error = security_inode_notifysecctx(inode, label->label, | ||
| 284 | label->len); | ||
| 285 | if (error) | ||
| 286 | printk(KERN_ERR "%s() %s %d " | ||
| 287 | "security_inode_notifysecctx() %d\n", | ||
| 288 | __func__, | ||
| 289 | (char *)label->label, | ||
| 290 | label->len, error); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) | ||
| 295 | { | ||
| 296 | struct nfs4_label *label = NULL; | ||
| 297 | int minor_version = server->nfs_client->cl_minorversion; | ||
| 298 | |||
| 299 | if (minor_version < 2) | ||
| 300 | return label; | ||
| 301 | |||
| 302 | if (!(server->caps & NFS_CAP_SECURITY_LABEL)) | ||
| 303 | return label; | ||
| 304 | |||
| 305 | label = kzalloc(sizeof(struct nfs4_label), flags); | ||
| 306 | if (label == NULL) | ||
| 307 | return ERR_PTR(-ENOMEM); | ||
| 308 | |||
| 309 | label->label = kzalloc(NFS4_MAXLABELLEN, flags); | ||
| 310 | if (label->label == NULL) { | ||
| 311 | kfree(label); | ||
| 312 | return ERR_PTR(-ENOMEM); | ||
| 313 | } | ||
| 314 | label->len = NFS4_MAXLABELLEN; | ||
| 315 | |||
| 316 | return label; | ||
| 317 | } | ||
| 318 | EXPORT_SYMBOL_GPL(nfs4_label_alloc); | ||
| 319 | #else | ||
| 320 | void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
| 321 | struct nfs4_label *label) | ||
| 322 | { | ||
| 323 | } | ||
| 324 | #endif | ||
| 325 | EXPORT_SYMBOL_GPL(nfs_setsecurity); | ||
| 326 | |||
| 260 | /* | 327 | /* |
| 261 | * This is our front-end to iget that looks up inodes by file handle | 328 | * This is our front-end to iget that looks up inodes by file handle |
| 262 | * instead of inode number. | 329 | * instead of inode number. |
| 263 | */ | 330 | */ |
| 264 | struct inode * | 331 | struct inode * |
| 265 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | 332 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label) |
| 266 | { | 333 | { |
| 267 | struct nfs_find_desc desc = { | 334 | struct nfs_find_desc desc = { |
| 268 | .fh = fh, | 335 | .fh = fh, |
| @@ -384,6 +451,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 384 | */ | 451 | */ |
| 385 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 452 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
| 386 | } | 453 | } |
| 454 | |||
| 455 | nfs_setsecurity(inode, fattr, label); | ||
| 456 | |||
| 387 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 457 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 388 | nfsi->attrtimeo_timestamp = now; | 458 | nfsi->attrtimeo_timestamp = now; |
| 389 | nfsi->access_cache = RB_ROOT; | 459 | nfsi->access_cache = RB_ROOT; |
| @@ -393,6 +463,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 393 | unlock_new_inode(inode); | 463 | unlock_new_inode(inode); |
| 394 | } else | 464 | } else |
| 395 | nfs_refresh_inode(inode, fattr); | 465 | nfs_refresh_inode(inode, fattr); |
| 466 | nfs_setsecurity(inode, fattr, label); | ||
| 396 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", | 467 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", |
| 397 | inode->i_sb->s_id, | 468 | inode->i_sb->s_id, |
| 398 | (long long)NFS_FILEID(inode), | 469 | (long long)NFS_FILEID(inode), |
| @@ -449,7 +520,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 449 | NFS_PROTO(inode)->return_delegation(inode); | 520 | NFS_PROTO(inode)->return_delegation(inode); |
| 450 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); | 521 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); |
| 451 | if (error == 0) | 522 | if (error == 0) |
| 452 | nfs_refresh_inode(inode, fattr); | 523 | error = nfs_refresh_inode(inode, fattr); |
| 453 | nfs_free_fattr(fattr); | 524 | nfs_free_fattr(fattr); |
| 454 | out: | 525 | out: |
| 455 | return error; | 526 | return error; |
| @@ -713,16 +784,23 @@ EXPORT_SYMBOL_GPL(put_nfs_open_context); | |||
| 713 | * Ensure that mmap has a recent RPC credential for use when writing out | 784 | * Ensure that mmap has a recent RPC credential for use when writing out |
| 714 | * shared pages | 785 | * shared pages |
| 715 | */ | 786 | */ |
| 716 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | 787 | void nfs_inode_attach_open_context(struct nfs_open_context *ctx) |
| 717 | { | 788 | { |
| 718 | struct inode *inode = file_inode(filp); | 789 | struct inode *inode = ctx->dentry->d_inode; |
| 719 | struct nfs_inode *nfsi = NFS_I(inode); | 790 | struct nfs_inode *nfsi = NFS_I(inode); |
| 720 | 791 | ||
| 721 | filp->private_data = get_nfs_open_context(ctx); | ||
| 722 | spin_lock(&inode->i_lock); | 792 | spin_lock(&inode->i_lock); |
| 723 | list_add(&ctx->list, &nfsi->open_files); | 793 | list_add(&ctx->list, &nfsi->open_files); |
| 724 | spin_unlock(&inode->i_lock); | 794 | spin_unlock(&inode->i_lock); |
| 725 | } | 795 | } |
| 796 | EXPORT_SYMBOL_GPL(nfs_inode_attach_open_context); | ||
| 797 | |||
| 798 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | ||
| 799 | { | ||
| 800 | filp->private_data = get_nfs_open_context(ctx); | ||
| 801 | if (list_empty(&ctx->list)) | ||
| 802 | nfs_inode_attach_open_context(ctx); | ||
| 803 | } | ||
| 726 | EXPORT_SYMBOL_GPL(nfs_file_set_open_context); | 804 | EXPORT_SYMBOL_GPL(nfs_file_set_open_context); |
| 727 | 805 | ||
| 728 | /* | 806 | /* |
| @@ -748,10 +826,11 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c | |||
| 748 | 826 | ||
| 749 | static void nfs_file_clear_open_context(struct file *filp) | 827 | static void nfs_file_clear_open_context(struct file *filp) |
| 750 | { | 828 | { |
| 751 | struct inode *inode = file_inode(filp); | ||
| 752 | struct nfs_open_context *ctx = nfs_file_open_context(filp); | 829 | struct nfs_open_context *ctx = nfs_file_open_context(filp); |
| 753 | 830 | ||
| 754 | if (ctx) { | 831 | if (ctx) { |
| 832 | struct inode *inode = ctx->dentry->d_inode; | ||
| 833 | |||
| 755 | filp->private_data = NULL; | 834 | filp->private_data = NULL; |
| 756 | spin_lock(&inode->i_lock); | 835 | spin_lock(&inode->i_lock); |
| 757 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); | 836 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); |
| @@ -790,6 +869,7 @@ int | |||
| 790 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 869 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
| 791 | { | 870 | { |
| 792 | int status = -ESTALE; | 871 | int status = -ESTALE; |
| 872 | struct nfs4_label *label = NULL; | ||
| 793 | struct nfs_fattr *fattr = NULL; | 873 | struct nfs_fattr *fattr = NULL; |
| 794 | struct nfs_inode *nfsi = NFS_I(inode); | 874 | struct nfs_inode *nfsi = NFS_I(inode); |
| 795 | 875 | ||
| @@ -807,7 +887,14 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 807 | goto out; | 887 | goto out; |
| 808 | 888 | ||
| 809 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 889 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
| 810 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr); | 890 | |
| 891 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); | ||
| 892 | if (IS_ERR(label)) { | ||
| 893 | status = PTR_ERR(label); | ||
| 894 | goto out; | ||
| 895 | } | ||
| 896 | |||
| 897 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label); | ||
| 811 | if (status != 0) { | 898 | if (status != 0) { |
| 812 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 899 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
| 813 | inode->i_sb->s_id, | 900 | inode->i_sb->s_id, |
| @@ -817,7 +904,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 817 | if (!S_ISDIR(inode->i_mode)) | 904 | if (!S_ISDIR(inode->i_mode)) |
| 818 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); | 905 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
| 819 | } | 906 | } |
| 820 | goto out; | 907 | goto err_out; |
| 821 | } | 908 | } |
| 822 | 909 | ||
| 823 | status = nfs_refresh_inode(inode, fattr); | 910 | status = nfs_refresh_inode(inode, fattr); |
| @@ -825,7 +912,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 825 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 912 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
| 826 | inode->i_sb->s_id, | 913 | inode->i_sb->s_id, |
| 827 | (long long)NFS_FILEID(inode), status); | 914 | (long long)NFS_FILEID(inode), status); |
| 828 | goto out; | 915 | goto err_out; |
| 829 | } | 916 | } |
| 830 | 917 | ||
| 831 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) | 918 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
| @@ -835,7 +922,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 835 | inode->i_sb->s_id, | 922 | inode->i_sb->s_id, |
| 836 | (long long)NFS_FILEID(inode)); | 923 | (long long)NFS_FILEID(inode)); |
| 837 | 924 | ||
| 838 | out: | 925 | err_out: |
| 926 | nfs4_label_free(label); | ||
| 927 | out: | ||
| 839 | nfs_free_fattr(fattr); | 928 | nfs_free_fattr(fattr); |
| 840 | return status; | 929 | return status; |
| 841 | } | 930 | } |
| @@ -863,7 +952,8 @@ static int nfs_attribute_cache_expired(struct inode *inode) | |||
| 863 | */ | 952 | */ |
| 864 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 953 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
| 865 | { | 954 | { |
| 866 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) | 955 | if (!(NFS_I(inode)->cache_validity & |
| 956 | (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) | ||
| 867 | && !nfs_attribute_cache_expired(inode)) | 957 | && !nfs_attribute_cache_expired(inode)) |
| 868 | return NFS_STALE(inode) ? -ESTALE : 0; | 958 | return NFS_STALE(inode) ? -ESTALE : 0; |
| 869 | return __nfs_revalidate_inode(server, inode); | 959 | return __nfs_revalidate_inode(server, inode); |
| @@ -1243,6 +1333,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1243 | spin_lock(&inode->i_lock); | 1333 | spin_lock(&inode->i_lock); |
| 1244 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1334 | status = nfs_post_op_update_inode_locked(inode, fattr); |
| 1245 | spin_unlock(&inode->i_lock); | 1335 | spin_unlock(&inode->i_lock); |
| 1336 | |||
| 1246 | return status; | 1337 | return status; |
| 1247 | } | 1338 | } |
| 1248 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1339 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
| @@ -1483,7 +1574,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1483 | inode->i_blocks = fattr->du.nfs2.blocks; | 1574 | inode->i_blocks = fattr->du.nfs2.blocks; |
| 1484 | 1575 | ||
| 1485 | /* Update attrtimeo value if we're out of the unstable period */ | 1576 | /* Update attrtimeo value if we're out of the unstable period */ |
| 1486 | if (invalid & NFS_INO_INVALID_ATTR) { | 1577 | if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { |
| 1487 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1578 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
| 1488 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1579 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 1489 | nfsi->attrtimeo_timestamp = now; | 1580 | nfsi->attrtimeo_timestamp = now; |
| @@ -1496,6 +1587,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1496 | } | 1587 | } |
| 1497 | } | 1588 | } |
| 1498 | invalid &= ~NFS_INO_INVALID_ATTR; | 1589 | invalid &= ~NFS_INO_INVALID_ATTR; |
| 1590 | invalid &= ~NFS_INO_INVALID_LABEL; | ||
| 1499 | /* Don't invalidate the data if we were to blame */ | 1591 | /* Don't invalidate the data if we were to blame */ |
| 1500 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1592 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
| 1501 | || S_ISLNK(inode->i_mode))) | 1593 | || S_ISLNK(inode->i_mode))) |
| @@ -1638,12 +1730,11 @@ EXPORT_SYMBOL_GPL(nfs_net_id); | |||
| 1638 | static int nfs_net_init(struct net *net) | 1730 | static int nfs_net_init(struct net *net) |
| 1639 | { | 1731 | { |
| 1640 | nfs_clients_init(net); | 1732 | nfs_clients_init(net); |
| 1641 | return nfs_dns_resolver_cache_init(net); | 1733 | return 0; |
| 1642 | } | 1734 | } |
| 1643 | 1735 | ||
| 1644 | static void nfs_net_exit(struct net *net) | 1736 | static void nfs_net_exit(struct net *net) |
| 1645 | { | 1737 | { |
| 1646 | nfs_dns_resolver_cache_destroy(net); | ||
| 1647 | nfs_cleanup_cb_ident_idr(net); | 1738 | nfs_cleanup_cb_ident_idr(net); |
| 1648 | } | 1739 | } |
| 1649 | 1740 | ||
| @@ -1661,10 +1752,6 @@ static int __init init_nfs_fs(void) | |||
| 1661 | { | 1752 | { |
| 1662 | int err; | 1753 | int err; |
| 1663 | 1754 | ||
| 1664 | err = nfs_dns_resolver_init(); | ||
| 1665 | if (err < 0) | ||
| 1666 | goto out10;; | ||
| 1667 | |||
| 1668 | err = register_pernet_subsys(&nfs_net_ops); | 1755 | err = register_pernet_subsys(&nfs_net_ops); |
| 1669 | if (err < 0) | 1756 | if (err < 0) |
| 1670 | goto out9; | 1757 | goto out9; |
| @@ -1730,8 +1817,6 @@ out7: | |||
| 1730 | out8: | 1817 | out8: |
| 1731 | unregister_pernet_subsys(&nfs_net_ops); | 1818 | unregister_pernet_subsys(&nfs_net_ops); |
| 1732 | out9: | 1819 | out9: |
| 1733 | nfs_dns_resolver_destroy(); | ||
| 1734 | out10: | ||
| 1735 | return err; | 1820 | return err; |
| 1736 | } | 1821 | } |
| 1737 | 1822 | ||
| @@ -1744,7 +1829,6 @@ static void __exit exit_nfs_fs(void) | |||
| 1744 | nfs_destroy_nfspagecache(); | 1829 | nfs_destroy_nfspagecache(); |
| 1745 | nfs_fscache_unregister(); | 1830 | nfs_fscache_unregister(); |
| 1746 | unregister_pernet_subsys(&nfs_net_ops); | 1831 | unregister_pernet_subsys(&nfs_net_ops); |
| 1747 | nfs_dns_resolver_destroy(); | ||
| 1748 | #ifdef CONFIG_PROC_FS | 1832 | #ifdef CONFIG_PROC_FS |
| 1749 | rpc_proc_unregister(&init_net, "nfs"); | 1833 | rpc_proc_unregister(&init_net, "nfs"); |
| 1750 | #endif | 1834 | #endif |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 91e59a39fc08..3c8373f90ab3 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -165,7 +165,7 @@ extern void nfs_free_client(struct nfs_client *); | |||
| 165 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); | 165 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); |
| 166 | extern struct nfs_client * | 166 | extern struct nfs_client * |
| 167 | nfs4_find_client_sessionid(struct net *, const struct sockaddr *, | 167 | nfs4_find_client_sessionid(struct net *, const struct sockaddr *, |
| 168 | struct nfs4_sessionid *); | 168 | struct nfs4_sessionid *, u32); |
| 169 | extern struct nfs_server *nfs_create_server(struct nfs_mount_info *, | 169 | extern struct nfs_server *nfs_create_server(struct nfs_mount_info *, |
| 170 | struct nfs_subversion *); | 170 | struct nfs_subversion *); |
| 171 | extern struct nfs_server *nfs4_create_server( | 171 | extern struct nfs_server *nfs4_create_server( |
| @@ -255,6 +255,7 @@ extern int nfs4_decode_dirent(struct xdr_stream *, | |||
| 255 | #ifdef CONFIG_NFS_V4_1 | 255 | #ifdef CONFIG_NFS_V4_1 |
| 256 | extern const u32 nfs41_maxread_overhead; | 256 | extern const u32 nfs41_maxread_overhead; |
| 257 | extern const u32 nfs41_maxwrite_overhead; | 257 | extern const u32 nfs41_maxwrite_overhead; |
| 258 | extern const u32 nfs41_maxgetdevinfo_overhead; | ||
| 258 | #endif | 259 | #endif |
| 259 | 260 | ||
| 260 | /* nfs4proc.c */ | 261 | /* nfs4proc.c */ |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 91a6faf811ac..99a45283b9ee 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
| @@ -139,7 +139,10 @@ struct mnt_fhstatus { | |||
| 139 | * nfs_mount - Obtain an NFS file handle for the given host and path | 139 | * nfs_mount - Obtain an NFS file handle for the given host and path |
| 140 | * @info: pointer to mount request arguments | 140 | * @info: pointer to mount request arguments |
| 141 | * | 141 | * |
| 142 | * Uses default timeout parameters specified by underlying transport. | 142 | * Uses default timeout parameters specified by underlying transport. On |
| 143 | * successful return, the auth_flavs list and auth_flav_len will be populated | ||
| 144 | * with the list from the server or a faked-up list if the server didn't | ||
| 145 | * provide one. | ||
| 143 | */ | 146 | */ |
| 144 | int nfs_mount(struct nfs_mount_request *info) | 147 | int nfs_mount(struct nfs_mount_request *info) |
| 145 | { | 148 | { |
| @@ -195,6 +198,15 @@ int nfs_mount(struct nfs_mount_request *info) | |||
| 195 | dprintk("NFS: MNT request succeeded\n"); | 198 | dprintk("NFS: MNT request succeeded\n"); |
| 196 | status = 0; | 199 | status = 0; |
| 197 | 200 | ||
| 201 | /* | ||
| 202 | * If the server didn't provide a flavor list, allow the | ||
| 203 | * client to try any flavor. | ||
| 204 | */ | ||
| 205 | if (info->version != NFS_MNT3_VERSION || *info->auth_flav_len == 0) { | ||
| 206 | dprintk("NFS: Faking up auth_flavs list\n"); | ||
| 207 | info->auth_flavs[0] = RPC_AUTH_NULL; | ||
| 208 | *info->auth_flav_len = 1; | ||
| 209 | } | ||
| 198 | out: | 210 | out: |
| 199 | return status; | 211 | return status; |
| 200 | 212 | ||
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index fc8dc20fdeb9..348b535cd786 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
| @@ -280,7 +280,7 @@ struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry, | |||
| 280 | struct dentry *parent = dget_parent(dentry); | 280 | struct dentry *parent = dget_parent(dentry); |
| 281 | 281 | ||
| 282 | /* Look it up again to get its attributes */ | 282 | /* Look it up again to get its attributes */ |
| 283 | err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr); | 283 | err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr, NULL); |
| 284 | dput(parent); | 284 | dput(parent); |
| 285 | if (err != 0) | 285 | if (err != 0) |
| 286 | return ERR_PTR(err); | 286 | return ERR_PTR(err); |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index ce90eb4775c2..f5c84c3efbca 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
| @@ -98,7 +98,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 98 | */ | 98 | */ |
| 99 | static int | 99 | static int |
| 100 | nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | 100 | nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
| 101 | struct nfs_fattr *fattr) | 101 | struct nfs_fattr *fattr, struct nfs4_label *label) |
| 102 | { | 102 | { |
| 103 | struct rpc_message msg = { | 103 | struct rpc_message msg = { |
| 104 | .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR], | 104 | .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR], |
| @@ -143,7 +143,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 143 | 143 | ||
| 144 | static int | 144 | static int |
| 145 | nfs3_proc_lookup(struct inode *dir, struct qstr *name, | 145 | nfs3_proc_lookup(struct inode *dir, struct qstr *name, |
| 146 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 146 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, |
| 147 | struct nfs4_label *label) | ||
| 147 | { | 148 | { |
| 148 | struct nfs3_diropargs arg = { | 149 | struct nfs3_diropargs arg = { |
| 149 | .fh = NFS_FH(dir), | 150 | .fh = NFS_FH(dir), |
| @@ -300,7 +301,7 @@ static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_ | |||
| 300 | status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); | 301 | status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); |
| 301 | nfs_post_op_update_inode(dir, data->res.dir_attr); | 302 | nfs_post_op_update_inode(dir, data->res.dir_attr); |
| 302 | if (status == 0) | 303 | if (status == 0) |
| 303 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 304 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
| 304 | return status; | 305 | return status; |
| 305 | } | 306 | } |
| 306 | 307 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index a1dd768d0a35..ee81e354bce7 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -194,7 +194,7 @@ struct nfs4_state_recovery_ops { | |||
| 194 | int (*recover_lock)(struct nfs4_state *, struct file_lock *); | 194 | int (*recover_lock)(struct nfs4_state *, struct file_lock *); |
| 195 | int (*establish_clid)(struct nfs_client *, struct rpc_cred *); | 195 | int (*establish_clid)(struct nfs_client *, struct rpc_cred *); |
| 196 | struct rpc_cred * (*get_clid_cred)(struct nfs_client *); | 196 | struct rpc_cred * (*get_clid_cred)(struct nfs_client *); |
| 197 | int (*reclaim_complete)(struct nfs_client *); | 197 | int (*reclaim_complete)(struct nfs_client *, struct rpc_cred *); |
| 198 | int (*detect_trunking)(struct nfs_client *, struct nfs_client **, | 198 | int (*detect_trunking)(struct nfs_client *, struct nfs_client **, |
| 199 | struct rpc_cred *); | 199 | struct rpc_cred *); |
| 200 | }; | 200 | }; |
| @@ -303,10 +303,10 @@ is_ds_client(struct nfs_client *clp) | |||
| 303 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; | 303 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; |
| 304 | 304 | ||
| 305 | extern const u32 nfs4_fattr_bitmap[3]; | 305 | extern const u32 nfs4_fattr_bitmap[3]; |
| 306 | extern const u32 nfs4_statfs_bitmap[2]; | 306 | extern const u32 nfs4_statfs_bitmap[3]; |
| 307 | extern const u32 nfs4_pathconf_bitmap[2]; | 307 | extern const u32 nfs4_pathconf_bitmap[3]; |
| 308 | extern const u32 nfs4_fsinfo_bitmap[3]; | 308 | extern const u32 nfs4_fsinfo_bitmap[3]; |
| 309 | extern const u32 nfs4_fs_locations_bitmap[2]; | 309 | extern const u32 nfs4_fs_locations_bitmap[3]; |
| 310 | 310 | ||
| 311 | void nfs4_free_client(struct nfs_client *); | 311 | void nfs4_free_client(struct nfs_client *); |
| 312 | 312 | ||
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 4cbad5d6b276..90dce91dd5b5 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
| @@ -66,6 +66,11 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | |||
| 66 | if (err) | 66 | if (err) |
| 67 | goto error; | 67 | goto error; |
| 68 | 68 | ||
| 69 | if (cl_init->minorversion > NFS4_MAX_MINOR_VERSION) { | ||
| 70 | err = -EINVAL; | ||
| 71 | goto error; | ||
| 72 | } | ||
| 73 | |||
| 69 | spin_lock_init(&clp->cl_lock); | 74 | spin_lock_init(&clp->cl_lock); |
| 70 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | 75 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); |
| 71 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | 76 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); |
| @@ -562,14 +567,14 @@ static bool nfs4_cb_match_client(const struct sockaddr *addr, | |||
| 562 | */ | 567 | */ |
| 563 | struct nfs_client * | 568 | struct nfs_client * |
| 564 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, | 569 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, |
| 565 | struct nfs4_sessionid *sid) | 570 | struct nfs4_sessionid *sid, u32 minorversion) |
| 566 | { | 571 | { |
| 567 | struct nfs_client *clp; | 572 | struct nfs_client *clp; |
| 568 | struct nfs_net *nn = net_generic(net, nfs_net_id); | 573 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
| 569 | 574 | ||
| 570 | spin_lock(&nn->nfs_client_lock); | 575 | spin_lock(&nn->nfs_client_lock); |
| 571 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { | 576 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { |
| 572 | if (nfs4_cb_match_client(addr, clp, 1) == false) | 577 | if (nfs4_cb_match_client(addr, clp, minorversion) == false) |
| 573 | continue; | 578 | continue; |
| 574 | 579 | ||
| 575 | if (!nfs4_has_session(clp)) | 580 | if (!nfs4_has_session(clp)) |
| @@ -592,7 +597,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, | |||
| 592 | 597 | ||
| 593 | struct nfs_client * | 598 | struct nfs_client * |
| 594 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, | 599 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, |
| 595 | struct nfs4_sessionid *sid) | 600 | struct nfs4_sessionid *sid, u32 minorversion) |
| 596 | { | 601 | { |
| 597 | return NULL; | 602 | return NULL; |
| 598 | } | 603 | } |
| @@ -626,6 +631,8 @@ static int nfs4_set_client(struct nfs_server *server, | |||
| 626 | 631 | ||
| 627 | if (server->flags & NFS_MOUNT_NORESVPORT) | 632 | if (server->flags & NFS_MOUNT_NORESVPORT) |
| 628 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); | 633 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); |
| 634 | if (server->options & NFS_OPTION_MIGRATION) | ||
| 635 | set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); | ||
| 629 | 636 | ||
| 630 | /* Allocate or find a client reference we can use */ | 637 | /* Allocate or find a client reference we can use */ |
| 631 | clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour); | 638 | clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour); |
| @@ -730,7 +737,7 @@ static int nfs4_server_common_setup(struct nfs_server *server, | |||
| 730 | return -ENOMEM; | 737 | return -ENOMEM; |
| 731 | 738 | ||
| 732 | /* We must ensure the session is initialised first */ | 739 | /* We must ensure the session is initialised first */ |
| 733 | error = nfs4_init_session(server); | 740 | error = nfs4_init_session(server->nfs_client); |
| 734 | if (error < 0) | 741 | if (error < 0) |
| 735 | goto out; | 742 | goto out; |
| 736 | 743 | ||
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 13e6bb3e3fe5..e5b804dd944c 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
| @@ -69,7 +69,6 @@ nfs4_file_open(struct inode *inode, struct file *filp) | |||
| 69 | goto out_drop; | 69 | goto out_drop; |
| 70 | } | 70 | } |
| 71 | } | 71 | } |
| 72 | iput(inode); | ||
| 73 | if (inode != dentry->d_inode) | 72 | if (inode != dentry->d_inode) |
| 74 | goto out_drop; | 73 | goto out_drop; |
| 75 | 74 | ||
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 22d10623f5ee..17ed87ef9de8 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -643,7 +643,8 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
| 643 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->pnfs_curr_ld, | 643 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->pnfs_curr_ld, |
| 644 | NFS_SERVER(lo->plh_inode)->nfs_client, id); | 644 | NFS_SERVER(lo->plh_inode)->nfs_client, id); |
| 645 | if (d == NULL) { | 645 | if (d == NULL) { |
| 646 | dsaddr = filelayout_get_device_info(lo->plh_inode, id, gfp_flags); | 646 | dsaddr = filelayout_get_device_info(lo->plh_inode, id, |
| 647 | lo->plh_lc_cred, gfp_flags); | ||
| 647 | if (dsaddr == NULL) | 648 | if (dsaddr == NULL) |
| 648 | goto out; | 649 | goto out; |
| 649 | } else | 650 | } else |
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index 235ff952d3c8..cebd20e7e923 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h | |||
| @@ -150,6 +150,7 @@ struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, | |||
| 150 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 150 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
| 151 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 151 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
| 152 | struct nfs4_file_layout_dsaddr * | 152 | struct nfs4_file_layout_dsaddr * |
| 153 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); | 153 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, |
| 154 | struct rpc_cred *cred, gfp_t gfp_flags); | ||
| 154 | 155 | ||
| 155 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ | 156 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 661a0f611215..95604f64cab8 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
| @@ -668,7 +668,10 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl | |||
| 668 | * of available devices, and return it. | 668 | * of available devices, and return it. |
| 669 | */ | 669 | */ |
| 670 | struct nfs4_file_layout_dsaddr * | 670 | struct nfs4_file_layout_dsaddr * |
| 671 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags) | 671 | filelayout_get_device_info(struct inode *inode, |
| 672 | struct nfs4_deviceid *dev_id, | ||
| 673 | struct rpc_cred *cred, | ||
| 674 | gfp_t gfp_flags) | ||
| 672 | { | 675 | { |
| 673 | struct pnfs_device *pdev = NULL; | 676 | struct pnfs_device *pdev = NULL; |
| 674 | u32 max_resp_sz; | 677 | u32 max_resp_sz; |
| @@ -708,8 +711,9 @@ filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gf | |||
| 708 | pdev->pgbase = 0; | 711 | pdev->pgbase = 0; |
| 709 | pdev->pglen = max_resp_sz; | 712 | pdev->pglen = max_resp_sz; |
| 710 | pdev->mincount = 0; | 713 | pdev->mincount = 0; |
| 714 | pdev->maxcount = max_resp_sz - nfs41_maxgetdevinfo_overhead; | ||
| 711 | 715 | ||
| 712 | rc = nfs4_proc_getdeviceinfo(server, pdev); | 716 | rc = nfs4_proc_getdeviceinfo(server, pdev, cred); |
| 713 | dprintk("%s getdevice info returns %d\n", __func__, rc); | 717 | dprintk("%s getdevice info returns %d\n", __func__, rc); |
| 714 | if (rc) | 718 | if (rc) |
| 715 | goto out_free; | 719 | goto out_free; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 28241a42f363..cf11799297c4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -77,15 +77,68 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | |||
| 77 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 77 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
| 78 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 78 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
| 79 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | 79 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); |
| 80 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); | 80 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); |
| 81 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 81 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); |
| 82 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 82 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
| 83 | struct nfs_fattr *fattr, struct iattr *sattr, | 83 | struct nfs_fattr *fattr, struct iattr *sattr, |
| 84 | struct nfs4_state *state); | 84 | struct nfs4_state *state, struct nfs4_label *ilabel, |
| 85 | struct nfs4_label *olabel); | ||
| 85 | #ifdef CONFIG_NFS_V4_1 | 86 | #ifdef CONFIG_NFS_V4_1 |
| 86 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *); | 87 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, |
| 87 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *); | 88 | struct rpc_cred *); |
| 89 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *, | ||
| 90 | struct rpc_cred *); | ||
| 88 | #endif | 91 | #endif |
| 92 | |||
| 93 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 94 | static inline struct nfs4_label * | ||
| 95 | nfs4_label_init_security(struct inode *dir, struct dentry *dentry, | ||
| 96 | struct iattr *sattr, struct nfs4_label *label) | ||
| 97 | { | ||
| 98 | int err; | ||
| 99 | |||
| 100 | if (label == NULL) | ||
| 101 | return NULL; | ||
| 102 | |||
| 103 | if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) | ||
| 104 | return NULL; | ||
| 105 | |||
| 106 | if (NFS_SERVER(dir)->nfs_client->cl_minorversion < 2) | ||
| 107 | return NULL; | ||
| 108 | |||
| 109 | err = security_dentry_init_security(dentry, sattr->ia_mode, | ||
| 110 | &dentry->d_name, (void **)&label->label, &label->len); | ||
| 111 | if (err == 0) | ||
| 112 | return label; | ||
| 113 | |||
| 114 | return NULL; | ||
| 115 | } | ||
| 116 | static inline void | ||
| 117 | nfs4_label_release_security(struct nfs4_label *label) | ||
| 118 | { | ||
| 119 | if (label) | ||
| 120 | security_release_secctx(label->label, label->len); | ||
| 121 | } | ||
| 122 | static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) | ||
| 123 | { | ||
| 124 | if (label) | ||
| 125 | return server->attr_bitmask; | ||
| 126 | |||
| 127 | return server->attr_bitmask_nl; | ||
| 128 | } | ||
| 129 | #else | ||
| 130 | static inline struct nfs4_label * | ||
| 131 | nfs4_label_init_security(struct inode *dir, struct dentry *dentry, | ||
| 132 | struct iattr *sattr, struct nfs4_label *l) | ||
| 133 | { return NULL; } | ||
| 134 | static inline void | ||
| 135 | nfs4_label_release_security(struct nfs4_label *label) | ||
| 136 | { return; } | ||
| 137 | static inline u32 * | ||
| 138 | nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) | ||
| 139 | { return server->attr_bitmask; } | ||
| 140 | #endif | ||
| 141 | |||
| 89 | /* Prevent leaks of NFSv4 errors into userland */ | 142 | /* Prevent leaks of NFSv4 errors into userland */ |
| 90 | static int nfs4_map_errors(int err) | 143 | static int nfs4_map_errors(int err) |
| 91 | { | 144 | { |
| @@ -134,7 +187,10 @@ const u32 nfs4_fattr_bitmap[3] = { | |||
| 134 | | FATTR4_WORD1_SPACE_USED | 187 | | FATTR4_WORD1_SPACE_USED |
| 135 | | FATTR4_WORD1_TIME_ACCESS | 188 | | FATTR4_WORD1_TIME_ACCESS |
| 136 | | FATTR4_WORD1_TIME_METADATA | 189 | | FATTR4_WORD1_TIME_METADATA |
| 137 | | FATTR4_WORD1_TIME_MODIFY | 190 | | FATTR4_WORD1_TIME_MODIFY, |
| 191 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 192 | FATTR4_WORD2_SECURITY_LABEL | ||
| 193 | #endif | ||
| 138 | }; | 194 | }; |
| 139 | 195 | ||
| 140 | static const u32 nfs4_pnfs_open_bitmap[3] = { | 196 | static const u32 nfs4_pnfs_open_bitmap[3] = { |
| @@ -161,7 +217,7 @@ static const u32 nfs4_open_noattr_bitmap[3] = { | |||
| 161 | | FATTR4_WORD0_FILEID, | 217 | | FATTR4_WORD0_FILEID, |
| 162 | }; | 218 | }; |
| 163 | 219 | ||
| 164 | const u32 nfs4_statfs_bitmap[2] = { | 220 | const u32 nfs4_statfs_bitmap[3] = { |
| 165 | FATTR4_WORD0_FILES_AVAIL | 221 | FATTR4_WORD0_FILES_AVAIL |
| 166 | | FATTR4_WORD0_FILES_FREE | 222 | | FATTR4_WORD0_FILES_FREE |
| 167 | | FATTR4_WORD0_FILES_TOTAL, | 223 | | FATTR4_WORD0_FILES_TOTAL, |
| @@ -170,7 +226,7 @@ const u32 nfs4_statfs_bitmap[2] = { | |||
| 170 | | FATTR4_WORD1_SPACE_TOTAL | 226 | | FATTR4_WORD1_SPACE_TOTAL |
| 171 | }; | 227 | }; |
| 172 | 228 | ||
| 173 | const u32 nfs4_pathconf_bitmap[2] = { | 229 | const u32 nfs4_pathconf_bitmap[3] = { |
| 174 | FATTR4_WORD0_MAXLINK | 230 | FATTR4_WORD0_MAXLINK |
| 175 | | FATTR4_WORD0_MAXNAME, | 231 | | FATTR4_WORD0_MAXNAME, |
| 176 | 0 | 232 | 0 |
| @@ -185,7 +241,7 @@ const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE | |||
| 185 | FATTR4_WORD2_LAYOUT_BLKSIZE | 241 | FATTR4_WORD2_LAYOUT_BLKSIZE |
| 186 | }; | 242 | }; |
| 187 | 243 | ||
| 188 | const u32 nfs4_fs_locations_bitmap[2] = { | 244 | const u32 nfs4_fs_locations_bitmap[3] = { |
| 189 | FATTR4_WORD0_TYPE | 245 | FATTR4_WORD0_TYPE |
| 190 | | FATTR4_WORD0_CHANGE | 246 | | FATTR4_WORD0_CHANGE |
| 191 | | FATTR4_WORD0_SIZE | 247 | | FATTR4_WORD0_SIZE |
| @@ -201,7 +257,7 @@ const u32 nfs4_fs_locations_bitmap[2] = { | |||
| 201 | | FATTR4_WORD1_TIME_ACCESS | 257 | | FATTR4_WORD1_TIME_ACCESS |
| 202 | | FATTR4_WORD1_TIME_METADATA | 258 | | FATTR4_WORD1_TIME_METADATA |
| 203 | | FATTR4_WORD1_TIME_MODIFY | 259 | | FATTR4_WORD1_TIME_MODIFY |
| 204 | | FATTR4_WORD1_MOUNTED_ON_FILEID | 260 | | FATTR4_WORD1_MOUNTED_ON_FILEID, |
| 205 | }; | 261 | }; |
| 206 | 262 | ||
| 207 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, | 263 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, |
| @@ -762,6 +818,7 @@ struct nfs4_opendata { | |||
| 762 | struct nfs4_string owner_name; | 818 | struct nfs4_string owner_name; |
| 763 | struct nfs4_string group_name; | 819 | struct nfs4_string group_name; |
| 764 | struct nfs_fattr f_attr; | 820 | struct nfs_fattr f_attr; |
| 821 | struct nfs4_label *f_label; | ||
| 765 | struct dentry *dir; | 822 | struct dentry *dir; |
| 766 | struct dentry *dentry; | 823 | struct dentry *dentry; |
| 767 | struct nfs4_state_owner *owner; | 824 | struct nfs4_state_owner *owner; |
| @@ -807,6 +864,7 @@ nfs4_map_atomic_open_claim(struct nfs_server *server, | |||
| 807 | static void nfs4_init_opendata_res(struct nfs4_opendata *p) | 864 | static void nfs4_init_opendata_res(struct nfs4_opendata *p) |
| 808 | { | 865 | { |
| 809 | p->o_res.f_attr = &p->f_attr; | 866 | p->o_res.f_attr = &p->f_attr; |
| 867 | p->o_res.f_label = p->f_label; | ||
| 810 | p->o_res.seqid = p->o_arg.seqid; | 868 | p->o_res.seqid = p->o_arg.seqid; |
| 811 | p->c_res.seqid = p->c_arg.seqid; | 869 | p->c_res.seqid = p->c_arg.seqid; |
| 812 | p->o_res.server = p->o_arg.server; | 870 | p->o_res.server = p->o_arg.server; |
| @@ -818,6 +876,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
| 818 | static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | 876 | static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, |
| 819 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, | 877 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, |
| 820 | const struct iattr *attrs, | 878 | const struct iattr *attrs, |
| 879 | struct nfs4_label *label, | ||
| 821 | enum open_claim_type4 claim, | 880 | enum open_claim_type4 claim, |
| 822 | gfp_t gfp_mask) | 881 | gfp_t gfp_mask) |
| 823 | { | 882 | { |
| @@ -829,9 +888,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
| 829 | p = kzalloc(sizeof(*p), gfp_mask); | 888 | p = kzalloc(sizeof(*p), gfp_mask); |
| 830 | if (p == NULL) | 889 | if (p == NULL) |
| 831 | goto err; | 890 | goto err; |
| 891 | |||
| 892 | p->f_label = nfs4_label_alloc(server, gfp_mask); | ||
| 893 | if (IS_ERR(p->f_label)) | ||
| 894 | goto err_free_p; | ||
| 895 | |||
| 832 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); | 896 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); |
| 833 | if (p->o_arg.seqid == NULL) | 897 | if (p->o_arg.seqid == NULL) |
| 834 | goto err_free; | 898 | goto err_free_label; |
| 835 | nfs_sb_active(dentry->d_sb); | 899 | nfs_sb_active(dentry->d_sb); |
| 836 | p->dentry = dget(dentry); | 900 | p->dentry = dget(dentry); |
| 837 | p->dir = parent; | 901 | p->dir = parent; |
| @@ -852,8 +916,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
| 852 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; | 916 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; |
| 853 | p->o_arg.name = &dentry->d_name; | 917 | p->o_arg.name = &dentry->d_name; |
| 854 | p->o_arg.server = server; | 918 | p->o_arg.server = server; |
| 855 | p->o_arg.bitmask = server->attr_bitmask; | 919 | p->o_arg.bitmask = nfs4_bitmask(server, label); |
| 856 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; | 920 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; |
| 921 | p->o_arg.label = label; | ||
| 857 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); | 922 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); |
| 858 | switch (p->o_arg.claim) { | 923 | switch (p->o_arg.claim) { |
| 859 | case NFS4_OPEN_CLAIM_NULL: | 924 | case NFS4_OPEN_CLAIM_NULL: |
| @@ -884,7 +949,10 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
| 884 | nfs4_init_opendata_res(p); | 949 | nfs4_init_opendata_res(p); |
| 885 | kref_init(&p->kref); | 950 | kref_init(&p->kref); |
| 886 | return p; | 951 | return p; |
| 887 | err_free: | 952 | |
| 953 | err_free_label: | ||
| 954 | nfs4_label_free(p->f_label); | ||
| 955 | err_free_p: | ||
| 888 | kfree(p); | 956 | kfree(p); |
| 889 | err: | 957 | err: |
| 890 | dput(parent); | 958 | dput(parent); |
| @@ -901,6 +969,9 @@ static void nfs4_opendata_free(struct kref *kref) | |||
| 901 | if (p->state != NULL) | 969 | if (p->state != NULL) |
| 902 | nfs4_put_open_state(p->state); | 970 | nfs4_put_open_state(p->state); |
| 903 | nfs4_put_state_owner(p->owner); | 971 | nfs4_put_state_owner(p->owner); |
| 972 | |||
| 973 | nfs4_label_free(p->f_label); | ||
| 974 | |||
| 904 | dput(p->dir); | 975 | dput(p->dir); |
| 905 | dput(p->dentry); | 976 | dput(p->dentry); |
| 906 | nfs_sb_deactive(sb); | 977 | nfs_sb_deactive(sb); |
| @@ -1179,6 +1250,8 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) | |||
| 1179 | if (ret) | 1250 | if (ret) |
| 1180 | goto err; | 1251 | goto err; |
| 1181 | 1252 | ||
| 1253 | nfs_setsecurity(inode, &data->f_attr, data->f_label); | ||
| 1254 | |||
| 1182 | if (data->o_res.delegation_type != 0) | 1255 | if (data->o_res.delegation_type != 0) |
| 1183 | nfs4_opendata_check_deleg(data, state); | 1256 | nfs4_opendata_check_deleg(data, state); |
| 1184 | update_open_stateid(state, &data->o_res.stateid, NULL, | 1257 | update_open_stateid(state, &data->o_res.stateid, NULL, |
| @@ -1205,7 +1278,7 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | |||
| 1205 | ret = -EAGAIN; | 1278 | ret = -EAGAIN; |
| 1206 | if (!(data->f_attr.valid & NFS_ATTR_FATTR)) | 1279 | if (!(data->f_attr.valid & NFS_ATTR_FATTR)) |
| 1207 | goto err; | 1280 | goto err; |
| 1208 | inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr); | 1281 | inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr, data->f_label); |
| 1209 | ret = PTR_ERR(inode); | 1282 | ret = PTR_ERR(inode); |
| 1210 | if (IS_ERR(inode)) | 1283 | if (IS_ERR(inode)) |
| 1211 | goto err; | 1284 | goto err; |
| @@ -1258,7 +1331,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context | |||
| 1258 | struct nfs4_opendata *opendata; | 1331 | struct nfs4_opendata *opendata; |
| 1259 | 1332 | ||
| 1260 | opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, | 1333 | opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, |
| 1261 | NULL, claim, GFP_NOFS); | 1334 | NULL, NULL, claim, GFP_NOFS); |
| 1262 | if (opendata == NULL) | 1335 | if (opendata == NULL) |
| 1263 | return ERR_PTR(-ENOMEM); | 1336 | return ERR_PTR(-ENOMEM); |
| 1264 | opendata->state = state; | 1337 | opendata->state = state; |
| @@ -1784,7 +1857,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
| 1784 | return status; | 1857 | return status; |
| 1785 | } | 1858 | } |
| 1786 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) | 1859 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) |
| 1787 | _nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr); | 1860 | _nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label); |
| 1788 | return 0; | 1861 | return 0; |
| 1789 | } | 1862 | } |
| 1790 | 1863 | ||
| @@ -1855,18 +1928,30 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
| 1855 | { | 1928 | { |
| 1856 | struct nfs_server *server = NFS_SERVER(state->inode); | 1929 | struct nfs_server *server = NFS_SERVER(state->inode); |
| 1857 | nfs4_stateid *stateid = &state->stateid; | 1930 | nfs4_stateid *stateid = &state->stateid; |
| 1858 | int status; | 1931 | struct nfs_delegation *delegation; |
| 1932 | struct rpc_cred *cred = NULL; | ||
| 1933 | int status = -NFS4ERR_BAD_STATEID; | ||
| 1859 | 1934 | ||
| 1860 | /* If a state reset has been done, test_stateid is unneeded */ | 1935 | /* If a state reset has been done, test_stateid is unneeded */ |
| 1861 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | 1936 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) |
| 1862 | return; | 1937 | return; |
| 1863 | 1938 | ||
| 1864 | status = nfs41_test_stateid(server, stateid); | 1939 | /* Get the delegation credential for use by test/free_stateid */ |
| 1940 | rcu_read_lock(); | ||
| 1941 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | ||
| 1942 | if (delegation != NULL && | ||
| 1943 | nfs4_stateid_match(&delegation->stateid, stateid)) { | ||
| 1944 | cred = get_rpccred(delegation->cred); | ||
| 1945 | rcu_read_unlock(); | ||
| 1946 | status = nfs41_test_stateid(server, stateid, cred); | ||
| 1947 | } else | ||
| 1948 | rcu_read_unlock(); | ||
| 1949 | |||
| 1865 | if (status != NFS_OK) { | 1950 | if (status != NFS_OK) { |
| 1866 | /* Free the stateid unless the server explicitly | 1951 | /* Free the stateid unless the server explicitly |
| 1867 | * informs us the stateid is unrecognized. */ | 1952 | * informs us the stateid is unrecognized. */ |
| 1868 | if (status != -NFS4ERR_BAD_STATEID) | 1953 | if (status != -NFS4ERR_BAD_STATEID) |
| 1869 | nfs41_free_stateid(server, stateid); | 1954 | nfs41_free_stateid(server, stateid, cred); |
| 1870 | nfs_remove_bad_delegation(state->inode); | 1955 | nfs_remove_bad_delegation(state->inode); |
| 1871 | 1956 | ||
| 1872 | write_seqlock(&state->seqlock); | 1957 | write_seqlock(&state->seqlock); |
| @@ -1874,6 +1959,9 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
| 1874 | write_sequnlock(&state->seqlock); | 1959 | write_sequnlock(&state->seqlock); |
| 1875 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 1960 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
| 1876 | } | 1961 | } |
| 1962 | |||
| 1963 | if (cred != NULL) | ||
| 1964 | put_rpccred(cred); | ||
| 1877 | } | 1965 | } |
| 1878 | 1966 | ||
| 1879 | /** | 1967 | /** |
| @@ -1888,6 +1976,7 @@ static int nfs41_check_open_stateid(struct nfs4_state *state) | |||
| 1888 | { | 1976 | { |
| 1889 | struct nfs_server *server = NFS_SERVER(state->inode); | 1977 | struct nfs_server *server = NFS_SERVER(state->inode); |
| 1890 | nfs4_stateid *stateid = &state->open_stateid; | 1978 | nfs4_stateid *stateid = &state->open_stateid; |
| 1979 | struct rpc_cred *cred = state->owner->so_cred; | ||
| 1891 | int status; | 1980 | int status; |
| 1892 | 1981 | ||
| 1893 | /* If a state reset has been done, test_stateid is unneeded */ | 1982 | /* If a state reset has been done, test_stateid is unneeded */ |
| @@ -1896,12 +1985,12 @@ static int nfs41_check_open_stateid(struct nfs4_state *state) | |||
| 1896 | (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0)) | 1985 | (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0)) |
| 1897 | return -NFS4ERR_BAD_STATEID; | 1986 | return -NFS4ERR_BAD_STATEID; |
| 1898 | 1987 | ||
| 1899 | status = nfs41_test_stateid(server, stateid); | 1988 | status = nfs41_test_stateid(server, stateid, cred); |
| 1900 | if (status != NFS_OK) { | 1989 | if (status != NFS_OK) { |
| 1901 | /* Free the stateid unless the server explicitly | 1990 | /* Free the stateid unless the server explicitly |
| 1902 | * informs us the stateid is unrecognized. */ | 1991 | * informs us the stateid is unrecognized. */ |
| 1903 | if (status != -NFS4ERR_BAD_STATEID) | 1992 | if (status != -NFS4ERR_BAD_STATEID) |
| 1904 | nfs41_free_stateid(server, stateid); | 1993 | nfs41_free_stateid(server, stateid, cred); |
| 1905 | 1994 | ||
| 1906 | clear_bit(NFS_O_RDONLY_STATE, &state->flags); | 1995 | clear_bit(NFS_O_RDONLY_STATE, &state->flags); |
| 1907 | clear_bit(NFS_O_WRONLY_STATE, &state->flags); | 1996 | clear_bit(NFS_O_WRONLY_STATE, &state->flags); |
| @@ -1942,10 +2031,11 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct | |||
| 1942 | static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | 2031 | static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, |
| 1943 | fmode_t fmode, | 2032 | fmode_t fmode, |
| 1944 | int flags, | 2033 | int flags, |
| 1945 | struct nfs4_state **res) | 2034 | struct nfs_open_context *ctx) |
| 1946 | { | 2035 | { |
| 1947 | struct nfs4_state_owner *sp = opendata->owner; | 2036 | struct nfs4_state_owner *sp = opendata->owner; |
| 1948 | struct nfs_server *server = sp->so_server; | 2037 | struct nfs_server *server = sp->so_server; |
| 2038 | struct dentry *dentry; | ||
| 1949 | struct nfs4_state *state; | 2039 | struct nfs4_state *state; |
| 1950 | unsigned int seq; | 2040 | unsigned int seq; |
| 1951 | int ret; | 2041 | int ret; |
| @@ -1963,13 +2053,31 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
| 1963 | if (server->caps & NFS_CAP_POSIX_LOCK) | 2053 | if (server->caps & NFS_CAP_POSIX_LOCK) |
| 1964 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | 2054 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
| 1965 | 2055 | ||
| 2056 | dentry = opendata->dentry; | ||
| 2057 | if (dentry->d_inode == NULL) { | ||
| 2058 | /* FIXME: Is this d_drop() ever needed? */ | ||
| 2059 | d_drop(dentry); | ||
| 2060 | dentry = d_add_unique(dentry, igrab(state->inode)); | ||
| 2061 | if (dentry == NULL) { | ||
| 2062 | dentry = opendata->dentry; | ||
| 2063 | } else if (dentry != ctx->dentry) { | ||
| 2064 | dput(ctx->dentry); | ||
| 2065 | ctx->dentry = dget(dentry); | ||
| 2066 | } | ||
| 2067 | nfs_set_verifier(dentry, | ||
| 2068 | nfs_save_change_attribute(opendata->dir->d_inode)); | ||
| 2069 | } | ||
| 2070 | |||
| 1966 | ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags); | 2071 | ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags); |
| 1967 | if (ret != 0) | 2072 | if (ret != 0) |
| 1968 | goto out; | 2073 | goto out; |
| 1969 | 2074 | ||
| 1970 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) | 2075 | ctx->state = state; |
| 1971 | nfs4_schedule_stateid_recovery(server, state); | 2076 | if (dentry->d_inode == state->inode) { |
| 1972 | *res = state; | 2077 | nfs_inode_attach_open_context(ctx); |
| 2078 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) | ||
| 2079 | nfs4_schedule_stateid_recovery(server, state); | ||
| 2080 | } | ||
| 1973 | out: | 2081 | out: |
| 1974 | return ret; | 2082 | return ret; |
| 1975 | } | 2083 | } |
| @@ -1978,19 +2086,21 @@ out: | |||
| 1978 | * Returns a referenced nfs4_state | 2086 | * Returns a referenced nfs4_state |
| 1979 | */ | 2087 | */ |
| 1980 | static int _nfs4_do_open(struct inode *dir, | 2088 | static int _nfs4_do_open(struct inode *dir, |
| 1981 | struct dentry *dentry, | 2089 | struct nfs_open_context *ctx, |
| 1982 | fmode_t fmode, | ||
| 1983 | int flags, | 2090 | int flags, |
| 1984 | struct iattr *sattr, | 2091 | struct iattr *sattr, |
| 1985 | struct rpc_cred *cred, | 2092 | struct nfs4_label *label) |
| 1986 | struct nfs4_state **res, | ||
| 1987 | struct nfs4_threshold **ctx_th) | ||
| 1988 | { | 2093 | { |
| 1989 | struct nfs4_state_owner *sp; | 2094 | struct nfs4_state_owner *sp; |
| 1990 | struct nfs4_state *state = NULL; | 2095 | struct nfs4_state *state = NULL; |
| 1991 | struct nfs_server *server = NFS_SERVER(dir); | 2096 | struct nfs_server *server = NFS_SERVER(dir); |
| 1992 | struct nfs4_opendata *opendata; | 2097 | struct nfs4_opendata *opendata; |
| 2098 | struct dentry *dentry = ctx->dentry; | ||
| 2099 | struct rpc_cred *cred = ctx->cred; | ||
| 2100 | struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; | ||
| 2101 | fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); | ||
| 1993 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; | 2102 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; |
| 2103 | struct nfs4_label *olabel = NULL; | ||
| 1994 | int status; | 2104 | int status; |
| 1995 | 2105 | ||
| 1996 | /* Protect against reboot recovery conflicts */ | 2106 | /* Protect against reboot recovery conflicts */ |
| @@ -2009,22 +2119,31 @@ static int _nfs4_do_open(struct inode *dir, | |||
| 2009 | if (dentry->d_inode) | 2119 | if (dentry->d_inode) |
| 2010 | claim = NFS4_OPEN_CLAIM_FH; | 2120 | claim = NFS4_OPEN_CLAIM_FH; |
| 2011 | opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, | 2121 | opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, |
| 2012 | claim, GFP_KERNEL); | 2122 | label, claim, GFP_KERNEL); |
| 2013 | if (opendata == NULL) | 2123 | if (opendata == NULL) |
| 2014 | goto err_put_state_owner; | 2124 | goto err_put_state_owner; |
| 2015 | 2125 | ||
| 2126 | if (label) { | ||
| 2127 | olabel = nfs4_label_alloc(server, GFP_KERNEL); | ||
| 2128 | if (IS_ERR(olabel)) { | ||
| 2129 | status = PTR_ERR(olabel); | ||
| 2130 | goto err_opendata_put; | ||
| 2131 | } | ||
| 2132 | } | ||
| 2133 | |||
| 2016 | if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) { | 2134 | if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) { |
| 2017 | opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); | 2135 | opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); |
| 2018 | if (!opendata->f_attr.mdsthreshold) | 2136 | if (!opendata->f_attr.mdsthreshold) |
| 2019 | goto err_opendata_put; | 2137 | goto err_free_label; |
| 2020 | opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; | 2138 | opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; |
| 2021 | } | 2139 | } |
| 2022 | if (dentry->d_inode != NULL) | 2140 | if (dentry->d_inode != NULL) |
| 2023 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); | 2141 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); |
| 2024 | 2142 | ||
| 2025 | status = _nfs4_open_and_get_state(opendata, fmode, flags, &state); | 2143 | status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx); |
| 2026 | if (status != 0) | 2144 | if (status != 0) |
| 2027 | goto err_opendata_put; | 2145 | goto err_free_label; |
| 2146 | state = ctx->state; | ||
| 2028 | 2147 | ||
| 2029 | if ((opendata->o_arg.open_flags & O_EXCL) && | 2148 | if ((opendata->o_arg.open_flags & O_EXCL) && |
| 2030 | (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { | 2149 | (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { |
| @@ -2033,10 +2152,12 @@ static int _nfs4_do_open(struct inode *dir, | |||
| 2033 | nfs_fattr_init(opendata->o_res.f_attr); | 2152 | nfs_fattr_init(opendata->o_res.f_attr); |
| 2034 | status = nfs4_do_setattr(state->inode, cred, | 2153 | status = nfs4_do_setattr(state->inode, cred, |
| 2035 | opendata->o_res.f_attr, sattr, | 2154 | opendata->o_res.f_attr, sattr, |
| 2036 | state); | 2155 | state, label, olabel); |
| 2037 | if (status == 0) | 2156 | if (status == 0) { |
| 2038 | nfs_setattr_update_inode(state->inode, sattr); | 2157 | nfs_setattr_update_inode(state->inode, sattr); |
| 2039 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | 2158 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); |
| 2159 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); | ||
| 2160 | } | ||
| 2040 | } | 2161 | } |
| 2041 | 2162 | ||
| 2042 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) | 2163 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) |
| @@ -2045,38 +2166,37 @@ static int _nfs4_do_open(struct inode *dir, | |||
| 2045 | kfree(opendata->f_attr.mdsthreshold); | 2166 | kfree(opendata->f_attr.mdsthreshold); |
| 2046 | opendata->f_attr.mdsthreshold = NULL; | 2167 | opendata->f_attr.mdsthreshold = NULL; |
| 2047 | 2168 | ||
| 2169 | nfs4_label_free(olabel); | ||
| 2170 | |||
| 2048 | nfs4_opendata_put(opendata); | 2171 | nfs4_opendata_put(opendata); |
| 2049 | nfs4_put_state_owner(sp); | 2172 | nfs4_put_state_owner(sp); |
| 2050 | *res = state; | ||
| 2051 | return 0; | 2173 | return 0; |
| 2174 | err_free_label: | ||
| 2175 | nfs4_label_free(olabel); | ||
| 2052 | err_opendata_put: | 2176 | err_opendata_put: |
| 2053 | kfree(opendata->f_attr.mdsthreshold); | 2177 | kfree(opendata->f_attr.mdsthreshold); |
| 2054 | nfs4_opendata_put(opendata); | 2178 | nfs4_opendata_put(opendata); |
| 2055 | err_put_state_owner: | 2179 | err_put_state_owner: |
| 2056 | nfs4_put_state_owner(sp); | 2180 | nfs4_put_state_owner(sp); |
| 2057 | out_err: | 2181 | out_err: |
| 2058 | *res = NULL; | ||
| 2059 | return status; | 2182 | return status; |
| 2060 | } | 2183 | } |
| 2061 | 2184 | ||
| 2062 | 2185 | ||
| 2063 | static struct nfs4_state *nfs4_do_open(struct inode *dir, | 2186 | static struct nfs4_state *nfs4_do_open(struct inode *dir, |
| 2064 | struct dentry *dentry, | 2187 | struct nfs_open_context *ctx, |
| 2065 | fmode_t fmode, | ||
| 2066 | int flags, | 2188 | int flags, |
| 2067 | struct iattr *sattr, | 2189 | struct iattr *sattr, |
| 2068 | struct rpc_cred *cred, | 2190 | struct nfs4_label *label) |
| 2069 | struct nfs4_threshold **ctx_th) | ||
| 2070 | { | 2191 | { |
| 2071 | struct nfs_server *server = NFS_SERVER(dir); | 2192 | struct nfs_server *server = NFS_SERVER(dir); |
| 2072 | struct nfs4_exception exception = { }; | 2193 | struct nfs4_exception exception = { }; |
| 2073 | struct nfs4_state *res; | 2194 | struct nfs4_state *res; |
| 2074 | int status; | 2195 | int status; |
| 2075 | 2196 | ||
| 2076 | fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC; | ||
| 2077 | do { | 2197 | do { |
| 2078 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, | 2198 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); |
| 2079 | &res, ctx_th); | 2199 | res = ctx->state; |
| 2080 | if (status == 0) | 2200 | if (status == 0) |
| 2081 | break; | 2201 | break; |
| 2082 | /* NOTE: BAD_SEQID means the server and client disagree about the | 2202 | /* NOTE: BAD_SEQID means the server and client disagree about the |
| @@ -2122,7 +2242,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
| 2122 | 2242 | ||
| 2123 | static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 2243 | static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
| 2124 | struct nfs_fattr *fattr, struct iattr *sattr, | 2244 | struct nfs_fattr *fattr, struct iattr *sattr, |
| 2125 | struct nfs4_state *state) | 2245 | struct nfs4_state *state, struct nfs4_label *ilabel, |
| 2246 | struct nfs4_label *olabel) | ||
| 2126 | { | 2247 | { |
| 2127 | struct nfs_server *server = NFS_SERVER(inode); | 2248 | struct nfs_server *server = NFS_SERVER(inode); |
| 2128 | struct nfs_setattrargs arg = { | 2249 | struct nfs_setattrargs arg = { |
| @@ -2130,9 +2251,11 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
| 2130 | .iap = sattr, | 2251 | .iap = sattr, |
| 2131 | .server = server, | 2252 | .server = server, |
| 2132 | .bitmask = server->attr_bitmask, | 2253 | .bitmask = server->attr_bitmask, |
| 2254 | .label = ilabel, | ||
| 2133 | }; | 2255 | }; |
| 2134 | struct nfs_setattrres res = { | 2256 | struct nfs_setattrres res = { |
| 2135 | .fattr = fattr, | 2257 | .fattr = fattr, |
| 2258 | .label = olabel, | ||
| 2136 | .server = server, | 2259 | .server = server, |
| 2137 | }; | 2260 | }; |
| 2138 | struct rpc_message msg = { | 2261 | struct rpc_message msg = { |
| @@ -2146,6 +2269,10 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
| 2146 | bool truncate; | 2269 | bool truncate; |
| 2147 | int status; | 2270 | int status; |
| 2148 | 2271 | ||
| 2272 | arg.bitmask = nfs4_bitmask(server, ilabel); | ||
| 2273 | if (ilabel) | ||
| 2274 | arg.bitmask = nfs4_bitmask(server, olabel); | ||
| 2275 | |||
| 2149 | nfs_fattr_init(fattr); | 2276 | nfs_fattr_init(fattr); |
| 2150 | 2277 | ||
| 2151 | /* Servers should only apply open mode checks for file size changes */ | 2278 | /* Servers should only apply open mode checks for file size changes */ |
| @@ -2172,7 +2299,8 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
| 2172 | 2299 | ||
| 2173 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 2300 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
| 2174 | struct nfs_fattr *fattr, struct iattr *sattr, | 2301 | struct nfs_fattr *fattr, struct iattr *sattr, |
| 2175 | struct nfs4_state *state) | 2302 | struct nfs4_state *state, struct nfs4_label *ilabel, |
| 2303 | struct nfs4_label *olabel) | ||
| 2176 | { | 2304 | { |
| 2177 | struct nfs_server *server = NFS_SERVER(inode); | 2305 | struct nfs_server *server = NFS_SERVER(inode); |
| 2178 | struct nfs4_exception exception = { | 2306 | struct nfs4_exception exception = { |
| @@ -2181,7 +2309,7 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
| 2181 | }; | 2309 | }; |
| 2182 | int err; | 2310 | int err; |
| 2183 | do { | 2311 | do { |
| 2184 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state); | 2312 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel); |
| 2185 | switch (err) { | 2313 | switch (err) { |
| 2186 | case -NFS4ERR_OPENMODE: | 2314 | case -NFS4ERR_OPENMODE: |
| 2187 | if (!(sattr->ia_valid & ATTR_SIZE)) { | 2315 | if (!(sattr->ia_valid & ATTR_SIZE)) { |
| @@ -2426,14 +2554,18 @@ static struct inode * | |||
| 2426 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) | 2554 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) |
| 2427 | { | 2555 | { |
| 2428 | struct nfs4_state *state; | 2556 | struct nfs4_state *state; |
| 2557 | struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; | ||
| 2558 | |||
| 2559 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); | ||
| 2429 | 2560 | ||
| 2430 | /* Protect against concurrent sillydeletes */ | 2561 | /* Protect against concurrent sillydeletes */ |
| 2431 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, | 2562 | state = nfs4_do_open(dir, ctx, open_flags, attr, label); |
| 2432 | ctx->cred, &ctx->mdsthreshold); | 2563 | |
| 2564 | nfs4_label_release_security(label); | ||
| 2565 | |||
| 2433 | if (IS_ERR(state)) | 2566 | if (IS_ERR(state)) |
| 2434 | return ERR_CAST(state); | 2567 | return ERR_CAST(state); |
| 2435 | ctx->state = state; | 2568 | return state->inode; |
| 2436 | return igrab(state->inode); | ||
| 2437 | } | 2569 | } |
| 2438 | 2570 | ||
| 2439 | static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) | 2571 | static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) |
| @@ -2489,7 +2621,17 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
| 2489 | server->caps |= NFS_CAP_CTIME; | 2621 | server->caps |= NFS_CAP_CTIME; |
| 2490 | if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY) | 2622 | if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY) |
| 2491 | server->caps |= NFS_CAP_MTIME; | 2623 | server->caps |= NFS_CAP_MTIME; |
| 2624 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 2625 | if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL) | ||
| 2626 | server->caps |= NFS_CAP_SECURITY_LABEL; | ||
| 2627 | #endif | ||
| 2628 | memcpy(server->attr_bitmask_nl, res.attr_bitmask, | ||
| 2629 | sizeof(server->attr_bitmask)); | ||
| 2492 | 2630 | ||
| 2631 | if (server->caps & NFS_CAP_SECURITY_LABEL) { | ||
| 2632 | server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
| 2633 | res.attr_bitmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
| 2634 | } | ||
| 2493 | memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); | 2635 | memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); |
| 2494 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; | 2636 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; |
| 2495 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | 2637 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
| @@ -2515,8 +2657,9 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) | |||
| 2515 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2657 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
| 2516 | struct nfs_fsinfo *info) | 2658 | struct nfs_fsinfo *info) |
| 2517 | { | 2659 | { |
| 2660 | u32 bitmask[3]; | ||
| 2518 | struct nfs4_lookup_root_arg args = { | 2661 | struct nfs4_lookup_root_arg args = { |
| 2519 | .bitmask = nfs4_fattr_bitmap, | 2662 | .bitmask = bitmask, |
| 2520 | }; | 2663 | }; |
| 2521 | struct nfs4_lookup_res res = { | 2664 | struct nfs4_lookup_res res = { |
| 2522 | .server = server, | 2665 | .server = server, |
| @@ -2529,6 +2672,13 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 2529 | .rpc_resp = &res, | 2672 | .rpc_resp = &res, |
| 2530 | }; | 2673 | }; |
| 2531 | 2674 | ||
| 2675 | bitmask[0] = nfs4_fattr_bitmap[0]; | ||
| 2676 | bitmask[1] = nfs4_fattr_bitmap[1]; | ||
| 2677 | /* | ||
| 2678 | * Process the label in the upcoming getfattr | ||
| 2679 | */ | ||
| 2680 | bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL; | ||
| 2681 | |||
| 2532 | nfs_fattr_init(info->fattr); | 2682 | nfs_fattr_init(info->fattr); |
| 2533 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2683 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
| 2534 | } | 2684 | } |
| @@ -2648,6 +2798,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh, | |||
| 2648 | { | 2798 | { |
| 2649 | int error; | 2799 | int error; |
| 2650 | struct nfs_fattr *fattr = info->fattr; | 2800 | struct nfs_fattr *fattr = info->fattr; |
| 2801 | struct nfs4_label *label = NULL; | ||
| 2651 | 2802 | ||
| 2652 | error = nfs4_server_capabilities(server, mntfh); | 2803 | error = nfs4_server_capabilities(server, mntfh); |
| 2653 | if (error < 0) { | 2804 | if (error < 0) { |
| @@ -2655,16 +2806,23 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh, | |||
| 2655 | return error; | 2806 | return error; |
| 2656 | } | 2807 | } |
| 2657 | 2808 | ||
| 2658 | error = nfs4_proc_getattr(server, mntfh, fattr); | 2809 | label = nfs4_label_alloc(server, GFP_KERNEL); |
| 2810 | if (IS_ERR(label)) | ||
| 2811 | return PTR_ERR(label); | ||
| 2812 | |||
| 2813 | error = nfs4_proc_getattr(server, mntfh, fattr, label); | ||
| 2659 | if (error < 0) { | 2814 | if (error < 0) { |
| 2660 | dprintk("nfs4_get_root: getattr error = %d\n", -error); | 2815 | dprintk("nfs4_get_root: getattr error = %d\n", -error); |
| 2661 | return error; | 2816 | goto err_free_label; |
| 2662 | } | 2817 | } |
| 2663 | 2818 | ||
| 2664 | if (fattr->valid & NFS_ATTR_FATTR_FSID && | 2819 | if (fattr->valid & NFS_ATTR_FATTR_FSID && |
| 2665 | !nfs_fsid_equal(&server->fsid, &fattr->fsid)) | 2820 | !nfs_fsid_equal(&server->fsid, &fattr->fsid)) |
| 2666 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); | 2821 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); |
| 2667 | 2822 | ||
| 2823 | err_free_label: | ||
| 2824 | nfs4_label_free(label); | ||
| 2825 | |||
| 2668 | return error; | 2826 | return error; |
| 2669 | } | 2827 | } |
| 2670 | 2828 | ||
| @@ -2711,7 +2869,8 @@ out: | |||
| 2711 | return status; | 2869 | return status; |
| 2712 | } | 2870 | } |
| 2713 | 2871 | ||
| 2714 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2872 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
| 2873 | struct nfs_fattr *fattr, struct nfs4_label *label) | ||
| 2715 | { | 2874 | { |
| 2716 | struct nfs4_getattr_arg args = { | 2875 | struct nfs4_getattr_arg args = { |
| 2717 | .fh = fhandle, | 2876 | .fh = fhandle, |
| @@ -2719,6 +2878,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 2719 | }; | 2878 | }; |
| 2720 | struct nfs4_getattr_res res = { | 2879 | struct nfs4_getattr_res res = { |
| 2721 | .fattr = fattr, | 2880 | .fattr = fattr, |
| 2881 | .label = label, | ||
| 2722 | .server = server, | 2882 | .server = server, |
| 2723 | }; | 2883 | }; |
| 2724 | struct rpc_message msg = { | 2884 | struct rpc_message msg = { |
| @@ -2726,18 +2886,21 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 2726 | .rpc_argp = &args, | 2886 | .rpc_argp = &args, |
| 2727 | .rpc_resp = &res, | 2887 | .rpc_resp = &res, |
| 2728 | }; | 2888 | }; |
| 2729 | 2889 | ||
| 2890 | args.bitmask = nfs4_bitmask(server, label); | ||
| 2891 | |||
| 2730 | nfs_fattr_init(fattr); | 2892 | nfs_fattr_init(fattr); |
| 2731 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2893 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
| 2732 | } | 2894 | } |
| 2733 | 2895 | ||
| 2734 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2896 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
| 2897 | struct nfs_fattr *fattr, struct nfs4_label *label) | ||
| 2735 | { | 2898 | { |
| 2736 | struct nfs4_exception exception = { }; | 2899 | struct nfs4_exception exception = { }; |
| 2737 | int err; | 2900 | int err; |
| 2738 | do { | 2901 | do { |
| 2739 | err = nfs4_handle_exception(server, | 2902 | err = nfs4_handle_exception(server, |
| 2740 | _nfs4_proc_getattr(server, fhandle, fattr), | 2903 | _nfs4_proc_getattr(server, fhandle, fattr, label), |
| 2741 | &exception); | 2904 | &exception); |
| 2742 | } while (exception.retry); | 2905 | } while (exception.retry); |
| 2743 | return err; | 2906 | return err; |
| @@ -2767,6 +2930,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 2767 | struct inode *inode = dentry->d_inode; | 2930 | struct inode *inode = dentry->d_inode; |
| 2768 | struct rpc_cred *cred = NULL; | 2931 | struct rpc_cred *cred = NULL; |
| 2769 | struct nfs4_state *state = NULL; | 2932 | struct nfs4_state *state = NULL; |
| 2933 | struct nfs4_label *label = NULL; | ||
| 2770 | int status; | 2934 | int status; |
| 2771 | 2935 | ||
| 2772 | if (pnfs_ld_layoutret_on_setattr(inode)) | 2936 | if (pnfs_ld_layoutret_on_setattr(inode)) |
| @@ -2793,15 +2957,22 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 2793 | } | 2957 | } |
| 2794 | } | 2958 | } |
| 2795 | 2959 | ||
| 2796 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state); | 2960 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); |
| 2797 | if (status == 0) | 2961 | if (IS_ERR(label)) |
| 2962 | return PTR_ERR(label); | ||
| 2963 | |||
| 2964 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); | ||
| 2965 | if (status == 0) { | ||
| 2798 | nfs_setattr_update_inode(inode, sattr); | 2966 | nfs_setattr_update_inode(inode, sattr); |
| 2967 | nfs_setsecurity(inode, fattr, label); | ||
| 2968 | } | ||
| 2969 | nfs4_label_free(label); | ||
| 2799 | return status; | 2970 | return status; |
| 2800 | } | 2971 | } |
| 2801 | 2972 | ||
| 2802 | static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | 2973 | static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, |
| 2803 | const struct qstr *name, struct nfs_fh *fhandle, | 2974 | const struct qstr *name, struct nfs_fh *fhandle, |
| 2804 | struct nfs_fattr *fattr) | 2975 | struct nfs_fattr *fattr, struct nfs4_label *label) |
| 2805 | { | 2976 | { |
| 2806 | struct nfs_server *server = NFS_SERVER(dir); | 2977 | struct nfs_server *server = NFS_SERVER(dir); |
| 2807 | int status; | 2978 | int status; |
| @@ -2813,6 +2984,7 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
| 2813 | struct nfs4_lookup_res res = { | 2984 | struct nfs4_lookup_res res = { |
| 2814 | .server = server, | 2985 | .server = server, |
| 2815 | .fattr = fattr, | 2986 | .fattr = fattr, |
| 2987 | .label = label, | ||
| 2816 | .fh = fhandle, | 2988 | .fh = fhandle, |
| 2817 | }; | 2989 | }; |
| 2818 | struct rpc_message msg = { | 2990 | struct rpc_message msg = { |
| @@ -2821,6 +2993,8 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
| 2821 | .rpc_resp = &res, | 2993 | .rpc_resp = &res, |
| 2822 | }; | 2994 | }; |
| 2823 | 2995 | ||
| 2996 | args.bitmask = nfs4_bitmask(server, label); | ||
| 2997 | |||
| 2824 | nfs_fattr_init(fattr); | 2998 | nfs_fattr_init(fattr); |
| 2825 | 2999 | ||
| 2826 | dprintk("NFS call lookup %s\n", name->name); | 3000 | dprintk("NFS call lookup %s\n", name->name); |
| @@ -2839,13 +3013,13 @@ static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr) | |||
| 2839 | 3013 | ||
| 2840 | static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | 3014 | static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, |
| 2841 | struct qstr *name, struct nfs_fh *fhandle, | 3015 | struct qstr *name, struct nfs_fh *fhandle, |
| 2842 | struct nfs_fattr *fattr) | 3016 | struct nfs_fattr *fattr, struct nfs4_label *label) |
| 2843 | { | 3017 | { |
| 2844 | struct nfs4_exception exception = { }; | 3018 | struct nfs4_exception exception = { }; |
| 2845 | struct rpc_clnt *client = *clnt; | 3019 | struct rpc_clnt *client = *clnt; |
| 2846 | int err; | 3020 | int err; |
| 2847 | do { | 3021 | do { |
| 2848 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr); | 3022 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label); |
| 2849 | switch (err) { | 3023 | switch (err) { |
| 2850 | case -NFS4ERR_BADNAME: | 3024 | case -NFS4ERR_BADNAME: |
| 2851 | err = -ENOENT; | 3025 | err = -ENOENT; |
| @@ -2879,12 +3053,13 @@ out: | |||
| 2879 | } | 3053 | } |
| 2880 | 3054 | ||
| 2881 | static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, | 3055 | static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, |
| 2882 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 3056 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, |
| 3057 | struct nfs4_label *label) | ||
| 2883 | { | 3058 | { |
| 2884 | int status; | 3059 | int status; |
| 2885 | struct rpc_clnt *client = NFS_CLIENT(dir); | 3060 | struct rpc_clnt *client = NFS_CLIENT(dir); |
| 2886 | 3061 | ||
| 2887 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | 3062 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label); |
| 2888 | if (client != NFS_CLIENT(dir)) { | 3063 | if (client != NFS_CLIENT(dir)) { |
| 2889 | rpc_shutdown_client(client); | 3064 | rpc_shutdown_client(client); |
| 2890 | nfs_fixup_secinfo_attributes(fattr); | 3065 | nfs_fixup_secinfo_attributes(fattr); |
| @@ -2899,7 +3074,7 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, | |||
| 2899 | int status; | 3074 | int status; |
| 2900 | struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); | 3075 | struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); |
| 2901 | 3076 | ||
| 2902 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | 3077 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL); |
| 2903 | if (status < 0) { | 3078 | if (status < 0) { |
| 2904 | rpc_shutdown_client(client); | 3079 | rpc_shutdown_client(client); |
| 2905 | return ERR_PTR(status); | 3080 | return ERR_PTR(status); |
| @@ -2924,7 +3099,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
| 2924 | .rpc_cred = entry->cred, | 3099 | .rpc_cred = entry->cred, |
| 2925 | }; | 3100 | }; |
| 2926 | int mode = entry->mask; | 3101 | int mode = entry->mask; |
| 2927 | int status; | 3102 | int status = 0; |
| 2928 | 3103 | ||
| 2929 | /* | 3104 | /* |
| 2930 | * Determine which access bits we want to ask for... | 3105 | * Determine which access bits we want to ask for... |
| @@ -3029,6 +3204,7 @@ static int | |||
| 3029 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 3204 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
| 3030 | int flags) | 3205 | int flags) |
| 3031 | { | 3206 | { |
| 3207 | struct nfs4_label l, *ilabel = NULL; | ||
| 3032 | struct nfs_open_context *ctx; | 3208 | struct nfs_open_context *ctx; |
| 3033 | struct nfs4_state *state; | 3209 | struct nfs4_state *state; |
| 3034 | int status = 0; | 3210 | int status = 0; |
| @@ -3037,19 +3213,16 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 3037 | if (IS_ERR(ctx)) | 3213 | if (IS_ERR(ctx)) |
| 3038 | return PTR_ERR(ctx); | 3214 | return PTR_ERR(ctx); |
| 3039 | 3215 | ||
| 3216 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
| 3217 | |||
| 3040 | sattr->ia_mode &= ~current_umask(); | 3218 | sattr->ia_mode &= ~current_umask(); |
| 3041 | state = nfs4_do_open(dir, dentry, ctx->mode, | 3219 | state = nfs4_do_open(dir, ctx, flags, sattr, ilabel); |
| 3042 | flags, sattr, ctx->cred, | ||
| 3043 | &ctx->mdsthreshold); | ||
| 3044 | d_drop(dentry); | ||
| 3045 | if (IS_ERR(state)) { | 3220 | if (IS_ERR(state)) { |
| 3046 | status = PTR_ERR(state); | 3221 | status = PTR_ERR(state); |
| 3047 | goto out; | 3222 | goto out; |
| 3048 | } | 3223 | } |
| 3049 | d_add(dentry, igrab(state->inode)); | ||
| 3050 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 3051 | ctx->state = state; | ||
| 3052 | out: | 3224 | out: |
| 3225 | nfs4_label_release_security(ilabel); | ||
| 3053 | put_nfs_open_context(ctx); | 3226 | put_nfs_open_context(ctx); |
| 3054 | return status; | 3227 | return status; |
| 3055 | } | 3228 | } |
| @@ -3098,6 +3271,8 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
| 3098 | res->server = server; | 3271 | res->server = server; |
| 3099 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 3272 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
| 3100 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | 3273 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); |
| 3274 | |||
| 3275 | nfs_fattr_init(res->dir_attr); | ||
| 3101 | } | 3276 | } |
| 3102 | 3277 | ||
| 3103 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) | 3278 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) |
| @@ -3173,7 +3348,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
| 3173 | .rpc_resp = &res, | 3348 | .rpc_resp = &res, |
| 3174 | }; | 3349 | }; |
| 3175 | int status = -ENOMEM; | 3350 | int status = -ENOMEM; |
| 3176 | 3351 | ||
| 3177 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3352 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
| 3178 | if (!status) { | 3353 | if (!status) { |
| 3179 | update_changeattr(old_dir, &res.old_cinfo); | 3354 | update_changeattr(old_dir, &res.old_cinfo); |
| @@ -3207,6 +3382,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
| 3207 | }; | 3382 | }; |
| 3208 | struct nfs4_link_res res = { | 3383 | struct nfs4_link_res res = { |
| 3209 | .server = server, | 3384 | .server = server, |
| 3385 | .label = NULL, | ||
| 3210 | }; | 3386 | }; |
| 3211 | struct rpc_message msg = { | 3387 | struct rpc_message msg = { |
| 3212 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], | 3388 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], |
| @@ -3219,11 +3395,24 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
| 3219 | if (res.fattr == NULL) | 3395 | if (res.fattr == NULL) |
| 3220 | goto out; | 3396 | goto out; |
| 3221 | 3397 | ||
| 3398 | res.label = nfs4_label_alloc(server, GFP_KERNEL); | ||
| 3399 | if (IS_ERR(res.label)) { | ||
| 3400 | status = PTR_ERR(res.label); | ||
| 3401 | goto out; | ||
| 3402 | } | ||
| 3403 | arg.bitmask = nfs4_bitmask(server, res.label); | ||
| 3404 | |||
| 3222 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3405 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
| 3223 | if (!status) { | 3406 | if (!status) { |
| 3224 | update_changeattr(dir, &res.cinfo); | 3407 | update_changeattr(dir, &res.cinfo); |
| 3225 | nfs_post_op_update_inode(inode, res.fattr); | 3408 | status = nfs_post_op_update_inode(inode, res.fattr); |
| 3409 | if (!status) | ||
| 3410 | nfs_setsecurity(inode, res.fattr, res.label); | ||
| 3226 | } | 3411 | } |
| 3412 | |||
| 3413 | |||
| 3414 | nfs4_label_free(res.label); | ||
| 3415 | |||
| 3227 | out: | 3416 | out: |
| 3228 | nfs_free_fattr(res.fattr); | 3417 | nfs_free_fattr(res.fattr); |
| 3229 | return status; | 3418 | return status; |
| @@ -3247,6 +3436,7 @@ struct nfs4_createdata { | |||
| 3247 | struct nfs4_create_res res; | 3436 | struct nfs4_create_res res; |
| 3248 | struct nfs_fh fh; | 3437 | struct nfs_fh fh; |
| 3249 | struct nfs_fattr fattr; | 3438 | struct nfs_fattr fattr; |
| 3439 | struct nfs4_label *label; | ||
| 3250 | }; | 3440 | }; |
| 3251 | 3441 | ||
| 3252 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | 3442 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, |
| @@ -3258,6 +3448,10 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
| 3258 | if (data != NULL) { | 3448 | if (data != NULL) { |
| 3259 | struct nfs_server *server = NFS_SERVER(dir); | 3449 | struct nfs_server *server = NFS_SERVER(dir); |
| 3260 | 3450 | ||
| 3451 | data->label = nfs4_label_alloc(server, GFP_KERNEL); | ||
| 3452 | if (IS_ERR(data->label)) | ||
| 3453 | goto out_free; | ||
| 3454 | |||
| 3261 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; | 3455 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; |
| 3262 | data->msg.rpc_argp = &data->arg; | 3456 | data->msg.rpc_argp = &data->arg; |
| 3263 | data->msg.rpc_resp = &data->res; | 3457 | data->msg.rpc_resp = &data->res; |
| @@ -3266,13 +3460,17 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
| 3266 | data->arg.name = name; | 3460 | data->arg.name = name; |
| 3267 | data->arg.attrs = sattr; | 3461 | data->arg.attrs = sattr; |
| 3268 | data->arg.ftype = ftype; | 3462 | data->arg.ftype = ftype; |
| 3269 | data->arg.bitmask = server->attr_bitmask; | 3463 | data->arg.bitmask = nfs4_bitmask(server, data->label); |
| 3270 | data->res.server = server; | 3464 | data->res.server = server; |
| 3271 | data->res.fh = &data->fh; | 3465 | data->res.fh = &data->fh; |
| 3272 | data->res.fattr = &data->fattr; | 3466 | data->res.fattr = &data->fattr; |
| 3467 | data->res.label = data->label; | ||
| 3273 | nfs_fattr_init(data->res.fattr); | 3468 | nfs_fattr_init(data->res.fattr); |
| 3274 | } | 3469 | } |
| 3275 | return data; | 3470 | return data; |
| 3471 | out_free: | ||
| 3472 | kfree(data); | ||
| 3473 | return NULL; | ||
| 3276 | } | 3474 | } |
| 3277 | 3475 | ||
| 3278 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) | 3476 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) |
| @@ -3281,18 +3479,20 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_ | |||
| 3281 | &data->arg.seq_args, &data->res.seq_res, 1); | 3479 | &data->arg.seq_args, &data->res.seq_res, 1); |
| 3282 | if (status == 0) { | 3480 | if (status == 0) { |
| 3283 | update_changeattr(dir, &data->res.dir_cinfo); | 3481 | update_changeattr(dir, &data->res.dir_cinfo); |
| 3284 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 3482 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label); |
| 3285 | } | 3483 | } |
| 3286 | return status; | 3484 | return status; |
| 3287 | } | 3485 | } |
| 3288 | 3486 | ||
| 3289 | static void nfs4_free_createdata(struct nfs4_createdata *data) | 3487 | static void nfs4_free_createdata(struct nfs4_createdata *data) |
| 3290 | { | 3488 | { |
| 3489 | nfs4_label_free(data->label); | ||
| 3291 | kfree(data); | 3490 | kfree(data); |
| 3292 | } | 3491 | } |
| 3293 | 3492 | ||
| 3294 | static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | 3493 | static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, |
| 3295 | struct page *page, unsigned int len, struct iattr *sattr) | 3494 | struct page *page, unsigned int len, struct iattr *sattr, |
| 3495 | struct nfs4_label *label) | ||
| 3296 | { | 3496 | { |
| 3297 | struct nfs4_createdata *data; | 3497 | struct nfs4_createdata *data; |
| 3298 | int status = -ENAMETOOLONG; | 3498 | int status = -ENAMETOOLONG; |
| @@ -3308,6 +3508,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
| 3308 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK]; | 3508 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK]; |
| 3309 | data->arg.u.symlink.pages = &page; | 3509 | data->arg.u.symlink.pages = &page; |
| 3310 | data->arg.u.symlink.len = len; | 3510 | data->arg.u.symlink.len = len; |
| 3511 | data->arg.label = label; | ||
| 3311 | 3512 | ||
| 3312 | status = nfs4_do_create(dir, dentry, data); | 3513 | status = nfs4_do_create(dir, dentry, data); |
| 3313 | 3514 | ||
| @@ -3320,18 +3521,24 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
| 3320 | struct page *page, unsigned int len, struct iattr *sattr) | 3521 | struct page *page, unsigned int len, struct iattr *sattr) |
| 3321 | { | 3522 | { |
| 3322 | struct nfs4_exception exception = { }; | 3523 | struct nfs4_exception exception = { }; |
| 3524 | struct nfs4_label l, *label = NULL; | ||
| 3323 | int err; | 3525 | int err; |
| 3526 | |||
| 3527 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
| 3528 | |||
| 3324 | do { | 3529 | do { |
| 3325 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3530 | err = nfs4_handle_exception(NFS_SERVER(dir), |
| 3326 | _nfs4_proc_symlink(dir, dentry, page, | 3531 | _nfs4_proc_symlink(dir, dentry, page, |
| 3327 | len, sattr), | 3532 | len, sattr, label), |
| 3328 | &exception); | 3533 | &exception); |
| 3329 | } while (exception.retry); | 3534 | } while (exception.retry); |
| 3535 | |||
| 3536 | nfs4_label_release_security(label); | ||
| 3330 | return err; | 3537 | return err; |
| 3331 | } | 3538 | } |
| 3332 | 3539 | ||
| 3333 | static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | 3540 | static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, |
| 3334 | struct iattr *sattr) | 3541 | struct iattr *sattr, struct nfs4_label *label) |
| 3335 | { | 3542 | { |
| 3336 | struct nfs4_createdata *data; | 3543 | struct nfs4_createdata *data; |
| 3337 | int status = -ENOMEM; | 3544 | int status = -ENOMEM; |
| @@ -3340,6 +3547,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
| 3340 | if (data == NULL) | 3547 | if (data == NULL) |
| 3341 | goto out; | 3548 | goto out; |
| 3342 | 3549 | ||
| 3550 | data->arg.label = label; | ||
| 3343 | status = nfs4_do_create(dir, dentry, data); | 3551 | status = nfs4_do_create(dir, dentry, data); |
| 3344 | 3552 | ||
| 3345 | nfs4_free_createdata(data); | 3553 | nfs4_free_createdata(data); |
| @@ -3351,14 +3559,19 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
| 3351 | struct iattr *sattr) | 3559 | struct iattr *sattr) |
| 3352 | { | 3560 | { |
| 3353 | struct nfs4_exception exception = { }; | 3561 | struct nfs4_exception exception = { }; |
| 3562 | struct nfs4_label l, *label = NULL; | ||
| 3354 | int err; | 3563 | int err; |
| 3355 | 3564 | ||
| 3565 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
| 3566 | |||
| 3356 | sattr->ia_mode &= ~current_umask(); | 3567 | sattr->ia_mode &= ~current_umask(); |
| 3357 | do { | 3568 | do { |
| 3358 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3569 | err = nfs4_handle_exception(NFS_SERVER(dir), |
| 3359 | _nfs4_proc_mkdir(dir, dentry, sattr), | 3570 | _nfs4_proc_mkdir(dir, dentry, sattr, label), |
| 3360 | &exception); | 3571 | &exception); |
| 3361 | } while (exception.retry); | 3572 | } while (exception.retry); |
| 3573 | nfs4_label_release_security(label); | ||
| 3574 | |||
| 3362 | return err; | 3575 | return err; |
| 3363 | } | 3576 | } |
| 3364 | 3577 | ||
| @@ -3416,7 +3629,7 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
| 3416 | } | 3629 | } |
| 3417 | 3630 | ||
| 3418 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | 3631 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, |
| 3419 | struct iattr *sattr, dev_t rdev) | 3632 | struct iattr *sattr, struct nfs4_label *label, dev_t rdev) |
| 3420 | { | 3633 | { |
| 3421 | struct nfs4_createdata *data; | 3634 | struct nfs4_createdata *data; |
| 3422 | int mode = sattr->ia_mode; | 3635 | int mode = sattr->ia_mode; |
| @@ -3441,7 +3654,8 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
| 3441 | status = -EINVAL; | 3654 | status = -EINVAL; |
| 3442 | goto out_free; | 3655 | goto out_free; |
| 3443 | } | 3656 | } |
| 3444 | 3657 | ||
| 3658 | data->arg.label = label; | ||
| 3445 | status = nfs4_do_create(dir, dentry, data); | 3659 | status = nfs4_do_create(dir, dentry, data); |
| 3446 | out_free: | 3660 | out_free: |
| 3447 | nfs4_free_createdata(data); | 3661 | nfs4_free_createdata(data); |
| @@ -3453,14 +3667,20 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
| 3453 | struct iattr *sattr, dev_t rdev) | 3667 | struct iattr *sattr, dev_t rdev) |
| 3454 | { | 3668 | { |
| 3455 | struct nfs4_exception exception = { }; | 3669 | struct nfs4_exception exception = { }; |
| 3670 | struct nfs4_label l, *label = NULL; | ||
| 3456 | int err; | 3671 | int err; |
| 3457 | 3672 | ||
| 3673 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
| 3674 | |||
| 3458 | sattr->ia_mode &= ~current_umask(); | 3675 | sattr->ia_mode &= ~current_umask(); |
| 3459 | do { | 3676 | do { |
| 3460 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3677 | err = nfs4_handle_exception(NFS_SERVER(dir), |
| 3461 | _nfs4_proc_mknod(dir, dentry, sattr, rdev), | 3678 | _nfs4_proc_mknod(dir, dentry, sattr, label, rdev), |
| 3462 | &exception); | 3679 | &exception); |
| 3463 | } while (exception.retry); | 3680 | } while (exception.retry); |
| 3681 | |||
| 3682 | nfs4_label_release_security(label); | ||
| 3683 | |||
| 3464 | return err; | 3684 | return err; |
| 3465 | } | 3685 | } |
| 3466 | 3686 | ||
| @@ -4187,6 +4407,155 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
| 4187 | return err; | 4407 | return err; |
| 4188 | } | 4408 | } |
| 4189 | 4409 | ||
| 4410 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 4411 | static int _nfs4_get_security_label(struct inode *inode, void *buf, | ||
| 4412 | size_t buflen) | ||
| 4413 | { | ||
| 4414 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 4415 | struct nfs_fattr fattr; | ||
| 4416 | struct nfs4_label label = {0, 0, buflen, buf}; | ||
| 4417 | |||
| 4418 | u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
| 4419 | struct nfs4_getattr_arg args = { | ||
| 4420 | .fh = NFS_FH(inode), | ||
| 4421 | .bitmask = bitmask, | ||
| 4422 | }; | ||
| 4423 | struct nfs4_getattr_res res = { | ||
| 4424 | .fattr = &fattr, | ||
| 4425 | .label = &label, | ||
| 4426 | .server = server, | ||
| 4427 | }; | ||
| 4428 | struct rpc_message msg = { | ||
| 4429 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR], | ||
| 4430 | .rpc_argp = &args, | ||
| 4431 | .rpc_resp = &res, | ||
| 4432 | }; | ||
| 4433 | int ret; | ||
| 4434 | |||
| 4435 | nfs_fattr_init(&fattr); | ||
| 4436 | |||
| 4437 | ret = rpc_call_sync(server->client, &msg, 0); | ||
| 4438 | if (ret) | ||
| 4439 | return ret; | ||
| 4440 | if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) | ||
| 4441 | return -ENOENT; | ||
| 4442 | if (buflen < label.len) | ||
| 4443 | return -ERANGE; | ||
| 4444 | return 0; | ||
| 4445 | } | ||
| 4446 | |||
| 4447 | static int nfs4_get_security_label(struct inode *inode, void *buf, | ||
| 4448 | size_t buflen) | ||
| 4449 | { | ||
| 4450 | struct nfs4_exception exception = { }; | ||
| 4451 | int err; | ||
| 4452 | |||
| 4453 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
| 4454 | return -EOPNOTSUPP; | ||
| 4455 | |||
| 4456 | do { | ||
| 4457 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
| 4458 | _nfs4_get_security_label(inode, buf, buflen), | ||
| 4459 | &exception); | ||
| 4460 | } while (exception.retry); | ||
| 4461 | return err; | ||
| 4462 | } | ||
| 4463 | |||
| 4464 | static int _nfs4_do_set_security_label(struct inode *inode, | ||
| 4465 | struct nfs4_label *ilabel, | ||
| 4466 | struct nfs_fattr *fattr, | ||
| 4467 | struct nfs4_label *olabel) | ||
| 4468 | { | ||
| 4469 | |||
| 4470 | struct iattr sattr = {0}; | ||
| 4471 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 4472 | const u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
| 4473 | struct nfs_setattrargs args = { | ||
| 4474 | .fh = NFS_FH(inode), | ||
| 4475 | .iap = &sattr, | ||
| 4476 | .server = server, | ||
| 4477 | .bitmask = bitmask, | ||
| 4478 | .label = ilabel, | ||
| 4479 | }; | ||
| 4480 | struct nfs_setattrres res = { | ||
| 4481 | .fattr = fattr, | ||
| 4482 | .label = olabel, | ||
| 4483 | .server = server, | ||
| 4484 | }; | ||
| 4485 | struct rpc_message msg = { | ||
| 4486 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], | ||
| 4487 | .rpc_argp = &args, | ||
| 4488 | .rpc_resp = &res, | ||
| 4489 | }; | ||
| 4490 | int status; | ||
| 4491 | |||
| 4492 | nfs4_stateid_copy(&args.stateid, &zero_stateid); | ||
| 4493 | |||
| 4494 | status = rpc_call_sync(server->client, &msg, 0); | ||
| 4495 | if (status) | ||
| 4496 | dprintk("%s failed: %d\n", __func__, status); | ||
| 4497 | |||
| 4498 | return status; | ||
| 4499 | } | ||
| 4500 | |||
| 4501 | static int nfs4_do_set_security_label(struct inode *inode, | ||
| 4502 | struct nfs4_label *ilabel, | ||
| 4503 | struct nfs_fattr *fattr, | ||
| 4504 | struct nfs4_label *olabel) | ||
| 4505 | { | ||
| 4506 | struct nfs4_exception exception = { }; | ||
| 4507 | int err; | ||
| 4508 | |||
| 4509 | do { | ||
| 4510 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
| 4511 | _nfs4_do_set_security_label(inode, ilabel, | ||
| 4512 | fattr, olabel), | ||
| 4513 | &exception); | ||
| 4514 | } while (exception.retry); | ||
| 4515 | return err; | ||
| 4516 | } | ||
| 4517 | |||
| 4518 | static int | ||
| 4519 | nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen) | ||
| 4520 | { | ||
| 4521 | struct nfs4_label ilabel, *olabel = NULL; | ||
| 4522 | struct nfs_fattr fattr; | ||
| 4523 | struct rpc_cred *cred; | ||
| 4524 | struct inode *inode = dentry->d_inode; | ||
| 4525 | int status; | ||
| 4526 | |||
| 4527 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
| 4528 | return -EOPNOTSUPP; | ||
| 4529 | |||
| 4530 | nfs_fattr_init(&fattr); | ||
| 4531 | |||
| 4532 | ilabel.pi = 0; | ||
| 4533 | ilabel.lfs = 0; | ||
| 4534 | ilabel.label = (char *)buf; | ||
| 4535 | ilabel.len = buflen; | ||
| 4536 | |||
| 4537 | cred = rpc_lookup_cred(); | ||
| 4538 | if (IS_ERR(cred)) | ||
| 4539 | return PTR_ERR(cred); | ||
| 4540 | |||
| 4541 | olabel = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); | ||
| 4542 | if (IS_ERR(olabel)) { | ||
| 4543 | status = -PTR_ERR(olabel); | ||
| 4544 | goto out; | ||
| 4545 | } | ||
| 4546 | |||
| 4547 | status = nfs4_do_set_security_label(inode, &ilabel, &fattr, olabel); | ||
| 4548 | if (status == 0) | ||
| 4549 | nfs_setsecurity(inode, &fattr, olabel); | ||
| 4550 | |||
| 4551 | nfs4_label_free(olabel); | ||
| 4552 | out: | ||
| 4553 | put_rpccred(cred); | ||
| 4554 | return status; | ||
| 4555 | } | ||
| 4556 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | ||
| 4557 | |||
| 4558 | |||
| 4190 | static int | 4559 | static int |
| 4191 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | 4560 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) |
| 4192 | { | 4561 | { |
| @@ -4345,7 +4714,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
| 4345 | /* cb_client4 */ | 4714 | /* cb_client4 */ |
| 4346 | rcu_read_lock(); | 4715 | rcu_read_lock(); |
| 4347 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | 4716 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
| 4348 | sizeof(setclientid.sc_netid), | 4717 | sizeof(setclientid.sc_netid), "%s", |
| 4349 | rpc_peeraddr2str(clp->cl_rpcclient, | 4718 | rpc_peeraddr2str(clp->cl_rpcclient, |
| 4350 | RPC_DISPLAY_NETID)); | 4719 | RPC_DISPLAY_NETID)); |
| 4351 | rcu_read_unlock(); | 4720 | rcu_read_unlock(); |
| @@ -5056,13 +5425,18 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
| 5056 | 5425 | ||
| 5057 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { | 5426 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { |
| 5058 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { | 5427 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { |
| 5059 | status = nfs41_test_stateid(server, &lsp->ls_stateid); | 5428 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; |
| 5429 | |||
| 5430 | status = nfs41_test_stateid(server, | ||
| 5431 | &lsp->ls_stateid, | ||
| 5432 | cred); | ||
| 5060 | if (status != NFS_OK) { | 5433 | if (status != NFS_OK) { |
| 5061 | /* Free the stateid unless the server | 5434 | /* Free the stateid unless the server |
| 5062 | * informs us the stateid is unrecognized. */ | 5435 | * informs us the stateid is unrecognized. */ |
| 5063 | if (status != -NFS4ERR_BAD_STATEID) | 5436 | if (status != -NFS4ERR_BAD_STATEID) |
| 5064 | nfs41_free_stateid(server, | 5437 | nfs41_free_stateid(server, |
| 5065 | &lsp->ls_stateid); | 5438 | &lsp->ls_stateid, |
| 5439 | cred); | ||
| 5066 | clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); | 5440 | clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); |
| 5067 | ret = status; | 5441 | ret = status; |
| 5068 | } | 5442 | } |
| @@ -5295,6 +5669,53 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list, | |||
| 5295 | return len; | 5669 | return len; |
| 5296 | } | 5670 | } |
| 5297 | 5671 | ||
| 5672 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 5673 | static inline int nfs4_server_supports_labels(struct nfs_server *server) | ||
| 5674 | { | ||
| 5675 | return server->caps & NFS_CAP_SECURITY_LABEL; | ||
| 5676 | } | ||
| 5677 | |||
| 5678 | static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key, | ||
| 5679 | const void *buf, size_t buflen, | ||
| 5680 | int flags, int type) | ||
| 5681 | { | ||
| 5682 | if (security_ismaclabel(key)) | ||
| 5683 | return nfs4_set_security_label(dentry, buf, buflen); | ||
| 5684 | |||
| 5685 | return -EOPNOTSUPP; | ||
| 5686 | } | ||
| 5687 | |||
| 5688 | static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key, | ||
| 5689 | void *buf, size_t buflen, int type) | ||
| 5690 | { | ||
| 5691 | if (security_ismaclabel(key)) | ||
| 5692 | return nfs4_get_security_label(dentry->d_inode, buf, buflen); | ||
| 5693 | return -EOPNOTSUPP; | ||
| 5694 | } | ||
| 5695 | |||
| 5696 | static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list, | ||
| 5697 | size_t list_len, const char *name, | ||
| 5698 | size_t name_len, int type) | ||
| 5699 | { | ||
| 5700 | size_t len = 0; | ||
| 5701 | |||
| 5702 | if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL)) { | ||
| 5703 | len = security_inode_listsecurity(dentry->d_inode, NULL, 0); | ||
| 5704 | if (list && len <= list_len) | ||
| 5705 | security_inode_listsecurity(dentry->d_inode, list, len); | ||
| 5706 | } | ||
| 5707 | return len; | ||
| 5708 | } | ||
| 5709 | |||
| 5710 | static const struct xattr_handler nfs4_xattr_nfs4_label_handler = { | ||
| 5711 | .prefix = XATTR_SECURITY_PREFIX, | ||
| 5712 | .list = nfs4_xattr_list_nfs4_label, | ||
| 5713 | .get = nfs4_xattr_get_nfs4_label, | ||
| 5714 | .set = nfs4_xattr_set_nfs4_label, | ||
| 5715 | }; | ||
| 5716 | #endif | ||
| 5717 | |||
| 5718 | |||
| 5298 | /* | 5719 | /* |
| 5299 | * nfs_fhget will use either the mounted_on_fileid or the fileid | 5720 | * nfs_fhget will use either the mounted_on_fileid or the fileid |
| 5300 | */ | 5721 | */ |
| @@ -5318,7 +5739,7 @@ static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |||
| 5318 | struct page *page) | 5739 | struct page *page) |
| 5319 | { | 5740 | { |
| 5320 | struct nfs_server *server = NFS_SERVER(dir); | 5741 | struct nfs_server *server = NFS_SERVER(dir); |
| 5321 | u32 bitmask[2] = { | 5742 | u32 bitmask[3] = { |
| 5322 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, | 5743 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, |
| 5323 | }; | 5744 | }; |
| 5324 | struct nfs4_fs_locations_arg args = { | 5745 | struct nfs4_fs_locations_arg args = { |
| @@ -5505,7 +5926,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 5505 | struct nfs41_exchange_id_args args = { | 5926 | struct nfs41_exchange_id_args args = { |
| 5506 | .verifier = &verifier, | 5927 | .verifier = &verifier, |
| 5507 | .client = clp, | 5928 | .client = clp, |
| 5508 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, | 5929 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER | |
| 5930 | EXCHGID4_FLAG_BIND_PRINC_STATEID, | ||
| 5509 | }; | 5931 | }; |
| 5510 | struct nfs41_exchange_id_res res = { | 5932 | struct nfs41_exchange_id_res res = { |
| 5511 | 0 | 5933 | 0 |
| @@ -5762,17 +6184,14 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
| 5762 | */ | 6184 | */ |
| 5763 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | 6185 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) |
| 5764 | { | 6186 | { |
| 5765 | struct nfs4_session *session = args->client->cl_session; | 6187 | unsigned int max_rqst_sz, max_resp_sz; |
| 5766 | unsigned int mxrqst_sz = session->fc_target_max_rqst_sz, | 6188 | |
| 5767 | mxresp_sz = session->fc_target_max_resp_sz; | 6189 | max_rqst_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxwrite_overhead; |
| 6190 | max_resp_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxread_overhead; | ||
| 5768 | 6191 | ||
| 5769 | if (mxrqst_sz == 0) | ||
| 5770 | mxrqst_sz = NFS_MAX_FILE_IO_SIZE; | ||
| 5771 | if (mxresp_sz == 0) | ||
| 5772 | mxresp_sz = NFS_MAX_FILE_IO_SIZE; | ||
| 5773 | /* Fore channel attributes */ | 6192 | /* Fore channel attributes */ |
| 5774 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 6193 | args->fc_attrs.max_rqst_sz = max_rqst_sz; |
| 5775 | args->fc_attrs.max_resp_sz = mxresp_sz; | 6194 | args->fc_attrs.max_resp_sz = max_resp_sz; |
| 5776 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 6195 | args->fc_attrs.max_ops = NFS4_MAX_OPS; |
| 5777 | args->fc_attrs.max_reqs = max_session_slots; | 6196 | args->fc_attrs.max_reqs = max_session_slots; |
| 5778 | 6197 | ||
| @@ -6159,12 +6578,14 @@ static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = { | |||
| 6159 | /* | 6578 | /* |
| 6160 | * Issue a global reclaim complete. | 6579 | * Issue a global reclaim complete. |
| 6161 | */ | 6580 | */ |
| 6162 | static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | 6581 | static int nfs41_proc_reclaim_complete(struct nfs_client *clp, |
| 6582 | struct rpc_cred *cred) | ||
| 6163 | { | 6583 | { |
| 6164 | struct nfs4_reclaim_complete_data *calldata; | 6584 | struct nfs4_reclaim_complete_data *calldata; |
| 6165 | struct rpc_task *task; | 6585 | struct rpc_task *task; |
| 6166 | struct rpc_message msg = { | 6586 | struct rpc_message msg = { |
| 6167 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE], | 6587 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE], |
| 6588 | .rpc_cred = cred, | ||
| 6168 | }; | 6589 | }; |
| 6169 | struct rpc_task_setup task_setup_data = { | 6590 | struct rpc_task_setup task_setup_data = { |
| 6170 | .rpc_client = clp->cl_rpcclient, | 6591 | .rpc_client = clp->cl_rpcclient, |
| @@ -6348,6 +6769,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
| 6348 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], | 6769 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], |
| 6349 | .rpc_argp = &lgp->args, | 6770 | .rpc_argp = &lgp->args, |
| 6350 | .rpc_resp = &lgp->res, | 6771 | .rpc_resp = &lgp->res, |
| 6772 | .rpc_cred = lgp->cred, | ||
| 6351 | }; | 6773 | }; |
| 6352 | struct rpc_task_setup task_setup_data = { | 6774 | struct rpc_task_setup task_setup_data = { |
| 6353 | .rpc_client = server->client, | 6775 | .rpc_client = server->client, |
| @@ -6451,6 +6873,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
| 6451 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN], | 6873 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN], |
| 6452 | .rpc_argp = &lrp->args, | 6874 | .rpc_argp = &lrp->args, |
| 6453 | .rpc_resp = &lrp->res, | 6875 | .rpc_resp = &lrp->res, |
| 6876 | .rpc_cred = lrp->cred, | ||
| 6454 | }; | 6877 | }; |
| 6455 | struct rpc_task_setup task_setup_data = { | 6878 | struct rpc_task_setup task_setup_data = { |
| 6456 | .rpc_client = lrp->clp->cl_rpcclient, | 6879 | .rpc_client = lrp->clp->cl_rpcclient, |
| @@ -6520,7 +6943,9 @@ int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
| 6520 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); | 6943 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); |
| 6521 | 6944 | ||
| 6522 | static int | 6945 | static int |
| 6523 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | 6946 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, |
| 6947 | struct pnfs_device *pdev, | ||
| 6948 | struct rpc_cred *cred) | ||
| 6524 | { | 6949 | { |
| 6525 | struct nfs4_getdeviceinfo_args args = { | 6950 | struct nfs4_getdeviceinfo_args args = { |
| 6526 | .pdev = pdev, | 6951 | .pdev = pdev, |
| @@ -6532,6 +6957,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
| 6532 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO], | 6957 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO], |
| 6533 | .rpc_argp = &args, | 6958 | .rpc_argp = &args, |
| 6534 | .rpc_resp = &res, | 6959 | .rpc_resp = &res, |
| 6960 | .rpc_cred = cred, | ||
| 6535 | }; | 6961 | }; |
| 6536 | int status; | 6962 | int status; |
| 6537 | 6963 | ||
| @@ -6542,14 +6968,16 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
| 6542 | return status; | 6968 | return status; |
| 6543 | } | 6969 | } |
| 6544 | 6970 | ||
| 6545 | int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | 6971 | int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
| 6972 | struct pnfs_device *pdev, | ||
| 6973 | struct rpc_cred *cred) | ||
| 6546 | { | 6974 | { |
| 6547 | struct nfs4_exception exception = { }; | 6975 | struct nfs4_exception exception = { }; |
| 6548 | int err; | 6976 | int err; |
| 6549 | 6977 | ||
| 6550 | do { | 6978 | do { |
| 6551 | err = nfs4_handle_exception(server, | 6979 | err = nfs4_handle_exception(server, |
| 6552 | _nfs4_proc_getdeviceinfo(server, pdev), | 6980 | _nfs4_proc_getdeviceinfo(server, pdev, cred), |
| 6553 | &exception); | 6981 | &exception); |
| 6554 | } while (exception.retry); | 6982 | } while (exception.retry); |
| 6555 | return err; | 6983 | return err; |
| @@ -6733,7 +7161,9 @@ out: | |||
| 6733 | return err; | 7161 | return err; |
| 6734 | } | 7162 | } |
| 6735 | 7163 | ||
| 6736 | static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7164 | static int _nfs41_test_stateid(struct nfs_server *server, |
| 7165 | nfs4_stateid *stateid, | ||
| 7166 | struct rpc_cred *cred) | ||
| 6737 | { | 7167 | { |
| 6738 | int status; | 7168 | int status; |
| 6739 | struct nfs41_test_stateid_args args = { | 7169 | struct nfs41_test_stateid_args args = { |
| @@ -6744,6 +7174,7 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
| 6744 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], | 7174 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], |
| 6745 | .rpc_argp = &args, | 7175 | .rpc_argp = &args, |
| 6746 | .rpc_resp = &res, | 7176 | .rpc_resp = &res, |
| 7177 | .rpc_cred = cred, | ||
| 6747 | }; | 7178 | }; |
| 6748 | 7179 | ||
| 6749 | dprintk("NFS call test_stateid %p\n", stateid); | 7180 | dprintk("NFS call test_stateid %p\n", stateid); |
| @@ -6764,17 +7195,20 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
| 6764 | * | 7195 | * |
| 6765 | * @server: server / transport on which to perform the operation | 7196 | * @server: server / transport on which to perform the operation |
| 6766 | * @stateid: state ID to test | 7197 | * @stateid: state ID to test |
| 7198 | * @cred: credential | ||
| 6767 | * | 7199 | * |
| 6768 | * Returns NFS_OK if the server recognizes that "stateid" is valid. | 7200 | * Returns NFS_OK if the server recognizes that "stateid" is valid. |
| 6769 | * Otherwise a negative NFS4ERR value is returned if the operation | 7201 | * Otherwise a negative NFS4ERR value is returned if the operation |
| 6770 | * failed or the state ID is not currently valid. | 7202 | * failed or the state ID is not currently valid. |
| 6771 | */ | 7203 | */ |
| 6772 | static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7204 | static int nfs41_test_stateid(struct nfs_server *server, |
| 7205 | nfs4_stateid *stateid, | ||
| 7206 | struct rpc_cred *cred) | ||
| 6773 | { | 7207 | { |
| 6774 | struct nfs4_exception exception = { }; | 7208 | struct nfs4_exception exception = { }; |
| 6775 | int err; | 7209 | int err; |
| 6776 | do { | 7210 | do { |
| 6777 | err = _nfs41_test_stateid(server, stateid); | 7211 | err = _nfs41_test_stateid(server, stateid, cred); |
| 6778 | if (err != -NFS4ERR_DELAY) | 7212 | if (err != -NFS4ERR_DELAY) |
| 6779 | break; | 7213 | break; |
| 6780 | nfs4_handle_exception(server, err, &exception); | 7214 | nfs4_handle_exception(server, err, &exception); |
| @@ -6823,10 +7257,12 @@ const struct rpc_call_ops nfs41_free_stateid_ops = { | |||
| 6823 | 7257 | ||
| 6824 | static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | 7258 | static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, |
| 6825 | nfs4_stateid *stateid, | 7259 | nfs4_stateid *stateid, |
| 7260 | struct rpc_cred *cred, | ||
| 6826 | bool privileged) | 7261 | bool privileged) |
| 6827 | { | 7262 | { |
| 6828 | struct rpc_message msg = { | 7263 | struct rpc_message msg = { |
| 6829 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], | 7264 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], |
| 7265 | .rpc_cred = cred, | ||
| 6830 | }; | 7266 | }; |
| 6831 | struct rpc_task_setup task_setup = { | 7267 | struct rpc_task_setup task_setup = { |
| 6832 | .rpc_client = server->client, | 7268 | .rpc_client = server->client, |
| @@ -6859,16 +7295,19 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | |||
| 6859 | * | 7295 | * |
| 6860 | * @server: server / transport on which to perform the operation | 7296 | * @server: server / transport on which to perform the operation |
| 6861 | * @stateid: state ID to release | 7297 | * @stateid: state ID to release |
| 7298 | * @cred: credential | ||
| 6862 | * | 7299 | * |
| 6863 | * Returns NFS_OK if the server freed "stateid". Otherwise a | 7300 | * Returns NFS_OK if the server freed "stateid". Otherwise a |
| 6864 | * negative NFS4ERR value is returned. | 7301 | * negative NFS4ERR value is returned. |
| 6865 | */ | 7302 | */ |
| 6866 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7303 | static int nfs41_free_stateid(struct nfs_server *server, |
| 7304 | nfs4_stateid *stateid, | ||
| 7305 | struct rpc_cred *cred) | ||
| 6867 | { | 7306 | { |
| 6868 | struct rpc_task *task; | 7307 | struct rpc_task *task; |
| 6869 | int ret; | 7308 | int ret; |
| 6870 | 7309 | ||
| 6871 | task = _nfs41_free_stateid(server, stateid, true); | 7310 | task = _nfs41_free_stateid(server, stateid, cred, true); |
| 6872 | if (IS_ERR(task)) | 7311 | if (IS_ERR(task)) |
| 6873 | return PTR_ERR(task); | 7312 | return PTR_ERR(task); |
| 6874 | ret = rpc_wait_for_completion_task(task); | 7313 | ret = rpc_wait_for_completion_task(task); |
| @@ -6881,8 +7320,9 @@ static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
| 6881 | static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp) | 7320 | static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp) |
| 6882 | { | 7321 | { |
| 6883 | struct rpc_task *task; | 7322 | struct rpc_task *task; |
| 7323 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; | ||
| 6884 | 7324 | ||
| 6885 | task = _nfs41_free_stateid(server, &lsp->ls_stateid, false); | 7325 | task = _nfs41_free_stateid(server, &lsp->ls_stateid, cred, false); |
| 6886 | nfs4_free_lock_state(server, lsp); | 7326 | nfs4_free_lock_state(server, lsp); |
| 6887 | if (IS_ERR(task)) | 7327 | if (IS_ERR(task)) |
| 6888 | return PTR_ERR(task); | 7328 | return PTR_ERR(task); |
| @@ -7004,11 +7444,33 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
| 7004 | }; | 7444 | }; |
| 7005 | #endif | 7445 | #endif |
| 7006 | 7446 | ||
| 7447 | #if defined(CONFIG_NFS_V4_2) | ||
| 7448 | static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | ||
| 7449 | .minor_version = 2, | ||
| 7450 | .init_caps = NFS_CAP_READDIRPLUS | ||
| 7451 | | NFS_CAP_ATOMIC_OPEN | ||
| 7452 | | NFS_CAP_CHANGE_ATTR | ||
| 7453 | | NFS_CAP_POSIX_LOCK | ||
| 7454 | | NFS_CAP_STATEID_NFSV41 | ||
| 7455 | | NFS_CAP_ATOMIC_OPEN_V1, | ||
| 7456 | .call_sync = nfs4_call_sync_sequence, | ||
| 7457 | .match_stateid = nfs41_match_stateid, | ||
| 7458 | .find_root_sec = nfs41_find_root_sec, | ||
| 7459 | .free_lock_state = nfs41_free_lock_state, | ||
| 7460 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | ||
| 7461 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | ||
| 7462 | .state_renewal_ops = &nfs41_state_renewal_ops, | ||
| 7463 | }; | ||
| 7464 | #endif | ||
| 7465 | |||
| 7007 | const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { | 7466 | const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { |
| 7008 | [0] = &nfs_v4_0_minor_ops, | 7467 | [0] = &nfs_v4_0_minor_ops, |
| 7009 | #if defined(CONFIG_NFS_V4_1) | 7468 | #if defined(CONFIG_NFS_V4_1) |
| 7010 | [1] = &nfs_v4_1_minor_ops, | 7469 | [1] = &nfs_v4_1_minor_ops, |
| 7011 | #endif | 7470 | #endif |
| 7471 | #if defined(CONFIG_NFS_V4_2) | ||
| 7472 | [2] = &nfs_v4_2_minor_ops, | ||
| 7473 | #endif | ||
| 7012 | }; | 7474 | }; |
| 7013 | 7475 | ||
| 7014 | const struct inode_operations nfs4_dir_inode_operations = { | 7476 | const struct inode_operations nfs4_dir_inode_operations = { |
| @@ -7108,6 +7570,9 @@ static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | |||
| 7108 | 7570 | ||
| 7109 | const struct xattr_handler *nfs4_xattr_handlers[] = { | 7571 | const struct xattr_handler *nfs4_xattr_handlers[] = { |
| 7110 | &nfs4_xattr_nfs4_acl_handler, | 7572 | &nfs4_xattr_nfs4_acl_handler, |
| 7573 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 7574 | &nfs4_xattr_nfs4_label_handler, | ||
| 7575 | #endif | ||
| 7111 | NULL | 7576 | NULL |
| 7112 | }; | 7577 | }; |
| 7113 | 7578 | ||
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index c4e225e4a9af..36e21cb29d65 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
| @@ -478,48 +478,12 @@ static int nfs41_check_session_ready(struct nfs_client *clp) | |||
| 478 | return 0; | 478 | return 0; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | int nfs4_init_session(struct nfs_server *server) | 481 | int nfs4_init_session(struct nfs_client *clp) |
| 482 | { | 482 | { |
| 483 | struct nfs_client *clp = server->nfs_client; | ||
| 484 | struct nfs4_session *session; | ||
| 485 | unsigned int target_max_rqst_sz = NFS_MAX_FILE_IO_SIZE; | ||
| 486 | unsigned int target_max_resp_sz = NFS_MAX_FILE_IO_SIZE; | ||
| 487 | |||
| 488 | if (!nfs4_has_session(clp)) | 483 | if (!nfs4_has_session(clp)) |
| 489 | return 0; | 484 | return 0; |
| 490 | 485 | ||
| 491 | if (server->rsize != 0) | 486 | clear_bit(NFS4_SESSION_INITING, &clp->cl_session->session_state); |
| 492 | target_max_resp_sz = server->rsize; | ||
| 493 | target_max_resp_sz += nfs41_maxread_overhead; | ||
| 494 | |||
| 495 | if (server->wsize != 0) | ||
| 496 | target_max_rqst_sz = server->wsize; | ||
| 497 | target_max_rqst_sz += nfs41_maxwrite_overhead; | ||
| 498 | |||
| 499 | session = clp->cl_session; | ||
| 500 | spin_lock(&clp->cl_lock); | ||
| 501 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
| 502 | /* Initialise targets and channel attributes */ | ||
| 503 | session->fc_target_max_rqst_sz = target_max_rqst_sz; | ||
| 504 | session->fc_attrs.max_rqst_sz = target_max_rqst_sz; | ||
| 505 | session->fc_target_max_resp_sz = target_max_resp_sz; | ||
| 506 | session->fc_attrs.max_resp_sz = target_max_resp_sz; | ||
| 507 | } else { | ||
| 508 | /* Just adjust the targets */ | ||
| 509 | if (target_max_rqst_sz > session->fc_target_max_rqst_sz) { | ||
| 510 | session->fc_target_max_rqst_sz = target_max_rqst_sz; | ||
| 511 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | ||
| 512 | } | ||
| 513 | if (target_max_resp_sz > session->fc_target_max_resp_sz) { | ||
| 514 | session->fc_target_max_resp_sz = target_max_resp_sz; | ||
| 515 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | ||
| 516 | } | ||
| 517 | } | ||
| 518 | spin_unlock(&clp->cl_lock); | ||
| 519 | |||
| 520 | if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) | ||
| 521 | nfs4_schedule_lease_recovery(clp); | ||
| 522 | |||
| 523 | return nfs41_check_session_ready(clp); | 487 | return nfs41_check_session_ready(clp); |
| 524 | } | 488 | } |
| 525 | 489 | ||
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index ff7d9f0f8a65..3a153d82b90c 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
| @@ -66,9 +66,6 @@ struct nfs4_session { | |||
| 66 | struct nfs4_channel_attrs bc_attrs; | 66 | struct nfs4_channel_attrs bc_attrs; |
| 67 | struct nfs4_slot_table bc_slot_table; | 67 | struct nfs4_slot_table bc_slot_table; |
| 68 | struct nfs_client *clp; | 68 | struct nfs_client *clp; |
| 69 | /* Create session arguments */ | ||
| 70 | unsigned int fc_target_max_rqst_sz; | ||
| 71 | unsigned int fc_target_max_resp_sz; | ||
| 72 | }; | 69 | }; |
| 73 | 70 | ||
| 74 | enum nfs4_session_state { | 71 | enum nfs4_session_state { |
| @@ -89,7 +86,7 @@ extern int nfs4_setup_session_slot_tables(struct nfs4_session *ses); | |||
| 89 | 86 | ||
| 90 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | 87 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); |
| 91 | extern void nfs4_destroy_session(struct nfs4_session *session); | 88 | extern void nfs4_destroy_session(struct nfs4_session *session); |
| 92 | extern int nfs4_init_session(struct nfs_server *server); | 89 | extern int nfs4_init_session(struct nfs_client *clp); |
| 93 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); | 90 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); |
| 94 | 91 | ||
| 95 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); | 92 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); |
| @@ -122,7 +119,7 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | |||
| 122 | 119 | ||
| 123 | #else /* defined(CONFIG_NFS_V4_1) */ | 120 | #else /* defined(CONFIG_NFS_V4_1) */ |
| 124 | 121 | ||
| 125 | static inline int nfs4_init_session(struct nfs_server *server) | 122 | static inline int nfs4_init_session(struct nfs_client *clp) |
| 126 | { | 123 | { |
| 127 | return 0; | 124 | return 0; |
| 128 | } | 125 | } |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 55418811a55a..e22862f13564 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -228,19 +228,8 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp) | |||
| 228 | return status; | 228 | return status; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | /* | 231 | static void nfs4_end_drain_slot_table(struct nfs4_slot_table *tbl) |
| 232 | * Back channel returns NFS4ERR_DELAY for new requests when | ||
| 233 | * NFS4_SESSION_DRAINING is set so there is no work to be done when draining | ||
| 234 | * is ended. | ||
| 235 | */ | ||
| 236 | static void nfs4_end_drain_session(struct nfs_client *clp) | ||
| 237 | { | 232 | { |
| 238 | struct nfs4_session *ses = clp->cl_session; | ||
| 239 | struct nfs4_slot_table *tbl; | ||
| 240 | |||
| 241 | if (ses == NULL) | ||
| 242 | return; | ||
| 243 | tbl = &ses->fc_slot_table; | ||
| 244 | if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) { | 233 | if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) { |
| 245 | spin_lock(&tbl->slot_tbl_lock); | 234 | spin_lock(&tbl->slot_tbl_lock); |
| 246 | nfs41_wake_slot_table(tbl); | 235 | nfs41_wake_slot_table(tbl); |
| @@ -248,6 +237,16 @@ static void nfs4_end_drain_session(struct nfs_client *clp) | |||
| 248 | } | 237 | } |
| 249 | } | 238 | } |
| 250 | 239 | ||
| 240 | static void nfs4_end_drain_session(struct nfs_client *clp) | ||
| 241 | { | ||
| 242 | struct nfs4_session *ses = clp->cl_session; | ||
| 243 | |||
| 244 | if (ses != NULL) { | ||
| 245 | nfs4_end_drain_slot_table(&ses->bc_slot_table); | ||
| 246 | nfs4_end_drain_slot_table(&ses->fc_slot_table); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 251 | /* | 250 | /* |
| 252 | * Signal state manager thread if session fore channel is drained | 251 | * Signal state manager thread if session fore channel is drained |
| 253 | */ | 252 | */ |
| @@ -1563,11 +1562,12 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp) | |||
| 1563 | } | 1562 | } |
| 1564 | 1563 | ||
| 1565 | static void nfs4_reclaim_complete(struct nfs_client *clp, | 1564 | static void nfs4_reclaim_complete(struct nfs_client *clp, |
| 1566 | const struct nfs4_state_recovery_ops *ops) | 1565 | const struct nfs4_state_recovery_ops *ops, |
| 1566 | struct rpc_cred *cred) | ||
| 1567 | { | 1567 | { |
| 1568 | /* Notify the server we're done reclaiming our state */ | 1568 | /* Notify the server we're done reclaiming our state */ |
| 1569 | if (ops->reclaim_complete) | 1569 | if (ops->reclaim_complete) |
| 1570 | (void)ops->reclaim_complete(clp); | 1570 | (void)ops->reclaim_complete(clp, cred); |
| 1571 | } | 1571 | } |
| 1572 | 1572 | ||
| 1573 | static void nfs4_clear_reclaim_server(struct nfs_server *server) | 1573 | static void nfs4_clear_reclaim_server(struct nfs_server *server) |
| @@ -1612,9 +1612,15 @@ static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp) | |||
| 1612 | 1612 | ||
| 1613 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | 1613 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) |
| 1614 | { | 1614 | { |
| 1615 | const struct nfs4_state_recovery_ops *ops; | ||
| 1616 | struct rpc_cred *cred; | ||
| 1617 | |||
| 1615 | if (!nfs4_state_clear_reclaim_reboot(clp)) | 1618 | if (!nfs4_state_clear_reclaim_reboot(clp)) |
| 1616 | return; | 1619 | return; |
| 1617 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); | 1620 | ops = clp->cl_mvops->reboot_recovery_ops; |
| 1621 | cred = ops->get_clid_cred(clp); | ||
| 1622 | nfs4_reclaim_complete(clp, ops, cred); | ||
| 1623 | put_rpccred(cred); | ||
| 1618 | } | 1624 | } |
| 1619 | 1625 | ||
| 1620 | static void nfs_delegation_clear_all(struct nfs_client *clp) | 1626 | static void nfs_delegation_clear_all(struct nfs_client *clp) |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index a5e1a3026d48..5dbe2d269210 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "delegation.h" | 9 | #include "delegation.h" |
| 10 | #include "internal.h" | 10 | #include "internal.h" |
| 11 | #include "nfs4_fs.h" | 11 | #include "nfs4_fs.h" |
| 12 | #include "dns_resolve.h" | ||
| 12 | #include "pnfs.h" | 13 | #include "pnfs.h" |
| 13 | #include "nfs.h" | 14 | #include "nfs.h" |
| 14 | 15 | ||
| @@ -331,18 +332,24 @@ static int __init init_nfs_v4(void) | |||
| 331 | { | 332 | { |
| 332 | int err; | 333 | int err; |
| 333 | 334 | ||
| 334 | err = nfs_idmap_init(); | 335 | err = nfs_dns_resolver_init(); |
| 335 | if (err) | 336 | if (err) |
| 336 | goto out; | 337 | goto out; |
| 337 | 338 | ||
| 338 | err = nfs4_register_sysctl(); | 339 | err = nfs_idmap_init(); |
| 339 | if (err) | 340 | if (err) |
| 340 | goto out1; | 341 | goto out1; |
| 341 | 342 | ||
| 343 | err = nfs4_register_sysctl(); | ||
| 344 | if (err) | ||
| 345 | goto out2; | ||
| 346 | |||
| 342 | register_nfs_version(&nfs_v4); | 347 | register_nfs_version(&nfs_v4); |
| 343 | return 0; | 348 | return 0; |
| 344 | out1: | 349 | out2: |
| 345 | nfs_idmap_quit(); | 350 | nfs_idmap_quit(); |
| 351 | out1: | ||
| 352 | nfs_dns_resolver_destroy(); | ||
| 346 | out: | 353 | out: |
| 347 | return err; | 354 | return err; |
| 348 | } | 355 | } |
| @@ -352,6 +359,7 @@ static void __exit exit_nfs_v4(void) | |||
| 352 | unregister_nfs_version(&nfs_v4); | 359 | unregister_nfs_version(&nfs_v4); |
| 353 | nfs4_unregister_sysctl(); | 360 | nfs4_unregister_sysctl(); |
| 354 | nfs_idmap_quit(); | 361 | nfs_idmap_quit(); |
| 362 | nfs_dns_resolver_destroy(); | ||
| 355 | } | 363 | } |
| 356 | 364 | ||
| 357 | MODULE_LICENSE("GPL"); | 365 | MODULE_LICENSE("GPL"); |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 4be8d135ed61..0abfb8466e79 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -102,12 +102,23 @@ static int nfs4_stat_to_errno(int); | |||
| 102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
| 103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
| 104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
| 105 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 106 | /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */ | ||
| 107 | #define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN)) | ||
| 108 | #define encode_readdir_space 24 | ||
| 109 | #define encode_readdir_bitmask_sz 3 | ||
| 110 | #else | ||
| 111 | #define nfs4_label_maxsz 0 | ||
| 112 | #define encode_readdir_space 20 | ||
| 113 | #define encode_readdir_bitmask_sz 2 | ||
| 114 | #endif | ||
| 105 | /* We support only one layout type per file system */ | 115 | /* We support only one layout type per file system */ |
| 106 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) | 116 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) |
| 107 | /* This is based on getfattr, which uses the most attributes: */ | 117 | /* This is based on getfattr, which uses the most attributes: */ |
| 108 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ | 118 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
| 109 | 3 + 3 + 3 + nfs4_owner_maxsz + \ | 119 | 3 + 3 + 3 + nfs4_owner_maxsz + \ |
| 110 | nfs4_group_maxsz + decode_mdsthreshold_maxsz)) | 120 | nfs4_group_maxsz + nfs4_label_maxsz + \ |
| 121 | decode_mdsthreshold_maxsz)) | ||
| 111 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ | 122 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ |
| 112 | nfs4_fattr_value_maxsz) | 123 | nfs4_fattr_value_maxsz) |
| 113 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 124 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
| @@ -115,6 +126,7 @@ static int nfs4_stat_to_errno(int); | |||
| 115 | 1 + 2 + 1 + \ | 126 | 1 + 2 + 1 + \ |
| 116 | nfs4_owner_maxsz + \ | 127 | nfs4_owner_maxsz + \ |
| 117 | nfs4_group_maxsz + \ | 128 | nfs4_group_maxsz + \ |
| 129 | nfs4_label_maxsz + \ | ||
| 118 | 4 + 4) | 130 | 4 + 4) |
| 119 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 131 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
| 120 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 132 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
| @@ -192,9 +204,11 @@ static int nfs4_stat_to_errno(int); | |||
| 192 | encode_stateid_maxsz + 3) | 204 | encode_stateid_maxsz + 3) |
| 193 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) | 205 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) |
| 194 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ | 206 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ |
| 195 | 2 + encode_verifier_maxsz + 5) | 207 | 2 + encode_verifier_maxsz + 5 + \ |
| 208 | nfs4_label_maxsz) | ||
| 196 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ | 209 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ |
| 197 | decode_verifier_maxsz) | 210 | decode_verifier_maxsz + \ |
| 211 | nfs4_label_maxsz + nfs4_fattr_maxsz) | ||
| 198 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) | 212 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) |
| 199 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) | 213 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) |
| 200 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ | 214 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ |
| @@ -853,6 +867,12 @@ const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | |||
| 853 | decode_sequence_maxsz + | 867 | decode_sequence_maxsz + |
| 854 | decode_putfh_maxsz) * | 868 | decode_putfh_maxsz) * |
| 855 | XDR_UNIT); | 869 | XDR_UNIT); |
| 870 | |||
| 871 | const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH + | ||
| 872 | compound_decode_hdr_maxsz + | ||
| 873 | decode_sequence_maxsz) * | ||
| 874 | XDR_UNIT); | ||
| 875 | EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead); | ||
| 856 | #endif /* CONFIG_NFS_V4_1 */ | 876 | #endif /* CONFIG_NFS_V4_1 */ |
| 857 | 877 | ||
| 858 | static const umode_t nfs_type2fmt[] = { | 878 | static const umode_t nfs_type2fmt[] = { |
| @@ -968,7 +988,9 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve | |||
| 968 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); | 988 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); |
| 969 | } | 989 | } |
| 970 | 990 | ||
| 971 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) | 991 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, |
| 992 | const struct nfs4_label *label, | ||
| 993 | const struct nfs_server *server) | ||
| 972 | { | 994 | { |
| 973 | char owner_name[IDMAP_NAMESZ]; | 995 | char owner_name[IDMAP_NAMESZ]; |
| 974 | char owner_group[IDMAP_NAMESZ]; | 996 | char owner_group[IDMAP_NAMESZ]; |
| @@ -979,15 +1001,16 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
| 979 | int len; | 1001 | int len; |
| 980 | uint32_t bmval0 = 0; | 1002 | uint32_t bmval0 = 0; |
| 981 | uint32_t bmval1 = 0; | 1003 | uint32_t bmval1 = 0; |
| 1004 | uint32_t bmval2 = 0; | ||
| 982 | 1005 | ||
| 983 | /* | 1006 | /* |
| 984 | * We reserve enough space to write the entire attribute buffer at once. | 1007 | * We reserve enough space to write the entire attribute buffer at once. |
| 985 | * In the worst-case, this would be | 1008 | * In the worst-case, this would be |
| 986 | * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) | 1009 | * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) |
| 987 | * = 36 bytes, plus any contribution from variable-length fields | 1010 | * = 40 bytes, plus any contribution from variable-length fields |
| 988 | * such as owner/group. | 1011 | * such as owner/group. |
| 989 | */ | 1012 | */ |
| 990 | len = 16; | 1013 | len = 20; |
| 991 | 1014 | ||
| 992 | /* Sigh */ | 1015 | /* Sigh */ |
| 993 | if (iap->ia_valid & ATTR_SIZE) | 1016 | if (iap->ia_valid & ATTR_SIZE) |
| @@ -1017,6 +1040,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
| 1017 | } | 1040 | } |
| 1018 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); | 1041 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); |
| 1019 | } | 1042 | } |
| 1043 | if (label) | ||
| 1044 | len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); | ||
| 1020 | if (iap->ia_valid & ATTR_ATIME_SET) | 1045 | if (iap->ia_valid & ATTR_ATIME_SET) |
| 1021 | len += 16; | 1046 | len += 16; |
| 1022 | else if (iap->ia_valid & ATTR_ATIME) | 1047 | else if (iap->ia_valid & ATTR_ATIME) |
| @@ -1031,9 +1056,9 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
| 1031 | * We write the bitmap length now, but leave the bitmap and the attribute | 1056 | * We write the bitmap length now, but leave the bitmap and the attribute |
| 1032 | * buffer length to be backfilled at the end of this routine. | 1057 | * buffer length to be backfilled at the end of this routine. |
| 1033 | */ | 1058 | */ |
| 1034 | *p++ = cpu_to_be32(2); | 1059 | *p++ = cpu_to_be32(3); |
| 1035 | q = p; | 1060 | q = p; |
| 1036 | p += 3; | 1061 | p += 4; |
| 1037 | 1062 | ||
| 1038 | if (iap->ia_valid & ATTR_SIZE) { | 1063 | if (iap->ia_valid & ATTR_SIZE) { |
| 1039 | bmval0 |= FATTR4_WORD0_SIZE; | 1064 | bmval0 |= FATTR4_WORD0_SIZE; |
| @@ -1071,6 +1096,13 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
| 1071 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | 1096 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; |
| 1072 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | 1097 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
| 1073 | } | 1098 | } |
| 1099 | if (label) { | ||
| 1100 | bmval2 |= FATTR4_WORD2_SECURITY_LABEL; | ||
| 1101 | *p++ = cpu_to_be32(label->lfs); | ||
| 1102 | *p++ = cpu_to_be32(label->pi); | ||
| 1103 | *p++ = cpu_to_be32(label->len); | ||
| 1104 | p = xdr_encode_opaque_fixed(p, label->label, label->len); | ||
| 1105 | } | ||
| 1074 | 1106 | ||
| 1075 | /* | 1107 | /* |
| 1076 | * Now we backfill the bitmap and the attribute buffer length. | 1108 | * Now we backfill the bitmap and the attribute buffer length. |
| @@ -1080,9 +1112,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
| 1080 | len, ((char *)p - (char *)q) + 4); | 1112 | len, ((char *)p - (char *)q) + 4); |
| 1081 | BUG(); | 1113 | BUG(); |
| 1082 | } | 1114 | } |
| 1083 | len = (char *)p - (char *)q - 12; | 1115 | len = (char *)p - (char *)q - 16; |
| 1084 | *q++ = htonl(bmval0); | 1116 | *q++ = htonl(bmval0); |
| 1085 | *q++ = htonl(bmval1); | 1117 | *q++ = htonl(bmval1); |
| 1118 | *q++ = htonl(bmval2); | ||
| 1086 | *q = htonl(len); | 1119 | *q = htonl(len); |
| 1087 | 1120 | ||
| 1088 | /* out: */ | 1121 | /* out: */ |
| @@ -1136,7 +1169,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg * | |||
| 1136 | } | 1169 | } |
| 1137 | 1170 | ||
| 1138 | encode_string(xdr, create->name->len, create->name->name); | 1171 | encode_string(xdr, create->name->len, create->name->name); |
| 1139 | encode_attrs(xdr, create->attrs, create->server); | 1172 | encode_attrs(xdr, create->attrs, create->label, create->server); |
| 1140 | } | 1173 | } |
| 1141 | 1174 | ||
| 1142 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) | 1175 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) |
| @@ -1188,8 +1221,10 @@ encode_getattr_three(struct xdr_stream *xdr, | |||
| 1188 | 1221 | ||
| 1189 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1222 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
| 1190 | { | 1223 | { |
| 1191 | encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], | 1224 | encode_getattr_three(xdr, bitmask[0] & nfs4_fattr_bitmap[0], |
| 1192 | bitmask[1] & nfs4_fattr_bitmap[1], hdr); | 1225 | bitmask[1] & nfs4_fattr_bitmap[1], |
| 1226 | bitmask[2] & nfs4_fattr_bitmap[2], | ||
| 1227 | hdr); | ||
| 1193 | } | 1228 | } |
| 1194 | 1229 | ||
| 1195 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, | 1230 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, |
| @@ -1367,11 +1402,11 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
| 1367 | switch(arg->createmode) { | 1402 | switch(arg->createmode) { |
| 1368 | case NFS4_CREATE_UNCHECKED: | 1403 | case NFS4_CREATE_UNCHECKED: |
| 1369 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); | 1404 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); |
| 1370 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1405 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
| 1371 | break; | 1406 | break; |
| 1372 | case NFS4_CREATE_GUARDED: | 1407 | case NFS4_CREATE_GUARDED: |
| 1373 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); | 1408 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); |
| 1374 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1409 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
| 1375 | break; | 1410 | break; |
| 1376 | case NFS4_CREATE_EXCLUSIVE: | 1411 | case NFS4_CREATE_EXCLUSIVE: |
| 1377 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); | 1412 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); |
| @@ -1381,7 +1416,7 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
| 1381 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); | 1416 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); |
| 1382 | encode_nfs4_verifier(xdr, &arg->u.verifier); | 1417 | encode_nfs4_verifier(xdr, &arg->u.verifier); |
| 1383 | dummy.ia_valid = 0; | 1418 | dummy.ia_valid = 0; |
| 1384 | encode_attrs(xdr, &dummy, arg->server); | 1419 | encode_attrs(xdr, &dummy, arg->label, arg->server); |
| 1385 | } | 1420 | } |
| 1386 | } | 1421 | } |
| 1387 | 1422 | ||
| @@ -1532,7 +1567,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
| 1532 | 1567 | ||
| 1533 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1568 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
| 1534 | { | 1569 | { |
| 1535 | uint32_t attrs[2] = { | 1570 | uint32_t attrs[3] = { |
| 1536 | FATTR4_WORD0_RDATTR_ERROR, | 1571 | FATTR4_WORD0_RDATTR_ERROR, |
| 1537 | FATTR4_WORD1_MOUNTED_ON_FILEID, | 1572 | FATTR4_WORD1_MOUNTED_ON_FILEID, |
| 1538 | }; | 1573 | }; |
| @@ -1555,20 +1590,26 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg | |||
| 1555 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); | 1590 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); |
| 1556 | encode_uint64(xdr, readdir->cookie); | 1591 | encode_uint64(xdr, readdir->cookie); |
| 1557 | encode_nfs4_verifier(xdr, &readdir->verifier); | 1592 | encode_nfs4_verifier(xdr, &readdir->verifier); |
| 1558 | p = reserve_space(xdr, 20); | 1593 | p = reserve_space(xdr, encode_readdir_space); |
| 1559 | *p++ = cpu_to_be32(dircount); | 1594 | *p++ = cpu_to_be32(dircount); |
| 1560 | *p++ = cpu_to_be32(readdir->count); | 1595 | *p++ = cpu_to_be32(readdir->count); |
| 1561 | *p++ = cpu_to_be32(2); | 1596 | *p++ = cpu_to_be32(encode_readdir_bitmask_sz); |
| 1562 | |||
| 1563 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); | 1597 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); |
| 1564 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); | 1598 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); |
| 1599 | if (encode_readdir_bitmask_sz > 2) { | ||
| 1600 | if (hdr->minorversion > 1) | ||
| 1601 | attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; | ||
| 1602 | p++, *p++ = cpu_to_be32(attrs[2] & readdir->bitmask[2]); | ||
| 1603 | } | ||
| 1565 | memcpy(verf, readdir->verifier.data, sizeof(verf)); | 1604 | memcpy(verf, readdir->verifier.data, sizeof(verf)); |
| 1566 | dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", | 1605 | |
| 1606 | dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", | ||
| 1567 | __func__, | 1607 | __func__, |
| 1568 | (unsigned long long)readdir->cookie, | 1608 | (unsigned long long)readdir->cookie, |
| 1569 | verf[0], verf[1], | 1609 | verf[0], verf[1], |
| 1570 | attrs[0] & readdir->bitmask[0], | 1610 | attrs[0] & readdir->bitmask[0], |
| 1571 | attrs[1] & readdir->bitmask[1]); | 1611 | attrs[1] & readdir->bitmask[1], |
| 1612 | attrs[2] & readdir->bitmask[2]); | ||
| 1572 | } | 1613 | } |
| 1573 | 1614 | ||
| 1574 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) | 1615 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) |
| @@ -1627,7 +1668,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs | |||
| 1627 | { | 1668 | { |
| 1628 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); | 1669 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); |
| 1629 | encode_nfs4_stateid(xdr, &arg->stateid); | 1670 | encode_nfs4_stateid(xdr, &arg->stateid); |
| 1630 | encode_attrs(xdr, arg->iap, server); | 1671 | encode_attrs(xdr, arg->iap, arg->label, server); |
| 1631 | } | 1672 | } |
| 1632 | 1673 | ||
| 1633 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) | 1674 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) |
| @@ -1889,7 +1930,7 @@ encode_getdeviceinfo(struct xdr_stream *xdr, | |||
| 1889 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, | 1930 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, |
| 1890 | NFS4_DEVICEID4_SIZE); | 1931 | NFS4_DEVICEID4_SIZE); |
| 1891 | *p++ = cpu_to_be32(args->pdev->layout_type); | 1932 | *p++ = cpu_to_be32(args->pdev->layout_type); |
| 1892 | *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ | 1933 | *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */ |
| 1893 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ | 1934 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ |
| 1894 | } | 1935 | } |
| 1895 | 1936 | ||
| @@ -4038,6 +4079,56 @@ static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, | |||
| 4038 | return status; | 4079 | return status; |
| 4039 | } | 4080 | } |
| 4040 | 4081 | ||
| 4082 | static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, | ||
| 4083 | struct nfs4_label *label) | ||
| 4084 | { | ||
| 4085 | uint32_t pi = 0; | ||
| 4086 | uint32_t lfs = 0; | ||
| 4087 | __u32 len; | ||
| 4088 | __be32 *p; | ||
| 4089 | int status = 0; | ||
| 4090 | |||
| 4091 | if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U))) | ||
| 4092 | return -EIO; | ||
| 4093 | if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { | ||
| 4094 | p = xdr_inline_decode(xdr, 4); | ||
| 4095 | if (unlikely(!p)) | ||
| 4096 | goto out_overflow; | ||
| 4097 | lfs = be32_to_cpup(p++); | ||
| 4098 | p = xdr_inline_decode(xdr, 4); | ||
| 4099 | if (unlikely(!p)) | ||
| 4100 | goto out_overflow; | ||
| 4101 | pi = be32_to_cpup(p++); | ||
| 4102 | p = xdr_inline_decode(xdr, 4); | ||
| 4103 | if (unlikely(!p)) | ||
| 4104 | goto out_overflow; | ||
| 4105 | len = be32_to_cpup(p++); | ||
| 4106 | p = xdr_inline_decode(xdr, len); | ||
| 4107 | if (unlikely(!p)) | ||
| 4108 | goto out_overflow; | ||
| 4109 | if (len < NFS4_MAXLABELLEN) { | ||
| 4110 | if (label) { | ||
| 4111 | memcpy(label->label, p, len); | ||
| 4112 | label->len = len; | ||
| 4113 | label->pi = pi; | ||
| 4114 | label->lfs = lfs; | ||
| 4115 | status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; | ||
| 4116 | } | ||
| 4117 | bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
| 4118 | } else | ||
| 4119 | printk(KERN_WARNING "%s: label too long (%u)!\n", | ||
| 4120 | __func__, len); | ||
| 4121 | } | ||
| 4122 | if (label && label->label) | ||
| 4123 | dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, | ||
| 4124 | (char *)label->label, label->len, label->pi, label->lfs); | ||
| 4125 | return status; | ||
| 4126 | |||
| 4127 | out_overflow: | ||
| 4128 | print_overflow_msg(__func__, xdr); | ||
| 4129 | return -EIO; | ||
| 4130 | } | ||
| 4131 | |||
| 4041 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4132 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
| 4042 | { | 4133 | { |
| 4043 | int status = 0; | 4134 | int status = 0; |
| @@ -4380,7 +4471,7 @@ out_overflow: | |||
| 4380 | 4471 | ||
| 4381 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4472 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
| 4382 | struct nfs_fattr *fattr, struct nfs_fh *fh, | 4473 | struct nfs_fattr *fattr, struct nfs_fh *fh, |
| 4383 | struct nfs4_fs_locations *fs_loc, | 4474 | struct nfs4_fs_locations *fs_loc, struct nfs4_label *label, |
| 4384 | const struct nfs_server *server) | 4475 | const struct nfs_server *server) |
| 4385 | { | 4476 | { |
| 4386 | int status; | 4477 | int status; |
| @@ -4488,6 +4579,13 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
| 4488 | if (status < 0) | 4579 | if (status < 0) |
| 4489 | goto xdr_error; | 4580 | goto xdr_error; |
| 4490 | 4581 | ||
| 4582 | if (label) { | ||
| 4583 | status = decode_attr_security_label(xdr, bitmap, label); | ||
| 4584 | if (status < 0) | ||
| 4585 | goto xdr_error; | ||
| 4586 | fattr->valid |= status; | ||
| 4587 | } | ||
| 4588 | |||
| 4491 | xdr_error: | 4589 | xdr_error: |
| 4492 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4590 | dprintk("%s: xdr returned %d\n", __func__, -status); |
| 4493 | return status; | 4591 | return status; |
| @@ -4495,7 +4593,7 @@ xdr_error: | |||
| 4495 | 4593 | ||
| 4496 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4594 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
| 4497 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, | 4595 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, |
| 4498 | const struct nfs_server *server) | 4596 | struct nfs4_label *label, const struct nfs_server *server) |
| 4499 | { | 4597 | { |
| 4500 | unsigned int savep; | 4598 | unsigned int savep; |
| 4501 | uint32_t attrlen, | 4599 | uint32_t attrlen, |
| @@ -4514,7 +4612,8 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat | |||
| 4514 | if (status < 0) | 4612 | if (status < 0) |
| 4515 | goto xdr_error; | 4613 | goto xdr_error; |
| 4516 | 4614 | ||
| 4517 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server); | 4615 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, |
| 4616 | label, server); | ||
| 4518 | if (status < 0) | 4617 | if (status < 0) |
| 4519 | goto xdr_error; | 4618 | goto xdr_error; |
| 4520 | 4619 | ||
| @@ -4524,10 +4623,16 @@ xdr_error: | |||
| 4524 | return status; | 4623 | return status; |
| 4525 | } | 4624 | } |
| 4526 | 4625 | ||
| 4626 | static int decode_getfattr_label(struct xdr_stream *xdr, struct nfs_fattr *fattr, | ||
| 4627 | struct nfs4_label *label, const struct nfs_server *server) | ||
| 4628 | { | ||
| 4629 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server); | ||
| 4630 | } | ||
| 4631 | |||
| 4527 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4632 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
| 4528 | const struct nfs_server *server) | 4633 | const struct nfs_server *server) |
| 4529 | { | 4634 | { |
| 4530 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, server); | 4635 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, NULL, server); |
| 4531 | } | 4636 | } |
| 4532 | 4637 | ||
| 4533 | /* | 4638 | /* |
| @@ -5919,7 +6024,7 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 5919 | status = decode_getfh(xdr, res->fh); | 6024 | status = decode_getfh(xdr, res->fh); |
| 5920 | if (status) | 6025 | if (status) |
| 5921 | goto out; | 6026 | goto out; |
| 5922 | status = decode_getfattr(xdr, res->fattr, res->server); | 6027 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
| 5923 | out: | 6028 | out: |
| 5924 | return status; | 6029 | return status; |
| 5925 | } | 6030 | } |
| @@ -5945,7 +6050,8 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, | |||
| 5945 | goto out; | 6050 | goto out; |
| 5946 | status = decode_getfh(xdr, res->fh); | 6051 | status = decode_getfh(xdr, res->fh); |
| 5947 | if (status == 0) | 6052 | if (status == 0) |
| 5948 | status = decode_getfattr(xdr, res->fattr, res->server); | 6053 | status = decode_getfattr_label(xdr, res->fattr, |
| 6054 | res->label, res->server); | ||
| 5949 | out: | 6055 | out: |
| 5950 | return status; | 6056 | return status; |
| 5951 | } | 6057 | } |
| @@ -6036,7 +6142,7 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 6036 | status = decode_restorefh(xdr); | 6142 | status = decode_restorefh(xdr); |
| 6037 | if (status) | 6143 | if (status) |
| 6038 | goto out; | 6144 | goto out; |
| 6039 | decode_getfattr(xdr, res->fattr, res->server); | 6145 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
| 6040 | out: | 6146 | out: |
| 6041 | return status; | 6147 | return status; |
| 6042 | } | 6148 | } |
| @@ -6065,7 +6171,7 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 6065 | status = decode_getfh(xdr, res->fh); | 6171 | status = decode_getfh(xdr, res->fh); |
| 6066 | if (status) | 6172 | if (status) |
| 6067 | goto out; | 6173 | goto out; |
| 6068 | decode_getfattr(xdr, res->fattr, res->server); | 6174 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
| 6069 | out: | 6175 | out: |
| 6070 | return status; | 6176 | return status; |
| 6071 | } | 6177 | } |
| @@ -6097,7 +6203,7 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 6097 | status = decode_putfh(xdr); | 6203 | status = decode_putfh(xdr); |
| 6098 | if (status) | 6204 | if (status) |
| 6099 | goto out; | 6205 | goto out; |
| 6100 | status = decode_getfattr(xdr, res->fattr, res->server); | 6206 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
| 6101 | out: | 6207 | out: |
| 6102 | return status; | 6208 | return status; |
| 6103 | } | 6209 | } |
| @@ -6230,7 +6336,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
| 6230 | goto out; | 6336 | goto out; |
| 6231 | if (res->access_request) | 6337 | if (res->access_request) |
| 6232 | decode_access(xdr, &res->access_supported, &res->access_result); | 6338 | decode_access(xdr, &res->access_supported, &res->access_result); |
| 6233 | decode_getfattr(xdr, res->f_attr, res->server); | 6339 | decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server); |
| 6234 | out: | 6340 | out: |
| 6235 | return status; | 6341 | return status; |
| 6236 | } | 6342 | } |
| @@ -6307,7 +6413,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, | |||
| 6307 | status = decode_setattr(xdr); | 6413 | status = decode_setattr(xdr); |
| 6308 | if (status) | 6414 | if (status) |
| 6309 | goto out; | 6415 | goto out; |
| 6310 | decode_getfattr(xdr, res->fattr, res->server); | 6416 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
| 6311 | out: | 6417 | out: |
| 6312 | return status; | 6418 | return status; |
| 6313 | } | 6419 | } |
| @@ -6696,7 +6802,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, | |||
| 6696 | xdr_enter_page(xdr, PAGE_SIZE); | 6802 | xdr_enter_page(xdr, PAGE_SIZE); |
| 6697 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, | 6803 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, |
| 6698 | NULL, res->fs_locations, | 6804 | NULL, res->fs_locations, |
| 6699 | res->fs_locations->server); | 6805 | NULL, res->fs_locations->server); |
| 6700 | out: | 6806 | out: |
| 6701 | return status; | 6807 | return status; |
| 6702 | } | 6808 | } |
| @@ -7109,7 +7215,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
| 7109 | goto out_overflow; | 7215 | goto out_overflow; |
| 7110 | 7216 | ||
| 7111 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 7217 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
| 7112 | NULL, entry->server) < 0) | 7218 | NULL, entry->label, entry->server) < 0) |
| 7113 | goto out_overflow; | 7219 | goto out_overflow; |
| 7114 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | 7220 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
| 7115 | entry->ino = entry->fattr->mounted_on_fileid; | 7221 | entry->ino = entry->fattr->mounted_on_fileid; |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index a9ebd817278b..e4f9cbfec67b 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
| @@ -613,8 +613,10 @@ int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | |||
| 613 | pd.pgbase = 0; | 613 | pd.pgbase = 0; |
| 614 | pd.pglen = PAGE_SIZE; | 614 | pd.pglen = PAGE_SIZE; |
| 615 | pd.mincount = 0; | 615 | pd.mincount = 0; |
| 616 | pd.maxcount = PAGE_SIZE; | ||
| 616 | 617 | ||
| 617 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd); | 618 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd, |
| 619 | pnfslay->plh_lc_cred); | ||
| 618 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); | 620 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); |
| 619 | if (err) | 621 | if (err) |
| 620 | goto err_out; | 622 | goto err_out; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index c5bd758e5637..3a3a79d6bf15 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -360,7 +360,7 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg) | |||
| 360 | } | 360 | } |
| 361 | EXPORT_SYMBOL_GPL(pnfs_put_lseg); | 361 | EXPORT_SYMBOL_GPL(pnfs_put_lseg); |
| 362 | 362 | ||
| 363 | static inline u64 | 363 | static u64 |
| 364 | end_offset(u64 start, u64 len) | 364 | end_offset(u64 start, u64 len) |
| 365 | { | 365 | { |
| 366 | u64 end; | 366 | u64 end; |
| @@ -376,9 +376,9 @@ end_offset(u64 start, u64 len) | |||
| 376 | * start2 end2 | 376 | * start2 end2 |
| 377 | * [----------------) | 377 | * [----------------) |
| 378 | */ | 378 | */ |
| 379 | static inline int | 379 | static bool |
| 380 | lo_seg_contained(struct pnfs_layout_range *l1, | 380 | pnfs_lseg_range_contained(const struct pnfs_layout_range *l1, |
| 381 | struct pnfs_layout_range *l2) | 381 | const struct pnfs_layout_range *l2) |
| 382 | { | 382 | { |
| 383 | u64 start1 = l1->offset; | 383 | u64 start1 = l1->offset; |
| 384 | u64 end1 = end_offset(start1, l1->length); | 384 | u64 end1 = end_offset(start1, l1->length); |
| @@ -395,9 +395,9 @@ lo_seg_contained(struct pnfs_layout_range *l1, | |||
| 395 | * start2 end2 | 395 | * start2 end2 |
| 396 | * [----------------) | 396 | * [----------------) |
| 397 | */ | 397 | */ |
| 398 | static inline int | 398 | static bool |
| 399 | lo_seg_intersecting(struct pnfs_layout_range *l1, | 399 | pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1, |
| 400 | struct pnfs_layout_range *l2) | 400 | const struct pnfs_layout_range *l2) |
| 401 | { | 401 | { |
| 402 | u64 start1 = l1->offset; | 402 | u64 start1 = l1->offset; |
| 403 | u64 end1 = end_offset(start1, l1->length); | 403 | u64 end1 = end_offset(start1, l1->length); |
| @@ -409,12 +409,12 @@ lo_seg_intersecting(struct pnfs_layout_range *l1, | |||
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | static bool | 411 | static bool |
| 412 | should_free_lseg(struct pnfs_layout_range *lseg_range, | 412 | should_free_lseg(const struct pnfs_layout_range *lseg_range, |
| 413 | struct pnfs_layout_range *recall_range) | 413 | const struct pnfs_layout_range *recall_range) |
| 414 | { | 414 | { |
| 415 | return (recall_range->iomode == IOMODE_ANY || | 415 | return (recall_range->iomode == IOMODE_ANY || |
| 416 | lseg_range->iomode == recall_range->iomode) && | 416 | lseg_range->iomode == recall_range->iomode) && |
| 417 | lo_seg_intersecting(lseg_range, recall_range); | 417 | pnfs_lseg_range_intersecting(lseg_range, recall_range); |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, | 420 | static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, |
| @@ -766,6 +766,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
| 766 | lgp->args.inode = ino; | 766 | lgp->args.inode = ino; |
| 767 | lgp->args.ctx = get_nfs_open_context(ctx); | 767 | lgp->args.ctx = get_nfs_open_context(ctx); |
| 768 | lgp->gfp_flags = gfp_flags; | 768 | lgp->gfp_flags = gfp_flags; |
| 769 | lgp->cred = lo->plh_lc_cred; | ||
| 769 | 770 | ||
| 770 | /* Synchronously retrieve layout information from server and | 771 | /* Synchronously retrieve layout information from server and |
| 771 | * store in lseg. | 772 | * store in lseg. |
| @@ -860,6 +861,7 @@ _pnfs_return_layout(struct inode *ino) | |||
| 860 | lrp->args.inode = ino; | 861 | lrp->args.inode = ino; |
| 861 | lrp->args.layout = lo; | 862 | lrp->args.layout = lo; |
| 862 | lrp->clp = NFS_SERVER(ino)->nfs_client; | 863 | lrp->clp = NFS_SERVER(ino)->nfs_client; |
| 864 | lrp->cred = lo->plh_lc_cred; | ||
| 863 | 865 | ||
| 864 | status = nfs4_proc_layoutreturn(lrp); | 866 | status = nfs4_proc_layoutreturn(lrp); |
| 865 | out: | 867 | out: |
| @@ -984,8 +986,8 @@ out: | |||
| 984 | * are seen first. | 986 | * are seen first. |
| 985 | */ | 987 | */ |
| 986 | static s64 | 988 | static s64 |
| 987 | cmp_layout(struct pnfs_layout_range *l1, | 989 | pnfs_lseg_range_cmp(const struct pnfs_layout_range *l1, |
| 988 | struct pnfs_layout_range *l2) | 990 | const struct pnfs_layout_range *l2) |
| 989 | { | 991 | { |
| 990 | s64 d; | 992 | s64 d; |
| 991 | 993 | ||
| @@ -1012,7 +1014,7 @@ pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo, | |||
| 1012 | dprintk("%s:Begin\n", __func__); | 1014 | dprintk("%s:Begin\n", __func__); |
| 1013 | 1015 | ||
| 1014 | list_for_each_entry(lp, &lo->plh_segs, pls_list) { | 1016 | list_for_each_entry(lp, &lo->plh_segs, pls_list) { |
| 1015 | if (cmp_layout(&lseg->pls_range, &lp->pls_range) > 0) | 1017 | if (pnfs_lseg_range_cmp(&lseg->pls_range, &lp->pls_range) > 0) |
| 1016 | continue; | 1018 | continue; |
| 1017 | list_add_tail(&lseg->pls_list, &lp->pls_list); | 1019 | list_add_tail(&lseg->pls_list, &lp->pls_list); |
| 1018 | dprintk("%s: inserted lseg %p " | 1020 | dprintk("%s: inserted lseg %p " |
| @@ -1050,7 +1052,7 @@ alloc_init_layout_hdr(struct inode *ino, | |||
| 1050 | INIT_LIST_HEAD(&lo->plh_segs); | 1052 | INIT_LIST_HEAD(&lo->plh_segs); |
| 1051 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); | 1053 | INIT_LIST_HEAD(&lo->plh_bulk_destroy); |
| 1052 | lo->plh_inode = ino; | 1054 | lo->plh_inode = ino; |
| 1053 | lo->plh_lc_cred = get_rpccred(ctx->state->owner->so_cred); | 1055 | lo->plh_lc_cred = get_rpccred(ctx->cred); |
| 1054 | return lo; | 1056 | return lo; |
| 1055 | } | 1057 | } |
| 1056 | 1058 | ||
| @@ -1091,21 +1093,21 @@ out_existing: | |||
| 1091 | * READ READ true | 1093 | * READ READ true |
| 1092 | * READ RW true | 1094 | * READ RW true |
| 1093 | */ | 1095 | */ |
| 1094 | static int | 1096 | static bool |
| 1095 | is_matching_lseg(struct pnfs_layout_range *ls_range, | 1097 | pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range, |
| 1096 | struct pnfs_layout_range *range) | 1098 | const struct pnfs_layout_range *range) |
| 1097 | { | 1099 | { |
| 1098 | struct pnfs_layout_range range1; | 1100 | struct pnfs_layout_range range1; |
| 1099 | 1101 | ||
| 1100 | if ((range->iomode == IOMODE_RW && | 1102 | if ((range->iomode == IOMODE_RW && |
| 1101 | ls_range->iomode != IOMODE_RW) || | 1103 | ls_range->iomode != IOMODE_RW) || |
| 1102 | !lo_seg_intersecting(ls_range, range)) | 1104 | !pnfs_lseg_range_intersecting(ls_range, range)) |
| 1103 | return 0; | 1105 | return 0; |
| 1104 | 1106 | ||
| 1105 | /* range1 covers only the first byte in the range */ | 1107 | /* range1 covers only the first byte in the range */ |
| 1106 | range1 = *range; | 1108 | range1 = *range; |
| 1107 | range1.length = 1; | 1109 | range1.length = 1; |
| 1108 | return lo_seg_contained(ls_range, &range1); | 1110 | return pnfs_lseg_range_contained(ls_range, &range1); |
| 1109 | } | 1111 | } |
| 1110 | 1112 | ||
| 1111 | /* | 1113 | /* |
| @@ -1121,7 +1123,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, | |||
| 1121 | 1123 | ||
| 1122 | list_for_each_entry(lseg, &lo->plh_segs, pls_list) { | 1124 | list_for_each_entry(lseg, &lo->plh_segs, pls_list) { |
| 1123 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && | 1125 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && |
| 1124 | is_matching_lseg(&lseg->pls_range, range)) { | 1126 | pnfs_lseg_range_match(&lseg->pls_range, range)) { |
| 1125 | ret = pnfs_get_lseg(lseg); | 1127 | ret = pnfs_get_lseg(lseg); |
| 1126 | break; | 1128 | break; |
| 1127 | } | 1129 | } |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index f5f8a470a647..a4f41810a7f4 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -149,9 +149,10 @@ struct pnfs_device { | |||
| 149 | struct nfs4_deviceid dev_id; | 149 | struct nfs4_deviceid dev_id; |
| 150 | unsigned int layout_type; | 150 | unsigned int layout_type; |
| 151 | unsigned int mincount; | 151 | unsigned int mincount; |
| 152 | unsigned int maxcount; /* gdia_maxcount */ | ||
| 152 | struct page **pages; | 153 | struct page **pages; |
| 153 | unsigned int pgbase; | 154 | unsigned int pgbase; |
| 154 | unsigned int pglen; | 155 | unsigned int pglen; /* reply buffer length */ |
| 155 | }; | 156 | }; |
| 156 | 157 | ||
| 157 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 | 158 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 |
| @@ -170,7 +171,8 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
| 170 | const struct nfs_fh *fh, | 171 | const struct nfs_fh *fh, |
| 171 | struct pnfs_devicelist *devlist); | 172 | struct pnfs_devicelist *devlist); |
| 172 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, | 173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
| 173 | struct pnfs_device *dev); | 174 | struct pnfs_device *dev, |
| 175 | struct rpc_cred *cred); | ||
| 174 | extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); | 176 | extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); |
| 175 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); | 177 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); |
| 176 | 178 | ||
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index fc8de9016acf..c041c41f7a52 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
| @@ -98,7 +98,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 98 | */ | 98 | */ |
| 99 | static int | 99 | static int |
| 100 | nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | 100 | nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
| 101 | struct nfs_fattr *fattr) | 101 | struct nfs_fattr *fattr, struct nfs4_label *label) |
| 102 | { | 102 | { |
| 103 | struct rpc_message msg = { | 103 | struct rpc_message msg = { |
| 104 | .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], | 104 | .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], |
| @@ -146,7 +146,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 146 | 146 | ||
| 147 | static int | 147 | static int |
| 148 | nfs_proc_lookup(struct inode *dir, struct qstr *name, | 148 | nfs_proc_lookup(struct inode *dir, struct qstr *name, |
| 149 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 149 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, |
| 150 | struct nfs4_label *label) | ||
| 150 | { | 151 | { |
| 151 | struct nfs_diropargs arg = { | 152 | struct nfs_diropargs arg = { |
| 152 | .fh = NFS_FH(dir), | 153 | .fh = NFS_FH(dir), |
| @@ -243,7 +244,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 243 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 244 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 244 | nfs_mark_for_revalidate(dir); | 245 | nfs_mark_for_revalidate(dir); |
| 245 | if (status == 0) | 246 | if (status == 0) |
| 246 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 247 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
| 247 | nfs_free_createdata(data); | 248 | nfs_free_createdata(data); |
| 248 | out: | 249 | out: |
| 249 | dprintk("NFS reply create: %d\n", status); | 250 | dprintk("NFS reply create: %d\n", status); |
| @@ -290,7 +291,7 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 290 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 291 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 291 | } | 292 | } |
| 292 | if (status == 0) | 293 | if (status == 0) |
| 293 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 294 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
| 294 | nfs_free_createdata(data); | 295 | nfs_free_createdata(data); |
| 295 | out: | 296 | out: |
| 296 | dprintk("NFS reply mknod: %d\n", status); | 297 | dprintk("NFS reply mknod: %d\n", status); |
| @@ -442,7 +443,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
| 442 | * should fill in the data with a LOOKUP call on the wire. | 443 | * should fill in the data with a LOOKUP call on the wire. |
| 443 | */ | 444 | */ |
| 444 | if (status == 0) | 445 | if (status == 0) |
| 445 | status = nfs_instantiate(dentry, fh, fattr); | 446 | status = nfs_instantiate(dentry, fh, fattr, NULL); |
| 446 | 447 | ||
| 447 | out_free: | 448 | out_free: |
| 448 | nfs_free_fattr(fattr); | 449 | nfs_free_fattr(fattr); |
| @@ -471,7 +472,7 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | |||
| 471 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 472 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 472 | nfs_mark_for_revalidate(dir); | 473 | nfs_mark_for_revalidate(dir); |
| 473 | if (status == 0) | 474 | if (status == 0) |
| 474 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 475 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
| 475 | nfs_free_createdata(data); | 476 | nfs_free_createdata(data); |
| 476 | out: | 477 | out: |
| 477 | dprintk("NFS reply mkdir: %d\n", status); | 478 | dprintk("NFS reply mkdir: %d\n", status); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2d7525fbcf25..71fdc0dfa0d2 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -269,7 +269,7 @@ static match_table_t nfs_local_lock_tokens = { | |||
| 269 | 269 | ||
| 270 | enum { | 270 | enum { |
| 271 | Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0, | 271 | Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0, |
| 272 | Opt_vers_4_1, | 272 | Opt_vers_4_1, Opt_vers_4_2, |
| 273 | 273 | ||
| 274 | Opt_vers_err | 274 | Opt_vers_err |
| 275 | }; | 275 | }; |
| @@ -280,6 +280,7 @@ static match_table_t nfs_vers_tokens = { | |||
| 280 | { Opt_vers_4, "4" }, | 280 | { Opt_vers_4, "4" }, |
| 281 | { Opt_vers_4_0, "4.0" }, | 281 | { Opt_vers_4_0, "4.0" }, |
| 282 | { Opt_vers_4_1, "4.1" }, | 282 | { Opt_vers_4_1, "4.1" }, |
| 283 | { Opt_vers_4_2, "4.2" }, | ||
| 283 | 284 | ||
| 284 | { Opt_vers_err, NULL } | 285 | { Opt_vers_err, NULL } |
| 285 | }; | 286 | }; |
| @@ -832,6 +833,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root) | |||
| 832 | seq_printf(m, "\n\tnfsv4:\t"); | 833 | seq_printf(m, "\n\tnfsv4:\t"); |
| 833 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); | 834 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); |
| 834 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); | 835 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); |
| 836 | seq_printf(m, ",bm2=0x%x", nfss->attr_bitmask[2]); | ||
| 835 | seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); | 837 | seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); |
| 836 | show_sessions(m, nfss); | 838 | show_sessions(m, nfss); |
| 837 | show_pnfs(m, nfss); | 839 | show_pnfs(m, nfss); |
| @@ -1097,6 +1099,10 @@ static int nfs_parse_version_string(char *string, | |||
| 1097 | mnt->version = 4; | 1099 | mnt->version = 4; |
| 1098 | mnt->minorversion = 1; | 1100 | mnt->minorversion = 1; |
| 1099 | break; | 1101 | break; |
| 1102 | case Opt_vers_4_2: | ||
| 1103 | mnt->version = 4; | ||
| 1104 | mnt->minorversion = 2; | ||
| 1105 | break; | ||
| 1100 | default: | 1106 | default: |
| 1101 | return 0; | 1107 | return 0; |
| 1102 | } | 1108 | } |
| @@ -1608,29 +1614,13 @@ out_security_failure: | |||
| 1608 | } | 1614 | } |
| 1609 | 1615 | ||
| 1610 | /* | 1616 | /* |
| 1611 | * Select a security flavor for this mount. The selected flavor | 1617 | * Ensure that the specified authtype in args->auth_flavors[0] is supported by |
| 1612 | * is planted in args->auth_flavors[0]. | 1618 | * the server. Returns 0 if it's ok, and -EACCES if not. |
| 1613 | * | ||
| 1614 | * Returns 0 on success, -EACCES on failure. | ||
| 1615 | */ | 1619 | */ |
| 1616 | static int nfs_select_flavor(struct nfs_parsed_mount_data *args, | 1620 | static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args, |
| 1617 | struct nfs_mount_request *request) | 1621 | rpc_authflavor_t *server_authlist, unsigned int count) |
| 1618 | { | 1622 | { |
| 1619 | unsigned int i, count = *(request->auth_flav_len); | 1623 | unsigned int i; |
| 1620 | rpc_authflavor_t flavor; | ||
| 1621 | |||
| 1622 | /* | ||
| 1623 | * The NFSv2 MNT operation does not return a flavor list. | ||
| 1624 | */ | ||
| 1625 | if (args->mount_server.version != NFS_MNT3_VERSION) | ||
| 1626 | goto out_default; | ||
| 1627 | |||
| 1628 | /* | ||
| 1629 | * Certain releases of Linux's mountd return an empty | ||
| 1630 | * flavor list in some cases. | ||
| 1631 | */ | ||
| 1632 | if (count == 0) | ||
| 1633 | goto out_default; | ||
| 1634 | 1624 | ||
| 1635 | /* | 1625 | /* |
| 1636 | * If the sec= mount option is used, the specified flavor or AUTH_NULL | 1626 | * If the sec= mount option is used, the specified flavor or AUTH_NULL |
| @@ -1640,60 +1630,19 @@ static int nfs_select_flavor(struct nfs_parsed_mount_data *args, | |||
| 1640 | * means that the server will ignore the rpc creds, so any flavor | 1630 | * means that the server will ignore the rpc creds, so any flavor |
| 1641 | * can be used. | 1631 | * can be used. |
| 1642 | */ | 1632 | */ |
| 1643 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | ||
| 1644 | for (i = 0; i < count; i++) { | ||
| 1645 | if (args->auth_flavors[0] == request->auth_flavs[i] || | ||
| 1646 | request->auth_flavs[i] == RPC_AUTH_NULL) | ||
| 1647 | goto out; | ||
| 1648 | } | ||
| 1649 | dfprintk(MOUNT, "NFS: auth flavor %d not supported by server\n", | ||
| 1650 | args->auth_flavors[0]); | ||
| 1651 | goto out_err; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | /* | ||
| 1655 | * RFC 2623, section 2.7 suggests we SHOULD prefer the | ||
| 1656 | * flavor listed first. However, some servers list | ||
| 1657 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. | ||
| 1658 | */ | ||
| 1659 | for (i = 0; i < count; i++) { | 1633 | for (i = 0; i < count; i++) { |
| 1660 | struct rpcsec_gss_info info; | 1634 | if (args->auth_flavors[0] == server_authlist[i] || |
| 1661 | 1635 | server_authlist[i] == RPC_AUTH_NULL) | |
| 1662 | flavor = request->auth_flavs[i]; | 1636 | goto out; |
| 1663 | switch (flavor) { | ||
| 1664 | case RPC_AUTH_UNIX: | ||
| 1665 | goto out_set; | ||
| 1666 | case RPC_AUTH_NULL: | ||
| 1667 | continue; | ||
| 1668 | default: | ||
| 1669 | if (rpcauth_get_gssinfo(flavor, &info) == 0) | ||
| 1670 | goto out_set; | ||
| 1671 | } | ||
| 1672 | } | 1637 | } |
| 1673 | 1638 | ||
| 1674 | /* | 1639 | dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n", |
| 1675 | * As a last chance, see if the server list contains AUTH_NULL - | 1640 | args->auth_flavors[0]); |
| 1676 | * if it does, use the default flavor. | 1641 | return -EACCES; |
| 1677 | */ | ||
| 1678 | for (i = 0; i < count; i++) { | ||
| 1679 | if (request->auth_flavs[i] == RPC_AUTH_NULL) | ||
| 1680 | goto out_default; | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | dfprintk(MOUNT, "NFS: no auth flavors in common with server\n"); | ||
| 1684 | goto out_err; | ||
| 1685 | 1642 | ||
| 1686 | out_default: | ||
| 1687 | /* use default if flavor not already set */ | ||
| 1688 | flavor = (args->auth_flavors[0] == RPC_AUTH_MAXFLAVOR) ? | ||
| 1689 | RPC_AUTH_UNIX : args->auth_flavors[0]; | ||
| 1690 | out_set: | ||
| 1691 | args->auth_flavors[0] = flavor; | ||
| 1692 | out: | 1643 | out: |
| 1693 | dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]); | 1644 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); |
| 1694 | return 0; | 1645 | return 0; |
| 1695 | out_err: | ||
| 1696 | return -EACCES; | ||
| 1697 | } | 1646 | } |
| 1698 | 1647 | ||
| 1699 | /* | 1648 | /* |
| @@ -1701,10 +1650,10 @@ out_err: | |||
| 1701 | * corresponding to the provided path. | 1650 | * corresponding to the provided path. |
| 1702 | */ | 1651 | */ |
| 1703 | static int nfs_request_mount(struct nfs_parsed_mount_data *args, | 1652 | static int nfs_request_mount(struct nfs_parsed_mount_data *args, |
| 1704 | struct nfs_fh *root_fh) | 1653 | struct nfs_fh *root_fh, |
| 1654 | rpc_authflavor_t *server_authlist, | ||
| 1655 | unsigned int *server_authlist_len) | ||
| 1705 | { | 1656 | { |
| 1706 | rpc_authflavor_t server_authlist[NFS_MAX_SECFLAVORS]; | ||
| 1707 | unsigned int server_authlist_len = ARRAY_SIZE(server_authlist); | ||
| 1708 | struct nfs_mount_request request = { | 1657 | struct nfs_mount_request request = { |
| 1709 | .sap = (struct sockaddr *) | 1658 | .sap = (struct sockaddr *) |
| 1710 | &args->mount_server.address, | 1659 | &args->mount_server.address, |
| @@ -1712,7 +1661,7 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, | |||
| 1712 | .protocol = args->mount_server.protocol, | 1661 | .protocol = args->mount_server.protocol, |
| 1713 | .fh = root_fh, | 1662 | .fh = root_fh, |
| 1714 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, | 1663 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, |
| 1715 | .auth_flav_len = &server_authlist_len, | 1664 | .auth_flav_len = server_authlist_len, |
| 1716 | .auth_flavs = server_authlist, | 1665 | .auth_flavs = server_authlist, |
| 1717 | .net = args->net, | 1666 | .net = args->net, |
| 1718 | }; | 1667 | }; |
| @@ -1756,24 +1705,92 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, | |||
| 1756 | return status; | 1705 | return status; |
| 1757 | } | 1706 | } |
| 1758 | 1707 | ||
| 1759 | return nfs_select_flavor(args, &request); | 1708 | return 0; |
| 1760 | } | 1709 | } |
| 1761 | 1710 | ||
| 1762 | struct dentry *nfs_try_mount(int flags, const char *dev_name, | 1711 | static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_info, |
| 1763 | struct nfs_mount_info *mount_info, | 1712 | struct nfs_subversion *nfs_mod) |
| 1764 | struct nfs_subversion *nfs_mod) | ||
| 1765 | { | 1713 | { |
| 1766 | int status; | 1714 | int status; |
| 1767 | struct nfs_server *server; | 1715 | unsigned int i; |
| 1716 | bool tried_auth_unix = false; | ||
| 1717 | bool auth_null_in_list = false; | ||
| 1718 | struct nfs_server *server = ERR_PTR(-EACCES); | ||
| 1719 | struct nfs_parsed_mount_data *args = mount_info->parsed; | ||
| 1720 | rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS]; | ||
| 1721 | unsigned int authlist_len = ARRAY_SIZE(authlist); | ||
| 1722 | |||
| 1723 | status = nfs_request_mount(args, mount_info->mntfh, authlist, | ||
| 1724 | &authlist_len); | ||
| 1725 | if (status) | ||
| 1726 | return ERR_PTR(status); | ||
| 1768 | 1727 | ||
| 1769 | if (mount_info->parsed->need_mount) { | 1728 | /* |
| 1770 | status = nfs_request_mount(mount_info->parsed, mount_info->mntfh); | 1729 | * Was a sec= authflavor specified in the options? First, verify |
| 1730 | * whether the server supports it, and then just try to use it if so. | ||
| 1731 | */ | ||
| 1732 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | ||
| 1733 | status = nfs_verify_authflavor(args, authlist, authlist_len); | ||
| 1734 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); | ||
| 1771 | if (status) | 1735 | if (status) |
| 1772 | return ERR_PTR(status); | 1736 | return ERR_PTR(status); |
| 1737 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
| 1738 | } | ||
| 1739 | |||
| 1740 | /* | ||
| 1741 | * No sec= option was provided. RFC 2623, section 2.7 suggests we | ||
| 1742 | * SHOULD prefer the flavor listed first. However, some servers list | ||
| 1743 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. | ||
| 1744 | */ | ||
| 1745 | for (i = 0; i < authlist_len; ++i) { | ||
| 1746 | rpc_authflavor_t flavor; | ||
| 1747 | struct rpcsec_gss_info info; | ||
| 1748 | |||
| 1749 | flavor = authlist[i]; | ||
| 1750 | switch (flavor) { | ||
| 1751 | case RPC_AUTH_UNIX: | ||
| 1752 | tried_auth_unix = true; | ||
| 1753 | break; | ||
| 1754 | case RPC_AUTH_NULL: | ||
| 1755 | auth_null_in_list = true; | ||
| 1756 | continue; | ||
| 1757 | default: | ||
| 1758 | if (rpcauth_get_gssinfo(flavor, &info) != 0) | ||
| 1759 | continue; | ||
| 1760 | /* Fallthrough */ | ||
| 1761 | } | ||
| 1762 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor); | ||
| 1763 | args->auth_flavors[0] = flavor; | ||
| 1764 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
| 1765 | if (!IS_ERR(server)) | ||
| 1766 | return server; | ||
| 1773 | } | 1767 | } |
| 1774 | 1768 | ||
| 1775 | /* Get a volume representation */ | 1769 | /* |
| 1776 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | 1770 | * Nothing we tried so far worked. At this point, give up if we've |
| 1771 | * already tried AUTH_UNIX or if the server's list doesn't contain | ||
| 1772 | * AUTH_NULL | ||
| 1773 | */ | ||
| 1774 | if (tried_auth_unix || !auth_null_in_list) | ||
| 1775 | return server; | ||
| 1776 | |||
| 1777 | /* Last chance! Try AUTH_UNIX */ | ||
| 1778 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX); | ||
| 1779 | args->auth_flavors[0] = RPC_AUTH_UNIX; | ||
| 1780 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
| 1781 | } | ||
| 1782 | |||
| 1783 | struct dentry *nfs_try_mount(int flags, const char *dev_name, | ||
| 1784 | struct nfs_mount_info *mount_info, | ||
| 1785 | struct nfs_subversion *nfs_mod) | ||
| 1786 | { | ||
| 1787 | struct nfs_server *server; | ||
| 1788 | |||
| 1789 | if (mount_info->parsed->need_mount) | ||
| 1790 | server = nfs_try_mount_request(mount_info, nfs_mod); | ||
| 1791 | else | ||
| 1792 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
| 1793 | |||
| 1777 | if (IS_ERR(server)) | 1794 | if (IS_ERR(server)) |
| 1778 | return ERR_CAST(server); | 1795 | return ERR_CAST(server); |
| 1779 | 1796 | ||
| @@ -2412,7 +2429,21 @@ static int nfs_bdi_register(struct nfs_server *server) | |||
| 2412 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, | 2429 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, |
| 2413 | struct nfs_mount_info *mount_info) | 2430 | struct nfs_mount_info *mount_info) |
| 2414 | { | 2431 | { |
| 2415 | return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); | 2432 | int error; |
| 2433 | unsigned long kflags = 0, kflags_out = 0; | ||
| 2434 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL) | ||
| 2435 | kflags |= SECURITY_LSM_NATIVE_LABELS; | ||
| 2436 | |||
| 2437 | error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts, | ||
| 2438 | kflags, &kflags_out); | ||
| 2439 | if (error) | ||
| 2440 | goto err; | ||
| 2441 | |||
| 2442 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL && | ||
| 2443 | !(kflags_out & SECURITY_LSM_NATIVE_LABELS)) | ||
| 2444 | NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL; | ||
| 2445 | err: | ||
| 2446 | return error; | ||
| 2416 | } | 2447 | } |
| 2417 | EXPORT_SYMBOL_GPL(nfs_set_sb_security); | 2448 | EXPORT_SYMBOL_GPL(nfs_set_sb_security); |
| 2418 | 2449 | ||
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 07a473fd49bc..c0d93170585d 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
| @@ -243,6 +243,12 @@ void nfsd_lockd_shutdown(void); | |||
| 243 | #define nfserr_reject_deleg cpu_to_be32(NFS4ERR_REJECT_DELEG) | 243 | #define nfserr_reject_deleg cpu_to_be32(NFS4ERR_REJECT_DELEG) |
| 244 | #define nfserr_returnconflict cpu_to_be32(NFS4ERR_RETURNCONFLICT) | 244 | #define nfserr_returnconflict cpu_to_be32(NFS4ERR_RETURNCONFLICT) |
| 245 | #define nfserr_deleg_revoked cpu_to_be32(NFS4ERR_DELEG_REVOKED) | 245 | #define nfserr_deleg_revoked cpu_to_be32(NFS4ERR_DELEG_REVOKED) |
| 246 | #define nfserr_partner_notsupp cpu_to_be32(NFS4ERR_PARTNER_NOTSUPP) | ||
| 247 | #define nfserr_partner_no_auth cpu_to_be32(NFS4ERR_PARTNER_NO_AUTH) | ||
| 248 | #define nfserr_metadata_notsupp cpu_to_be32(NFS4ERR_METADATA_NOTSUPP) | ||
| 249 | #define nfserr_offload_denied cpu_to_be32(NFS4ERR_OFFLOAD_DENIED) | ||
| 250 | #define nfserr_wrong_lfs cpu_to_be32(NFS4ERR_WRONG_LFS) | ||
| 251 | #define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL) | ||
| 246 | 252 | ||
| 247 | /* error codes for internal use */ | 253 | /* error codes for internal use */ |
| 248 | /* if a request fails due to kmalloc failure, it gets dropped. | 254 | /* if a request fails due to kmalloc failure, it gets dropped. |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 7b8fc73810ad..e36dee52f224 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
| @@ -32,6 +32,15 @@ struct nfs4_acl { | |||
| 32 | struct nfs4_ace aces[0]; | 32 | struct nfs4_ace aces[0]; |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | #define NFS4_MAXLABELLEN 2048 | ||
| 36 | |||
| 37 | struct nfs4_label { | ||
| 38 | uint32_t lfs; | ||
| 39 | uint32_t pi; | ||
| 40 | u32 len; | ||
| 41 | char *label; | ||
| 42 | }; | ||
| 43 | |||
| 35 | typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier; | 44 | typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier; |
| 36 | 45 | ||
| 37 | struct nfs_stateid4 { | 46 | struct nfs_stateid4 { |
| @@ -219,6 +228,14 @@ enum nfsstat4 { | |||
| 219 | NFS4ERR_REJECT_DELEG = 10085, /* on callback */ | 228 | NFS4ERR_REJECT_DELEG = 10085, /* on callback */ |
| 220 | NFS4ERR_RETURNCONFLICT = 10086, /* outstanding layoutreturn */ | 229 | NFS4ERR_RETURNCONFLICT = 10086, /* outstanding layoutreturn */ |
| 221 | NFS4ERR_DELEG_REVOKED = 10087, /* deleg./layout revoked */ | 230 | NFS4ERR_DELEG_REVOKED = 10087, /* deleg./layout revoked */ |
| 231 | |||
| 232 | /* nfs42 */ | ||
| 233 | NFS4ERR_PARTNER_NOTSUPP = 10088, | ||
| 234 | NFS4ERR_PARTNER_NO_AUTH = 10089, | ||
| 235 | NFS4ERR_METADATA_NOTSUPP = 10090, | ||
| 236 | NFS4ERR_OFFLOAD_DENIED = 10091, | ||
| 237 | NFS4ERR_WRONG_LFS = 10092, | ||
| 238 | NFS4ERR_BADLABEL = 10093, | ||
| 222 | }; | 239 | }; |
| 223 | 240 | ||
| 224 | static inline bool seqid_mutating_err(u32 err) | 241 | static inline bool seqid_mutating_err(u32 err) |
| @@ -378,6 +395,7 @@ enum lock_type4 { | |||
| 378 | #define FATTR4_WORD1_FS_LAYOUT_TYPES (1UL << 30) | 395 | #define FATTR4_WORD1_FS_LAYOUT_TYPES (1UL << 30) |
| 379 | #define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1) | 396 | #define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1) |
| 380 | #define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4) | 397 | #define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4) |
| 398 | #define FATTR4_WORD2_SECURITY_LABEL (1UL << 17) | ||
| 381 | 399 | ||
| 382 | /* MDS threshold bitmap bits */ | 400 | /* MDS threshold bitmap bits */ |
| 383 | #define THRESHOLD_RD (1UL << 0) | 401 | #define THRESHOLD_RD (1UL << 0) |
| @@ -390,11 +408,15 @@ enum lock_type4 { | |||
| 390 | #define NFS4_VERSION 4 | 408 | #define NFS4_VERSION 4 |
| 391 | #define NFS4_MINOR_VERSION 0 | 409 | #define NFS4_MINOR_VERSION 0 |
| 392 | 410 | ||
| 411 | #if defined(CONFIG_NFS_V4_2) | ||
| 412 | #define NFS4_MAX_MINOR_VERSION 2 | ||
| 413 | #else | ||
| 393 | #if defined(CONFIG_NFS_V4_1) | 414 | #if defined(CONFIG_NFS_V4_1) |
| 394 | #define NFS4_MAX_MINOR_VERSION 1 | 415 | #define NFS4_MAX_MINOR_VERSION 1 |
| 395 | #else | 416 | #else |
| 396 | #define NFS4_MAX_MINOR_VERSION 0 | 417 | #define NFS4_MAX_MINOR_VERSION 0 |
| 397 | #endif /* CONFIG_NFS_V4_1 */ | 418 | #endif /* CONFIG_NFS_V4_1 */ |
| 419 | #endif /* CONFIG_NFS_V4_2 */ | ||
| 398 | 420 | ||
| 399 | #define NFS4_DEBUG 1 | 421 | #define NFS4_DEBUG 1 |
| 400 | 422 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index fc01d5cb4cf1..0b176297aaf6 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
| @@ -207,6 +207,7 @@ struct nfs_inode { | |||
| 207 | #define NFS_INO_INVALID_ACL 0x0010 /* cached acls are invalid */ | 207 | #define NFS_INO_INVALID_ACL 0x0010 /* cached acls are invalid */ |
| 208 | #define NFS_INO_REVAL_PAGECACHE 0x0020 /* must revalidate pagecache */ | 208 | #define NFS_INO_REVAL_PAGECACHE 0x0020 /* must revalidate pagecache */ |
| 209 | #define NFS_INO_REVAL_FORCED 0x0040 /* force revalidation ignoring a delegation */ | 209 | #define NFS_INO_REVAL_FORCED 0x0040 /* force revalidation ignoring a delegation */ |
| 210 | #define NFS_INO_INVALID_LABEL 0x0080 /* cached label is invalid */ | ||
| 210 | 211 | ||
| 211 | /* | 212 | /* |
| 212 | * Bit offsets in flags field | 213 | * Bit offsets in flags field |
| @@ -336,7 +337,7 @@ extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping); | |||
| 336 | extern void nfs_zap_caches(struct inode *); | 337 | extern void nfs_zap_caches(struct inode *); |
| 337 | extern void nfs_invalidate_atime(struct inode *); | 338 | extern void nfs_invalidate_atime(struct inode *); |
| 338 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, | 339 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, |
| 339 | struct nfs_fattr *); | 340 | struct nfs_fattr *, struct nfs4_label *); |
| 340 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); | 341 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); |
| 341 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); | 342 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); |
| 342 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); | 343 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); |
| @@ -352,10 +353,13 @@ extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); | |||
| 352 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); | 353 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); |
| 353 | extern int nfs_setattr(struct dentry *, struct iattr *); | 354 | extern int nfs_setattr(struct dentry *, struct iattr *); |
| 354 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); | 355 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); |
| 356 | extern void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
| 357 | struct nfs4_label *label); | ||
| 355 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); | 358 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); |
| 356 | extern void put_nfs_open_context(struct nfs_open_context *ctx); | 359 | extern void put_nfs_open_context(struct nfs_open_context *ctx); |
| 357 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); | 360 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); |
| 358 | extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode); | 361 | extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode); |
| 362 | extern void nfs_inode_attach_open_context(struct nfs_open_context *ctx); | ||
| 359 | extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); | 363 | extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); |
| 360 | extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); | 364 | extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); |
| 361 | extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); | 365 | extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); |
| @@ -468,7 +472,8 @@ extern const struct file_operations nfs_dir_operations; | |||
| 468 | extern const struct dentry_operations nfs_dentry_operations; | 472 | extern const struct dentry_operations nfs_dentry_operations; |
| 469 | 473 | ||
| 470 | extern void nfs_force_lookup_revalidate(struct inode *dir); | 474 | extern void nfs_force_lookup_revalidate(struct inode *dir); |
| 471 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); | 475 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, |
| 476 | struct nfs_fattr *fattr, struct nfs4_label *label); | ||
| 472 | extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); | 477 | extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); |
| 473 | extern void nfs_access_zap_cache(struct inode *inode); | 478 | extern void nfs_access_zap_cache(struct inode *inode); |
| 474 | 479 | ||
| @@ -497,6 +502,24 @@ extern int nfs_mountpoint_expiry_timeout; | |||
| 497 | extern void nfs_release_automount_timer(void); | 502 | extern void nfs_release_automount_timer(void); |
| 498 | 503 | ||
| 499 | /* | 504 | /* |
| 505 | * linux/fs/nfs/nfs4proc.c | ||
| 506 | */ | ||
| 507 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
| 508 | extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); | ||
| 509 | static inline void nfs4_label_free(struct nfs4_label *label) | ||
| 510 | { | ||
| 511 | if (label) { | ||
| 512 | kfree(label->label); | ||
| 513 | kfree(label); | ||
| 514 | } | ||
| 515 | return; | ||
| 516 | } | ||
| 517 | #else | ||
| 518 | static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } | ||
| 519 | static inline void nfs4_label_free(void *label) {} | ||
| 520 | #endif | ||
| 521 | |||
| 522 | /* | ||
| 500 | * linux/fs/nfs/unlink.c | 523 | * linux/fs/nfs/unlink.c |
| 501 | */ | 524 | */ |
| 502 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); | 525 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 3b7fa2abecca..d2212432c456 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
| @@ -146,7 +146,12 @@ struct nfs_server { | |||
| 146 | u32 attr_bitmask[3];/* V4 bitmask representing the set | 146 | u32 attr_bitmask[3];/* V4 bitmask representing the set |
| 147 | of attributes supported on this | 147 | of attributes supported on this |
| 148 | filesystem */ | 148 | filesystem */ |
| 149 | u32 cache_consistency_bitmask[2]; | 149 | u32 attr_bitmask_nl[3]; |
| 150 | /* V4 bitmask representing the | ||
| 151 | set of attributes supported | ||
| 152 | on this filesystem excluding | ||
| 153 | the label support bit. */ | ||
| 154 | u32 cache_consistency_bitmask[3]; | ||
| 150 | /* V4 bitmask representing the subset | 155 | /* V4 bitmask representing the subset |
| 151 | of change attribute, size, ctime | 156 | of change attribute, size, ctime |
| 152 | and mtime attributes supported by | 157 | and mtime attributes supported by |
| @@ -200,5 +205,6 @@ struct nfs_server { | |||
| 200 | #define NFS_CAP_UIDGID_NOMAP (1U << 15) | 205 | #define NFS_CAP_UIDGID_NOMAP (1U << 15) |
| 201 | #define NFS_CAP_STATEID_NFSV41 (1U << 16) | 206 | #define NFS_CAP_STATEID_NFSV41 (1U << 16) |
| 202 | #define NFS_CAP_ATOMIC_OPEN_V1 (1U << 17) | 207 | #define NFS_CAP_ATOMIC_OPEN_V1 (1U << 17) |
| 208 | #define NFS_CAP_SECURITY_LABEL (1U << 18) | ||
| 203 | 209 | ||
| 204 | #endif | 210 | #endif |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 104b62f23ee0..8651574a305b 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
| @@ -101,6 +101,7 @@ struct nfs_fattr { | |||
| 101 | #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 22) | 101 | #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 22) |
| 102 | #define NFS_ATTR_FATTR_OWNER_NAME (1U << 23) | 102 | #define NFS_ATTR_FATTR_OWNER_NAME (1U << 23) |
| 103 | #define NFS_ATTR_FATTR_GROUP_NAME (1U << 24) | 103 | #define NFS_ATTR_FATTR_GROUP_NAME (1U << 24) |
| 104 | #define NFS_ATTR_FATTR_V4_SECURITY_LABEL (1U << 25) | ||
| 104 | 105 | ||
| 105 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ | 106 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ |
| 106 | | NFS_ATTR_FATTR_MODE \ | 107 | | NFS_ATTR_FATTR_MODE \ |
| @@ -120,7 +121,8 @@ struct nfs_fattr { | |||
| 120 | #define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \ | 121 | #define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \ |
| 121 | | NFS_ATTR_FATTR_SPACE_USED) | 122 | | NFS_ATTR_FATTR_SPACE_USED) |
| 122 | #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ | 123 | #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ |
| 123 | | NFS_ATTR_FATTR_SPACE_USED) | 124 | | NFS_ATTR_FATTR_SPACE_USED \ |
| 125 | | NFS_ATTR_FATTR_V4_SECURITY_LABEL) | ||
| 124 | 126 | ||
| 125 | /* | 127 | /* |
| 126 | * Info on the file system | 128 | * Info on the file system |
| @@ -246,6 +248,7 @@ struct nfs4_layoutget_res { | |||
| 246 | struct nfs4_layoutget { | 248 | struct nfs4_layoutget { |
| 247 | struct nfs4_layoutget_args args; | 249 | struct nfs4_layoutget_args args; |
| 248 | struct nfs4_layoutget_res res; | 250 | struct nfs4_layoutget_res res; |
| 251 | struct rpc_cred *cred; | ||
| 249 | gfp_t gfp_flags; | 252 | gfp_t gfp_flags; |
| 250 | }; | 253 | }; |
| 251 | 254 | ||
| @@ -347,6 +350,7 @@ struct nfs_openargs { | |||
| 347 | const u32 * open_bitmap; | 350 | const u32 * open_bitmap; |
| 348 | __u32 claim; | 351 | __u32 claim; |
| 349 | enum createmode4 createmode; | 352 | enum createmode4 createmode; |
| 353 | const struct nfs4_label *label; | ||
| 350 | }; | 354 | }; |
| 351 | 355 | ||
| 352 | struct nfs_openres { | 356 | struct nfs_openres { |
| @@ -356,6 +360,7 @@ struct nfs_openres { | |||
| 356 | struct nfs4_change_info cinfo; | 360 | struct nfs4_change_info cinfo; |
| 357 | __u32 rflags; | 361 | __u32 rflags; |
| 358 | struct nfs_fattr * f_attr; | 362 | struct nfs_fattr * f_attr; |
| 363 | struct nfs4_label *f_label; | ||
| 359 | struct nfs_seqid * seqid; | 364 | struct nfs_seqid * seqid; |
| 360 | const struct nfs_server *server; | 365 | const struct nfs_server *server; |
| 361 | fmode_t delegation_type; | 366 | fmode_t delegation_type; |
| @@ -598,6 +603,7 @@ struct nfs_entry { | |||
| 598 | int eof; | 603 | int eof; |
| 599 | struct nfs_fh * fh; | 604 | struct nfs_fh * fh; |
| 600 | struct nfs_fattr * fattr; | 605 | struct nfs_fattr * fattr; |
| 606 | struct nfs4_label *label; | ||
| 601 | unsigned char d_type; | 607 | unsigned char d_type; |
| 602 | struct nfs_server * server; | 608 | struct nfs_server * server; |
| 603 | }; | 609 | }; |
| @@ -630,6 +636,7 @@ struct nfs_setattrargs { | |||
| 630 | struct iattr * iap; | 636 | struct iattr * iap; |
| 631 | const struct nfs_server * server; /* Needed for name mapping */ | 637 | const struct nfs_server * server; /* Needed for name mapping */ |
| 632 | const u32 * bitmask; | 638 | const u32 * bitmask; |
| 639 | const struct nfs4_label *label; | ||
| 633 | }; | 640 | }; |
| 634 | 641 | ||
| 635 | struct nfs_setaclargs { | 642 | struct nfs_setaclargs { |
| @@ -665,6 +672,7 @@ struct nfs_getaclres { | |||
| 665 | struct nfs_setattrres { | 672 | struct nfs_setattrres { |
| 666 | struct nfs4_sequence_res seq_res; | 673 | struct nfs4_sequence_res seq_res; |
| 667 | struct nfs_fattr * fattr; | 674 | struct nfs_fattr * fattr; |
| 675 | struct nfs4_label *label; | ||
| 668 | const struct nfs_server * server; | 676 | const struct nfs_server * server; |
| 669 | }; | 677 | }; |
| 670 | 678 | ||
| @@ -862,6 +870,7 @@ struct nfs4_create_arg { | |||
| 862 | const struct iattr * attrs; | 870 | const struct iattr * attrs; |
| 863 | const struct nfs_fh * dir_fh; | 871 | const struct nfs_fh * dir_fh; |
| 864 | const u32 * bitmask; | 872 | const u32 * bitmask; |
| 873 | const struct nfs4_label *label; | ||
| 865 | }; | 874 | }; |
| 866 | 875 | ||
| 867 | struct nfs4_create_res { | 876 | struct nfs4_create_res { |
| @@ -869,6 +878,7 @@ struct nfs4_create_res { | |||
| 869 | const struct nfs_server * server; | 878 | const struct nfs_server * server; |
| 870 | struct nfs_fh * fh; | 879 | struct nfs_fh * fh; |
| 871 | struct nfs_fattr * fattr; | 880 | struct nfs_fattr * fattr; |
| 881 | struct nfs4_label *label; | ||
| 872 | struct nfs4_change_info dir_cinfo; | 882 | struct nfs4_change_info dir_cinfo; |
| 873 | }; | 883 | }; |
| 874 | 884 | ||
| @@ -893,6 +903,7 @@ struct nfs4_getattr_res { | |||
| 893 | struct nfs4_sequence_res seq_res; | 903 | struct nfs4_sequence_res seq_res; |
| 894 | const struct nfs_server * server; | 904 | const struct nfs_server * server; |
| 895 | struct nfs_fattr * fattr; | 905 | struct nfs_fattr * fattr; |
| 906 | struct nfs4_label *label; | ||
| 896 | }; | 907 | }; |
| 897 | 908 | ||
| 898 | struct nfs4_link_arg { | 909 | struct nfs4_link_arg { |
| @@ -907,6 +918,7 @@ struct nfs4_link_res { | |||
| 907 | struct nfs4_sequence_res seq_res; | 918 | struct nfs4_sequence_res seq_res; |
| 908 | const struct nfs_server * server; | 919 | const struct nfs_server * server; |
| 909 | struct nfs_fattr * fattr; | 920 | struct nfs_fattr * fattr; |
| 921 | struct nfs4_label *label; | ||
| 910 | struct nfs4_change_info cinfo; | 922 | struct nfs4_change_info cinfo; |
| 911 | struct nfs_fattr * dir_attr; | 923 | struct nfs_fattr * dir_attr; |
| 912 | }; | 924 | }; |
| @@ -924,6 +936,7 @@ struct nfs4_lookup_res { | |||
| 924 | const struct nfs_server * server; | 936 | const struct nfs_server * server; |
| 925 | struct nfs_fattr * fattr; | 937 | struct nfs_fattr * fattr; |
| 926 | struct nfs_fh * fh; | 938 | struct nfs_fh * fh; |
| 939 | struct nfs4_label *label; | ||
| 927 | }; | 940 | }; |
| 928 | 941 | ||
| 929 | struct nfs4_lookup_root_arg { | 942 | struct nfs4_lookup_root_arg { |
| @@ -1366,11 +1379,12 @@ struct nfs_rpc_ops { | |||
| 1366 | struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *, | 1379 | struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *, |
| 1367 | struct nfs_subversion *); | 1380 | struct nfs_subversion *); |
| 1368 | int (*getattr) (struct nfs_server *, struct nfs_fh *, | 1381 | int (*getattr) (struct nfs_server *, struct nfs_fh *, |
| 1369 | struct nfs_fattr *); | 1382 | struct nfs_fattr *, struct nfs4_label *); |
| 1370 | int (*setattr) (struct dentry *, struct nfs_fattr *, | 1383 | int (*setattr) (struct dentry *, struct nfs_fattr *, |
| 1371 | struct iattr *); | 1384 | struct iattr *); |
| 1372 | int (*lookup) (struct inode *, struct qstr *, | 1385 | int (*lookup) (struct inode *, struct qstr *, |
| 1373 | struct nfs_fh *, struct nfs_fattr *); | 1386 | struct nfs_fh *, struct nfs_fattr *, |
| 1387 | struct nfs4_label *); | ||
| 1374 | int (*access) (struct inode *, struct nfs_access_entry *); | 1388 | int (*access) (struct inode *, struct nfs_access_entry *); |
| 1375 | int (*readlink)(struct inode *, struct page *, unsigned int, | 1389 | int (*readlink)(struct inode *, struct page *, unsigned int, |
| 1376 | unsigned int); | 1390 | unsigned int); |
diff --git a/include/linux/security.h b/include/linux/security.h index 40560f41e3d5..7ce53ae1266b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/capability.h> | 26 | #include <linux/capability.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
| 29 | #include <linux/string.h> | ||
| 29 | 30 | ||
| 30 | struct linux_binprm; | 31 | struct linux_binprm; |
| 31 | struct cred; | 32 | struct cred; |
| @@ -60,6 +61,9 @@ struct mm_struct; | |||
| 60 | #define SECURITY_CAP_NOAUDIT 0 | 61 | #define SECURITY_CAP_NOAUDIT 0 |
| 61 | #define SECURITY_CAP_AUDIT 1 | 62 | #define SECURITY_CAP_AUDIT 1 |
| 62 | 63 | ||
| 64 | /* LSM Agnostic defines for sb_set_mnt_opts */ | ||
| 65 | #define SECURITY_LSM_NATIVE_LABELS 1 | ||
| 66 | |||
| 63 | struct ctl_table; | 67 | struct ctl_table; |
| 64 | struct audit_krule; | 68 | struct audit_krule; |
| 65 | struct user_namespace; | 69 | struct user_namespace; |
| @@ -306,6 +310,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 306 | * Parse a string of security data filling in the opts structure | 310 | * Parse a string of security data filling in the opts structure |
| 307 | * @options string containing all mount options known by the LSM | 311 | * @options string containing all mount options known by the LSM |
| 308 | * @opts binary data structure usable by the LSM | 312 | * @opts binary data structure usable by the LSM |
| 313 | * @dentry_init_security: | ||
| 314 | * Compute a context for a dentry as the inode is not yet available | ||
| 315 | * since NFSv4 has no label backed by an EA anyway. | ||
| 316 | * @dentry dentry to use in calculating the context. | ||
| 317 | * @mode mode used to determine resource type. | ||
| 318 | * @name name of the last path component used to create file | ||
| 319 | * @ctx pointer to place the pointer to the resulting context in. | ||
| 320 | * @ctxlen point to place the length of the resulting context. | ||
| 321 | * | ||
| 309 | * | 322 | * |
| 310 | * Security hooks for inode operations. | 323 | * Security hooks for inode operations. |
| 311 | * | 324 | * |
| @@ -1313,6 +1326,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 1313 | * @pages contains the number of pages. | 1326 | * @pages contains the number of pages. |
| 1314 | * Return 0 if permission is granted. | 1327 | * Return 0 if permission is granted. |
| 1315 | * | 1328 | * |
| 1329 | * @ismaclabel: | ||
| 1330 | * Check if the extended attribute specified by @name | ||
| 1331 | * represents a MAC label. Returns 1 if name is a MAC | ||
| 1332 | * attribute otherwise returns 0. | ||
| 1333 | * @name full extended attribute name to check against | ||
| 1334 | * LSM as a MAC label. | ||
| 1335 | * | ||
| 1316 | * @secid_to_secctx: | 1336 | * @secid_to_secctx: |
| 1317 | * Convert secid to security context. If secdata is NULL the length of | 1337 | * Convert secid to security context. If secdata is NULL the length of |
| 1318 | * the result will be returned in seclen, but no secdata will be returned. | 1338 | * the result will be returned in seclen, but no secdata will be returned. |
| @@ -1440,10 +1460,16 @@ struct security_operations { | |||
| 1440 | int (*sb_pivotroot) (struct path *old_path, | 1460 | int (*sb_pivotroot) (struct path *old_path, |
| 1441 | struct path *new_path); | 1461 | struct path *new_path); |
| 1442 | int (*sb_set_mnt_opts) (struct super_block *sb, | 1462 | int (*sb_set_mnt_opts) (struct super_block *sb, |
| 1443 | struct security_mnt_opts *opts); | 1463 | struct security_mnt_opts *opts, |
| 1464 | unsigned long kern_flags, | ||
| 1465 | unsigned long *set_kern_flags); | ||
| 1444 | int (*sb_clone_mnt_opts) (const struct super_block *oldsb, | 1466 | int (*sb_clone_mnt_opts) (const struct super_block *oldsb, |
| 1445 | struct super_block *newsb); | 1467 | struct super_block *newsb); |
| 1446 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1468 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
| 1469 | int (*dentry_init_security) (struct dentry *dentry, int mode, | ||
| 1470 | struct qstr *name, void **ctx, | ||
| 1471 | u32 *ctxlen); | ||
| 1472 | |||
| 1447 | 1473 | ||
| 1448 | #ifdef CONFIG_SECURITY_PATH | 1474 | #ifdef CONFIG_SECURITY_PATH |
| 1449 | int (*path_unlink) (struct path *dir, struct dentry *dentry); | 1475 | int (*path_unlink) (struct path *dir, struct dentry *dentry); |
| @@ -1591,6 +1617,7 @@ struct security_operations { | |||
| 1591 | 1617 | ||
| 1592 | int (*getprocattr) (struct task_struct *p, char *name, char **value); | 1618 | int (*getprocattr) (struct task_struct *p, char *name, char **value); |
| 1593 | int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size); | 1619 | int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size); |
| 1620 | int (*ismaclabel) (const char *name); | ||
| 1594 | int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); | 1621 | int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); |
| 1595 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); | 1622 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); |
| 1596 | void (*release_secctx) (char *secdata, u32 seclen); | 1623 | void (*release_secctx) (char *secdata, u32 seclen); |
| @@ -1726,10 +1753,16 @@ int security_sb_mount(const char *dev_name, struct path *path, | |||
| 1726 | const char *type, unsigned long flags, void *data); | 1753 | const char *type, unsigned long flags, void *data); |
| 1727 | int security_sb_umount(struct vfsmount *mnt, int flags); | 1754 | int security_sb_umount(struct vfsmount *mnt, int flags); |
| 1728 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); | 1755 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); |
| 1729 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); | 1756 | int security_sb_set_mnt_opts(struct super_block *sb, |
| 1757 | struct security_mnt_opts *opts, | ||
| 1758 | unsigned long kern_flags, | ||
| 1759 | unsigned long *set_kern_flags); | ||
| 1730 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, | 1760 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, |
| 1731 | struct super_block *newsb); | 1761 | struct super_block *newsb); |
| 1732 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); | 1762 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); |
| 1763 | int security_dentry_init_security(struct dentry *dentry, int mode, | ||
| 1764 | struct qstr *name, void **ctx, | ||
| 1765 | u32 *ctxlen); | ||
| 1733 | 1766 | ||
| 1734 | int security_inode_alloc(struct inode *inode); | 1767 | int security_inode_alloc(struct inode *inode); |
| 1735 | void security_inode_free(struct inode *inode); | 1768 | void security_inode_free(struct inode *inode); |
| @@ -1841,6 +1874,7 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode); | |||
| 1841 | int security_getprocattr(struct task_struct *p, char *name, char **value); | 1874 | int security_getprocattr(struct task_struct *p, char *name, char **value); |
| 1842 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); | 1875 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); |
| 1843 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); | 1876 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); |
| 1877 | int security_ismaclabel(const char *name); | ||
| 1844 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); | 1878 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); |
| 1845 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); | 1879 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); |
| 1846 | void security_release_secctx(char *secdata, u32 seclen); | 1880 | void security_release_secctx(char *secdata, u32 seclen); |
| @@ -2012,7 +2046,9 @@ static inline int security_sb_pivotroot(struct path *old_path, | |||
| 2012 | } | 2046 | } |
| 2013 | 2047 | ||
| 2014 | static inline int security_sb_set_mnt_opts(struct super_block *sb, | 2048 | static inline int security_sb_set_mnt_opts(struct super_block *sb, |
| 2015 | struct security_mnt_opts *opts) | 2049 | struct security_mnt_opts *opts, |
| 2050 | unsigned long kern_flags, | ||
| 2051 | unsigned long *set_kern_flags) | ||
| 2016 | { | 2052 | { |
| 2017 | return 0; | 2053 | return 0; |
| 2018 | } | 2054 | } |
| @@ -2036,6 +2072,16 @@ static inline int security_inode_alloc(struct inode *inode) | |||
| 2036 | static inline void security_inode_free(struct inode *inode) | 2072 | static inline void security_inode_free(struct inode *inode) |
| 2037 | { } | 2073 | { } |
| 2038 | 2074 | ||
| 2075 | static inline int security_dentry_init_security(struct dentry *dentry, | ||
| 2076 | int mode, | ||
| 2077 | struct qstr *name, | ||
| 2078 | void **ctx, | ||
| 2079 | u32 *ctxlen) | ||
| 2080 | { | ||
| 2081 | return -EOPNOTSUPP; | ||
| 2082 | } | ||
| 2083 | |||
| 2084 | |||
| 2039 | static inline int security_inode_init_security(struct inode *inode, | 2085 | static inline int security_inode_init_security(struct inode *inode, |
| 2040 | struct inode *dir, | 2086 | struct inode *dir, |
| 2041 | const struct qstr *qstr, | 2087 | const struct qstr *qstr, |
| @@ -2521,6 +2567,11 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
| 2521 | return cap_netlink_send(sk, skb); | 2567 | return cap_netlink_send(sk, skb); |
| 2522 | } | 2568 | } |
| 2523 | 2569 | ||
| 2570 | static inline int security_ismaclabel(const char *name) | ||
| 2571 | { | ||
| 2572 | return 0; | ||
| 2573 | } | ||
| 2574 | |||
| 2524 | static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 2575 | static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
| 2525 | { | 2576 | { |
| 2526 | return -EOPNOTSUPP; | 2577 | return -EOPNOTSUPP; |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 84ca436b76c2..6d870353674a 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
| @@ -88,15 +88,6 @@ struct rpc_task { | |||
| 88 | tk_rebind_retry : 2; | 88 | tk_rebind_retry : 2; |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | /* support walking a list of tasks on a wait queue */ | ||
| 92 | #define task_for_each(task, pos, head) \ | ||
| 93 | list_for_each(pos, head) \ | ||
| 94 | if ((task=list_entry(pos, struct rpc_task, u.tk_wait.list)),1) | ||
| 95 | |||
| 96 | #define task_for_first(task, head) \ | ||
| 97 | if (!list_empty(head) && \ | ||
| 98 | ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1)) | ||
| 99 | |||
| 100 | typedef void (*rpc_action)(struct rpc_task *); | 91 | typedef void (*rpc_action)(struct rpc_task *); |
| 101 | 92 | ||
| 102 | struct rpc_call_ops { | 93 | struct rpc_call_ops { |
| @@ -238,7 +229,6 @@ struct rpc_task *rpc_wake_up_first(struct rpc_wait_queue *, | |||
| 238 | bool (*)(struct rpc_task *, void *), | 229 | bool (*)(struct rpc_task *, void *), |
| 239 | void *); | 230 | void *); |
| 240 | void rpc_wake_up_status(struct rpc_wait_queue *, int); | 231 | void rpc_wake_up_status(struct rpc_wait_queue *, int); |
| 241 | int rpc_queue_empty(struct rpc_wait_queue *); | ||
| 242 | void rpc_delay(struct rpc_task *, unsigned long); | 232 | void rpc_delay(struct rpc_task *, unsigned long); |
| 243 | void * rpc_malloc(struct rpc_task *, size_t); | 233 | void * rpc_malloc(struct rpc_task *, size_t); |
| 244 | void rpc_free(void *); | 234 | void rpc_free(void *); |
| @@ -259,16 +249,6 @@ static inline int rpc_wait_for_completion_task(struct rpc_task *task) | |||
| 259 | return __rpc_wait_for_completion_task(task, NULL); | 249 | return __rpc_wait_for_completion_task(task, NULL); |
| 260 | } | 250 | } |
| 261 | 251 | ||
| 262 | static inline void rpc_task_set_priority(struct rpc_task *task, unsigned char prio) | ||
| 263 | { | ||
| 264 | task->tk_priority = prio - RPC_PRIORITY_LOW; | ||
| 265 | } | ||
| 266 | |||
| 267 | static inline int rpc_task_has_priority(struct rpc_task *task, unsigned char prio) | ||
| 268 | { | ||
| 269 | return (task->tk_priority + RPC_PRIORITY_LOW == prio); | ||
| 270 | } | ||
| 271 | |||
| 272 | #if defined(RPC_DEBUG) || defined (RPC_TRACEPOINTS) | 252 | #if defined(RPC_DEBUG) || defined (RPC_TRACEPOINTS) |
| 273 | static inline const char * rpc_qname(const struct rpc_wait_queue *q) | 253 | static inline const char * rpc_qname(const struct rpc_wait_queue *q) |
| 274 | { | 254 | { |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 5a750b9c3640..f0339ae9bf37 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -157,20 +157,15 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | |||
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | static int | 159 | static int |
| 160 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) | 160 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name, |
| 161 | struct super_block *pipefs_sb) | ||
| 161 | { | 162 | { |
| 162 | struct net *net = rpc_net_ns(clnt); | ||
| 163 | struct super_block *pipefs_sb; | ||
| 164 | struct dentry *dentry; | 163 | struct dentry *dentry; |
| 165 | 164 | ||
| 166 | clnt->cl_dentry = NULL; | 165 | clnt->cl_dentry = NULL; |
| 167 | if (dir_name == NULL) | 166 | if (dir_name == NULL) |
| 168 | return 0; | 167 | return 0; |
| 169 | pipefs_sb = rpc_get_sb_net(net); | ||
| 170 | if (!pipefs_sb) | ||
| 171 | return 0; | ||
| 172 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | 168 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); |
| 173 | rpc_put_sb_net(net); | ||
| 174 | if (IS_ERR(dentry)) | 169 | if (IS_ERR(dentry)) |
| 175 | return PTR_ERR(dentry); | 170 | return PTR_ERR(dentry); |
| 176 | clnt->cl_dentry = dentry; | 171 | clnt->cl_dentry = dentry; |
| @@ -182,6 +177,8 @@ static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event | |||
| 182 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | 177 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || |
| 183 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | 178 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) |
| 184 | return 1; | 179 | return 1; |
| 180 | if ((event == RPC_PIPEFS_MOUNT) && atomic_read(&clnt->cl_count) == 0) | ||
| 181 | return 1; | ||
| 185 | return 0; | 182 | return 0; |
| 186 | } | 183 | } |
| 187 | 184 | ||
| @@ -241,8 +238,6 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | |||
| 241 | continue; | 238 | continue; |
| 242 | if (rpc_clnt_skip_event(clnt, event)) | 239 | if (rpc_clnt_skip_event(clnt, event)) |
| 243 | continue; | 240 | continue; |
| 244 | if (atomic_inc_not_zero(&clnt->cl_count) == 0) | ||
| 245 | continue; | ||
| 246 | spin_unlock(&sn->rpc_client_lock); | 241 | spin_unlock(&sn->rpc_client_lock); |
| 247 | return clnt; | 242 | return clnt; |
| 248 | } | 243 | } |
| @@ -259,7 +254,6 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | |||
| 259 | 254 | ||
| 260 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { | 255 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { |
| 261 | error = __rpc_pipefs_event(clnt, event, sb); | 256 | error = __rpc_pipefs_event(clnt, event, sb); |
| 262 | rpc_release_client(clnt); | ||
| 263 | if (error) | 257 | if (error) |
| 264 | break; | 258 | break; |
| 265 | } | 259 | } |
| @@ -289,12 +283,46 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | |||
| 289 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); | 283 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); |
| 290 | } | 284 | } |
| 291 | 285 | ||
| 286 | static int rpc_client_register(const struct rpc_create_args *args, | ||
| 287 | struct rpc_clnt *clnt) | ||
| 288 | { | ||
| 289 | const struct rpc_program *program = args->program; | ||
| 290 | struct rpc_auth *auth; | ||
| 291 | struct net *net = rpc_net_ns(clnt); | ||
| 292 | struct super_block *pipefs_sb; | ||
| 293 | int err = 0; | ||
| 294 | |||
| 295 | pipefs_sb = rpc_get_sb_net(net); | ||
| 296 | if (pipefs_sb) { | ||
| 297 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name, pipefs_sb); | ||
| 298 | if (err) | ||
| 299 | goto out; | ||
| 300 | } | ||
| 301 | |||
| 302 | auth = rpcauth_create(args->authflavor, clnt); | ||
| 303 | if (IS_ERR(auth)) { | ||
| 304 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | ||
| 305 | args->authflavor); | ||
| 306 | err = PTR_ERR(auth); | ||
| 307 | goto err_auth; | ||
| 308 | } | ||
| 309 | |||
| 310 | rpc_register_client(clnt); | ||
| 311 | out: | ||
| 312 | if (pipefs_sb) | ||
| 313 | rpc_put_sb_net(net); | ||
| 314 | return err; | ||
| 315 | |||
| 316 | err_auth: | ||
| 317 | __rpc_clnt_remove_pipedir(clnt); | ||
| 318 | goto out; | ||
| 319 | } | ||
| 320 | |||
| 292 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 321 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
| 293 | { | 322 | { |
| 294 | const struct rpc_program *program = args->program; | 323 | const struct rpc_program *program = args->program; |
| 295 | const struct rpc_version *version; | 324 | const struct rpc_version *version; |
| 296 | struct rpc_clnt *clnt = NULL; | 325 | struct rpc_clnt *clnt = NULL; |
| 297 | struct rpc_auth *auth; | ||
| 298 | int err; | 326 | int err; |
| 299 | 327 | ||
| 300 | /* sanity check the name before trying to print it */ | 328 | /* sanity check the name before trying to print it */ |
| @@ -354,25 +382,14 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
| 354 | 382 | ||
| 355 | atomic_set(&clnt->cl_count, 1); | 383 | atomic_set(&clnt->cl_count, 1); |
| 356 | 384 | ||
| 357 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | ||
| 358 | if (err < 0) | ||
| 359 | goto out_no_path; | ||
| 360 | |||
| 361 | auth = rpcauth_create(args->authflavor, clnt); | ||
| 362 | if (IS_ERR(auth)) { | ||
| 363 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | ||
| 364 | args->authflavor); | ||
| 365 | err = PTR_ERR(auth); | ||
| 366 | goto out_no_auth; | ||
| 367 | } | ||
| 368 | |||
| 369 | /* save the nodename */ | 385 | /* save the nodename */ |
| 370 | rpc_clnt_set_nodename(clnt, utsname()->nodename); | 386 | rpc_clnt_set_nodename(clnt, utsname()->nodename); |
| 371 | rpc_register_client(clnt); | 387 | |
| 388 | err = rpc_client_register(args, clnt); | ||
| 389 | if (err) | ||
| 390 | goto out_no_path; | ||
| 372 | return clnt; | 391 | return clnt; |
| 373 | 392 | ||
| 374 | out_no_auth: | ||
| 375 | rpc_clnt_remove_pipedir(clnt); | ||
| 376 | out_no_path: | 393 | out_no_path: |
| 377 | kfree(clnt->cl_principal); | 394 | kfree(clnt->cl_principal); |
| 378 | out_no_principal: | 395 | out_no_principal: |
| @@ -637,8 +654,8 @@ rpc_free_client(struct rpc_clnt *clnt) | |||
| 637 | rcu_dereference(clnt->cl_xprt)->servername); | 654 | rcu_dereference(clnt->cl_xprt)->servername); |
| 638 | if (clnt->cl_parent != clnt) | 655 | if (clnt->cl_parent != clnt) |
| 639 | rpc_release_client(clnt->cl_parent); | 656 | rpc_release_client(clnt->cl_parent); |
| 640 | rpc_unregister_client(clnt); | ||
| 641 | rpc_clnt_remove_pipedir(clnt); | 657 | rpc_clnt_remove_pipedir(clnt); |
| 658 | rpc_unregister_client(clnt); | ||
| 642 | rpc_free_iostats(clnt->cl_metrics); | 659 | rpc_free_iostats(clnt->cl_metrics); |
| 643 | kfree(clnt->cl_principal); | 660 | kfree(clnt->cl_principal); |
| 644 | clnt->cl_metrics = NULL; | 661 | clnt->cl_metrics = NULL; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index e7ce4b3eb0bd..4679df5a6d50 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -667,7 +667,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | |||
| 667 | return ERR_PTR(-ENOMEM); | 667 | return ERR_PTR(-ENOMEM); |
| 668 | } | 668 | } |
| 669 | if (dentry->d_inode == NULL) { | 669 | if (dentry->d_inode == NULL) { |
| 670 | d_set_d_op(dentry, &rpc_dentry_operations); | 670 | if (!dentry->d_op) |
| 671 | d_set_d_op(dentry, &rpc_dentry_operations); | ||
| 671 | return dentry; | 672 | return dentry; |
| 672 | } | 673 | } |
| 673 | dput(dentry); | 674 | dput(dentry); |
| @@ -1126,6 +1127,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1126 | return -ENOMEM; | 1127 | return -ENOMEM; |
| 1127 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", | 1128 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", |
| 1128 | net, NET_NAME(net)); | 1129 | net, NET_NAME(net)); |
| 1130 | mutex_lock(&sn->pipefs_sb_lock); | ||
| 1129 | sn->pipefs_sb = sb; | 1131 | sn->pipefs_sb = sb; |
| 1130 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1132 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
| 1131 | RPC_PIPEFS_MOUNT, | 1133 | RPC_PIPEFS_MOUNT, |
| @@ -1133,6 +1135,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1133 | if (err) | 1135 | if (err) |
| 1134 | goto err_depopulate; | 1136 | goto err_depopulate; |
| 1135 | sb->s_fs_info = get_net(net); | 1137 | sb->s_fs_info = get_net(net); |
| 1138 | mutex_unlock(&sn->pipefs_sb_lock); | ||
| 1136 | return 0; | 1139 | return 0; |
| 1137 | 1140 | ||
| 1138 | err_depopulate: | 1141 | err_depopulate: |
| @@ -1141,6 +1144,7 @@ err_depopulate: | |||
| 1141 | sb); | 1144 | sb); |
| 1142 | sn->pipefs_sb = NULL; | 1145 | sn->pipefs_sb = NULL; |
| 1143 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); | 1146 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); |
| 1147 | mutex_unlock(&sn->pipefs_sb_lock); | ||
| 1144 | return err; | 1148 | return err; |
| 1145 | } | 1149 | } |
| 1146 | 1150 | ||
| @@ -1162,12 +1166,12 @@ static void rpc_kill_sb(struct super_block *sb) | |||
| 1162 | goto out; | 1166 | goto out; |
| 1163 | } | 1167 | } |
| 1164 | sn->pipefs_sb = NULL; | 1168 | sn->pipefs_sb = NULL; |
| 1165 | mutex_unlock(&sn->pipefs_sb_lock); | ||
| 1166 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", | 1169 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", |
| 1167 | net, NET_NAME(net)); | 1170 | net, NET_NAME(net)); |
| 1168 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1171 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
| 1169 | RPC_PIPEFS_UMOUNT, | 1172 | RPC_PIPEFS_UMOUNT, |
| 1170 | sb); | 1173 | sb); |
| 1174 | mutex_unlock(&sn->pipefs_sb_lock); | ||
| 1171 | put_net(net); | 1175 | put_net(net); |
| 1172 | out: | 1176 | out: |
| 1173 | kill_litter_super(sb); | 1177 | kill_litter_super(sb); |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 77d251e02593..93a7a4e94d80 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
| @@ -446,20 +446,6 @@ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct r | |||
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | /* | 448 | /* |
| 449 | * Tests whether rpc queue is empty | ||
| 450 | */ | ||
| 451 | int rpc_queue_empty(struct rpc_wait_queue *queue) | ||
| 452 | { | ||
| 453 | int res; | ||
| 454 | |||
| 455 | spin_lock_bh(&queue->lock); | ||
| 456 | res = queue->qlen; | ||
| 457 | spin_unlock_bh(&queue->lock); | ||
| 458 | return res == 0; | ||
| 459 | } | ||
| 460 | EXPORT_SYMBOL_GPL(rpc_queue_empty); | ||
| 461 | |||
| 462 | /* | ||
| 463 | * Wake up a task on a specific queue | 449 | * Wake up a task on a specific queue |
| 464 | */ | 450 | */ |
| 465 | void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task) | 451 | void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task) |
| @@ -804,7 +790,6 @@ static void __rpc_execute(struct rpc_task *task) | |||
| 804 | task->tk_flags |= RPC_TASK_KILLED; | 790 | task->tk_flags |= RPC_TASK_KILLED; |
| 805 | rpc_exit(task, -ERESTARTSYS); | 791 | rpc_exit(task, -ERESTARTSYS); |
| 806 | } | 792 | } |
| 807 | rpc_set_running(task); | ||
| 808 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); | 793 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); |
| 809 | } | 794 | } |
| 810 | 795 | ||
| @@ -825,9 +810,11 @@ static void __rpc_execute(struct rpc_task *task) | |||
| 825 | */ | 810 | */ |
| 826 | void rpc_execute(struct rpc_task *task) | 811 | void rpc_execute(struct rpc_task *task) |
| 827 | { | 812 | { |
| 813 | bool is_async = RPC_IS_ASYNC(task); | ||
| 814 | |||
| 828 | rpc_set_active(task); | 815 | rpc_set_active(task); |
| 829 | rpc_make_runnable(task); | 816 | rpc_make_runnable(task); |
| 830 | if (!RPC_IS_ASYNC(task)) | 817 | if (!is_async) |
| 831 | __rpc_execute(task); | 818 | __rpc_execute(task); |
| 832 | } | 819 | } |
| 833 | 820 | ||
diff --git a/security/capability.c b/security/capability.c index 1728d4e375db..d32e16e3c6ae 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -91,7 +91,10 @@ static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static int cap_sb_set_mnt_opts(struct super_block *sb, | 93 | static int cap_sb_set_mnt_opts(struct super_block *sb, |
| 94 | struct security_mnt_opts *opts) | 94 | struct security_mnt_opts *opts, |
| 95 | unsigned long kern_flags, | ||
| 96 | unsigned long *set_kern_flags) | ||
| 97 | |||
| 95 | { | 98 | { |
| 96 | if (unlikely(opts->num_mnt_opts)) | 99 | if (unlikely(opts->num_mnt_opts)) |
| 97 | return -EOPNOTSUPP; | 100 | return -EOPNOTSUPP; |
| @@ -109,6 +112,13 @@ static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | |||
| 109 | return 0; | 112 | return 0; |
| 110 | } | 113 | } |
| 111 | 114 | ||
| 115 | static int cap_dentry_init_security(struct dentry *dentry, int mode, | ||
| 116 | struct qstr *name, void **ctx, | ||
| 117 | u32 *ctxlen) | ||
| 118 | { | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 112 | static int cap_inode_alloc_security(struct inode *inode) | 122 | static int cap_inode_alloc_security(struct inode *inode) |
| 113 | { | 123 | { |
| 114 | return 0; | 124 | return 0; |
| @@ -816,6 +826,11 @@ static int cap_setprocattr(struct task_struct *p, char *name, void *value, | |||
| 816 | return -EINVAL; | 826 | return -EINVAL; |
| 817 | } | 827 | } |
| 818 | 828 | ||
| 829 | static int cap_ismaclabel(const char *name) | ||
| 830 | { | ||
| 831 | return 0; | ||
| 832 | } | ||
| 833 | |||
| 819 | static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 834 | static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
| 820 | { | 835 | { |
| 821 | return -EOPNOTSUPP; | 836 | return -EOPNOTSUPP; |
| @@ -931,6 +946,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
| 931 | set_to_cap_if_null(ops, sb_set_mnt_opts); | 946 | set_to_cap_if_null(ops, sb_set_mnt_opts); |
| 932 | set_to_cap_if_null(ops, sb_clone_mnt_opts); | 947 | set_to_cap_if_null(ops, sb_clone_mnt_opts); |
| 933 | set_to_cap_if_null(ops, sb_parse_opts_str); | 948 | set_to_cap_if_null(ops, sb_parse_opts_str); |
| 949 | set_to_cap_if_null(ops, dentry_init_security); | ||
| 934 | set_to_cap_if_null(ops, inode_alloc_security); | 950 | set_to_cap_if_null(ops, inode_alloc_security); |
| 935 | set_to_cap_if_null(ops, inode_free_security); | 951 | set_to_cap_if_null(ops, inode_free_security); |
| 936 | set_to_cap_if_null(ops, inode_init_security); | 952 | set_to_cap_if_null(ops, inode_init_security); |
| @@ -1034,6 +1050,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
| 1034 | set_to_cap_if_null(ops, d_instantiate); | 1050 | set_to_cap_if_null(ops, d_instantiate); |
| 1035 | set_to_cap_if_null(ops, getprocattr); | 1051 | set_to_cap_if_null(ops, getprocattr); |
| 1036 | set_to_cap_if_null(ops, setprocattr); | 1052 | set_to_cap_if_null(ops, setprocattr); |
| 1053 | set_to_cap_if_null(ops, ismaclabel); | ||
| 1037 | set_to_cap_if_null(ops, secid_to_secctx); | 1054 | set_to_cap_if_null(ops, secid_to_secctx); |
| 1038 | set_to_cap_if_null(ops, secctx_to_secid); | 1055 | set_to_cap_if_null(ops, secctx_to_secid); |
| 1039 | set_to_cap_if_null(ops, release_secctx); | 1056 | set_to_cap_if_null(ops, release_secctx); |
diff --git a/security/security.c b/security/security.c index a3dce87d1aef..94b35aef6871 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/capability.h> | 14 | #include <linux/capability.h> |
| 15 | #include <linux/dcache.h> | ||
| 15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| @@ -293,9 +294,12 @@ int security_sb_pivotroot(struct path *old_path, struct path *new_path) | |||
| 293 | } | 294 | } |
| 294 | 295 | ||
| 295 | int security_sb_set_mnt_opts(struct super_block *sb, | 296 | int security_sb_set_mnt_opts(struct super_block *sb, |
| 296 | struct security_mnt_opts *opts) | 297 | struct security_mnt_opts *opts, |
| 298 | unsigned long kern_flags, | ||
| 299 | unsigned long *set_kern_flags) | ||
| 297 | { | 300 | { |
| 298 | return security_ops->sb_set_mnt_opts(sb, opts); | 301 | return security_ops->sb_set_mnt_opts(sb, opts, kern_flags, |
| 302 | set_kern_flags); | ||
| 299 | } | 303 | } |
| 300 | EXPORT_SYMBOL(security_sb_set_mnt_opts); | 304 | EXPORT_SYMBOL(security_sb_set_mnt_opts); |
| 301 | 305 | ||
| @@ -324,6 +328,15 @@ void security_inode_free(struct inode *inode) | |||
| 324 | security_ops->inode_free_security(inode); | 328 | security_ops->inode_free_security(inode); |
| 325 | } | 329 | } |
| 326 | 330 | ||
| 331 | int security_dentry_init_security(struct dentry *dentry, int mode, | ||
| 332 | struct qstr *name, void **ctx, | ||
| 333 | u32 *ctxlen) | ||
| 334 | { | ||
| 335 | return security_ops->dentry_init_security(dentry, mode, name, | ||
| 336 | ctx, ctxlen); | ||
| 337 | } | ||
| 338 | EXPORT_SYMBOL(security_dentry_init_security); | ||
| 339 | |||
| 327 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 340 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
| 328 | const struct qstr *qstr, | 341 | const struct qstr *qstr, |
| 329 | const initxattrs initxattrs, void *fs_data) | 342 | const initxattrs initxattrs, void *fs_data) |
| @@ -647,6 +660,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer | |||
| 647 | return 0; | 660 | return 0; |
| 648 | return security_ops->inode_listsecurity(inode, buffer, buffer_size); | 661 | return security_ops->inode_listsecurity(inode, buffer, buffer_size); |
| 649 | } | 662 | } |
| 663 | EXPORT_SYMBOL(security_inode_listsecurity); | ||
| 650 | 664 | ||
| 651 | void security_inode_getsecid(const struct inode *inode, u32 *secid) | 665 | void security_inode_getsecid(const struct inode *inode, u32 *secid) |
| 652 | { | 666 | { |
| @@ -1047,6 +1061,12 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
| 1047 | return security_ops->netlink_send(sk, skb); | 1061 | return security_ops->netlink_send(sk, skb); |
| 1048 | } | 1062 | } |
| 1049 | 1063 | ||
| 1064 | int security_ismaclabel(const char *name) | ||
| 1065 | { | ||
| 1066 | return security_ops->ismaclabel(name); | ||
| 1067 | } | ||
| 1068 | EXPORT_SYMBOL(security_ismaclabel); | ||
| 1069 | |||
| 1050 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 1070 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
| 1051 | { | 1071 | { |
| 1052 | return security_ops->secid_to_secctx(secid, secdata, seclen); | 1072 | return security_ops->secid_to_secctx(secid, secdata, seclen); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index db1fca990a24..c956390a9136 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -81,6 +81,7 @@ | |||
| 81 | #include <linux/syslog.h> | 81 | #include <linux/syslog.h> |
| 82 | #include <linux/user_namespace.h> | 82 | #include <linux/user_namespace.h> |
| 83 | #include <linux/export.h> | 83 | #include <linux/export.h> |
| 84 | #include <linux/security.h> | ||
| 84 | #include <linux/msg.h> | 85 | #include <linux/msg.h> |
| 85 | #include <linux/shm.h> | 86 | #include <linux/shm.h> |
| 86 | 87 | ||
| @@ -284,13 +285,14 @@ static void superblock_free_security(struct super_block *sb) | |||
| 284 | 285 | ||
| 285 | /* The file system's label must be initialized prior to use. */ | 286 | /* The file system's label must be initialized prior to use. */ |
| 286 | 287 | ||
| 287 | static const char *labeling_behaviors[6] = { | 288 | static const char *labeling_behaviors[7] = { |
| 288 | "uses xattr", | 289 | "uses xattr", |
| 289 | "uses transition SIDs", | 290 | "uses transition SIDs", |
| 290 | "uses task SIDs", | 291 | "uses task SIDs", |
| 291 | "uses genfs_contexts", | 292 | "uses genfs_contexts", |
| 292 | "not configured for labeling", | 293 | "not configured for labeling", |
| 293 | "uses mountpoint labeling", | 294 | "uses mountpoint labeling", |
| 295 | "uses native labeling", | ||
| 294 | }; | 296 | }; |
| 295 | 297 | ||
| 296 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); | 298 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); |
| @@ -552,7 +554,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, | |||
| 552 | * labeling information. | 554 | * labeling information. |
| 553 | */ | 555 | */ |
| 554 | static int selinux_set_mnt_opts(struct super_block *sb, | 556 | static int selinux_set_mnt_opts(struct super_block *sb, |
| 555 | struct security_mnt_opts *opts) | 557 | struct security_mnt_opts *opts, |
| 558 | unsigned long kern_flags, | ||
| 559 | unsigned long *set_kern_flags) | ||
| 556 | { | 560 | { |
| 557 | const struct cred *cred = current_cred(); | 561 | const struct cred *cred = current_cred(); |
| 558 | int rc = 0, i; | 562 | int rc = 0, i; |
| @@ -580,6 +584,12 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 580 | "before the security server is initialized\n"); | 584 | "before the security server is initialized\n"); |
| 581 | goto out; | 585 | goto out; |
| 582 | } | 586 | } |
| 587 | if (kern_flags && !set_kern_flags) { | ||
| 588 | /* Specifying internal flags without providing a place to | ||
| 589 | * place the results is not allowed */ | ||
| 590 | rc = -EINVAL; | ||
| 591 | goto out; | ||
| 592 | } | ||
| 583 | 593 | ||
| 584 | /* | 594 | /* |
| 585 | * Binary mount data FS will come through this function twice. Once | 595 | * Binary mount data FS will come through this function twice. Once |
| @@ -670,14 +680,21 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 670 | if (strcmp(sb->s_type->name, "proc") == 0) | 680 | if (strcmp(sb->s_type->name, "proc") == 0) |
| 671 | sbsec->flags |= SE_SBPROC; | 681 | sbsec->flags |= SE_SBPROC; |
| 672 | 682 | ||
| 673 | /* Determine the labeling behavior to use for this filesystem type. */ | 683 | if (!sbsec->behavior) { |
| 674 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); | 684 | /* |
| 675 | if (rc) { | 685 | * Determine the labeling behavior to use for this |
| 676 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", | 686 | * filesystem type. |
| 677 | __func__, sb->s_type->name, rc); | 687 | */ |
| 678 | goto out; | 688 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? |
| 689 | "proc" : sb->s_type->name, | ||
| 690 | &sbsec->behavior, &sbsec->sid); | ||
| 691 | if (rc) { | ||
| 692 | printk(KERN_WARNING | ||
| 693 | "%s: security_fs_use(%s) returned %d\n", | ||
| 694 | __func__, sb->s_type->name, rc); | ||
| 695 | goto out; | ||
| 696 | } | ||
| 679 | } | 697 | } |
| 680 | |||
| 681 | /* sets the context of the superblock for the fs being mounted. */ | 698 | /* sets the context of the superblock for the fs being mounted. */ |
| 682 | if (fscontext_sid) { | 699 | if (fscontext_sid) { |
| 683 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); | 700 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); |
| @@ -692,6 +709,11 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 692 | * sets the label used on all file below the mountpoint, and will set | 709 | * sets the label used on all file below the mountpoint, and will set |
| 693 | * the superblock context if not already set. | 710 | * the superblock context if not already set. |
| 694 | */ | 711 | */ |
| 712 | if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) { | ||
| 713 | sbsec->behavior = SECURITY_FS_USE_NATIVE; | ||
| 714 | *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS; | ||
| 715 | } | ||
| 716 | |||
| 695 | if (context_sid) { | 717 | if (context_sid) { |
| 696 | if (!fscontext_sid) { | 718 | if (!fscontext_sid) { |
| 697 | rc = may_context_mount_sb_relabel(context_sid, sbsec, | 719 | rc = may_context_mount_sb_relabel(context_sid, sbsec, |
| @@ -723,7 +745,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 723 | } | 745 | } |
| 724 | 746 | ||
| 725 | if (defcontext_sid) { | 747 | if (defcontext_sid) { |
| 726 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { | 748 | if (sbsec->behavior != SECURITY_FS_USE_XATTR && |
| 749 | sbsec->behavior != SECURITY_FS_USE_NATIVE) { | ||
| 727 | rc = -EINVAL; | 750 | rc = -EINVAL; |
| 728 | printk(KERN_WARNING "SELinux: defcontext option is " | 751 | printk(KERN_WARNING "SELinux: defcontext option is " |
| 729 | "invalid for this filesystem type\n"); | 752 | "invalid for this filesystem type\n"); |
| @@ -980,7 +1003,7 @@ static int superblock_doinit(struct super_block *sb, void *data) | |||
| 980 | goto out_err; | 1003 | goto out_err; |
| 981 | 1004 | ||
| 982 | out: | 1005 | out: |
| 983 | rc = selinux_set_mnt_opts(sb, &opts); | 1006 | rc = selinux_set_mnt_opts(sb, &opts, 0, NULL); |
| 984 | 1007 | ||
| 985 | out_err: | 1008 | out_err: |
| 986 | security_free_mnt_opts(&opts); | 1009 | security_free_mnt_opts(&opts); |
| @@ -1222,6 +1245,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 1222 | } | 1245 | } |
| 1223 | 1246 | ||
| 1224 | switch (sbsec->behavior) { | 1247 | switch (sbsec->behavior) { |
| 1248 | case SECURITY_FS_USE_NATIVE: | ||
| 1249 | break; | ||
| 1225 | case SECURITY_FS_USE_XATTR: | 1250 | case SECURITY_FS_USE_XATTR: |
| 1226 | if (!inode->i_op->getxattr) { | 1251 | if (!inode->i_op->getxattr) { |
| 1227 | isec->sid = sbsec->def_sid; | 1252 | isec->sid = sbsec->def_sid; |
| @@ -2527,6 +2552,40 @@ static void selinux_inode_free_security(struct inode *inode) | |||
| 2527 | inode_free_security(inode); | 2552 | inode_free_security(inode); |
| 2528 | } | 2553 | } |
| 2529 | 2554 | ||
| 2555 | static int selinux_dentry_init_security(struct dentry *dentry, int mode, | ||
| 2556 | struct qstr *name, void **ctx, | ||
| 2557 | u32 *ctxlen) | ||
| 2558 | { | ||
| 2559 | const struct cred *cred = current_cred(); | ||
| 2560 | struct task_security_struct *tsec; | ||
| 2561 | struct inode_security_struct *dsec; | ||
| 2562 | struct superblock_security_struct *sbsec; | ||
| 2563 | struct inode *dir = dentry->d_parent->d_inode; | ||
| 2564 | u32 newsid; | ||
| 2565 | int rc; | ||
| 2566 | |||
| 2567 | tsec = cred->security; | ||
| 2568 | dsec = dir->i_security; | ||
| 2569 | sbsec = dir->i_sb->s_security; | ||
| 2570 | |||
| 2571 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
| 2572 | newsid = tsec->create_sid; | ||
| 2573 | } else { | ||
| 2574 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
| 2575 | inode_mode_to_security_class(mode), | ||
| 2576 | name, | ||
| 2577 | &newsid); | ||
| 2578 | if (rc) { | ||
| 2579 | printk(KERN_WARNING | ||
| 2580 | "%s: security_transition_sid failed, rc=%d\n", | ||
| 2581 | __func__, -rc); | ||
| 2582 | return rc; | ||
| 2583 | } | ||
| 2584 | } | ||
| 2585 | |||
| 2586 | return security_sid_to_context(newsid, (char **)ctx, ctxlen); | ||
| 2587 | } | ||
| 2588 | |||
| 2530 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | 2589 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
| 2531 | const struct qstr *qstr, char **name, | 2590 | const struct qstr *qstr, char **name, |
| 2532 | void **value, size_t *len) | 2591 | void **value, size_t *len) |
| @@ -2861,7 +2920,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
| 2861 | return; | 2920 | return; |
| 2862 | } | 2921 | } |
| 2863 | 2922 | ||
| 2923 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
| 2864 | isec->sid = newsid; | 2924 | isec->sid = newsid; |
| 2925 | isec->initialized = 1; | ||
| 2926 | |||
| 2865 | return; | 2927 | return; |
| 2866 | } | 2928 | } |
| 2867 | 2929 | ||
| @@ -2949,6 +3011,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
| 2949 | if (rc) | 3011 | if (rc) |
| 2950 | return rc; | 3012 | return rc; |
| 2951 | 3013 | ||
| 3014 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
| 2952 | isec->sid = newsid; | 3015 | isec->sid = newsid; |
| 2953 | isec->initialized = 1; | 3016 | isec->initialized = 1; |
| 2954 | return 0; | 3017 | return 0; |
| @@ -5432,6 +5495,11 @@ abort_change: | |||
| 5432 | return error; | 5495 | return error; |
| 5433 | } | 5496 | } |
| 5434 | 5497 | ||
| 5498 | static int selinux_ismaclabel(const char *name) | ||
| 5499 | { | ||
| 5500 | return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0); | ||
| 5501 | } | ||
| 5502 | |||
| 5435 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 5503 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
| 5436 | { | 5504 | { |
| 5437 | return security_sid_to_context(secid, secdata, seclen); | 5505 | return security_sid_to_context(secid, secdata, seclen); |
| @@ -5574,6 +5642,7 @@ static struct security_operations selinux_ops = { | |||
| 5574 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, | 5642 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, |
| 5575 | .sb_parse_opts_str = selinux_parse_opts_str, | 5643 | .sb_parse_opts_str = selinux_parse_opts_str, |
| 5576 | 5644 | ||
| 5645 | .dentry_init_security = selinux_dentry_init_security, | ||
| 5577 | 5646 | ||
| 5578 | .inode_alloc_security = selinux_inode_alloc_security, | 5647 | .inode_alloc_security = selinux_inode_alloc_security, |
| 5579 | .inode_free_security = selinux_inode_free_security, | 5648 | .inode_free_security = selinux_inode_free_security, |
| @@ -5669,6 +5738,7 @@ static struct security_operations selinux_ops = { | |||
| 5669 | .getprocattr = selinux_getprocattr, | 5738 | .getprocattr = selinux_getprocattr, |
| 5670 | .setprocattr = selinux_setprocattr, | 5739 | .setprocattr = selinux_setprocattr, |
| 5671 | 5740 | ||
| 5741 | .ismaclabel = selinux_ismaclabel, | ||
| 5672 | .secid_to_secctx = selinux_secid_to_secctx, | 5742 | .secid_to_secctx = selinux_secid_to_secctx, |
| 5673 | .secctx_to_secid = selinux_secctx_to_secid, | 5743 | .secctx_to_secid = selinux_secctx_to_secid, |
| 5674 | .release_secctx = selinux_release_secctx, | 5744 | .release_secctx = selinux_release_secctx, |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 6d3885165d14..8fd8e18ea340 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
| @@ -169,6 +169,8 @@ int security_get_allow_unknown(void); | |||
| 169 | #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ | 169 | #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ |
| 170 | #define SECURITY_FS_USE_NONE 5 /* no labeling support */ | 170 | #define SECURITY_FS_USE_NONE 5 /* no labeling support */ |
| 171 | #define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */ | 171 | #define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */ |
| 172 | #define SECURITY_FS_USE_NATIVE 7 /* use native label support */ | ||
| 173 | #define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */ | ||
| 172 | 174 | ||
| 173 | int security_fs_use(const char *fstype, unsigned int *behavior, | 175 | int security_fs_use(const char *fstype, unsigned int *behavior, |
| 174 | u32 *sid); | 176 | u32 *sid); |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 9cd9b7c661ec..c8adde3aff8f 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
| @@ -2168,7 +2168,10 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
| 2168 | 2168 | ||
| 2169 | rc = -EINVAL; | 2169 | rc = -EINVAL; |
| 2170 | c->v.behavior = le32_to_cpu(buf[0]); | 2170 | c->v.behavior = le32_to_cpu(buf[0]); |
| 2171 | if (c->v.behavior > SECURITY_FS_USE_NONE) | 2171 | /* Determined at runtime, not in policy DB. */ |
| 2172 | if (c->v.behavior == SECURITY_FS_USE_MNTPOINT) | ||
| 2173 | goto out; | ||
| 2174 | if (c->v.behavior > SECURITY_FS_USE_MAX) | ||
| 2172 | goto out; | 2175 | goto out; |
| 2173 | 2176 | ||
| 2174 | rc = -ENOMEM; | 2177 | rc = -ENOMEM; |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 6a083303501d..3f7682a387b7 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -3640,6 +3640,16 @@ static void smack_audit_rule_free(void *vrule) | |||
| 3640 | #endif /* CONFIG_AUDIT */ | 3640 | #endif /* CONFIG_AUDIT */ |
| 3641 | 3641 | ||
| 3642 | /** | 3642 | /** |
| 3643 | * smack_ismaclabel - check if xattr @name references a smack MAC label | ||
| 3644 | * @name: Full xattr name to check. | ||
| 3645 | */ | ||
| 3646 | static int smack_ismaclabel(const char *name) | ||
| 3647 | { | ||
| 3648 | return (strcmp(name, XATTR_SMACK_SUFFIX) == 0); | ||
| 3649 | } | ||
| 3650 | |||
| 3651 | |||
| 3652 | /** | ||
| 3643 | * smack_secid_to_secctx - return the smack label for a secid | 3653 | * smack_secid_to_secctx - return the smack label for a secid |
| 3644 | * @secid: incoming integer | 3654 | * @secid: incoming integer |
| 3645 | * @secdata: destination | 3655 | * @secdata: destination |
| @@ -3836,6 +3846,7 @@ struct security_operations smack_ops = { | |||
| 3836 | .audit_rule_free = smack_audit_rule_free, | 3846 | .audit_rule_free = smack_audit_rule_free, |
| 3837 | #endif /* CONFIG_AUDIT */ | 3847 | #endif /* CONFIG_AUDIT */ |
| 3838 | 3848 | ||
| 3849 | .ismaclabel = smack_ismaclabel, | ||
| 3839 | .secid_to_secctx = smack_secid_to_secctx, | 3850 | .secid_to_secctx = smack_secid_to_secctx, |
| 3840 | .secctx_to_secid = smack_secctx_to_secid, | 3851 | .secctx_to_secid = smack_secctx_to_secid, |
| 3841 | .release_secctx = smack_release_secctx, | 3852 | .release_secctx = smack_release_secctx, |
