diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 699 |
1 files changed, 581 insertions, 118 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d7ba5616989c..108a774095f7 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); |
@@ -2896,15 +3071,13 @@ struct rpc_clnt * | |||
2896 | nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, | 3071 | nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, |
2897 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 3072 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
2898 | { | 3073 | { |
3074 | struct rpc_clnt *client = NFS_CLIENT(dir); | ||
2899 | int status; | 3075 | int status; |
2900 | 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); | ||
2905 | return ERR_PTR(status); | 3079 | return ERR_PTR(status); |
2906 | } | 3080 | return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client; |
2907 | return client; | ||
2908 | } | 3081 | } |
2909 | 3082 | ||
2910 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 3083 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
@@ -2924,7 +3097,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2924 | .rpc_cred = entry->cred, | 3097 | .rpc_cred = entry->cred, |
2925 | }; | 3098 | }; |
2926 | int mode = entry->mask; | 3099 | int mode = entry->mask; |
2927 | int status; | 3100 | int status = 0; |
2928 | 3101 | ||
2929 | /* | 3102 | /* |
2930 | * Determine which access bits we want to ask for... | 3103 | * Determine which access bits we want to ask for... |
@@ -3029,6 +3202,7 @@ static int | |||
3029 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 3202 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
3030 | int flags) | 3203 | int flags) |
3031 | { | 3204 | { |
3205 | struct nfs4_label l, *ilabel = NULL; | ||
3032 | struct nfs_open_context *ctx; | 3206 | struct nfs_open_context *ctx; |
3033 | struct nfs4_state *state; | 3207 | struct nfs4_state *state; |
3034 | int status = 0; | 3208 | int status = 0; |
@@ -3037,19 +3211,16 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
3037 | if (IS_ERR(ctx)) | 3211 | if (IS_ERR(ctx)) |
3038 | return PTR_ERR(ctx); | 3212 | return PTR_ERR(ctx); |
3039 | 3213 | ||
3214 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3215 | |||
3040 | sattr->ia_mode &= ~current_umask(); | 3216 | sattr->ia_mode &= ~current_umask(); |
3041 | state = nfs4_do_open(dir, dentry, ctx->mode, | 3217 | 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)) { | 3218 | if (IS_ERR(state)) { |
3046 | status = PTR_ERR(state); | 3219 | status = PTR_ERR(state); |
3047 | goto out; | 3220 | goto out; |
3048 | } | 3221 | } |
3049 | d_add(dentry, igrab(state->inode)); | ||
3050 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
3051 | ctx->state = state; | ||
3052 | out: | 3222 | out: |
3223 | nfs4_label_release_security(ilabel); | ||
3053 | put_nfs_open_context(ctx); | 3224 | put_nfs_open_context(ctx); |
3054 | return status; | 3225 | return status; |
3055 | } | 3226 | } |
@@ -3098,6 +3269,8 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
3098 | res->server = server; | 3269 | res->server = server; |
3099 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 3270 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
3100 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | 3271 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); |
3272 | |||
3273 | nfs_fattr_init(res->dir_attr); | ||
3101 | } | 3274 | } |
3102 | 3275 | ||
3103 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) | 3276 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) |
@@ -3173,7 +3346,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
3173 | .rpc_resp = &res, | 3346 | .rpc_resp = &res, |
3174 | }; | 3347 | }; |
3175 | int status = -ENOMEM; | 3348 | int status = -ENOMEM; |
3176 | 3349 | ||
3177 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3350 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3178 | if (!status) { | 3351 | if (!status) { |
3179 | update_changeattr(old_dir, &res.old_cinfo); | 3352 | update_changeattr(old_dir, &res.old_cinfo); |
@@ -3207,6 +3380,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
3207 | }; | 3380 | }; |
3208 | struct nfs4_link_res res = { | 3381 | struct nfs4_link_res res = { |
3209 | .server = server, | 3382 | .server = server, |
3383 | .label = NULL, | ||
3210 | }; | 3384 | }; |
3211 | struct rpc_message msg = { | 3385 | struct rpc_message msg = { |
3212 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], | 3386 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], |
@@ -3219,11 +3393,24 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
3219 | if (res.fattr == NULL) | 3393 | if (res.fattr == NULL) |
3220 | goto out; | 3394 | goto out; |
3221 | 3395 | ||
3396 | res.label = nfs4_label_alloc(server, GFP_KERNEL); | ||
3397 | if (IS_ERR(res.label)) { | ||
3398 | status = PTR_ERR(res.label); | ||
3399 | goto out; | ||
3400 | } | ||
3401 | arg.bitmask = nfs4_bitmask(server, res.label); | ||
3402 | |||
3222 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3403 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3223 | if (!status) { | 3404 | if (!status) { |
3224 | update_changeattr(dir, &res.cinfo); | 3405 | update_changeattr(dir, &res.cinfo); |
3225 | nfs_post_op_update_inode(inode, res.fattr); | 3406 | status = nfs_post_op_update_inode(inode, res.fattr); |
3407 | if (!status) | ||
3408 | nfs_setsecurity(inode, res.fattr, res.label); | ||
3226 | } | 3409 | } |
3410 | |||
3411 | |||
3412 | nfs4_label_free(res.label); | ||
3413 | |||
3227 | out: | 3414 | out: |
3228 | nfs_free_fattr(res.fattr); | 3415 | nfs_free_fattr(res.fattr); |
3229 | return status; | 3416 | return status; |
@@ -3247,6 +3434,7 @@ struct nfs4_createdata { | |||
3247 | struct nfs4_create_res res; | 3434 | struct nfs4_create_res res; |
3248 | struct nfs_fh fh; | 3435 | struct nfs_fh fh; |
3249 | struct nfs_fattr fattr; | 3436 | struct nfs_fattr fattr; |
3437 | struct nfs4_label *label; | ||
3250 | }; | 3438 | }; |
3251 | 3439 | ||
3252 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | 3440 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, |
@@ -3258,6 +3446,10 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
3258 | if (data != NULL) { | 3446 | if (data != NULL) { |
3259 | struct nfs_server *server = NFS_SERVER(dir); | 3447 | struct nfs_server *server = NFS_SERVER(dir); |
3260 | 3448 | ||
3449 | data->label = nfs4_label_alloc(server, GFP_KERNEL); | ||
3450 | if (IS_ERR(data->label)) | ||
3451 | goto out_free; | ||
3452 | |||
3261 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; | 3453 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; |
3262 | data->msg.rpc_argp = &data->arg; | 3454 | data->msg.rpc_argp = &data->arg; |
3263 | data->msg.rpc_resp = &data->res; | 3455 | data->msg.rpc_resp = &data->res; |
@@ -3266,13 +3458,17 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
3266 | data->arg.name = name; | 3458 | data->arg.name = name; |
3267 | data->arg.attrs = sattr; | 3459 | data->arg.attrs = sattr; |
3268 | data->arg.ftype = ftype; | 3460 | data->arg.ftype = ftype; |
3269 | data->arg.bitmask = server->attr_bitmask; | 3461 | data->arg.bitmask = nfs4_bitmask(server, data->label); |
3270 | data->res.server = server; | 3462 | data->res.server = server; |
3271 | data->res.fh = &data->fh; | 3463 | data->res.fh = &data->fh; |
3272 | data->res.fattr = &data->fattr; | 3464 | data->res.fattr = &data->fattr; |
3465 | data->res.label = data->label; | ||
3273 | nfs_fattr_init(data->res.fattr); | 3466 | nfs_fattr_init(data->res.fattr); |
3274 | } | 3467 | } |
3275 | return data; | 3468 | return data; |
3469 | out_free: | ||
3470 | kfree(data); | ||
3471 | return NULL; | ||
3276 | } | 3472 | } |
3277 | 3473 | ||
3278 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) | 3474 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) |
@@ -3281,18 +3477,20 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_ | |||
3281 | &data->arg.seq_args, &data->res.seq_res, 1); | 3477 | &data->arg.seq_args, &data->res.seq_res, 1); |
3282 | if (status == 0) { | 3478 | if (status == 0) { |
3283 | update_changeattr(dir, &data->res.dir_cinfo); | 3479 | update_changeattr(dir, &data->res.dir_cinfo); |
3284 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 3480 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label); |
3285 | } | 3481 | } |
3286 | return status; | 3482 | return status; |
3287 | } | 3483 | } |
3288 | 3484 | ||
3289 | static void nfs4_free_createdata(struct nfs4_createdata *data) | 3485 | static void nfs4_free_createdata(struct nfs4_createdata *data) |
3290 | { | 3486 | { |
3487 | nfs4_label_free(data->label); | ||
3291 | kfree(data); | 3488 | kfree(data); |
3292 | } | 3489 | } |
3293 | 3490 | ||
3294 | static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | 3491 | static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, |
3295 | struct page *page, unsigned int len, struct iattr *sattr) | 3492 | struct page *page, unsigned int len, struct iattr *sattr, |
3493 | struct nfs4_label *label) | ||
3296 | { | 3494 | { |
3297 | struct nfs4_createdata *data; | 3495 | struct nfs4_createdata *data; |
3298 | int status = -ENAMETOOLONG; | 3496 | int status = -ENAMETOOLONG; |
@@ -3308,6 +3506,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
3308 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK]; | 3506 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK]; |
3309 | data->arg.u.symlink.pages = &page; | 3507 | data->arg.u.symlink.pages = &page; |
3310 | data->arg.u.symlink.len = len; | 3508 | data->arg.u.symlink.len = len; |
3509 | data->arg.label = label; | ||
3311 | 3510 | ||
3312 | status = nfs4_do_create(dir, dentry, data); | 3511 | status = nfs4_do_create(dir, dentry, data); |
3313 | 3512 | ||
@@ -3320,18 +3519,24 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
3320 | struct page *page, unsigned int len, struct iattr *sattr) | 3519 | struct page *page, unsigned int len, struct iattr *sattr) |
3321 | { | 3520 | { |
3322 | struct nfs4_exception exception = { }; | 3521 | struct nfs4_exception exception = { }; |
3522 | struct nfs4_label l, *label = NULL; | ||
3323 | int err; | 3523 | int err; |
3524 | |||
3525 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3526 | |||
3324 | do { | 3527 | do { |
3325 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3528 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3326 | _nfs4_proc_symlink(dir, dentry, page, | 3529 | _nfs4_proc_symlink(dir, dentry, page, |
3327 | len, sattr), | 3530 | len, sattr, label), |
3328 | &exception); | 3531 | &exception); |
3329 | } while (exception.retry); | 3532 | } while (exception.retry); |
3533 | |||
3534 | nfs4_label_release_security(label); | ||
3330 | return err; | 3535 | return err; |
3331 | } | 3536 | } |
3332 | 3537 | ||
3333 | static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | 3538 | static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, |
3334 | struct iattr *sattr) | 3539 | struct iattr *sattr, struct nfs4_label *label) |
3335 | { | 3540 | { |
3336 | struct nfs4_createdata *data; | 3541 | struct nfs4_createdata *data; |
3337 | int status = -ENOMEM; | 3542 | int status = -ENOMEM; |
@@ -3340,6 +3545,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
3340 | if (data == NULL) | 3545 | if (data == NULL) |
3341 | goto out; | 3546 | goto out; |
3342 | 3547 | ||
3548 | data->arg.label = label; | ||
3343 | status = nfs4_do_create(dir, dentry, data); | 3549 | status = nfs4_do_create(dir, dentry, data); |
3344 | 3550 | ||
3345 | nfs4_free_createdata(data); | 3551 | nfs4_free_createdata(data); |
@@ -3351,14 +3557,19 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
3351 | struct iattr *sattr) | 3557 | struct iattr *sattr) |
3352 | { | 3558 | { |
3353 | struct nfs4_exception exception = { }; | 3559 | struct nfs4_exception exception = { }; |
3560 | struct nfs4_label l, *label = NULL; | ||
3354 | int err; | 3561 | int err; |
3355 | 3562 | ||
3563 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3564 | |||
3356 | sattr->ia_mode &= ~current_umask(); | 3565 | sattr->ia_mode &= ~current_umask(); |
3357 | do { | 3566 | do { |
3358 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3567 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3359 | _nfs4_proc_mkdir(dir, dentry, sattr), | 3568 | _nfs4_proc_mkdir(dir, dentry, sattr, label), |
3360 | &exception); | 3569 | &exception); |
3361 | } while (exception.retry); | 3570 | } while (exception.retry); |
3571 | nfs4_label_release_security(label); | ||
3572 | |||
3362 | return err; | 3573 | return err; |
3363 | } | 3574 | } |
3364 | 3575 | ||
@@ -3416,7 +3627,7 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
3416 | } | 3627 | } |
3417 | 3628 | ||
3418 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | 3629 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, |
3419 | struct iattr *sattr, dev_t rdev) | 3630 | struct iattr *sattr, struct nfs4_label *label, dev_t rdev) |
3420 | { | 3631 | { |
3421 | struct nfs4_createdata *data; | 3632 | struct nfs4_createdata *data; |
3422 | int mode = sattr->ia_mode; | 3633 | int mode = sattr->ia_mode; |
@@ -3441,7 +3652,8 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3441 | status = -EINVAL; | 3652 | status = -EINVAL; |
3442 | goto out_free; | 3653 | goto out_free; |
3443 | } | 3654 | } |
3444 | 3655 | ||
3656 | data->arg.label = label; | ||
3445 | status = nfs4_do_create(dir, dentry, data); | 3657 | status = nfs4_do_create(dir, dentry, data); |
3446 | out_free: | 3658 | out_free: |
3447 | nfs4_free_createdata(data); | 3659 | nfs4_free_createdata(data); |
@@ -3453,14 +3665,20 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3453 | struct iattr *sattr, dev_t rdev) | 3665 | struct iattr *sattr, dev_t rdev) |
3454 | { | 3666 | { |
3455 | struct nfs4_exception exception = { }; | 3667 | struct nfs4_exception exception = { }; |
3668 | struct nfs4_label l, *label = NULL; | ||
3456 | int err; | 3669 | int err; |
3457 | 3670 | ||
3671 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3672 | |||
3458 | sattr->ia_mode &= ~current_umask(); | 3673 | sattr->ia_mode &= ~current_umask(); |
3459 | do { | 3674 | do { |
3460 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3675 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3461 | _nfs4_proc_mknod(dir, dentry, sattr, rdev), | 3676 | _nfs4_proc_mknod(dir, dentry, sattr, label, rdev), |
3462 | &exception); | 3677 | &exception); |
3463 | } while (exception.retry); | 3678 | } while (exception.retry); |
3679 | |||
3680 | nfs4_label_release_security(label); | ||
3681 | |||
3464 | return err; | 3682 | return err; |
3465 | } | 3683 | } |
3466 | 3684 | ||
@@ -4187,6 +4405,155 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
4187 | return err; | 4405 | return err; |
4188 | } | 4406 | } |
4189 | 4407 | ||
4408 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
4409 | static int _nfs4_get_security_label(struct inode *inode, void *buf, | ||
4410 | size_t buflen) | ||
4411 | { | ||
4412 | struct nfs_server *server = NFS_SERVER(inode); | ||
4413 | struct nfs_fattr fattr; | ||
4414 | struct nfs4_label label = {0, 0, buflen, buf}; | ||
4415 | |||
4416 | u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
4417 | struct nfs4_getattr_arg args = { | ||
4418 | .fh = NFS_FH(inode), | ||
4419 | .bitmask = bitmask, | ||
4420 | }; | ||
4421 | struct nfs4_getattr_res res = { | ||
4422 | .fattr = &fattr, | ||
4423 | .label = &label, | ||
4424 | .server = server, | ||
4425 | }; | ||
4426 | struct rpc_message msg = { | ||
4427 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR], | ||
4428 | .rpc_argp = &args, | ||
4429 | .rpc_resp = &res, | ||
4430 | }; | ||
4431 | int ret; | ||
4432 | |||
4433 | nfs_fattr_init(&fattr); | ||
4434 | |||
4435 | ret = rpc_call_sync(server->client, &msg, 0); | ||
4436 | if (ret) | ||
4437 | return ret; | ||
4438 | if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) | ||
4439 | return -ENOENT; | ||
4440 | if (buflen < label.len) | ||
4441 | return -ERANGE; | ||
4442 | return 0; | ||
4443 | } | ||
4444 | |||
4445 | static int nfs4_get_security_label(struct inode *inode, void *buf, | ||
4446 | size_t buflen) | ||
4447 | { | ||
4448 | struct nfs4_exception exception = { }; | ||
4449 | int err; | ||
4450 | |||
4451 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
4452 | return -EOPNOTSUPP; | ||
4453 | |||
4454 | do { | ||
4455 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
4456 | _nfs4_get_security_label(inode, buf, buflen), | ||
4457 | &exception); | ||
4458 | } while (exception.retry); | ||
4459 | return err; | ||
4460 | } | ||
4461 | |||
4462 | static int _nfs4_do_set_security_label(struct inode *inode, | ||
4463 | struct nfs4_label *ilabel, | ||
4464 | struct nfs_fattr *fattr, | ||
4465 | struct nfs4_label *olabel) | ||
4466 | { | ||
4467 | |||
4468 | struct iattr sattr = {0}; | ||
4469 | struct nfs_server *server = NFS_SERVER(inode); | ||
4470 | const u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
4471 | struct nfs_setattrargs args = { | ||
4472 | .fh = NFS_FH(inode), | ||
4473 | .iap = &sattr, | ||
4474 | .server = server, | ||
4475 | .bitmask = bitmask, | ||
4476 | .label = ilabel, | ||
4477 | }; | ||
4478 | struct nfs_setattrres res = { | ||
4479 | .fattr = fattr, | ||
4480 | .label = olabel, | ||
4481 | .server = server, | ||
4482 | }; | ||
4483 | struct rpc_message msg = { | ||
4484 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], | ||
4485 | .rpc_argp = &args, | ||
4486 | .rpc_resp = &res, | ||
4487 | }; | ||
4488 | int status; | ||
4489 | |||
4490 | nfs4_stateid_copy(&args.stateid, &zero_stateid); | ||
4491 | |||
4492 | status = rpc_call_sync(server->client, &msg, 0); | ||
4493 | if (status) | ||
4494 | dprintk("%s failed: %d\n", __func__, status); | ||
4495 | |||
4496 | return status; | ||
4497 | } | ||
4498 | |||
4499 | static int nfs4_do_set_security_label(struct inode *inode, | ||
4500 | struct nfs4_label *ilabel, | ||
4501 | struct nfs_fattr *fattr, | ||
4502 | struct nfs4_label *olabel) | ||
4503 | { | ||
4504 | struct nfs4_exception exception = { }; | ||
4505 | int err; | ||
4506 | |||
4507 | do { | ||
4508 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
4509 | _nfs4_do_set_security_label(inode, ilabel, | ||
4510 | fattr, olabel), | ||
4511 | &exception); | ||
4512 | } while (exception.retry); | ||
4513 | return err; | ||
4514 | } | ||
4515 | |||
4516 | static int | ||
4517 | nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen) | ||
4518 | { | ||
4519 | struct nfs4_label ilabel, *olabel = NULL; | ||
4520 | struct nfs_fattr fattr; | ||
4521 | struct rpc_cred *cred; | ||
4522 | struct inode *inode = dentry->d_inode; | ||
4523 | int status; | ||
4524 | |||
4525 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
4526 | return -EOPNOTSUPP; | ||
4527 | |||
4528 | nfs_fattr_init(&fattr); | ||
4529 | |||
4530 | ilabel.pi = 0; | ||
4531 | ilabel.lfs = 0; | ||
4532 | ilabel.label = (char *)buf; | ||
4533 | ilabel.len = buflen; | ||
4534 | |||
4535 | cred = rpc_lookup_cred(); | ||
4536 | if (IS_ERR(cred)) | ||
4537 | return PTR_ERR(cred); | ||
4538 | |||
4539 | olabel = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); | ||
4540 | if (IS_ERR(olabel)) { | ||
4541 | status = -PTR_ERR(olabel); | ||
4542 | goto out; | ||
4543 | } | ||
4544 | |||
4545 | status = nfs4_do_set_security_label(inode, &ilabel, &fattr, olabel); | ||
4546 | if (status == 0) | ||
4547 | nfs_setsecurity(inode, &fattr, olabel); | ||
4548 | |||
4549 | nfs4_label_free(olabel); | ||
4550 | out: | ||
4551 | put_rpccred(cred); | ||
4552 | return status; | ||
4553 | } | ||
4554 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | ||
4555 | |||
4556 | |||
4190 | static int | 4557 | static int |
4191 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | 4558 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) |
4192 | { | 4559 | { |
@@ -4345,7 +4712,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
4345 | /* cb_client4 */ | 4712 | /* cb_client4 */ |
4346 | rcu_read_lock(); | 4713 | rcu_read_lock(); |
4347 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | 4714 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
4348 | sizeof(setclientid.sc_netid), | 4715 | sizeof(setclientid.sc_netid), "%s", |
4349 | rpc_peeraddr2str(clp->cl_rpcclient, | 4716 | rpc_peeraddr2str(clp->cl_rpcclient, |
4350 | RPC_DISPLAY_NETID)); | 4717 | RPC_DISPLAY_NETID)); |
4351 | rcu_read_unlock(); | 4718 | rcu_read_unlock(); |
@@ -4528,7 +4895,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 | |||
4528 | static unsigned long | 4895 | static unsigned long |
4529 | nfs4_set_lock_task_retry(unsigned long timeout) | 4896 | nfs4_set_lock_task_retry(unsigned long timeout) |
4530 | { | 4897 | { |
4531 | freezable_schedule_timeout_killable(timeout); | 4898 | freezable_schedule_timeout_killable_unsafe(timeout); |
4532 | timeout <<= 1; | 4899 | timeout <<= 1; |
4533 | if (timeout > NFS4_LOCK_MAXTIMEOUT) | 4900 | if (timeout > NFS4_LOCK_MAXTIMEOUT) |
4534 | return NFS4_LOCK_MAXTIMEOUT; | 4901 | return NFS4_LOCK_MAXTIMEOUT; |
@@ -5056,13 +5423,18 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
5056 | 5423 | ||
5057 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { | 5424 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { |
5058 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { | 5425 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { |
5059 | status = nfs41_test_stateid(server, &lsp->ls_stateid); | 5426 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; |
5427 | |||
5428 | status = nfs41_test_stateid(server, | ||
5429 | &lsp->ls_stateid, | ||
5430 | cred); | ||
5060 | if (status != NFS_OK) { | 5431 | if (status != NFS_OK) { |
5061 | /* Free the stateid unless the server | 5432 | /* Free the stateid unless the server |
5062 | * informs us the stateid is unrecognized. */ | 5433 | * informs us the stateid is unrecognized. */ |
5063 | if (status != -NFS4ERR_BAD_STATEID) | 5434 | if (status != -NFS4ERR_BAD_STATEID) |
5064 | nfs41_free_stateid(server, | 5435 | nfs41_free_stateid(server, |
5065 | &lsp->ls_stateid); | 5436 | &lsp->ls_stateid, |
5437 | cred); | ||
5066 | clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); | 5438 | clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); |
5067 | ret = status; | 5439 | ret = status; |
5068 | } | 5440 | } |
@@ -5295,6 +5667,53 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list, | |||
5295 | return len; | 5667 | return len; |
5296 | } | 5668 | } |
5297 | 5669 | ||
5670 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
5671 | static inline int nfs4_server_supports_labels(struct nfs_server *server) | ||
5672 | { | ||
5673 | return server->caps & NFS_CAP_SECURITY_LABEL; | ||
5674 | } | ||
5675 | |||
5676 | static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key, | ||
5677 | const void *buf, size_t buflen, | ||
5678 | int flags, int type) | ||
5679 | { | ||
5680 | if (security_ismaclabel(key)) | ||
5681 | return nfs4_set_security_label(dentry, buf, buflen); | ||
5682 | |||
5683 | return -EOPNOTSUPP; | ||
5684 | } | ||
5685 | |||
5686 | static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key, | ||
5687 | void *buf, size_t buflen, int type) | ||
5688 | { | ||
5689 | if (security_ismaclabel(key)) | ||
5690 | return nfs4_get_security_label(dentry->d_inode, buf, buflen); | ||
5691 | return -EOPNOTSUPP; | ||
5692 | } | ||
5693 | |||
5694 | static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list, | ||
5695 | size_t list_len, const char *name, | ||
5696 | size_t name_len, int type) | ||
5697 | { | ||
5698 | size_t len = 0; | ||
5699 | |||
5700 | if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL)) { | ||
5701 | len = security_inode_listsecurity(dentry->d_inode, NULL, 0); | ||
5702 | if (list && len <= list_len) | ||
5703 | security_inode_listsecurity(dentry->d_inode, list, len); | ||
5704 | } | ||
5705 | return len; | ||
5706 | } | ||
5707 | |||
5708 | static const struct xattr_handler nfs4_xattr_nfs4_label_handler = { | ||
5709 | .prefix = XATTR_SECURITY_PREFIX, | ||
5710 | .list = nfs4_xattr_list_nfs4_label, | ||
5711 | .get = nfs4_xattr_get_nfs4_label, | ||
5712 | .set = nfs4_xattr_set_nfs4_label, | ||
5713 | }; | ||
5714 | #endif | ||
5715 | |||
5716 | |||
5298 | /* | 5717 | /* |
5299 | * nfs_fhget will use either the mounted_on_fileid or the fileid | 5718 | * nfs_fhget will use either the mounted_on_fileid or the fileid |
5300 | */ | 5719 | */ |
@@ -5318,7 +5737,7 @@ static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |||
5318 | struct page *page) | 5737 | struct page *page) |
5319 | { | 5738 | { |
5320 | struct nfs_server *server = NFS_SERVER(dir); | 5739 | struct nfs_server *server = NFS_SERVER(dir); |
5321 | u32 bitmask[2] = { | 5740 | u32 bitmask[3] = { |
5322 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, | 5741 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, |
5323 | }; | 5742 | }; |
5324 | struct nfs4_fs_locations_arg args = { | 5743 | struct nfs4_fs_locations_arg args = { |
@@ -5505,7 +5924,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5505 | struct nfs41_exchange_id_args args = { | 5924 | struct nfs41_exchange_id_args args = { |
5506 | .verifier = &verifier, | 5925 | .verifier = &verifier, |
5507 | .client = clp, | 5926 | .client = clp, |
5508 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, | 5927 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER | |
5928 | EXCHGID4_FLAG_BIND_PRINC_STATEID, | ||
5509 | }; | 5929 | }; |
5510 | struct nfs41_exchange_id_res res = { | 5930 | struct nfs41_exchange_id_res res = { |
5511 | 0 | 5931 | 0 |
@@ -5762,17 +6182,14 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
5762 | */ | 6182 | */ |
5763 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | 6183 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) |
5764 | { | 6184 | { |
5765 | struct nfs4_session *session = args->client->cl_session; | 6185 | unsigned int max_rqst_sz, max_resp_sz; |
5766 | unsigned int mxrqst_sz = session->fc_target_max_rqst_sz, | 6186 | |
5767 | mxresp_sz = session->fc_target_max_resp_sz; | 6187 | max_rqst_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxwrite_overhead; |
6188 | max_resp_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxread_overhead; | ||
5768 | 6189 | ||
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 */ | 6190 | /* Fore channel attributes */ |
5774 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 6191 | args->fc_attrs.max_rqst_sz = max_rqst_sz; |
5775 | args->fc_attrs.max_resp_sz = mxresp_sz; | 6192 | args->fc_attrs.max_resp_sz = max_resp_sz; |
5776 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 6193 | args->fc_attrs.max_ops = NFS4_MAX_OPS; |
5777 | args->fc_attrs.max_reqs = max_session_slots; | 6194 | args->fc_attrs.max_reqs = max_session_slots; |
5778 | 6195 | ||
@@ -6159,12 +6576,14 @@ static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = { | |||
6159 | /* | 6576 | /* |
6160 | * Issue a global reclaim complete. | 6577 | * Issue a global reclaim complete. |
6161 | */ | 6578 | */ |
6162 | static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | 6579 | static int nfs41_proc_reclaim_complete(struct nfs_client *clp, |
6580 | struct rpc_cred *cred) | ||
6163 | { | 6581 | { |
6164 | struct nfs4_reclaim_complete_data *calldata; | 6582 | struct nfs4_reclaim_complete_data *calldata; |
6165 | struct rpc_task *task; | 6583 | struct rpc_task *task; |
6166 | struct rpc_message msg = { | 6584 | struct rpc_message msg = { |
6167 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE], | 6585 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE], |
6586 | .rpc_cred = cred, | ||
6168 | }; | 6587 | }; |
6169 | struct rpc_task_setup task_setup_data = { | 6588 | struct rpc_task_setup task_setup_data = { |
6170 | .rpc_client = clp->cl_rpcclient, | 6589 | .rpc_client = clp->cl_rpcclient, |
@@ -6348,6 +6767,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6348 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], | 6767 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], |
6349 | .rpc_argp = &lgp->args, | 6768 | .rpc_argp = &lgp->args, |
6350 | .rpc_resp = &lgp->res, | 6769 | .rpc_resp = &lgp->res, |
6770 | .rpc_cred = lgp->cred, | ||
6351 | }; | 6771 | }; |
6352 | struct rpc_task_setup task_setup_data = { | 6772 | struct rpc_task_setup task_setup_data = { |
6353 | .rpc_client = server->client, | 6773 | .rpc_client = server->client, |
@@ -6451,6 +6871,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
6451 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN], | 6871 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN], |
6452 | .rpc_argp = &lrp->args, | 6872 | .rpc_argp = &lrp->args, |
6453 | .rpc_resp = &lrp->res, | 6873 | .rpc_resp = &lrp->res, |
6874 | .rpc_cred = lrp->cred, | ||
6454 | }; | 6875 | }; |
6455 | struct rpc_task_setup task_setup_data = { | 6876 | struct rpc_task_setup task_setup_data = { |
6456 | .rpc_client = lrp->clp->cl_rpcclient, | 6877 | .rpc_client = lrp->clp->cl_rpcclient, |
@@ -6520,7 +6941,9 @@ int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
6520 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); | 6941 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); |
6521 | 6942 | ||
6522 | static int | 6943 | static int |
6523 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | 6944 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, |
6945 | struct pnfs_device *pdev, | ||
6946 | struct rpc_cred *cred) | ||
6524 | { | 6947 | { |
6525 | struct nfs4_getdeviceinfo_args args = { | 6948 | struct nfs4_getdeviceinfo_args args = { |
6526 | .pdev = pdev, | 6949 | .pdev = pdev, |
@@ -6532,6 +6955,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
6532 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO], | 6955 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO], |
6533 | .rpc_argp = &args, | 6956 | .rpc_argp = &args, |
6534 | .rpc_resp = &res, | 6957 | .rpc_resp = &res, |
6958 | .rpc_cred = cred, | ||
6535 | }; | 6959 | }; |
6536 | int status; | 6960 | int status; |
6537 | 6961 | ||
@@ -6542,14 +6966,16 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
6542 | return status; | 6966 | return status; |
6543 | } | 6967 | } |
6544 | 6968 | ||
6545 | int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | 6969 | int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
6970 | struct pnfs_device *pdev, | ||
6971 | struct rpc_cred *cred) | ||
6546 | { | 6972 | { |
6547 | struct nfs4_exception exception = { }; | 6973 | struct nfs4_exception exception = { }; |
6548 | int err; | 6974 | int err; |
6549 | 6975 | ||
6550 | do { | 6976 | do { |
6551 | err = nfs4_handle_exception(server, | 6977 | err = nfs4_handle_exception(server, |
6552 | _nfs4_proc_getdeviceinfo(server, pdev), | 6978 | _nfs4_proc_getdeviceinfo(server, pdev, cred), |
6553 | &exception); | 6979 | &exception); |
6554 | } while (exception.retry); | 6980 | } while (exception.retry); |
6555 | return err; | 6981 | return err; |
@@ -6733,7 +7159,9 @@ out: | |||
6733 | return err; | 7159 | return err; |
6734 | } | 7160 | } |
6735 | 7161 | ||
6736 | static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7162 | static int _nfs41_test_stateid(struct nfs_server *server, |
7163 | nfs4_stateid *stateid, | ||
7164 | struct rpc_cred *cred) | ||
6737 | { | 7165 | { |
6738 | int status; | 7166 | int status; |
6739 | struct nfs41_test_stateid_args args = { | 7167 | struct nfs41_test_stateid_args args = { |
@@ -6744,6 +7172,7 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6744 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], | 7172 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], |
6745 | .rpc_argp = &args, | 7173 | .rpc_argp = &args, |
6746 | .rpc_resp = &res, | 7174 | .rpc_resp = &res, |
7175 | .rpc_cred = cred, | ||
6747 | }; | 7176 | }; |
6748 | 7177 | ||
6749 | dprintk("NFS call test_stateid %p\n", stateid); | 7178 | dprintk("NFS call test_stateid %p\n", stateid); |
@@ -6764,17 +7193,20 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6764 | * | 7193 | * |
6765 | * @server: server / transport on which to perform the operation | 7194 | * @server: server / transport on which to perform the operation |
6766 | * @stateid: state ID to test | 7195 | * @stateid: state ID to test |
7196 | * @cred: credential | ||
6767 | * | 7197 | * |
6768 | * Returns NFS_OK if the server recognizes that "stateid" is valid. | 7198 | * Returns NFS_OK if the server recognizes that "stateid" is valid. |
6769 | * Otherwise a negative NFS4ERR value is returned if the operation | 7199 | * Otherwise a negative NFS4ERR value is returned if the operation |
6770 | * failed or the state ID is not currently valid. | 7200 | * failed or the state ID is not currently valid. |
6771 | */ | 7201 | */ |
6772 | static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7202 | static int nfs41_test_stateid(struct nfs_server *server, |
7203 | nfs4_stateid *stateid, | ||
7204 | struct rpc_cred *cred) | ||
6773 | { | 7205 | { |
6774 | struct nfs4_exception exception = { }; | 7206 | struct nfs4_exception exception = { }; |
6775 | int err; | 7207 | int err; |
6776 | do { | 7208 | do { |
6777 | err = _nfs41_test_stateid(server, stateid); | 7209 | err = _nfs41_test_stateid(server, stateid, cred); |
6778 | if (err != -NFS4ERR_DELAY) | 7210 | if (err != -NFS4ERR_DELAY) |
6779 | break; | 7211 | break; |
6780 | nfs4_handle_exception(server, err, &exception); | 7212 | nfs4_handle_exception(server, err, &exception); |
@@ -6823,10 +7255,12 @@ const struct rpc_call_ops nfs41_free_stateid_ops = { | |||
6823 | 7255 | ||
6824 | static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | 7256 | static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, |
6825 | nfs4_stateid *stateid, | 7257 | nfs4_stateid *stateid, |
7258 | struct rpc_cred *cred, | ||
6826 | bool privileged) | 7259 | bool privileged) |
6827 | { | 7260 | { |
6828 | struct rpc_message msg = { | 7261 | struct rpc_message msg = { |
6829 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], | 7262 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], |
7263 | .rpc_cred = cred, | ||
6830 | }; | 7264 | }; |
6831 | struct rpc_task_setup task_setup = { | 7265 | struct rpc_task_setup task_setup = { |
6832 | .rpc_client = server->client, | 7266 | .rpc_client = server->client, |
@@ -6859,16 +7293,19 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | |||
6859 | * | 7293 | * |
6860 | * @server: server / transport on which to perform the operation | 7294 | * @server: server / transport on which to perform the operation |
6861 | * @stateid: state ID to release | 7295 | * @stateid: state ID to release |
7296 | * @cred: credential | ||
6862 | * | 7297 | * |
6863 | * Returns NFS_OK if the server freed "stateid". Otherwise a | 7298 | * Returns NFS_OK if the server freed "stateid". Otherwise a |
6864 | * negative NFS4ERR value is returned. | 7299 | * negative NFS4ERR value is returned. |
6865 | */ | 7300 | */ |
6866 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 7301 | static int nfs41_free_stateid(struct nfs_server *server, |
7302 | nfs4_stateid *stateid, | ||
7303 | struct rpc_cred *cred) | ||
6867 | { | 7304 | { |
6868 | struct rpc_task *task; | 7305 | struct rpc_task *task; |
6869 | int ret; | 7306 | int ret; |
6870 | 7307 | ||
6871 | task = _nfs41_free_stateid(server, stateid, true); | 7308 | task = _nfs41_free_stateid(server, stateid, cred, true); |
6872 | if (IS_ERR(task)) | 7309 | if (IS_ERR(task)) |
6873 | return PTR_ERR(task); | 7310 | return PTR_ERR(task); |
6874 | ret = rpc_wait_for_completion_task(task); | 7311 | ret = rpc_wait_for_completion_task(task); |
@@ -6881,8 +7318,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) | 7318 | static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp) |
6882 | { | 7319 | { |
6883 | struct rpc_task *task; | 7320 | struct rpc_task *task; |
7321 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; | ||
6884 | 7322 | ||
6885 | task = _nfs41_free_stateid(server, &lsp->ls_stateid, false); | 7323 | task = _nfs41_free_stateid(server, &lsp->ls_stateid, cred, false); |
6886 | nfs4_free_lock_state(server, lsp); | 7324 | nfs4_free_lock_state(server, lsp); |
6887 | if (IS_ERR(task)) | 7325 | if (IS_ERR(task)) |
6888 | return PTR_ERR(task); | 7326 | return PTR_ERR(task); |
@@ -7004,11 +7442,33 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
7004 | }; | 7442 | }; |
7005 | #endif | 7443 | #endif |
7006 | 7444 | ||
7445 | #if defined(CONFIG_NFS_V4_2) | ||
7446 | static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | ||
7447 | .minor_version = 2, | ||
7448 | .init_caps = NFS_CAP_READDIRPLUS | ||
7449 | | NFS_CAP_ATOMIC_OPEN | ||
7450 | | NFS_CAP_CHANGE_ATTR | ||
7451 | | NFS_CAP_POSIX_LOCK | ||
7452 | | NFS_CAP_STATEID_NFSV41 | ||
7453 | | NFS_CAP_ATOMIC_OPEN_V1, | ||
7454 | .call_sync = nfs4_call_sync_sequence, | ||
7455 | .match_stateid = nfs41_match_stateid, | ||
7456 | .find_root_sec = nfs41_find_root_sec, | ||
7457 | .free_lock_state = nfs41_free_lock_state, | ||
7458 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | ||
7459 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | ||
7460 | .state_renewal_ops = &nfs41_state_renewal_ops, | ||
7461 | }; | ||
7462 | #endif | ||
7463 | |||
7007 | const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { | 7464 | const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { |
7008 | [0] = &nfs_v4_0_minor_ops, | 7465 | [0] = &nfs_v4_0_minor_ops, |
7009 | #if defined(CONFIG_NFS_V4_1) | 7466 | #if defined(CONFIG_NFS_V4_1) |
7010 | [1] = &nfs_v4_1_minor_ops, | 7467 | [1] = &nfs_v4_1_minor_ops, |
7011 | #endif | 7468 | #endif |
7469 | #if defined(CONFIG_NFS_V4_2) | ||
7470 | [2] = &nfs_v4_2_minor_ops, | ||
7471 | #endif | ||
7012 | }; | 7472 | }; |
7013 | 7473 | ||
7014 | const struct inode_operations nfs4_dir_inode_operations = { | 7474 | const struct inode_operations nfs4_dir_inode_operations = { |
@@ -7108,6 +7568,9 @@ static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | |||
7108 | 7568 | ||
7109 | const struct xattr_handler *nfs4_xattr_handlers[] = { | 7569 | const struct xattr_handler *nfs4_xattr_handlers[] = { |
7110 | &nfs4_xattr_nfs4_acl_handler, | 7570 | &nfs4_xattr_nfs4_acl_handler, |
7571 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
7572 | &nfs4_xattr_nfs4_label_handler, | ||
7573 | #endif | ||
7111 | NULL | 7574 | NULL |
7112 | }; | 7575 | }; |
7113 | 7576 | ||