aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-06-20 15:35:32 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-09 12:08:37 -0400
commit57dc9a5747942f131a1a8b36d661fec6e6a5e9f6 (patch)
tree853999af6586fcda2da1e3cf49b75ac73b40c7ca /fs/nfs
parentf57e91682d141ea50d8c6d42cdc251b6256a3755 (diff)
NFS: Reduce the stack usage in NFSv4 create operations
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c204
1 files changed, 97 insertions, 107 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1293e0acd82b..26fbeb3467cb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2079,47 +2079,81 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
2079 return err; 2079 return err;
2080} 2080}
2081 2081
2082struct nfs4_createdata {
2083 struct rpc_message msg;
2084 struct nfs4_create_arg arg;
2085 struct nfs4_create_res res;
2086 struct nfs_fh fh;
2087 struct nfs_fattr fattr;
2088 struct nfs_fattr dir_fattr;
2089};
2090
2091static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
2092 struct qstr *name, struct iattr *sattr, u32 ftype)
2093{
2094 struct nfs4_createdata *data;
2095
2096 data = kzalloc(sizeof(*data), GFP_KERNEL);
2097 if (data != NULL) {
2098 struct nfs_server *server = NFS_SERVER(dir);
2099
2100 data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
2101 data->msg.rpc_argp = &data->arg;
2102 data->msg.rpc_resp = &data->res;
2103 data->arg.dir_fh = NFS_FH(dir);
2104 data->arg.server = server;
2105 data->arg.name = name;
2106 data->arg.attrs = sattr;
2107 data->arg.ftype = ftype;
2108 data->arg.bitmask = server->attr_bitmask;
2109 data->res.server = server;
2110 data->res.fh = &data->fh;
2111 data->res.fattr = &data->fattr;
2112 data->res.dir_fattr = &data->dir_fattr;
2113 nfs_fattr_init(data->res.fattr);
2114 nfs_fattr_init(data->res.dir_fattr);
2115 }
2116 return data;
2117}
2118
2119static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
2120{
2121 int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
2122 if (status == 0) {
2123 update_changeattr(dir, &data->res.dir_cinfo);
2124 nfs_post_op_update_inode(dir, data->res.dir_fattr);
2125 status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
2126 }
2127 return status;
2128}
2129
2130static void nfs4_free_createdata(struct nfs4_createdata *data)
2131{
2132 kfree(data);
2133}
2134
2082static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, 2135static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
2083 struct page *page, unsigned int len, struct iattr *sattr) 2136 struct page *page, unsigned int len, struct iattr *sattr)
2084{ 2137{
2085 struct nfs_server *server = NFS_SERVER(dir); 2138 struct nfs4_createdata *data;
2086 struct nfs_fh fhandle; 2139 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 2140
2109 if (len > NFS4_MAXPATHLEN) 2141 if (len > NFS4_MAXPATHLEN)
2110 return -ENAMETOOLONG; 2142 goto out;
2111 2143
2112 arg.u.symlink.pages = &page; 2144 status = -ENOMEM;
2113 arg.u.symlink.len = len; 2145 data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4LNK);
2114 nfs_fattr_init(&fattr); 2146 if (data == NULL)
2115 nfs_fattr_init(&dir_fattr); 2147 goto out;
2148
2149 data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
2150 data->arg.u.symlink.pages = &page;
2151 data->arg.u.symlink.len = len;
2116 2152
2117 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2153 status = nfs4_do_create(dir, dentry, data);
2118 if (!status) { 2154
2119 update_changeattr(dir, &res.dir_cinfo); 2155 nfs4_free_createdata(data);
2120 nfs_post_op_update_inode(dir, res.dir_fattr); 2156out:
2121 status = nfs_instantiate(dentry, &fhandle, &fattr);
2122 }
2123 return status; 2157 return status;
2124} 2158}
2125 2159
@@ -2140,39 +2174,17 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
2140static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, 2174static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
2141 struct iattr *sattr) 2175 struct iattr *sattr)
2142{ 2176{
2143 struct nfs_server *server = NFS_SERVER(dir); 2177 struct nfs4_createdata *data;
2144 struct nfs_fh fhandle; 2178 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 2179
2167 nfs_fattr_init(&fattr); 2180 data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR);
2168 nfs_fattr_init(&dir_fattr); 2181 if (data == NULL)
2169 2182 goto out;
2170 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2183
2171 if (!status) { 2184 status = nfs4_do_create(dir, dentry, data);
2172 update_changeattr(dir, &res.dir_cinfo); 2185
2173 nfs_post_op_update_inode(dir, res.dir_fattr); 2186 nfs4_free_createdata(data);
2174 status = nfs_instantiate(dentry, &fhandle, &fattr); 2187out:
2175 }
2176 return status; 2188 return status;
2177} 2189}
2178 2190
@@ -2242,56 +2254,34 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
2242static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, 2254static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
2243 struct iattr *sattr, dev_t rdev) 2255 struct iattr *sattr, dev_t rdev)
2244{ 2256{
2245 struct nfs_server *server = NFS_SERVER(dir); 2257 struct nfs4_createdata *data;
2246 struct nfs_fh fh; 2258 int mode = sattr->ia_mode;
2247 struct nfs_fattr fattr, dir_fattr; 2259 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 2260
2272 BUG_ON(!(sattr->ia_valid & ATTR_MODE)); 2261 BUG_ON(!(sattr->ia_valid & ATTR_MODE));
2273 BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); 2262 BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
2263
2264 data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
2265 if (data == NULL)
2266 goto out;
2267
2274 if (S_ISFIFO(mode)) 2268 if (S_ISFIFO(mode))
2275 arg.ftype = NF4FIFO; 2269 data->arg.ftype = NF4FIFO;
2276 else if (S_ISBLK(mode)) { 2270 else if (S_ISBLK(mode)) {
2277 arg.ftype = NF4BLK; 2271 data->arg.ftype = NF4BLK;
2278 arg.u.device.specdata1 = MAJOR(rdev); 2272 data->arg.u.device.specdata1 = MAJOR(rdev);
2279 arg.u.device.specdata2 = MINOR(rdev); 2273 data->arg.u.device.specdata2 = MINOR(rdev);
2280 } 2274 }
2281 else if (S_ISCHR(mode)) { 2275 else if (S_ISCHR(mode)) {
2282 arg.ftype = NF4CHR; 2276 data->arg.ftype = NF4CHR;
2283 arg.u.device.specdata1 = MAJOR(rdev); 2277 data->arg.u.device.specdata1 = MAJOR(rdev);
2284 arg.u.device.specdata2 = MINOR(rdev); 2278 data->arg.u.device.specdata2 = MINOR(rdev);
2285 } 2279 }
2286 else
2287 arg.ftype = NF4SOCK;
2288 2280
2289 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2281 status = nfs4_do_create(dir, dentry, data);
2290 if (status == 0) { 2282
2291 update_changeattr(dir, &res.dir_cinfo); 2283 nfs4_free_createdata(data);
2292 nfs_post_op_update_inode(dir, res.dir_fattr); 2284out:
2293 status = nfs_instantiate(dentry, &fh, &fattr);
2294 }
2295 return status; 2285 return status;
2296} 2286}
2297 2287