|
@@ -224,35 +224,60 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page,
|
|
|
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
|
|
|
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|
|
int flags, struct nameidata *nd)
|
|
|
{
|
|
|
- struct nfs_fh fhandle;
|
|
|
- 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 nfs_createdata *data;
|
|
|
struct rpc_message msg = {
|
|
|
.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);
|
|
|
+ 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);
|
|
|
nfs_mark_for_revalidate(dir);
|
|
|
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);
|
|
|
return status;
|
|
|
}
|
|
@@ -264,24 +289,12 @@ static int
|
|
|
nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|
|
dev_t rdev)
|
|
|
{
|
|
|
- struct nfs_fh fhandle;
|
|
|
- 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 nfs_createdata *data;
|
|
|
struct rpc_message msg = {
|
|
|
.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);
|
|
|
|
|
@@ -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 */
|
|
|
}
|
|
|
|
|
|
- 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);
|
|
|
nfs_mark_for_revalidate(dir);
|
|
|
|
|
|
if (status == -EINVAL && S_ISFIFO(mode)) {
|
|
|
sattr->ia_mode = mode;
|
|
|
- nfs_fattr_init(&fattr);
|
|
|
+ nfs_fattr_init(data->res.fattr);
|
|
|
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 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);
|
|
|
return status;
|
|
|
}
|
|
@@ -440,31 +460,25 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
|
|
|
static int
|
|
|
nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
|
|
{
|
|
|
- struct nfs_fh fhandle;
|
|
|
- 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 nfs_createdata *data;
|
|
|
struct rpc_message msg = {
|
|
|
.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);
|
|
|
- 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);
|
|
|
nfs_mark_for_revalidate(dir);
|
|
|
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);
|
|
|
return status;
|
|
|
}
|