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