NFS: Reduce the stack footprint of nfs_proc_create
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
118
fs/nfs/proc.c
118
fs/nfs/proc.c
@@ -224,35 +224,60 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct nfs_createdata {
|
||||||
|
struct nfs_createargs arg;
|
||||||
|
struct nfs_diropok res;
|
||||||
|
struct nfs_fh fhandle;
|
||||||
|
struct nfs_fattr fattr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct nfs_createdata *nfs_alloc_createdata(struct inode *dir,
|
||||||
|
struct dentry *dentry, struct iattr *sattr)
|
||||||
|
{
|
||||||
|
struct nfs_createdata *data;
|
||||||
|
|
||||||
|
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
||||||
|
|
||||||
|
if (data != NULL) {
|
||||||
|
data->arg.fh = NFS_FH(dir);
|
||||||
|
data->arg.name = dentry->d_name.name;
|
||||||
|
data->arg.len = dentry->d_name.len;
|
||||||
|
data->arg.sattr = sattr;
|
||||||
|
nfs_fattr_init(&data->fattr);
|
||||||
|
data->fhandle.size = 0;
|
||||||
|
data->res.fh = &data->fhandle;
|
||||||
|
data->res.fattr = &data->fattr;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void nfs_free_createdata(const struct nfs_createdata *data)
|
||||||
|
{
|
||||||
|
kfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
||||||
int flags, struct nameidata *nd)
|
int flags, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct nfs_fh fhandle;
|
struct nfs_createdata *data;
|
||||||
struct nfs_fattr fattr;
|
|
||||||
struct nfs_createargs arg = {
|
|
||||||
.fh = NFS_FH(dir),
|
|
||||||
.name = dentry->d_name.name,
|
|
||||||
.len = dentry->d_name.len,
|
|
||||||
.sattr = sattr
|
|
||||||
};
|
|
||||||
struct nfs_diropok res = {
|
|
||||||
.fh = &fhandle,
|
|
||||||
.fattr = &fattr
|
|
||||||
};
|
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
.rpc_proc = &nfs_procedures[NFSPROC_CREATE],
|
.rpc_proc = &nfs_procedures[NFSPROC_CREATE],
|
||||||
.rpc_argp = &arg,
|
|
||||||
.rpc_resp = &res,
|
|
||||||
};
|
};
|
||||||
int status;
|
int status = -ENOMEM;
|
||||||
|
|
||||||
nfs_fattr_init(&fattr);
|
|
||||||
dprintk("NFS call create %s\n", dentry->d_name.name);
|
dprintk("NFS call create %s\n", dentry->d_name.name);
|
||||||
|
data = nfs_alloc_createdata(dir, dentry, sattr);
|
||||||
|
if (data == NULL)
|
||||||
|
goto out;
|
||||||
|
msg.rpc_argp = &data->arg;
|
||||||
|
msg.rpc_resp = &data->res;
|
||||||
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
||||||
nfs_mark_for_revalidate(dir);
|
nfs_mark_for_revalidate(dir);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
status = nfs_instantiate(dentry, &fhandle, &fattr);
|
status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
|
||||||
|
nfs_free_createdata(data);
|
||||||
|
out:
|
||||||
dprintk("NFS reply create: %d\n", status);
|
dprintk("NFS reply create: %d\n", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -264,24 +289,12 @@ static int
|
|||||||
nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
||||||
dev_t rdev)
|
dev_t rdev)
|
||||||
{
|
{
|
||||||
struct nfs_fh fhandle;
|
struct nfs_createdata *data;
|
||||||
struct nfs_fattr fattr;
|
|
||||||
struct nfs_createargs arg = {
|
|
||||||
.fh = NFS_FH(dir),
|
|
||||||
.name = dentry->d_name.name,
|
|
||||||
.len = dentry->d_name.len,
|
|
||||||
.sattr = sattr
|
|
||||||
};
|
|
||||||
struct nfs_diropok res = {
|
|
||||||
.fh = &fhandle,
|
|
||||||
.fattr = &fattr
|
|
||||||
};
|
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
.rpc_proc = &nfs_procedures[NFSPROC_CREATE],
|
.rpc_proc = &nfs_procedures[NFSPROC_CREATE],
|
||||||
.rpc_argp = &arg,
|
|
||||||
.rpc_resp = &res,
|
|
||||||
};
|
};
|
||||||
int status, mode;
|
umode_t mode;
|
||||||
|
int status = -ENOMEM;
|
||||||
|
|
||||||
dprintk("NFS call mknod %s\n", dentry->d_name.name);
|
dprintk("NFS call mknod %s\n", dentry->d_name.name);
|
||||||
|
|
||||||
@@ -294,17 +307,24 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|||||||
sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
|
sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
|
||||||
}
|
}
|
||||||
|
|
||||||
nfs_fattr_init(&fattr);
|
data = nfs_alloc_createdata(dir, dentry, sattr);
|
||||||
|
if (data == NULL)
|
||||||
|
goto out;
|
||||||
|
msg.rpc_argp = &data->arg;
|
||||||
|
msg.rpc_resp = &data->res;
|
||||||
|
|
||||||
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
||||||
nfs_mark_for_revalidate(dir);
|
nfs_mark_for_revalidate(dir);
|
||||||
|
|
||||||
if (status == -EINVAL && S_ISFIFO(mode)) {
|
if (status == -EINVAL && S_ISFIFO(mode)) {
|
||||||
sattr->ia_mode = mode;
|
sattr->ia_mode = mode;
|
||||||
nfs_fattr_init(&fattr);
|
nfs_fattr_init(data->res.fattr);
|
||||||
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
||||||
}
|
}
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
status = nfs_instantiate(dentry, &fhandle, &fattr);
|
status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
|
||||||
|
nfs_free_createdata(data);
|
||||||
|
out:
|
||||||
dprintk("NFS reply mknod: %d\n", status);
|
dprintk("NFS reply mknod: %d\n", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -440,31 +460,25 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
|
|||||||
static int
|
static int
|
||||||
nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
||||||
{
|
{
|
||||||
struct nfs_fh fhandle;
|
struct nfs_createdata *data;
|
||||||
struct nfs_fattr fattr;
|
|
||||||
struct nfs_createargs arg = {
|
|
||||||
.fh = NFS_FH(dir),
|
|
||||||
.name = dentry->d_name.name,
|
|
||||||
.len = dentry->d_name.len,
|
|
||||||
.sattr = sattr
|
|
||||||
};
|
|
||||||
struct nfs_diropok res = {
|
|
||||||
.fh = &fhandle,
|
|
||||||
.fattr = &fattr
|
|
||||||
};
|
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
.rpc_proc = &nfs_procedures[NFSPROC_MKDIR],
|
.rpc_proc = &nfs_procedures[NFSPROC_MKDIR],
|
||||||
.rpc_argp = &arg,
|
|
||||||
.rpc_resp = &res,
|
|
||||||
};
|
};
|
||||||
int status;
|
int status = -ENOMEM;
|
||||||
|
|
||||||
dprintk("NFS call mkdir %s\n", dentry->d_name.name);
|
dprintk("NFS call mkdir %s\n", dentry->d_name.name);
|
||||||
nfs_fattr_init(&fattr);
|
data = nfs_alloc_createdata(dir, dentry, sattr);
|
||||||
|
if (data == NULL)
|
||||||
|
goto out;
|
||||||
|
msg.rpc_argp = &data->arg;
|
||||||
|
msg.rpc_resp = &data->res;
|
||||||
|
|
||||||
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
||||||
nfs_mark_for_revalidate(dir);
|
nfs_mark_for_revalidate(dir);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
status = nfs_instantiate(dentry, &fhandle, &fattr);
|
status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
|
||||||
|
nfs_free_createdata(data);
|
||||||
|
out:
|
||||||
dprintk("NFS reply mkdir: %d\n", status);
|
dprintk("NFS reply mkdir: %d\n", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user