diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 691 |
1 files changed, 578 insertions, 113 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d7ba5616989c..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, |
| @@ -268,7 +324,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | |||
| 268 | *timeout = NFS4_POLL_RETRY_MIN; | 324 | *timeout = NFS4_POLL_RETRY_MIN; |
| 269 | if (*timeout > NFS4_POLL_RETRY_MAX) | 325 | if (*timeout > NFS4_POLL_RETRY_MAX) |
| 270 | *timeout = NFS4_POLL_RETRY_MAX; | 326 | *timeout = NFS4_POLL_RETRY_MAX; |
| 271 | freezable_schedule_timeout_killable(*timeout); | 327 | freezable_schedule_timeout_killable_unsafe(*timeout); |
| 272 | if (fatal_signal_pending(current)) | 328 | if (fatal_signal_pending(current)) |
| 273 | res = -ERESTARTSYS; | 329 | res = -ERESTARTSYS; |
| 274 | *timeout <<= 1; | 330 | *timeout <<= 1; |
| @@ -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(); |
| @@ -4528,7 +4897,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 | |||
| 4528 | static unsigned long | 4897 | static unsigned long |
| 4529 | nfs4_set_lock_task_retry(unsigned long timeout) | 4898 | nfs4_set_lock_task_retry(unsigned long timeout) |
| 4530 | { | 4899 | { |
| 4531 | freezable_schedule_timeout_killable(timeout); | 4900 | freezable_schedule_timeout_killable_unsafe(timeout); |
| 4532 | timeout <<= 1; | 4901 | timeout <<= 1; |
| 4533 | if (timeout > NFS4_LOCK_MAXTIMEOUT) | 4902 | if (timeout > NFS4_LOCK_MAXTIMEOUT) |
| 4534 | return NFS4_LOCK_MAXTIMEOUT; | 4903 | return NFS4_LOCK_MAXTIMEOUT; |
| @@ -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 | ||
