aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c265
1 files changed, 126 insertions, 139 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1293e0acd82b..c910413eaeca 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -451,9 +451,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
451 /* Save the delegation */ 451 /* Save the delegation */
452 memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data)); 452 memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data));
453 rcu_read_unlock(); 453 rcu_read_unlock();
454 lock_kernel();
455 ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); 454 ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
456 unlock_kernel();
457 if (ret != 0) 455 if (ret != 0)
458 goto out; 456 goto out;
459 ret = -EAGAIN; 457 ret = -EAGAIN;
@@ -1139,8 +1137,9 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int
1139 return res; 1137 return res;
1140} 1138}
1141 1139
1142static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, 1140static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1143 struct iattr *sattr, struct nfs4_state *state) 1141 struct nfs_fattr *fattr, struct iattr *sattr,
1142 struct nfs4_state *state)
1144{ 1143{
1145 struct nfs_server *server = NFS_SERVER(inode); 1144 struct nfs_server *server = NFS_SERVER(inode);
1146 struct nfs_setattrargs arg = { 1145 struct nfs_setattrargs arg = {
@@ -1154,9 +1153,10 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
1154 .server = server, 1153 .server = server,
1155 }; 1154 };
1156 struct rpc_message msg = { 1155 struct rpc_message msg = {
1157 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], 1156 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
1158 .rpc_argp = &arg, 1157 .rpc_argp = &arg,
1159 .rpc_resp = &res, 1158 .rpc_resp = &res,
1159 .rpc_cred = cred,
1160 }; 1160 };
1161 unsigned long timestamp = jiffies; 1161 unsigned long timestamp = jiffies;
1162 int status; 1162 int status;
@@ -1166,7 +1166,6 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
1166 if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { 1166 if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
1167 /* Use that stateid */ 1167 /* Use that stateid */
1168 } else if (state != NULL) { 1168 } else if (state != NULL) {
1169 msg.rpc_cred = state->owner->so_cred;
1170 nfs4_copy_stateid(&arg.stateid, state, current->files); 1169 nfs4_copy_stateid(&arg.stateid, state, current->files);
1171 } else 1170 } else
1172 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); 1171 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
@@ -1177,15 +1176,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
1177 return status; 1176 return status;
1178} 1177}
1179 1178
1180static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, 1179static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1181 struct iattr *sattr, struct nfs4_state *state) 1180 struct nfs_fattr *fattr, struct iattr *sattr,
1181 struct nfs4_state *state)
1182{ 1182{
1183 struct nfs_server *server = NFS_SERVER(inode); 1183 struct nfs_server *server = NFS_SERVER(inode);
1184 struct nfs4_exception exception = { }; 1184 struct nfs4_exception exception = { };
1185 int err; 1185 int err;
1186 do { 1186 do {
1187 err = nfs4_handle_exception(server, 1187 err = nfs4_handle_exception(server,
1188 _nfs4_do_setattr(inode, fattr, sattr, state), 1188 _nfs4_do_setattr(inode, cred, fattr, sattr, state),
1189 &exception); 1189 &exception);
1190 } while (exception.retry); 1190 } while (exception.retry);
1191 return err; 1191 return err;
@@ -1647,29 +1647,25 @@ static int
1647nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, 1647nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1648 struct iattr *sattr) 1648 struct iattr *sattr)
1649{ 1649{
1650 struct rpc_cred *cred;
1651 struct inode *inode = dentry->d_inode; 1650 struct inode *inode = dentry->d_inode;
1652 struct nfs_open_context *ctx; 1651 struct rpc_cred *cred = NULL;
1653 struct nfs4_state *state = NULL; 1652 struct nfs4_state *state = NULL;
1654 int status; 1653 int status;
1655 1654
1656 nfs_fattr_init(fattr); 1655 nfs_fattr_init(fattr);
1657 1656
1658 cred = rpc_lookup_cred();
1659 if (IS_ERR(cred))
1660 return PTR_ERR(cred);
1661
1662 /* Search for an existing open(O_WRITE) file */ 1657 /* Search for an existing open(O_WRITE) file */
1663 ctx = nfs_find_open_context(inode, cred, FMODE_WRITE); 1658 if (sattr->ia_valid & ATTR_FILE) {
1664 if (ctx != NULL) 1659 struct nfs_open_context *ctx;
1660
1661 ctx = nfs_file_open_context(sattr->ia_file);
1662 cred = ctx->cred;
1665 state = ctx->state; 1663 state = ctx->state;
1664 }
1666 1665
1667 status = nfs4_do_setattr(inode, fattr, sattr, state); 1666 status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
1668 if (status == 0) 1667 if (status == 0)
1669 nfs_setattr_update_inode(inode, sattr); 1668 nfs_setattr_update_inode(inode, sattr);
1670 if (ctx != NULL)
1671 put_nfs_open_context(ctx);
1672 put_rpccred(cred);
1673 return status; 1669 return status;
1674} 1670}
1675 1671
@@ -1897,17 +1893,16 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1897 goto out; 1893 goto out;
1898 } 1894 }
1899 state = nfs4_do_open(dir, &path, flags, sattr, cred); 1895 state = nfs4_do_open(dir, &path, flags, sattr, cred);
1900 put_rpccred(cred);
1901 d_drop(dentry); 1896 d_drop(dentry);
1902 if (IS_ERR(state)) { 1897 if (IS_ERR(state)) {
1903 status = PTR_ERR(state); 1898 status = PTR_ERR(state);
1904 goto out; 1899 goto out_putcred;
1905 } 1900 }
1906 d_add(dentry, igrab(state->inode)); 1901 d_add(dentry, igrab(state->inode));
1907 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1902 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1908 if (flags & O_EXCL) { 1903 if (flags & O_EXCL) {
1909 struct nfs_fattr fattr; 1904 struct nfs_fattr fattr;
1910 status = nfs4_do_setattr(state->inode, &fattr, sattr, state); 1905 status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state);
1911 if (status == 0) 1906 if (status == 0)
1912 nfs_setattr_update_inode(state->inode, sattr); 1907 nfs_setattr_update_inode(state->inode, sattr);
1913 nfs_post_op_update_inode(state->inode, &fattr); 1908 nfs_post_op_update_inode(state->inode, &fattr);
@@ -1916,6 +1911,8 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1916 status = nfs4_intent_set_file(nd, &path, state); 1911 status = nfs4_intent_set_file(nd, &path, state);
1917 else 1912 else
1918 nfs4_close_sync(&path, state, flags); 1913 nfs4_close_sync(&path, state, flags);
1914out_putcred:
1915 put_rpccred(cred);
1919out: 1916out:
1920 return status; 1917 return status;
1921} 1918}
@@ -2079,47 +2076,81 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
2079 return err; 2076 return err;
2080} 2077}
2081 2078
2079struct nfs4_createdata {
2080 struct rpc_message msg;
2081 struct nfs4_create_arg arg;
2082 struct nfs4_create_res res;
2083 struct nfs_fh fh;
2084 struct nfs_fattr fattr;
2085 struct nfs_fattr dir_fattr;
2086};
2087
2088static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
2089 struct qstr *name, struct iattr *sattr, u32 ftype)
2090{
2091 struct nfs4_createdata *data;
2092
2093 data = kzalloc(sizeof(*data), GFP_KERNEL);
2094 if (data != NULL) {
2095 struct nfs_server *server = NFS_SERVER(dir);
2096
2097 data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
2098 data->msg.rpc_argp = &data->arg;
2099 data->msg.rpc_resp = &data->res;
2100 data->arg.dir_fh = NFS_FH(dir);
2101 data->arg.server = server;
2102 data->arg.name = name;
2103 data->arg.attrs = sattr;
2104 data->arg.ftype = ftype;
2105 data->arg.bitmask = server->attr_bitmask;
2106 data->res.server = server;
2107 data->res.fh = &data->fh;
2108 data->res.fattr = &data->fattr;
2109 data->res.dir_fattr = &data->dir_fattr;
2110 nfs_fattr_init(data->res.fattr);
2111 nfs_fattr_init(data->res.dir_fattr);
2112 }
2113 return data;
2114}
2115
2116static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
2117{
2118 int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
2119 if (status == 0) {
2120 update_changeattr(dir, &data->res.dir_cinfo);
2121 nfs_post_op_update_inode(dir, data->res.dir_fattr);
2122 status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
2123 }
2124 return status;
2125}
2126
2127static void nfs4_free_createdata(struct nfs4_createdata *data)
2128{
2129 kfree(data);
2130}
2131
2082static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, 2132static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
2083 struct page *page, unsigned int len, struct iattr *sattr) 2133 struct page *page, unsigned int len, struct iattr *sattr)
2084{ 2134{
2085 struct nfs_server *server = NFS_SERVER(dir); 2135 struct nfs4_createdata *data;
2086 struct nfs_fh fhandle; 2136 int status = -ENAMETOOLONG;
2087 struct nfs_fattr fattr, dir_fattr;
2088 struct nfs4_create_arg arg = {
2089 .dir_fh = NFS_FH(dir),
2090 .server = server,
2091 .name = &dentry->d_name,
2092 .attrs = sattr,
2093 .ftype = NF4LNK,
2094 .bitmask = server->attr_bitmask,
2095 };
2096 struct nfs4_create_res res = {
2097 .server = server,
2098 .fh = &fhandle,
2099 .fattr = &fattr,
2100 .dir_fattr = &dir_fattr,
2101 };
2102 struct rpc_message msg = {
2103 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
2104 .rpc_argp = &arg,
2105 .rpc_resp = &res,
2106 };
2107 int status;
2108 2137
2109 if (len > NFS4_MAXPATHLEN) 2138 if (len > NFS4_MAXPATHLEN)
2110 return -ENAMETOOLONG; 2139 goto out;
2111 2140
2112 arg.u.symlink.pages = &page; 2141 status = -ENOMEM;
2113 arg.u.symlink.len = len; 2142 data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4LNK);
2114 nfs_fattr_init(&fattr); 2143 if (data == NULL)
2115 nfs_fattr_init(&dir_fattr); 2144 goto out;
2145
2146 data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
2147 data->arg.u.symlink.pages = &page;
2148 data->arg.u.symlink.len = len;
2116 2149
2117 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2150 status = nfs4_do_create(dir, dentry, data);
2118 if (!status) { 2151
2119 update_changeattr(dir, &res.dir_cinfo); 2152 nfs4_free_createdata(data);
2120 nfs_post_op_update_inode(dir, res.dir_fattr); 2153out:
2121 status = nfs_instantiate(dentry, &fhandle, &fattr);
2122 }
2123 return status; 2154 return status;
2124} 2155}
2125 2156
@@ -2140,39 +2171,17 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
2140static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, 2171static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
2141 struct iattr *sattr) 2172 struct iattr *sattr)
2142{ 2173{
2143 struct nfs_server *server = NFS_SERVER(dir); 2174 struct nfs4_createdata *data;
2144 struct nfs_fh fhandle; 2175 int status = -ENOMEM;
2145 struct nfs_fattr fattr, dir_fattr;
2146 struct nfs4_create_arg arg = {
2147 .dir_fh = NFS_FH(dir),
2148 .server = server,
2149 .name = &dentry->d_name,
2150 .attrs = sattr,
2151 .ftype = NF4DIR,
2152 .bitmask = server->attr_bitmask,
2153 };
2154 struct nfs4_create_res res = {
2155 .server = server,
2156 .fh = &fhandle,
2157 .fattr = &fattr,
2158 .dir_fattr = &dir_fattr,
2159 };
2160 struct rpc_message msg = {
2161 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
2162 .rpc_argp = &arg,
2163 .rpc_resp = &res,
2164 };
2165 int status;
2166 2176
2167 nfs_fattr_init(&fattr); 2177 data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR);
2168 nfs_fattr_init(&dir_fattr); 2178 if (data == NULL)
2169 2179 goto out;
2170 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2180
2171 if (!status) { 2181 status = nfs4_do_create(dir, dentry, data);
2172 update_changeattr(dir, &res.dir_cinfo); 2182
2173 nfs_post_op_update_inode(dir, res.dir_fattr); 2183 nfs4_free_createdata(data);
2174 status = nfs_instantiate(dentry, &fhandle, &fattr); 2184out:
2175 }
2176 return status; 2185 return status;
2177} 2186}
2178 2187
@@ -2242,56 +2251,34 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
2242static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, 2251static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
2243 struct iattr *sattr, dev_t rdev) 2252 struct iattr *sattr, dev_t rdev)
2244{ 2253{
2245 struct nfs_server *server = NFS_SERVER(dir); 2254 struct nfs4_createdata *data;
2246 struct nfs_fh fh; 2255 int mode = sattr->ia_mode;
2247 struct nfs_fattr fattr, dir_fattr; 2256 int status = -ENOMEM;
2248 struct nfs4_create_arg arg = {
2249 .dir_fh = NFS_FH(dir),
2250 .server = server,
2251 .name = &dentry->d_name,
2252 .attrs = sattr,
2253 .bitmask = server->attr_bitmask,
2254 };
2255 struct nfs4_create_res res = {
2256 .server = server,
2257 .fh = &fh,
2258 .fattr = &fattr,
2259 .dir_fattr = &dir_fattr,
2260 };
2261 struct rpc_message msg = {
2262 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
2263 .rpc_argp = &arg,
2264 .rpc_resp = &res,
2265 };
2266 int status;
2267 int mode = sattr->ia_mode;
2268
2269 nfs_fattr_init(&fattr);
2270 nfs_fattr_init(&dir_fattr);
2271 2257
2272 BUG_ON(!(sattr->ia_valid & ATTR_MODE)); 2258 BUG_ON(!(sattr->ia_valid & ATTR_MODE));
2273 BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); 2259 BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
2260
2261 data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
2262 if (data == NULL)
2263 goto out;
2264
2274 if (S_ISFIFO(mode)) 2265 if (S_ISFIFO(mode))
2275 arg.ftype = NF4FIFO; 2266 data->arg.ftype = NF4FIFO;
2276 else if (S_ISBLK(mode)) { 2267 else if (S_ISBLK(mode)) {
2277 arg.ftype = NF4BLK; 2268 data->arg.ftype = NF4BLK;
2278 arg.u.device.specdata1 = MAJOR(rdev); 2269 data->arg.u.device.specdata1 = MAJOR(rdev);
2279 arg.u.device.specdata2 = MINOR(rdev); 2270 data->arg.u.device.specdata2 = MINOR(rdev);
2280 } 2271 }
2281 else if (S_ISCHR(mode)) { 2272 else if (S_ISCHR(mode)) {
2282 arg.ftype = NF4CHR; 2273 data->arg.ftype = NF4CHR;
2283 arg.u.device.specdata1 = MAJOR(rdev); 2274 data->arg.u.device.specdata1 = MAJOR(rdev);
2284 arg.u.device.specdata2 = MINOR(rdev); 2275 data->arg.u.device.specdata2 = MINOR(rdev);
2285 } 2276 }
2286 else
2287 arg.ftype = NF4SOCK;
2288 2277
2289 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2278 status = nfs4_do_create(dir, dentry, data);
2290 if (status == 0) { 2279
2291 update_changeattr(dir, &res.dir_cinfo); 2280 nfs4_free_createdata(data);
2292 nfs_post_op_update_inode(dir, res.dir_fattr); 2281out:
2293 status = nfs_instantiate(dentry, &fh, &fattr);
2294 }
2295 return status; 2282 return status;
2296} 2283}
2297 2284
@@ -2706,6 +2693,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
2706 ret = nfs_revalidate_inode(server, inode); 2693 ret = nfs_revalidate_inode(server, inode);
2707 if (ret < 0) 2694 if (ret < 0)
2708 return ret; 2695 return ret;
2696 if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
2697 nfs_zap_acl_cache(inode);
2709 ret = nfs4_read_cached_acl(inode, buf, buflen); 2698 ret = nfs4_read_cached_acl(inode, buf, buflen);
2710 if (ret != -ENOENT) 2699 if (ret != -ENOENT)
2711 return ret; 2700 return ret;
@@ -2733,7 +2722,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
2733 nfs_inode_return_delegation(inode); 2722 nfs_inode_return_delegation(inode);
2734 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); 2723 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
2735 ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 2724 ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
2736 nfs_zap_caches(inode); 2725 nfs_access_zap_cache(inode);
2726 nfs_zap_acl_cache(inode);
2737 return ret; 2727 return ret;
2738} 2728}
2739 2729
@@ -2767,8 +2757,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
2767 task->tk_status = 0; 2757 task->tk_status = 0;
2768 return -EAGAIN; 2758 return -EAGAIN;
2769 case -NFS4ERR_DELAY: 2759 case -NFS4ERR_DELAY:
2770 nfs_inc_server_stats((struct nfs_server *) server, 2760 nfs_inc_server_stats(server, NFSIOS_DELAY);
2771 NFSIOS_DELAY);
2772 case -NFS4ERR_GRACE: 2761 case -NFS4ERR_GRACE:
2773 rpc_delay(task, NFS4_POLL_RETRY_MAX); 2762 rpc_delay(task, NFS4_POLL_RETRY_MAX);
2774 task->tk_status = 0; 2763 task->tk_status = 0;
@@ -2933,7 +2922,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre
2933 2922
2934int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) 2923int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred)
2935{ 2924{
2936 long timeout; 2925 long timeout = 0;
2937 int err; 2926 int err;
2938 do { 2927 do {
2939 err = _nfs4_proc_setclientid_confirm(clp, cred); 2928 err = _nfs4_proc_setclientid_confirm(clp, cred);
@@ -3725,8 +3714,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
3725 .write_done = nfs4_write_done, 3714 .write_done = nfs4_write_done,
3726 .commit_setup = nfs4_proc_commit_setup, 3715 .commit_setup = nfs4_proc_commit_setup,
3727 .commit_done = nfs4_commit_done, 3716 .commit_done = nfs4_commit_done,
3728 .file_open = nfs_open,
3729 .file_release = nfs_release,
3730 .lock = nfs4_proc_lock, 3717 .lock = nfs4_proc_lock,
3731 .clear_acl_cache = nfs4_zap_acl_attr, 3718 .clear_acl_cache = nfs4_zap_acl_attr,
3732}; 3719};