1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/fs/nfs/nfs3proc.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Client-side NFSv3 procedures stubs.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 1997, Olaf Kirch
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/mm.h>
11*4882a593Smuzhiyun #include <linux/errno.h>
12*4882a593Smuzhiyun #include <linux/string.h>
13*4882a593Smuzhiyun #include <linux/sunrpc/clnt.h>
14*4882a593Smuzhiyun #include <linux/slab.h>
15*4882a593Smuzhiyun #include <linux/nfs.h>
16*4882a593Smuzhiyun #include <linux/nfs3.h>
17*4882a593Smuzhiyun #include <linux/nfs_fs.h>
18*4882a593Smuzhiyun #include <linux/nfs_page.h>
19*4882a593Smuzhiyun #include <linux/lockd/bind.h>
20*4882a593Smuzhiyun #include <linux/nfs_mount.h>
21*4882a593Smuzhiyun #include <linux/freezer.h>
22*4882a593Smuzhiyun #include <linux/xattr.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include "iostat.h"
25*4882a593Smuzhiyun #include "internal.h"
26*4882a593Smuzhiyun #include "nfs3_fs.h"
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define NFSDBG_FACILITY NFSDBG_PROC
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /* A wrapper to handle the EJUKEBOX error messages */
31*4882a593Smuzhiyun static int
nfs3_rpc_wrapper(struct rpc_clnt * clnt,struct rpc_message * msg,int flags)32*4882a593Smuzhiyun nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun int res;
35*4882a593Smuzhiyun do {
36*4882a593Smuzhiyun res = rpc_call_sync(clnt, msg, flags);
37*4882a593Smuzhiyun if (res != -EJUKEBOX)
38*4882a593Smuzhiyun break;
39*4882a593Smuzhiyun freezable_schedule_timeout_killable_unsafe(NFS_JUKEBOX_RETRY_TIME);
40*4882a593Smuzhiyun res = -ERESTARTSYS;
41*4882a593Smuzhiyun } while (!fatal_signal_pending(current));
42*4882a593Smuzhiyun return res;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #define rpc_call_sync(clnt, msg, flags) nfs3_rpc_wrapper(clnt, msg, flags)
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static int
nfs3_async_handle_jukebox(struct rpc_task * task,struct inode * inode)48*4882a593Smuzhiyun nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun if (task->tk_status != -EJUKEBOX)
51*4882a593Smuzhiyun return 0;
52*4882a593Smuzhiyun if (task->tk_status == -EJUKEBOX)
53*4882a593Smuzhiyun nfs_inc_stats(inode, NFSIOS_DELAY);
54*4882a593Smuzhiyun task->tk_status = 0;
55*4882a593Smuzhiyun rpc_restart_call(task);
56*4882a593Smuzhiyun rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
57*4882a593Smuzhiyun return 1;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun static int
do_proc_get_root(struct rpc_clnt * client,struct nfs_fh * fhandle,struct nfs_fsinfo * info)61*4882a593Smuzhiyun do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
62*4882a593Smuzhiyun struct nfs_fsinfo *info)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun struct rpc_message msg = {
65*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
66*4882a593Smuzhiyun .rpc_argp = fhandle,
67*4882a593Smuzhiyun .rpc_resp = info,
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun int status;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun dprintk("%s: call fsinfo\n", __func__);
72*4882a593Smuzhiyun nfs_fattr_init(info->fattr);
73*4882a593Smuzhiyun status = rpc_call_sync(client, &msg, 0);
74*4882a593Smuzhiyun dprintk("%s: reply fsinfo: %d\n", __func__, status);
75*4882a593Smuzhiyun if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) {
76*4882a593Smuzhiyun msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
77*4882a593Smuzhiyun msg.rpc_resp = info->fattr;
78*4882a593Smuzhiyun status = rpc_call_sync(client, &msg, 0);
79*4882a593Smuzhiyun dprintk("%s: reply getattr: %d\n", __func__, status);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun return status;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /*
85*4882a593Smuzhiyun * Bare-bones access to getattr: this is for nfs_get_root/nfs_get_sb
86*4882a593Smuzhiyun */
87*4882a593Smuzhiyun static int
nfs3_proc_get_root(struct nfs_server * server,struct nfs_fh * fhandle,struct nfs_fsinfo * info)88*4882a593Smuzhiyun nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
89*4882a593Smuzhiyun struct nfs_fsinfo *info)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun int status;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun status = do_proc_get_root(server->client, fhandle, info);
94*4882a593Smuzhiyun if (status && server->nfs_client->cl_rpcclient != server->client)
95*4882a593Smuzhiyun status = do_proc_get_root(server->nfs_client->cl_rpcclient, fhandle, info);
96*4882a593Smuzhiyun return status;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun * One function for each procedure in the NFS protocol.
101*4882a593Smuzhiyun */
102*4882a593Smuzhiyun static int
nfs3_proc_getattr(struct nfs_server * server,struct nfs_fh * fhandle,struct nfs_fattr * fattr,struct nfs4_label * label,struct inode * inode)103*4882a593Smuzhiyun nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
104*4882a593Smuzhiyun struct nfs_fattr *fattr, struct nfs4_label *label,
105*4882a593Smuzhiyun struct inode *inode)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun struct rpc_message msg = {
108*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR],
109*4882a593Smuzhiyun .rpc_argp = fhandle,
110*4882a593Smuzhiyun .rpc_resp = fattr,
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun int status;
113*4882a593Smuzhiyun unsigned short task_flags = 0;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* Is this is an attribute revalidation, subject to softreval? */
116*4882a593Smuzhiyun if (inode && (server->flags & NFS_MOUNT_SOFTREVAL))
117*4882a593Smuzhiyun task_flags |= RPC_TASK_TIMEOUT;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun dprintk("NFS call getattr\n");
120*4882a593Smuzhiyun nfs_fattr_init(fattr);
121*4882a593Smuzhiyun status = rpc_call_sync(server->client, &msg, task_flags);
122*4882a593Smuzhiyun dprintk("NFS reply getattr: %d\n", status);
123*4882a593Smuzhiyun return status;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun static int
nfs3_proc_setattr(struct dentry * dentry,struct nfs_fattr * fattr,struct iattr * sattr)127*4882a593Smuzhiyun nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
128*4882a593Smuzhiyun struct iattr *sattr)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun struct inode *inode = d_inode(dentry);
131*4882a593Smuzhiyun struct nfs3_sattrargs arg = {
132*4882a593Smuzhiyun .fh = NFS_FH(inode),
133*4882a593Smuzhiyun .sattr = sattr,
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun struct rpc_message msg = {
136*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_SETATTR],
137*4882a593Smuzhiyun .rpc_argp = &arg,
138*4882a593Smuzhiyun .rpc_resp = fattr,
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun int status;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun dprintk("NFS call setattr\n");
143*4882a593Smuzhiyun if (sattr->ia_valid & ATTR_FILE)
144*4882a593Smuzhiyun msg.rpc_cred = nfs_file_cred(sattr->ia_file);
145*4882a593Smuzhiyun nfs_fattr_init(fattr);
146*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
147*4882a593Smuzhiyun if (status == 0) {
148*4882a593Smuzhiyun nfs_setattr_update_inode(inode, sattr, fattr);
149*4882a593Smuzhiyun if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
150*4882a593Smuzhiyun nfs_zap_acl_cache(inode);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun dprintk("NFS reply setattr: %d\n", status);
153*4882a593Smuzhiyun return status;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun static int
nfs3_proc_lookup(struct inode * dir,struct dentry * dentry,struct nfs_fh * fhandle,struct nfs_fattr * fattr,struct nfs4_label * label)157*4882a593Smuzhiyun nfs3_proc_lookup(struct inode *dir, struct dentry *dentry,
158*4882a593Smuzhiyun struct nfs_fh *fhandle, struct nfs_fattr *fattr,
159*4882a593Smuzhiyun struct nfs4_label *label)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun struct nfs3_diropargs arg = {
162*4882a593Smuzhiyun .fh = NFS_FH(dir),
163*4882a593Smuzhiyun .name = dentry->d_name.name,
164*4882a593Smuzhiyun .len = dentry->d_name.len
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun struct nfs3_diropres res = {
167*4882a593Smuzhiyun .fh = fhandle,
168*4882a593Smuzhiyun .fattr = fattr
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun struct rpc_message msg = {
171*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_LOOKUP],
172*4882a593Smuzhiyun .rpc_argp = &arg,
173*4882a593Smuzhiyun .rpc_resp = &res,
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun int status;
176*4882a593Smuzhiyun unsigned short task_flags = 0;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun /* Is this is an attribute revalidation, subject to softreval? */
179*4882a593Smuzhiyun if (nfs_lookup_is_soft_revalidate(dentry))
180*4882a593Smuzhiyun task_flags |= RPC_TASK_TIMEOUT;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun res.dir_attr = nfs_alloc_fattr();
183*4882a593Smuzhiyun if (res.dir_attr == NULL)
184*4882a593Smuzhiyun return -ENOMEM;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun dprintk("NFS call lookup %pd2\n", dentry);
187*4882a593Smuzhiyun nfs_fattr_init(fattr);
188*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags);
189*4882a593Smuzhiyun nfs_refresh_inode(dir, res.dir_attr);
190*4882a593Smuzhiyun if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
191*4882a593Smuzhiyun msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
192*4882a593Smuzhiyun msg.rpc_argp = fhandle;
193*4882a593Smuzhiyun msg.rpc_resp = fattr;
194*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun nfs_free_fattr(res.dir_attr);
197*4882a593Smuzhiyun dprintk("NFS reply lookup: %d\n", status);
198*4882a593Smuzhiyun return status;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
nfs3_proc_access(struct inode * inode,struct nfs_access_entry * entry)201*4882a593Smuzhiyun static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun struct nfs3_accessargs arg = {
204*4882a593Smuzhiyun .fh = NFS_FH(inode),
205*4882a593Smuzhiyun .access = entry->mask,
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun struct nfs3_accessres res;
208*4882a593Smuzhiyun struct rpc_message msg = {
209*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
210*4882a593Smuzhiyun .rpc_argp = &arg,
211*4882a593Smuzhiyun .rpc_resp = &res,
212*4882a593Smuzhiyun .rpc_cred = entry->cred,
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun int status = -ENOMEM;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun dprintk("NFS call access\n");
217*4882a593Smuzhiyun res.fattr = nfs_alloc_fattr();
218*4882a593Smuzhiyun if (res.fattr == NULL)
219*4882a593Smuzhiyun goto out;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
222*4882a593Smuzhiyun nfs_refresh_inode(inode, res.fattr);
223*4882a593Smuzhiyun if (status == 0)
224*4882a593Smuzhiyun nfs_access_set_mask(entry, res.access);
225*4882a593Smuzhiyun nfs_free_fattr(res.fattr);
226*4882a593Smuzhiyun out:
227*4882a593Smuzhiyun dprintk("NFS reply access: %d\n", status);
228*4882a593Smuzhiyun return status;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
nfs3_proc_readlink(struct inode * inode,struct page * page,unsigned int pgbase,unsigned int pglen)231*4882a593Smuzhiyun static int nfs3_proc_readlink(struct inode *inode, struct page *page,
232*4882a593Smuzhiyun unsigned int pgbase, unsigned int pglen)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun struct nfs_fattr *fattr;
235*4882a593Smuzhiyun struct nfs3_readlinkargs args = {
236*4882a593Smuzhiyun .fh = NFS_FH(inode),
237*4882a593Smuzhiyun .pgbase = pgbase,
238*4882a593Smuzhiyun .pglen = pglen,
239*4882a593Smuzhiyun .pages = &page
240*4882a593Smuzhiyun };
241*4882a593Smuzhiyun struct rpc_message msg = {
242*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_READLINK],
243*4882a593Smuzhiyun .rpc_argp = &args,
244*4882a593Smuzhiyun };
245*4882a593Smuzhiyun int status = -ENOMEM;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun dprintk("NFS call readlink\n");
248*4882a593Smuzhiyun fattr = nfs_alloc_fattr();
249*4882a593Smuzhiyun if (fattr == NULL)
250*4882a593Smuzhiyun goto out;
251*4882a593Smuzhiyun msg.rpc_resp = fattr;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
254*4882a593Smuzhiyun nfs_refresh_inode(inode, fattr);
255*4882a593Smuzhiyun nfs_free_fattr(fattr);
256*4882a593Smuzhiyun out:
257*4882a593Smuzhiyun dprintk("NFS reply readlink: %d\n", status);
258*4882a593Smuzhiyun return status;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun struct nfs3_createdata {
262*4882a593Smuzhiyun struct rpc_message msg;
263*4882a593Smuzhiyun union {
264*4882a593Smuzhiyun struct nfs3_createargs create;
265*4882a593Smuzhiyun struct nfs3_mkdirargs mkdir;
266*4882a593Smuzhiyun struct nfs3_symlinkargs symlink;
267*4882a593Smuzhiyun struct nfs3_mknodargs mknod;
268*4882a593Smuzhiyun } arg;
269*4882a593Smuzhiyun struct nfs3_diropres res;
270*4882a593Smuzhiyun struct nfs_fh fh;
271*4882a593Smuzhiyun struct nfs_fattr fattr;
272*4882a593Smuzhiyun struct nfs_fattr dir_attr;
273*4882a593Smuzhiyun };
274*4882a593Smuzhiyun
nfs3_alloc_createdata(void)275*4882a593Smuzhiyun static struct nfs3_createdata *nfs3_alloc_createdata(void)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct nfs3_createdata *data;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun data = kzalloc(sizeof(*data), GFP_KERNEL);
280*4882a593Smuzhiyun if (data != NULL) {
281*4882a593Smuzhiyun data->msg.rpc_argp = &data->arg;
282*4882a593Smuzhiyun data->msg.rpc_resp = &data->res;
283*4882a593Smuzhiyun data->res.fh = &data->fh;
284*4882a593Smuzhiyun data->res.fattr = &data->fattr;
285*4882a593Smuzhiyun data->res.dir_attr = &data->dir_attr;
286*4882a593Smuzhiyun nfs_fattr_init(data->res.fattr);
287*4882a593Smuzhiyun nfs_fattr_init(data->res.dir_attr);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun return data;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static struct dentry *
nfs3_do_create(struct inode * dir,struct dentry * dentry,struct nfs3_createdata * data)293*4882a593Smuzhiyun nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_createdata *data)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun int status;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
298*4882a593Smuzhiyun nfs_post_op_update_inode(dir, data->res.dir_attr);
299*4882a593Smuzhiyun if (status != 0)
300*4882a593Smuzhiyun return ERR_PTR(status);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun return nfs_add_or_obtain(dentry, data->res.fh, data->res.fattr, NULL);
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
nfs3_free_createdata(struct nfs3_createdata * data)305*4882a593Smuzhiyun static void nfs3_free_createdata(struct nfs3_createdata *data)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun kfree(data);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun /*
311*4882a593Smuzhiyun * Create a regular file.
312*4882a593Smuzhiyun */
313*4882a593Smuzhiyun static int
nfs3_proc_create(struct inode * dir,struct dentry * dentry,struct iattr * sattr,int flags)314*4882a593Smuzhiyun nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
315*4882a593Smuzhiyun int flags)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun struct posix_acl *default_acl, *acl;
318*4882a593Smuzhiyun struct nfs3_createdata *data;
319*4882a593Smuzhiyun struct dentry *d_alias;
320*4882a593Smuzhiyun int status = -ENOMEM;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun dprintk("NFS call create %pd\n", dentry);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun data = nfs3_alloc_createdata();
325*4882a593Smuzhiyun if (data == NULL)
326*4882a593Smuzhiyun goto out;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_CREATE];
329*4882a593Smuzhiyun data->arg.create.fh = NFS_FH(dir);
330*4882a593Smuzhiyun data->arg.create.name = dentry->d_name.name;
331*4882a593Smuzhiyun data->arg.create.len = dentry->d_name.len;
332*4882a593Smuzhiyun data->arg.create.sattr = sattr;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
335*4882a593Smuzhiyun if (flags & O_EXCL) {
336*4882a593Smuzhiyun data->arg.create.createmode = NFS3_CREATE_EXCLUSIVE;
337*4882a593Smuzhiyun data->arg.create.verifier[0] = cpu_to_be32(jiffies);
338*4882a593Smuzhiyun data->arg.create.verifier[1] = cpu_to_be32(current->pid);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
342*4882a593Smuzhiyun if (status)
343*4882a593Smuzhiyun goto out;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun for (;;) {
346*4882a593Smuzhiyun d_alias = nfs3_do_create(dir, dentry, data);
347*4882a593Smuzhiyun status = PTR_ERR_OR_ZERO(d_alias);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun if (status != -ENOTSUPP)
350*4882a593Smuzhiyun break;
351*4882a593Smuzhiyun /* If the server doesn't support the exclusive creation
352*4882a593Smuzhiyun * semantics, try again with simple 'guarded' mode. */
353*4882a593Smuzhiyun switch (data->arg.create.createmode) {
354*4882a593Smuzhiyun case NFS3_CREATE_EXCLUSIVE:
355*4882a593Smuzhiyun data->arg.create.createmode = NFS3_CREATE_GUARDED;
356*4882a593Smuzhiyun break;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun case NFS3_CREATE_GUARDED:
359*4882a593Smuzhiyun data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
360*4882a593Smuzhiyun break;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun case NFS3_CREATE_UNCHECKED:
363*4882a593Smuzhiyun goto out_release_acls;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun nfs_fattr_init(data->res.dir_attr);
366*4882a593Smuzhiyun nfs_fattr_init(data->res.fattr);
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun if (status != 0)
370*4882a593Smuzhiyun goto out_release_acls;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun if (d_alias)
373*4882a593Smuzhiyun dentry = d_alias;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun /* When we created the file with exclusive semantics, make
376*4882a593Smuzhiyun * sure we set the attributes afterwards. */
377*4882a593Smuzhiyun if (data->arg.create.createmode == NFS3_CREATE_EXCLUSIVE) {
378*4882a593Smuzhiyun dprintk("NFS call setattr (post-create)\n");
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (!(sattr->ia_valid & ATTR_ATIME_SET))
381*4882a593Smuzhiyun sattr->ia_valid |= ATTR_ATIME;
382*4882a593Smuzhiyun if (!(sattr->ia_valid & ATTR_MTIME_SET))
383*4882a593Smuzhiyun sattr->ia_valid |= ATTR_MTIME;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun /* Note: we could use a guarded setattr here, but I'm
386*4882a593Smuzhiyun * not sure this buys us anything (and I'd have
387*4882a593Smuzhiyun * to revamp the NFSv3 XDR code) */
388*4882a593Smuzhiyun status = nfs3_proc_setattr(dentry, data->res.fattr, sattr);
389*4882a593Smuzhiyun nfs_post_op_update_inode(d_inode(dentry), data->res.fattr);
390*4882a593Smuzhiyun dprintk("NFS reply setattr (post-create): %d\n", status);
391*4882a593Smuzhiyun if (status != 0)
392*4882a593Smuzhiyun goto out_dput;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun out_dput:
398*4882a593Smuzhiyun dput(d_alias);
399*4882a593Smuzhiyun out_release_acls:
400*4882a593Smuzhiyun posix_acl_release(acl);
401*4882a593Smuzhiyun posix_acl_release(default_acl);
402*4882a593Smuzhiyun out:
403*4882a593Smuzhiyun nfs3_free_createdata(data);
404*4882a593Smuzhiyun dprintk("NFS reply create: %d\n", status);
405*4882a593Smuzhiyun return status;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun static int
nfs3_proc_remove(struct inode * dir,struct dentry * dentry)409*4882a593Smuzhiyun nfs3_proc_remove(struct inode *dir, struct dentry *dentry)
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun struct nfs_removeargs arg = {
412*4882a593Smuzhiyun .fh = NFS_FH(dir),
413*4882a593Smuzhiyun .name = dentry->d_name,
414*4882a593Smuzhiyun };
415*4882a593Smuzhiyun struct nfs_removeres res;
416*4882a593Smuzhiyun struct rpc_message msg = {
417*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE],
418*4882a593Smuzhiyun .rpc_argp = &arg,
419*4882a593Smuzhiyun .rpc_resp = &res,
420*4882a593Smuzhiyun };
421*4882a593Smuzhiyun int status = -ENOMEM;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun dprintk("NFS call remove %pd2\n", dentry);
424*4882a593Smuzhiyun res.dir_attr = nfs_alloc_fattr();
425*4882a593Smuzhiyun if (res.dir_attr == NULL)
426*4882a593Smuzhiyun goto out;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
429*4882a593Smuzhiyun nfs_post_op_update_inode(dir, res.dir_attr);
430*4882a593Smuzhiyun nfs_free_fattr(res.dir_attr);
431*4882a593Smuzhiyun out:
432*4882a593Smuzhiyun dprintk("NFS reply remove: %d\n", status);
433*4882a593Smuzhiyun return status;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun static void
nfs3_proc_unlink_setup(struct rpc_message * msg,struct dentry * dentry,struct inode * inode)437*4882a593Smuzhiyun nfs3_proc_unlink_setup(struct rpc_message *msg,
438*4882a593Smuzhiyun struct dentry *dentry,
439*4882a593Smuzhiyun struct inode *inode)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
nfs3_proc_unlink_rpc_prepare(struct rpc_task * task,struct nfs_unlinkdata * data)444*4882a593Smuzhiyun static void nfs3_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun rpc_call_start(task);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun static int
nfs3_proc_unlink_done(struct rpc_task * task,struct inode * dir)450*4882a593Smuzhiyun nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun struct nfs_removeres *res;
453*4882a593Smuzhiyun if (nfs3_async_handle_jukebox(task, dir))
454*4882a593Smuzhiyun return 0;
455*4882a593Smuzhiyun res = task->tk_msg.rpc_resp;
456*4882a593Smuzhiyun nfs_post_op_update_inode(dir, res->dir_attr);
457*4882a593Smuzhiyun return 1;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun static void
nfs3_proc_rename_setup(struct rpc_message * msg,struct dentry * old_dentry,struct dentry * new_dentry)461*4882a593Smuzhiyun nfs3_proc_rename_setup(struct rpc_message *msg,
462*4882a593Smuzhiyun struct dentry *old_dentry,
463*4882a593Smuzhiyun struct dentry *new_dentry)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
nfs3_proc_rename_rpc_prepare(struct rpc_task * task,struct nfs_renamedata * data)468*4882a593Smuzhiyun static void nfs3_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun rpc_call_start(task);
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun static int
nfs3_proc_rename_done(struct rpc_task * task,struct inode * old_dir,struct inode * new_dir)474*4882a593Smuzhiyun nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
475*4882a593Smuzhiyun struct inode *new_dir)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun struct nfs_renameres *res;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (nfs3_async_handle_jukebox(task, old_dir))
480*4882a593Smuzhiyun return 0;
481*4882a593Smuzhiyun res = task->tk_msg.rpc_resp;
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun nfs_post_op_update_inode(old_dir, res->old_fattr);
484*4882a593Smuzhiyun nfs_post_op_update_inode(new_dir, res->new_fattr);
485*4882a593Smuzhiyun return 1;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun static int
nfs3_proc_link(struct inode * inode,struct inode * dir,const struct qstr * name)489*4882a593Smuzhiyun nfs3_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun struct nfs3_linkargs arg = {
492*4882a593Smuzhiyun .fromfh = NFS_FH(inode),
493*4882a593Smuzhiyun .tofh = NFS_FH(dir),
494*4882a593Smuzhiyun .toname = name->name,
495*4882a593Smuzhiyun .tolen = name->len
496*4882a593Smuzhiyun };
497*4882a593Smuzhiyun struct nfs3_linkres res;
498*4882a593Smuzhiyun struct rpc_message msg = {
499*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_LINK],
500*4882a593Smuzhiyun .rpc_argp = &arg,
501*4882a593Smuzhiyun .rpc_resp = &res,
502*4882a593Smuzhiyun };
503*4882a593Smuzhiyun int status = -ENOMEM;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun dprintk("NFS call link %s\n", name->name);
506*4882a593Smuzhiyun res.fattr = nfs_alloc_fattr();
507*4882a593Smuzhiyun res.dir_attr = nfs_alloc_fattr();
508*4882a593Smuzhiyun if (res.fattr == NULL || res.dir_attr == NULL)
509*4882a593Smuzhiyun goto out;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
512*4882a593Smuzhiyun nfs_post_op_update_inode(dir, res.dir_attr);
513*4882a593Smuzhiyun nfs_post_op_update_inode(inode, res.fattr);
514*4882a593Smuzhiyun out:
515*4882a593Smuzhiyun nfs_free_fattr(res.dir_attr);
516*4882a593Smuzhiyun nfs_free_fattr(res.fattr);
517*4882a593Smuzhiyun dprintk("NFS reply link: %d\n", status);
518*4882a593Smuzhiyun return status;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun static int
nfs3_proc_symlink(struct inode * dir,struct dentry * dentry,struct page * page,unsigned int len,struct iattr * sattr)522*4882a593Smuzhiyun nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
523*4882a593Smuzhiyun unsigned int len, struct iattr *sattr)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun struct nfs3_createdata *data;
526*4882a593Smuzhiyun struct dentry *d_alias;
527*4882a593Smuzhiyun int status = -ENOMEM;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun if (len > NFS3_MAXPATHLEN)
530*4882a593Smuzhiyun return -ENAMETOOLONG;
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun dprintk("NFS call symlink %pd\n", dentry);
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun data = nfs3_alloc_createdata();
535*4882a593Smuzhiyun if (data == NULL)
536*4882a593Smuzhiyun goto out;
537*4882a593Smuzhiyun data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK];
538*4882a593Smuzhiyun data->arg.symlink.fromfh = NFS_FH(dir);
539*4882a593Smuzhiyun data->arg.symlink.fromname = dentry->d_name.name;
540*4882a593Smuzhiyun data->arg.symlink.fromlen = dentry->d_name.len;
541*4882a593Smuzhiyun data->arg.symlink.pages = &page;
542*4882a593Smuzhiyun data->arg.symlink.pathlen = len;
543*4882a593Smuzhiyun data->arg.symlink.sattr = sattr;
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun d_alias = nfs3_do_create(dir, dentry, data);
546*4882a593Smuzhiyun status = PTR_ERR_OR_ZERO(d_alias);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if (status == 0)
549*4882a593Smuzhiyun dput(d_alias);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun nfs3_free_createdata(data);
552*4882a593Smuzhiyun out:
553*4882a593Smuzhiyun dprintk("NFS reply symlink: %d\n", status);
554*4882a593Smuzhiyun return status;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun static int
nfs3_proc_mkdir(struct inode * dir,struct dentry * dentry,struct iattr * sattr)558*4882a593Smuzhiyun nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun struct posix_acl *default_acl, *acl;
561*4882a593Smuzhiyun struct nfs3_createdata *data;
562*4882a593Smuzhiyun struct dentry *d_alias;
563*4882a593Smuzhiyun int status = -ENOMEM;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun dprintk("NFS call mkdir %pd\n", dentry);
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun data = nfs3_alloc_createdata();
568*4882a593Smuzhiyun if (data == NULL)
569*4882a593Smuzhiyun goto out;
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
572*4882a593Smuzhiyun if (status)
573*4882a593Smuzhiyun goto out;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR];
576*4882a593Smuzhiyun data->arg.mkdir.fh = NFS_FH(dir);
577*4882a593Smuzhiyun data->arg.mkdir.name = dentry->d_name.name;
578*4882a593Smuzhiyun data->arg.mkdir.len = dentry->d_name.len;
579*4882a593Smuzhiyun data->arg.mkdir.sattr = sattr;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun d_alias = nfs3_do_create(dir, dentry, data);
582*4882a593Smuzhiyun status = PTR_ERR_OR_ZERO(d_alias);
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun if (status != 0)
585*4882a593Smuzhiyun goto out_release_acls;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun if (d_alias)
588*4882a593Smuzhiyun dentry = d_alias;
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun dput(d_alias);
593*4882a593Smuzhiyun out_release_acls:
594*4882a593Smuzhiyun posix_acl_release(acl);
595*4882a593Smuzhiyun posix_acl_release(default_acl);
596*4882a593Smuzhiyun out:
597*4882a593Smuzhiyun nfs3_free_createdata(data);
598*4882a593Smuzhiyun dprintk("NFS reply mkdir: %d\n", status);
599*4882a593Smuzhiyun return status;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun static int
nfs3_proc_rmdir(struct inode * dir,const struct qstr * name)603*4882a593Smuzhiyun nfs3_proc_rmdir(struct inode *dir, const struct qstr *name)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun struct nfs_fattr *dir_attr;
606*4882a593Smuzhiyun struct nfs3_diropargs arg = {
607*4882a593Smuzhiyun .fh = NFS_FH(dir),
608*4882a593Smuzhiyun .name = name->name,
609*4882a593Smuzhiyun .len = name->len
610*4882a593Smuzhiyun };
611*4882a593Smuzhiyun struct rpc_message msg = {
612*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR],
613*4882a593Smuzhiyun .rpc_argp = &arg,
614*4882a593Smuzhiyun };
615*4882a593Smuzhiyun int status = -ENOMEM;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun dprintk("NFS call rmdir %s\n", name->name);
618*4882a593Smuzhiyun dir_attr = nfs_alloc_fattr();
619*4882a593Smuzhiyun if (dir_attr == NULL)
620*4882a593Smuzhiyun goto out;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun msg.rpc_resp = dir_attr;
623*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
624*4882a593Smuzhiyun nfs_post_op_update_inode(dir, dir_attr);
625*4882a593Smuzhiyun nfs_free_fattr(dir_attr);
626*4882a593Smuzhiyun out:
627*4882a593Smuzhiyun dprintk("NFS reply rmdir: %d\n", status);
628*4882a593Smuzhiyun return status;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun /*
632*4882a593Smuzhiyun * The READDIR implementation is somewhat hackish - we pass the user buffer
633*4882a593Smuzhiyun * to the encode function, which installs it in the receive iovec.
634*4882a593Smuzhiyun * The decode function itself doesn't perform any decoding, it just makes
635*4882a593Smuzhiyun * sure the reply is syntactically correct.
636*4882a593Smuzhiyun *
637*4882a593Smuzhiyun * Also note that this implementation handles both plain readdir and
638*4882a593Smuzhiyun * readdirplus.
639*4882a593Smuzhiyun */
640*4882a593Smuzhiyun static int
nfs3_proc_readdir(struct dentry * dentry,const struct cred * cred,u64 cookie,struct page ** pages,unsigned int count,bool plus)641*4882a593Smuzhiyun nfs3_proc_readdir(struct dentry *dentry, const struct cred *cred,
642*4882a593Smuzhiyun u64 cookie, struct page **pages, unsigned int count, bool plus)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun struct inode *dir = d_inode(dentry);
645*4882a593Smuzhiyun __be32 *verf = NFS_I(dir)->cookieverf;
646*4882a593Smuzhiyun struct nfs3_readdirargs arg = {
647*4882a593Smuzhiyun .fh = NFS_FH(dir),
648*4882a593Smuzhiyun .cookie = cookie,
649*4882a593Smuzhiyun .verf = {verf[0], verf[1]},
650*4882a593Smuzhiyun .plus = plus,
651*4882a593Smuzhiyun .count = count,
652*4882a593Smuzhiyun .pages = pages
653*4882a593Smuzhiyun };
654*4882a593Smuzhiyun struct nfs3_readdirres res = {
655*4882a593Smuzhiyun .verf = verf,
656*4882a593Smuzhiyun .plus = plus
657*4882a593Smuzhiyun };
658*4882a593Smuzhiyun struct rpc_message msg = {
659*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_READDIR],
660*4882a593Smuzhiyun .rpc_argp = &arg,
661*4882a593Smuzhiyun .rpc_resp = &res,
662*4882a593Smuzhiyun .rpc_cred = cred,
663*4882a593Smuzhiyun };
664*4882a593Smuzhiyun int status = -ENOMEM;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun if (plus)
667*4882a593Smuzhiyun msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun dprintk("NFS call readdir%s %d\n",
670*4882a593Smuzhiyun plus? "plus" : "", (unsigned int) cookie);
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun res.dir_attr = nfs_alloc_fattr();
673*4882a593Smuzhiyun if (res.dir_attr == NULL)
674*4882a593Smuzhiyun goto out;
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun nfs_invalidate_atime(dir);
679*4882a593Smuzhiyun nfs_refresh_inode(dir, res.dir_attr);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun nfs_free_fattr(res.dir_attr);
682*4882a593Smuzhiyun out:
683*4882a593Smuzhiyun dprintk("NFS reply readdir%s: %d\n",
684*4882a593Smuzhiyun plus? "plus" : "", status);
685*4882a593Smuzhiyun return status;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun static int
nfs3_proc_mknod(struct inode * dir,struct dentry * dentry,struct iattr * sattr,dev_t rdev)689*4882a593Smuzhiyun nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
690*4882a593Smuzhiyun dev_t rdev)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun struct posix_acl *default_acl, *acl;
693*4882a593Smuzhiyun struct nfs3_createdata *data;
694*4882a593Smuzhiyun struct dentry *d_alias;
695*4882a593Smuzhiyun int status = -ENOMEM;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun dprintk("NFS call mknod %pd %u:%u\n", dentry,
698*4882a593Smuzhiyun MAJOR(rdev), MINOR(rdev));
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun data = nfs3_alloc_createdata();
701*4882a593Smuzhiyun if (data == NULL)
702*4882a593Smuzhiyun goto out;
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
705*4882a593Smuzhiyun if (status)
706*4882a593Smuzhiyun goto out;
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD];
709*4882a593Smuzhiyun data->arg.mknod.fh = NFS_FH(dir);
710*4882a593Smuzhiyun data->arg.mknod.name = dentry->d_name.name;
711*4882a593Smuzhiyun data->arg.mknod.len = dentry->d_name.len;
712*4882a593Smuzhiyun data->arg.mknod.sattr = sattr;
713*4882a593Smuzhiyun data->arg.mknod.rdev = rdev;
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun switch (sattr->ia_mode & S_IFMT) {
716*4882a593Smuzhiyun case S_IFBLK:
717*4882a593Smuzhiyun data->arg.mknod.type = NF3BLK;
718*4882a593Smuzhiyun break;
719*4882a593Smuzhiyun case S_IFCHR:
720*4882a593Smuzhiyun data->arg.mknod.type = NF3CHR;
721*4882a593Smuzhiyun break;
722*4882a593Smuzhiyun case S_IFIFO:
723*4882a593Smuzhiyun data->arg.mknod.type = NF3FIFO;
724*4882a593Smuzhiyun break;
725*4882a593Smuzhiyun case S_IFSOCK:
726*4882a593Smuzhiyun data->arg.mknod.type = NF3SOCK;
727*4882a593Smuzhiyun break;
728*4882a593Smuzhiyun default:
729*4882a593Smuzhiyun status = -EINVAL;
730*4882a593Smuzhiyun goto out_release_acls;
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun d_alias = nfs3_do_create(dir, dentry, data);
734*4882a593Smuzhiyun status = PTR_ERR_OR_ZERO(d_alias);
735*4882a593Smuzhiyun if (status != 0)
736*4882a593Smuzhiyun goto out_release_acls;
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun if (d_alias)
739*4882a593Smuzhiyun dentry = d_alias;
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun dput(d_alias);
744*4882a593Smuzhiyun out_release_acls:
745*4882a593Smuzhiyun posix_acl_release(acl);
746*4882a593Smuzhiyun posix_acl_release(default_acl);
747*4882a593Smuzhiyun out:
748*4882a593Smuzhiyun nfs3_free_createdata(data);
749*4882a593Smuzhiyun dprintk("NFS reply mknod: %d\n", status);
750*4882a593Smuzhiyun return status;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun static int
nfs3_proc_statfs(struct nfs_server * server,struct nfs_fh * fhandle,struct nfs_fsstat * stat)754*4882a593Smuzhiyun nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
755*4882a593Smuzhiyun struct nfs_fsstat *stat)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun struct rpc_message msg = {
758*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_FSSTAT],
759*4882a593Smuzhiyun .rpc_argp = fhandle,
760*4882a593Smuzhiyun .rpc_resp = stat,
761*4882a593Smuzhiyun };
762*4882a593Smuzhiyun int status;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun dprintk("NFS call fsstat\n");
765*4882a593Smuzhiyun nfs_fattr_init(stat->fattr);
766*4882a593Smuzhiyun status = rpc_call_sync(server->client, &msg, 0);
767*4882a593Smuzhiyun dprintk("NFS reply fsstat: %d\n", status);
768*4882a593Smuzhiyun return status;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun static int
do_proc_fsinfo(struct rpc_clnt * client,struct nfs_fh * fhandle,struct nfs_fsinfo * info)772*4882a593Smuzhiyun do_proc_fsinfo(struct rpc_clnt *client, struct nfs_fh *fhandle,
773*4882a593Smuzhiyun struct nfs_fsinfo *info)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun struct rpc_message msg = {
776*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
777*4882a593Smuzhiyun .rpc_argp = fhandle,
778*4882a593Smuzhiyun .rpc_resp = info,
779*4882a593Smuzhiyun };
780*4882a593Smuzhiyun int status;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun dprintk("NFS call fsinfo\n");
783*4882a593Smuzhiyun nfs_fattr_init(info->fattr);
784*4882a593Smuzhiyun status = rpc_call_sync(client, &msg, 0);
785*4882a593Smuzhiyun dprintk("NFS reply fsinfo: %d\n", status);
786*4882a593Smuzhiyun return status;
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun /*
790*4882a593Smuzhiyun * Bare-bones access to fsinfo: this is for nfs_get_root/nfs_get_sb via
791*4882a593Smuzhiyun * nfs_create_server
792*4882a593Smuzhiyun */
793*4882a593Smuzhiyun static int
nfs3_proc_fsinfo(struct nfs_server * server,struct nfs_fh * fhandle,struct nfs_fsinfo * info)794*4882a593Smuzhiyun nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
795*4882a593Smuzhiyun struct nfs_fsinfo *info)
796*4882a593Smuzhiyun {
797*4882a593Smuzhiyun int status;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun status = do_proc_fsinfo(server->client, fhandle, info);
800*4882a593Smuzhiyun if (status && server->nfs_client->cl_rpcclient != server->client)
801*4882a593Smuzhiyun status = do_proc_fsinfo(server->nfs_client->cl_rpcclient, fhandle, info);
802*4882a593Smuzhiyun return status;
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun static int
nfs3_proc_pathconf(struct nfs_server * server,struct nfs_fh * fhandle,struct nfs_pathconf * info)806*4882a593Smuzhiyun nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
807*4882a593Smuzhiyun struct nfs_pathconf *info)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun struct rpc_message msg = {
810*4882a593Smuzhiyun .rpc_proc = &nfs3_procedures[NFS3PROC_PATHCONF],
811*4882a593Smuzhiyun .rpc_argp = fhandle,
812*4882a593Smuzhiyun .rpc_resp = info,
813*4882a593Smuzhiyun };
814*4882a593Smuzhiyun int status;
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun dprintk("NFS call pathconf\n");
817*4882a593Smuzhiyun nfs_fattr_init(info->fattr);
818*4882a593Smuzhiyun status = rpc_call_sync(server->client, &msg, 0);
819*4882a593Smuzhiyun dprintk("NFS reply pathconf: %d\n", status);
820*4882a593Smuzhiyun return status;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun
nfs3_read_done(struct rpc_task * task,struct nfs_pgio_header * hdr)823*4882a593Smuzhiyun static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
824*4882a593Smuzhiyun {
825*4882a593Smuzhiyun struct inode *inode = hdr->inode;
826*4882a593Smuzhiyun struct nfs_server *server = NFS_SERVER(inode);
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun if (hdr->pgio_done_cb != NULL)
829*4882a593Smuzhiyun return hdr->pgio_done_cb(task, hdr);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun if (nfs3_async_handle_jukebox(task, inode))
832*4882a593Smuzhiyun return -EAGAIN;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun if (task->tk_status >= 0 && !server->read_hdrsize)
835*4882a593Smuzhiyun cmpxchg(&server->read_hdrsize, 0, hdr->res.replen);
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun nfs_invalidate_atime(inode);
838*4882a593Smuzhiyun nfs_refresh_inode(inode, &hdr->fattr);
839*4882a593Smuzhiyun return 0;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun
nfs3_proc_read_setup(struct nfs_pgio_header * hdr,struct rpc_message * msg)842*4882a593Smuzhiyun static void nfs3_proc_read_setup(struct nfs_pgio_header *hdr,
843*4882a593Smuzhiyun struct rpc_message *msg)
844*4882a593Smuzhiyun {
845*4882a593Smuzhiyun msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ];
846*4882a593Smuzhiyun hdr->args.replen = NFS_SERVER(hdr->inode)->read_hdrsize;
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
nfs3_proc_pgio_rpc_prepare(struct rpc_task * task,struct nfs_pgio_header * hdr)849*4882a593Smuzhiyun static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task,
850*4882a593Smuzhiyun struct nfs_pgio_header *hdr)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun rpc_call_start(task);
853*4882a593Smuzhiyun return 0;
854*4882a593Smuzhiyun }
855*4882a593Smuzhiyun
nfs3_write_done(struct rpc_task * task,struct nfs_pgio_header * hdr)856*4882a593Smuzhiyun static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
857*4882a593Smuzhiyun {
858*4882a593Smuzhiyun struct inode *inode = hdr->inode;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun if (hdr->pgio_done_cb != NULL)
861*4882a593Smuzhiyun return hdr->pgio_done_cb(task, hdr);
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun if (nfs3_async_handle_jukebox(task, inode))
864*4882a593Smuzhiyun return -EAGAIN;
865*4882a593Smuzhiyun if (task->tk_status >= 0)
866*4882a593Smuzhiyun nfs_writeback_update_inode(hdr);
867*4882a593Smuzhiyun return 0;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun
nfs3_proc_write_setup(struct nfs_pgio_header * hdr,struct rpc_message * msg,struct rpc_clnt ** clnt)870*4882a593Smuzhiyun static void nfs3_proc_write_setup(struct nfs_pgio_header *hdr,
871*4882a593Smuzhiyun struct rpc_message *msg,
872*4882a593Smuzhiyun struct rpc_clnt **clnt)
873*4882a593Smuzhiyun {
874*4882a593Smuzhiyun msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE];
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
nfs3_proc_commit_rpc_prepare(struct rpc_task * task,struct nfs_commit_data * data)877*4882a593Smuzhiyun static void nfs3_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun rpc_call_start(task);
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun
nfs3_commit_done(struct rpc_task * task,struct nfs_commit_data * data)882*4882a593Smuzhiyun static int nfs3_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
883*4882a593Smuzhiyun {
884*4882a593Smuzhiyun if (data->commit_done_cb != NULL)
885*4882a593Smuzhiyun return data->commit_done_cb(task, data);
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun if (nfs3_async_handle_jukebox(task, data->inode))
888*4882a593Smuzhiyun return -EAGAIN;
889*4882a593Smuzhiyun nfs_refresh_inode(data->inode, data->res.fattr);
890*4882a593Smuzhiyun return 0;
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun
nfs3_proc_commit_setup(struct nfs_commit_data * data,struct rpc_message * msg,struct rpc_clnt ** clnt)893*4882a593Smuzhiyun static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg,
894*4882a593Smuzhiyun struct rpc_clnt **clnt)
895*4882a593Smuzhiyun {
896*4882a593Smuzhiyun msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT];
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun
nfs3_nlm_alloc_call(void * data)899*4882a593Smuzhiyun static void nfs3_nlm_alloc_call(void *data)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun struct nfs_lock_context *l_ctx = data;
902*4882a593Smuzhiyun if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags)) {
903*4882a593Smuzhiyun get_nfs_open_context(l_ctx->open_context);
904*4882a593Smuzhiyun nfs_get_lock_context(l_ctx->open_context);
905*4882a593Smuzhiyun }
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
nfs3_nlm_unlock_prepare(struct rpc_task * task,void * data)908*4882a593Smuzhiyun static bool nfs3_nlm_unlock_prepare(struct rpc_task *task, void *data)
909*4882a593Smuzhiyun {
910*4882a593Smuzhiyun struct nfs_lock_context *l_ctx = data;
911*4882a593Smuzhiyun if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags))
912*4882a593Smuzhiyun return nfs_async_iocounter_wait(task, l_ctx);
913*4882a593Smuzhiyun return false;
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
nfs3_nlm_release_call(void * data)917*4882a593Smuzhiyun static void nfs3_nlm_release_call(void *data)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun struct nfs_lock_context *l_ctx = data;
920*4882a593Smuzhiyun struct nfs_open_context *ctx;
921*4882a593Smuzhiyun if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags)) {
922*4882a593Smuzhiyun ctx = l_ctx->open_context;
923*4882a593Smuzhiyun nfs_put_lock_context(l_ctx);
924*4882a593Smuzhiyun put_nfs_open_context(ctx);
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun static const struct nlmclnt_operations nlmclnt_fl_close_lock_ops = {
929*4882a593Smuzhiyun .nlmclnt_alloc_call = nfs3_nlm_alloc_call,
930*4882a593Smuzhiyun .nlmclnt_unlock_prepare = nfs3_nlm_unlock_prepare,
931*4882a593Smuzhiyun .nlmclnt_release_call = nfs3_nlm_release_call,
932*4882a593Smuzhiyun };
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun static int
nfs3_proc_lock(struct file * filp,int cmd,struct file_lock * fl)935*4882a593Smuzhiyun nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
936*4882a593Smuzhiyun {
937*4882a593Smuzhiyun struct inode *inode = file_inode(filp);
938*4882a593Smuzhiyun struct nfs_lock_context *l_ctx = NULL;
939*4882a593Smuzhiyun struct nfs_open_context *ctx = nfs_file_open_context(filp);
940*4882a593Smuzhiyun int status;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun if (fl->fl_flags & FL_CLOSE) {
943*4882a593Smuzhiyun l_ctx = nfs_get_lock_context(ctx);
944*4882a593Smuzhiyun if (IS_ERR(l_ctx))
945*4882a593Smuzhiyun l_ctx = NULL;
946*4882a593Smuzhiyun else
947*4882a593Smuzhiyun set_bit(NFS_CONTEXT_UNLOCK, &ctx->flags);
948*4882a593Smuzhiyun }
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun status = nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, l_ctx);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun if (l_ctx)
953*4882a593Smuzhiyun nfs_put_lock_context(l_ctx);
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun return status;
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
nfs3_have_delegation(struct inode * inode,fmode_t flags)958*4882a593Smuzhiyun static int nfs3_have_delegation(struct inode *inode, fmode_t flags)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun return 0;
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun static const struct inode_operations nfs3_dir_inode_operations = {
964*4882a593Smuzhiyun .create = nfs_create,
965*4882a593Smuzhiyun .lookup = nfs_lookup,
966*4882a593Smuzhiyun .link = nfs_link,
967*4882a593Smuzhiyun .unlink = nfs_unlink,
968*4882a593Smuzhiyun .symlink = nfs_symlink,
969*4882a593Smuzhiyun .mkdir = nfs_mkdir,
970*4882a593Smuzhiyun .rmdir = nfs_rmdir,
971*4882a593Smuzhiyun .mknod = nfs_mknod,
972*4882a593Smuzhiyun .rename = nfs_rename,
973*4882a593Smuzhiyun .permission = nfs_permission,
974*4882a593Smuzhiyun .getattr = nfs_getattr,
975*4882a593Smuzhiyun .setattr = nfs_setattr,
976*4882a593Smuzhiyun #ifdef CONFIG_NFS_V3_ACL
977*4882a593Smuzhiyun .listxattr = nfs3_listxattr,
978*4882a593Smuzhiyun .get_acl = nfs3_get_acl,
979*4882a593Smuzhiyun .set_acl = nfs3_set_acl,
980*4882a593Smuzhiyun #endif
981*4882a593Smuzhiyun };
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun static const struct inode_operations nfs3_file_inode_operations = {
984*4882a593Smuzhiyun .permission = nfs_permission,
985*4882a593Smuzhiyun .getattr = nfs_getattr,
986*4882a593Smuzhiyun .setattr = nfs_setattr,
987*4882a593Smuzhiyun #ifdef CONFIG_NFS_V3_ACL
988*4882a593Smuzhiyun .listxattr = nfs3_listxattr,
989*4882a593Smuzhiyun .get_acl = nfs3_get_acl,
990*4882a593Smuzhiyun .set_acl = nfs3_set_acl,
991*4882a593Smuzhiyun #endif
992*4882a593Smuzhiyun };
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun const struct nfs_rpc_ops nfs_v3_clientops = {
995*4882a593Smuzhiyun .version = 3, /* protocol version */
996*4882a593Smuzhiyun .dentry_ops = &nfs_dentry_operations,
997*4882a593Smuzhiyun .dir_inode_ops = &nfs3_dir_inode_operations,
998*4882a593Smuzhiyun .file_inode_ops = &nfs3_file_inode_operations,
999*4882a593Smuzhiyun .file_ops = &nfs_file_operations,
1000*4882a593Smuzhiyun .nlmclnt_ops = &nlmclnt_fl_close_lock_ops,
1001*4882a593Smuzhiyun .getroot = nfs3_proc_get_root,
1002*4882a593Smuzhiyun .submount = nfs_submount,
1003*4882a593Smuzhiyun .try_get_tree = nfs_try_get_tree,
1004*4882a593Smuzhiyun .getattr = nfs3_proc_getattr,
1005*4882a593Smuzhiyun .setattr = nfs3_proc_setattr,
1006*4882a593Smuzhiyun .lookup = nfs3_proc_lookup,
1007*4882a593Smuzhiyun .access = nfs3_proc_access,
1008*4882a593Smuzhiyun .readlink = nfs3_proc_readlink,
1009*4882a593Smuzhiyun .create = nfs3_proc_create,
1010*4882a593Smuzhiyun .remove = nfs3_proc_remove,
1011*4882a593Smuzhiyun .unlink_setup = nfs3_proc_unlink_setup,
1012*4882a593Smuzhiyun .unlink_rpc_prepare = nfs3_proc_unlink_rpc_prepare,
1013*4882a593Smuzhiyun .unlink_done = nfs3_proc_unlink_done,
1014*4882a593Smuzhiyun .rename_setup = nfs3_proc_rename_setup,
1015*4882a593Smuzhiyun .rename_rpc_prepare = nfs3_proc_rename_rpc_prepare,
1016*4882a593Smuzhiyun .rename_done = nfs3_proc_rename_done,
1017*4882a593Smuzhiyun .link = nfs3_proc_link,
1018*4882a593Smuzhiyun .symlink = nfs3_proc_symlink,
1019*4882a593Smuzhiyun .mkdir = nfs3_proc_mkdir,
1020*4882a593Smuzhiyun .rmdir = nfs3_proc_rmdir,
1021*4882a593Smuzhiyun .readdir = nfs3_proc_readdir,
1022*4882a593Smuzhiyun .mknod = nfs3_proc_mknod,
1023*4882a593Smuzhiyun .statfs = nfs3_proc_statfs,
1024*4882a593Smuzhiyun .fsinfo = nfs3_proc_fsinfo,
1025*4882a593Smuzhiyun .pathconf = nfs3_proc_pathconf,
1026*4882a593Smuzhiyun .decode_dirent = nfs3_decode_dirent,
1027*4882a593Smuzhiyun .pgio_rpc_prepare = nfs3_proc_pgio_rpc_prepare,
1028*4882a593Smuzhiyun .read_setup = nfs3_proc_read_setup,
1029*4882a593Smuzhiyun .read_done = nfs3_read_done,
1030*4882a593Smuzhiyun .write_setup = nfs3_proc_write_setup,
1031*4882a593Smuzhiyun .write_done = nfs3_write_done,
1032*4882a593Smuzhiyun .commit_setup = nfs3_proc_commit_setup,
1033*4882a593Smuzhiyun .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare,
1034*4882a593Smuzhiyun .commit_done = nfs3_commit_done,
1035*4882a593Smuzhiyun .lock = nfs3_proc_lock,
1036*4882a593Smuzhiyun .clear_acl_cache = forget_all_cached_acls,
1037*4882a593Smuzhiyun .close_context = nfs_close_context,
1038*4882a593Smuzhiyun .have_delegation = nfs3_have_delegation,
1039*4882a593Smuzhiyun .alloc_client = nfs_alloc_client,
1040*4882a593Smuzhiyun .init_client = nfs_init_client,
1041*4882a593Smuzhiyun .free_client = nfs_free_client,
1042*4882a593Smuzhiyun .create_server = nfs3_create_server,
1043*4882a593Smuzhiyun .clone_server = nfs3_clone_server,
1044*4882a593Smuzhiyun };
1045