diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-06-20 15:35:32 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-07-09 12:08:37 -0400 |
commit | 57dc9a5747942f131a1a8b36d661fec6e6a5e9f6 (patch) | |
tree | 853999af6586fcda2da1e3cf49b75ac73b40c7ca /fs/nfs | |
parent | f57e91682d141ea50d8c6d42cdc251b6256a3755 (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.c | 204 |
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 | ||
2082 | struct 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 | |||
2091 | static 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 | |||
2119 | static 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 | |||
2130 | static void nfs4_free_createdata(struct nfs4_createdata *data) | ||
2131 | { | ||
2132 | kfree(data); | ||
2133 | } | ||
2134 | |||
2082 | static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | 2135 | static 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); | 2156 | out: |
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, | |||
2140 | static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | 2174 | static 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); | 2187 | out: |
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, | |||
2242 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | 2254 | static 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); | 2284 | out: |
2293 | status = nfs_instantiate(dentry, &fh, &fattr); | ||
2294 | } | ||
2295 | return status; | 2285 | return status; |
2296 | } | 2286 | } |
2297 | 2287 | ||