blob: 44bf961d581253b47a6d7662f16c06db2a4309b6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/fs/nfs/nfs3proc.c
3 *
4 * Client-side NFSv3 procedures stubs.
5 *
6 * Copyright (C) 1997, Olaf Kirch
7 */
8
9#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/errno.h>
11#include <linux/string.h>
12#include <linux/sunrpc/clnt.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/nfs.h>
15#include <linux/nfs3.h>
16#include <linux/nfs_fs.h>
17#include <linux/nfs_page.h>
18#include <linux/lockd/bind.h>
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +000019#include <linux/nfs_mount.h>
Jeff Laytond3103102011-12-01 22:44:39 +010020#include <linux/freezer.h>
Tejun Heo0a6be652014-02-03 14:31:07 -050021#include <linux/xattr.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
Chuck Lever006ea732006-03-20 13:44:14 -050023#include "iostat.h"
David Howellsf7b422b2006-06-09 09:34:33 -040024#include "internal.h"
Anna Schumaker00a36a102014-09-03 12:19:08 -040025#include "nfs3_fs.h"
Chuck Lever006ea732006-03-20 13:44:14 -050026
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#define NFSDBG_FACILITY NFSDBG_PROC
28
Andy Adamsoneb96d5c2012-11-27 10:34:19 -050029/* A wrapper to handle the EJUKEBOX error messages */
Linus Torvalds1da177e2005-04-16 15:20:36 -070030static int
31nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
32{
Linus Torvalds1da177e2005-04-16 15:20:36 -070033 int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 do {
35 res = rpc_call_sync(clnt, msg, flags);
Andy Adamsoneb96d5c2012-11-27 10:34:19 -050036 if (res != -EJUKEBOX)
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 break;
Colin Cross416ad3c2013-05-06 23:50:06 +000038 freezable_schedule_timeout_killable_unsafe(NFS_JUKEBOX_RETRY_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -070039 res = -ERESTARTSYS;
Matthew Wilcox150030b2007-12-06 16:24:39 -050040 } while (!fatal_signal_pending(current));
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 return res;
42}
43
Chuck Leverdead28d2006-03-20 13:44:23 -050044#define rpc_call_sync(clnt, msg, flags) nfs3_rpc_wrapper(clnt, msg, flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46static int
Chuck Lever006ea732006-03-20 13:44:14 -050047nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048{
Andy Adamsoneb96d5c2012-11-27 10:34:19 -050049 if (task->tk_status != -EJUKEBOX)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 return 0;
Jeff Laytonb68d69b2010-01-07 09:42:04 -050051 if (task->tk_status == -EJUKEBOX)
52 nfs_inc_stats(inode, NFSIOS_DELAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 task->tk_status = 0;
54 rpc_restart_call(task);
55 rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
56 return 1;
57}
58
J. Bruce Fields03c21732006-01-03 09:55:48 +010059static int
60do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
61 struct nfs_fsinfo *info)
62{
Chuck Leverdead28d2006-03-20 13:44:23 -050063 struct rpc_message msg = {
64 .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
65 .rpc_argp = fhandle,
66 .rpc_resp = info,
67 };
J. Bruce Fields03c21732006-01-03 09:55:48 +010068 int status;
69
Harvey Harrison3110ff82008-05-02 13:42:44 -070070 dprintk("%s: call fsinfo\n", __func__);
J. Bruce Fields03c21732006-01-03 09:55:48 +010071 nfs_fattr_init(info->fattr);
Chuck Leverdead28d2006-03-20 13:44:23 -050072 status = rpc_call_sync(client, &msg, 0);
Harvey Harrison3110ff82008-05-02 13:42:44 -070073 dprintk("%s: reply fsinfo: %d\n", __func__, status);
Trond Myklebust08660042012-08-20 12:42:15 -040074 if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) {
Chuck Leverdead28d2006-03-20 13:44:23 -050075 msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
76 msg.rpc_resp = info->fattr;
77 status = rpc_call_sync(client, &msg, 0);
Harvey Harrison3110ff82008-05-02 13:42:44 -070078 dprintk("%s: reply getattr: %d\n", __func__, status);
J. Bruce Fields03c21732006-01-03 09:55:48 +010079 }
80 return status;
81}
82
Linus Torvalds1da177e2005-04-16 15:20:36 -070083/*
David Howells54ceac42006-08-22 20:06:13 -040084 * Bare-bones access to getattr: this is for nfs_get_root/nfs_get_sb
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 */
86static int
87nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
88 struct nfs_fsinfo *info)
89{
90 int status;
91
J. Bruce Fields03c21732006-01-03 09:55:48 +010092 status = do_proc_get_root(server->client, fhandle, info);
David Howells5006a762006-08-22 20:06:12 -040093 if (status && server->nfs_client->cl_rpcclient != server->client)
94 status = do_proc_get_root(server->nfs_client->cl_rpcclient, fhandle, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 return status;
96}
97
98/*
99 * One function for each procedure in the NFS protocol.
100 */
101static int
102nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
David Quigley1775fd32013-05-22 12:50:42 -0400103 struct nfs_fattr *fattr, struct nfs4_label *label)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104{
Chuck Leverdead28d2006-03-20 13:44:23 -0500105 struct rpc_message msg = {
106 .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR],
107 .rpc_argp = fhandle,
108 .rpc_resp = fattr,
109 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 int status;
111
112 dprintk("NFS call getattr\n");
Trond Myklebust0e574af2005-10-27 22:12:38 -0400113 nfs_fattr_init(fattr);
Chuck Leverdead28d2006-03-20 13:44:23 -0500114 status = rpc_call_sync(server->client, &msg, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 dprintk("NFS reply getattr: %d\n", status);
116 return status;
117}
118
119static int
120nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
121 struct iattr *sattr)
122{
David Howells2b0143b2015-03-17 22:25:59 +0000123 struct inode *inode = d_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 struct nfs3_sattrargs arg = {
125 .fh = NFS_FH(inode),
126 .sattr = sattr,
127 };
Chuck Leverdead28d2006-03-20 13:44:23 -0500128 struct rpc_message msg = {
129 .rpc_proc = &nfs3_procedures[NFS3PROC_SETATTR],
130 .rpc_argp = &arg,
131 .rpc_resp = fattr,
132 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 int status;
134
135 dprintk("NFS call setattr\n");
Trond Myklebust659bfcd2008-06-10 19:39:41 -0400136 if (sattr->ia_valid & ATTR_FILE)
137 msg.rpc_cred = nfs_file_cred(sattr->ia_file);
Trond Myklebust0e574af2005-10-27 22:12:38 -0400138 nfs_fattr_init(fattr);
Chuck Leverdead28d2006-03-20 13:44:23 -0500139 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
Trond Myklebust65e43082005-08-16 11:49:44 -0400140 if (status == 0)
Trond Myklebustf0446362015-02-26 16:09:04 -0500141 nfs_setattr_update_inode(inode, sattr, fattr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 dprintk("NFS reply setattr: %d\n", status);
143 return status;
144}
145
146static int
Al Virobeffb8f2016-07-20 16:34:42 -0400147nfs3_proc_lookup(struct inode *dir, const struct qstr *name,
David Quigley1775fd32013-05-22 12:50:42 -0400148 struct nfs_fh *fhandle, struct nfs_fattr *fattr,
149 struct nfs4_label *label)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 struct nfs3_diropargs arg = {
152 .fh = NFS_FH(dir),
153 .name = name->name,
154 .len = name->len
155 };
156 struct nfs3_diropres res = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 .fh = fhandle,
158 .fattr = fattr
159 };
Chuck Leverdead28d2006-03-20 13:44:23 -0500160 struct rpc_message msg = {
161 .rpc_proc = &nfs3_procedures[NFS3PROC_LOOKUP],
162 .rpc_argp = &arg,
163 .rpc_resp = &res,
164 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 int status;
166
167 dprintk("NFS call lookup %s\n", name->name);
Trond Myklebuste1fb4d02010-04-16 16:22:47 -0400168 res.dir_attr = nfs_alloc_fattr();
169 if (res.dir_attr == NULL)
170 return -ENOMEM;
171
Trond Myklebust0e574af2005-10-27 22:12:38 -0400172 nfs_fattr_init(fattr);
Chuck Leverdead28d2006-03-20 13:44:23 -0500173 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
Trond Myklebuste1fb4d02010-04-16 16:22:47 -0400174 nfs_refresh_inode(dir, res.dir_attr);
Chuck Leverdead28d2006-03-20 13:44:23 -0500175 if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
176 msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
177 msg.rpc_argp = fhandle;
178 msg.rpc_resp = fattr;
179 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
180 }
Trond Myklebuste1fb4d02010-04-16 16:22:47 -0400181 nfs_free_fattr(res.dir_attr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 dprintk("NFS reply lookup: %d\n", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 return status;
184}
185
186static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
187{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 struct nfs3_accessargs arg = {
189 .fh = NFS_FH(inode),
Anna Schumaker1750d922017-07-26 12:00:21 -0400190 .access = entry->mask,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 };
Trond Myklebustc407d412010-04-16 16:22:48 -0400192 struct nfs3_accessres res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 struct rpc_message msg = {
194 .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
195 .rpc_argp = &arg,
196 .rpc_resp = &res,
Chuck Leverdead28d2006-03-20 13:44:23 -0500197 .rpc_cred = entry->cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 };
Trond Myklebustc407d412010-04-16 16:22:48 -0400199 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201 dprintk("NFS call access\n");
Trond Myklebustc407d412010-04-16 16:22:48 -0400202 res.fattr = nfs_alloc_fattr();
203 if (res.fattr == NULL)
204 goto out;
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
Trond Myklebustc407d412010-04-16 16:22:48 -0400207 nfs_refresh_inode(inode, res.fattr);
Trond Myklebusteda3e202017-07-11 17:54:33 -0400208 if (status == 0)
209 nfs_access_set_mask(entry, res.access);
Trond Myklebustc407d412010-04-16 16:22:48 -0400210 nfs_free_fattr(res.fattr);
211out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 dprintk("NFS reply access: %d\n", status);
213 return status;
214}
215
216static int nfs3_proc_readlink(struct inode *inode, struct page *page,
217 unsigned int pgbase, unsigned int pglen)
218{
Trond Myklebust3b14d652010-04-16 16:22:50 -0400219 struct nfs_fattr *fattr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 struct nfs3_readlinkargs args = {
221 .fh = NFS_FH(inode),
222 .pgbase = pgbase,
223 .pglen = pglen,
224 .pages = &page
225 };
Chuck Leverdead28d2006-03-20 13:44:23 -0500226 struct rpc_message msg = {
227 .rpc_proc = &nfs3_procedures[NFS3PROC_READLINK],
228 .rpc_argp = &args,
Chuck Leverdead28d2006-03-20 13:44:23 -0500229 };
Trond Myklebust3b14d652010-04-16 16:22:50 -0400230 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
232 dprintk("NFS call readlink\n");
Trond Myklebust3b14d652010-04-16 16:22:50 -0400233 fattr = nfs_alloc_fattr();
234 if (fattr == NULL)
235 goto out;
236 msg.rpc_resp = fattr;
237
Chuck Leverdead28d2006-03-20 13:44:23 -0500238 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
Trond Myklebust3b14d652010-04-16 16:22:50 -0400239 nfs_refresh_inode(inode, fattr);
240 nfs_free_fattr(fattr);
241out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 dprintk("NFS reply readlink: %d\n", status);
243 return status;
244}
245
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400246struct nfs3_createdata {
247 struct rpc_message msg;
248 union {
249 struct nfs3_createargs create;
250 struct nfs3_mkdirargs mkdir;
251 struct nfs3_symlinkargs symlink;
252 struct nfs3_mknodargs mknod;
253 } arg;
254 struct nfs3_diropres res;
255 struct nfs_fh fh;
256 struct nfs_fattr fattr;
257 struct nfs_fattr dir_attr;
258};
259
260static struct nfs3_createdata *nfs3_alloc_createdata(void)
261{
262 struct nfs3_createdata *data;
263
264 data = kzalloc(sizeof(*data), GFP_KERNEL);
265 if (data != NULL) {
266 data->msg.rpc_argp = &data->arg;
267 data->msg.rpc_resp = &data->res;
268 data->res.fh = &data->fh;
269 data->res.fattr = &data->fattr;
270 data->res.dir_attr = &data->dir_attr;
271 nfs_fattr_init(data->res.fattr);
272 nfs_fattr_init(data->res.dir_attr);
273 }
274 return data;
275}
276
277static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_createdata *data)
278{
279 int status;
280
281 status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
282 nfs_post_op_update_inode(dir, data->res.dir_attr);
283 if (status == 0)
David Quigley1775fd32013-05-22 12:50:42 -0400284 status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400285 return status;
286}
287
288static void nfs3_free_createdata(struct nfs3_createdata *data)
289{
290 kfree(data);
291}
292
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293/*
294 * Create a regular file.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 */
296static int
297nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
Miklos Szeredi8867fe52012-06-05 15:10:19 +0200298 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299{
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800300 struct posix_acl *default_acl, *acl;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400301 struct nfs3_createdata *data;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400302 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Al Viro6de14722013-09-16 10:53:17 -0400304 dprintk("NFS call create %pd\n", dentry);
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400305
306 data = nfs3_alloc_createdata();
307 if (data == NULL)
308 goto out;
309
310 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_CREATE];
311 data->arg.create.fh = NFS_FH(dir);
312 data->arg.create.name = dentry->d_name.name;
313 data->arg.create.len = dentry->d_name.len;
314 data->arg.create.sattr = sattr;
315
316 data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 if (flags & O_EXCL) {
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400318 data->arg.create.createmode = NFS3_CREATE_EXCLUSIVE;
Trond Myklebusta9943d12013-08-20 21:04:11 -0400319 data->arg.create.verifier[0] = cpu_to_be32(jiffies);
320 data->arg.create.verifier[1] = cpu_to_be32(current->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 }
322
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800323 status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
324 if (status)
325 goto out;
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000326
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400327 for (;;) {
328 status = nfs3_do_create(dir, dentry, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400330 if (status != -ENOTSUPP)
331 break;
332 /* If the server doesn't support the exclusive creation
333 * semantics, try again with simple 'guarded' mode. */
334 switch (data->arg.create.createmode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 case NFS3_CREATE_EXCLUSIVE:
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400336 data->arg.create.createmode = NFS3_CREATE_GUARDED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 break;
338
339 case NFS3_CREATE_GUARDED:
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400340 data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 break;
342
343 case NFS3_CREATE_UNCHECKED:
344 goto out;
345 }
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400346 nfs_fattr_init(data->res.dir_attr);
347 nfs_fattr_init(data->res.fattr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 }
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 if (status != 0)
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800351 goto out_release_acls;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 /* When we created the file with exclusive semantics, make
354 * sure we set the attributes afterwards. */
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400355 if (data->arg.create.createmode == NFS3_CREATE_EXCLUSIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 dprintk("NFS call setattr (post-create)\n");
357
358 if (!(sattr->ia_valid & ATTR_ATIME_SET))
359 sattr->ia_valid |= ATTR_ATIME;
360 if (!(sattr->ia_valid & ATTR_MTIME_SET))
361 sattr->ia_valid |= ATTR_MTIME;
362
363 /* Note: we could use a guarded setattr here, but I'm
364 * not sure this buys us anything (and I'd have
365 * to revamp the NFSv3 XDR code) */
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400366 status = nfs3_proc_setattr(dentry, data->res.fattr, sattr);
David Howells2b0143b2015-03-17 22:25:59 +0000367 nfs_post_op_update_inode(d_inode(dentry), data->res.fattr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 dprintk("NFS reply setattr (post-create): %d\n", status);
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400369 if (status != 0)
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800370 goto out_release_acls;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 }
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800372
David Howells2b0143b2015-03-17 22:25:59 +0000373 status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800374
375out_release_acls:
376 posix_acl_release(acl);
377 posix_acl_release(default_acl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378out:
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400379 nfs3_free_createdata(data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 dprintk("NFS reply create: %d\n", status);
381 return status;
382}
383
384static int
Al Virobeffb8f2016-07-20 16:34:42 -0400385nfs3_proc_remove(struct inode *dir, const struct qstr *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
Trond Myklebust4fdc17b2007-07-14 15:39:57 -0400387 struct nfs_removeargs arg = {
388 .fh = NFS_FH(dir),
Linus Torvalds26fe5752012-05-10 13:14:12 -0700389 .name = *name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 };
Trond Myklebust4fdc17b2007-07-14 15:39:57 -0400391 struct nfs_removeres res;
392 struct rpc_message msg = {
393 .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE],
394 .rpc_argp = &arg,
395 .rpc_resp = &res,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 };
Trond Myklebustd3468902010-04-16 16:22:50 -0400397 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
399 dprintk("NFS call remove %s\n", name->name);
Trond Myklebustd3468902010-04-16 16:22:50 -0400400 res.dir_attr = nfs_alloc_fattr();
401 if (res.dir_attr == NULL)
402 goto out;
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
Trond Myklebustd3468902010-04-16 16:22:50 -0400405 nfs_post_op_update_inode(dir, res.dir_attr);
406 nfs_free_fattr(res.dir_attr);
407out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 dprintk("NFS reply remove: %d\n", status);
409 return status;
410}
411
Trond Myklebuste4eff1a2007-07-14 15:39:58 -0400412static void
413nfs3_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416}
417
Bryan Schumaker34e137c2012-03-19 14:54:41 -0400418static void nfs3_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
419{
420 rpc_call_start(task);
421}
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423static int
Trond Myklebuste4eff1a2007-07-14 15:39:58 -0400424nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
Trond Myklebuste4eff1a2007-07-14 15:39:58 -0400426 struct nfs_removeres *res;
427 if (nfs3_async_handle_jukebox(task, dir))
428 return 0;
429 res = task->tk_msg.rpc_resp;
Trond Myklebustd3468902010-04-16 16:22:50 -0400430 nfs_post_op_update_inode(dir, res->dir_attr);
Trond Myklebuste4eff1a2007-07-14 15:39:58 -0400431 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432}
433
Jeff Laytond3d41522010-09-17 17:31:57 -0400434static void
435nfs3_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
436{
437 msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
438}
439
Bryan Schumakerc6bfa1a2012-03-19 14:54:42 -0400440static void nfs3_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
441{
442 rpc_call_start(task);
443}
444
Jeff Laytond3d41522010-09-17 17:31:57 -0400445static int
446nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
447 struct inode *new_dir)
448{
449 struct nfs_renameres *res;
450
451 if (nfs3_async_handle_jukebox(task, old_dir))
452 return 0;
453 res = task->tk_msg.rpc_resp;
454
455 nfs_post_op_update_inode(old_dir, res->old_fattr);
456 nfs_post_op_update_inode(new_dir, res->new_fattr);
457 return 1;
458}
459
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460static int
Al Virobeffb8f2016-07-20 16:34:42 -0400461nfs3_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 struct nfs3_linkargs arg = {
464 .fromfh = NFS_FH(inode),
465 .tofh = NFS_FH(dir),
466 .toname = name->name,
467 .tolen = name->len
468 };
Trond Myklebust136f2622010-04-16 16:22:49 -0400469 struct nfs3_linkres res;
Chuck Leverdead28d2006-03-20 13:44:23 -0500470 struct rpc_message msg = {
471 .rpc_proc = &nfs3_procedures[NFS3PROC_LINK],
472 .rpc_argp = &arg,
473 .rpc_resp = &res,
474 };
Trond Myklebust136f2622010-04-16 16:22:49 -0400475 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
477 dprintk("NFS call link %s\n", name->name);
Trond Myklebust136f2622010-04-16 16:22:49 -0400478 res.fattr = nfs_alloc_fattr();
479 res.dir_attr = nfs_alloc_fattr();
480 if (res.fattr == NULL || res.dir_attr == NULL)
481 goto out;
482
Chuck Leverdead28d2006-03-20 13:44:23 -0500483 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
Trond Myklebust136f2622010-04-16 16:22:49 -0400484 nfs_post_op_update_inode(dir, res.dir_attr);
485 nfs_post_op_update_inode(inode, res.fattr);
486out:
487 nfs_free_fattr(res.dir_attr);
488 nfs_free_fattr(res.fattr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 dprintk("NFS reply link: %d\n", status);
490 return status;
491}
492
493static int
Chuck Lever94a6d752006-08-22 20:06:23 -0400494nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
495 unsigned int len, struct iattr *sattr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400497 struct nfs3_createdata *data;
498 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Chuck Lever94a6d752006-08-22 20:06:23 -0400500 if (len > NFS3_MAXPATHLEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 return -ENAMETOOLONG;
Chuck Lever4f390c12006-08-22 20:06:22 -0400502
Al Viro6de14722013-09-16 10:53:17 -0400503 dprintk("NFS call symlink %pd\n", dentry);
Chuck Lever94a6d752006-08-22 20:06:23 -0400504
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400505 data = nfs3_alloc_createdata();
506 if (data == NULL)
Chuck Lever4f390c12006-08-22 20:06:22 -0400507 goto out;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400508 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK];
509 data->arg.symlink.fromfh = NFS_FH(dir);
510 data->arg.symlink.fromname = dentry->d_name.name;
511 data->arg.symlink.fromlen = dentry->d_name.len;
512 data->arg.symlink.pages = &page;
513 data->arg.symlink.pathlen = len;
514 data->arg.symlink.sattr = sattr;
515
516 status = nfs3_do_create(dir, dentry, data);
517
518 nfs3_free_createdata(data);
Chuck Lever4f390c12006-08-22 20:06:22 -0400519out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 dprintk("NFS reply symlink: %d\n", status);
521 return status;
522}
523
524static int
525nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
526{
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800527 struct posix_acl *default_acl, *acl;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400528 struct nfs3_createdata *data;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400529 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Al Viro6de14722013-09-16 10:53:17 -0400531 dprintk("NFS call mkdir %pd\n", dentry);
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000532
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400533 data = nfs3_alloc_createdata();
534 if (data == NULL)
535 goto out;
536
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800537 status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
538 if (status)
539 goto out;
540
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400541 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR];
542 data->arg.mkdir.fh = NFS_FH(dir);
543 data->arg.mkdir.name = dentry->d_name.name;
544 data->arg.mkdir.len = dentry->d_name.len;
545 data->arg.mkdir.sattr = sattr;
546
547 status = nfs3_do_create(dir, dentry, data);
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000548 if (status != 0)
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800549 goto out_release_acls;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400550
David Howells2b0143b2015-03-17 22:25:59 +0000551 status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800552
553out_release_acls:
554 posix_acl_release(acl);
555 posix_acl_release(default_acl);
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000556out:
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400557 nfs3_free_createdata(data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 dprintk("NFS reply mkdir: %d\n", status);
559 return status;
560}
561
562static int
Al Virobeffb8f2016-07-20 16:34:42 -0400563nfs3_proc_rmdir(struct inode *dir, const struct qstr *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564{
Trond Myklebust39967dd2010-04-16 16:22:50 -0400565 struct nfs_fattr *dir_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 struct nfs3_diropargs arg = {
567 .fh = NFS_FH(dir),
568 .name = name->name,
569 .len = name->len
570 };
Chuck Leverdead28d2006-03-20 13:44:23 -0500571 struct rpc_message msg = {
572 .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR],
573 .rpc_argp = &arg,
Chuck Leverdead28d2006-03-20 13:44:23 -0500574 };
Trond Myklebust39967dd2010-04-16 16:22:50 -0400575 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
577 dprintk("NFS call rmdir %s\n", name->name);
Trond Myklebust39967dd2010-04-16 16:22:50 -0400578 dir_attr = nfs_alloc_fattr();
579 if (dir_attr == NULL)
580 goto out;
581
582 msg.rpc_resp = dir_attr;
Chuck Leverdead28d2006-03-20 13:44:23 -0500583 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
Trond Myklebust39967dd2010-04-16 16:22:50 -0400584 nfs_post_op_update_inode(dir, dir_attr);
585 nfs_free_fattr(dir_attr);
586out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 dprintk("NFS reply rmdir: %d\n", status);
588 return status;
589}
590
591/*
592 * The READDIR implementation is somewhat hackish - we pass the user buffer
593 * to the encode function, which installs it in the receive iovec.
594 * The decode function itself doesn't perform any decoding, it just makes
595 * sure the reply is syntactically correct.
596 *
597 * Also note that this implementation handles both plain readdir and
598 * readdirplus.
599 */
600static int
601nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
Benjamin Coddingtona7a3b1e2017-06-20 08:33:44 -0400602 u64 cookie, struct page **pages, unsigned int count, bool plus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
David Howells2b0143b2015-03-17 22:25:59 +0000604 struct inode *dir = d_inode(dentry);
Trond Myklebustc3f52af2012-09-03 14:56:02 -0400605 __be32 *verf = NFS_I(dir)->cookieverf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 struct nfs3_readdirargs arg = {
607 .fh = NFS_FH(dir),
608 .cookie = cookie,
609 .verf = {verf[0], verf[1]},
610 .plus = plus,
611 .count = count,
Bryan Schumaker56e4ebf2010-10-20 15:44:37 -0400612 .pages = pages
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 };
614 struct nfs3_readdirres res = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 .verf = verf,
616 .plus = plus
617 };
618 struct rpc_message msg = {
619 .rpc_proc = &nfs3_procedures[NFS3PROC_READDIR],
620 .rpc_argp = &arg,
621 .rpc_resp = &res,
622 .rpc_cred = cred
623 };
Trond Myklebustaa49b4c2010-04-16 16:22:49 -0400624 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 if (plus)
627 msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];
628
629 dprintk("NFS call readdir%s %d\n",
630 plus? "plus" : "", (unsigned int) cookie);
631
Trond Myklebustaa49b4c2010-04-16 16:22:49 -0400632 res.dir_attr = nfs_alloc_fattr();
633 if (res.dir_attr == NULL)
634 goto out;
635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
Trond Myklebustc4812992007-09-28 17:11:45 -0400637
638 nfs_invalidate_atime(dir);
Trond Myklebustaa49b4c2010-04-16 16:22:49 -0400639 nfs_refresh_inode(dir, res.dir_attr);
Trond Myklebustc4812992007-09-28 17:11:45 -0400640
Trond Myklebustaa49b4c2010-04-16 16:22:49 -0400641 nfs_free_fattr(res.dir_attr);
642out:
Chuck Leverd141d972010-09-21 16:55:47 -0400643 dprintk("NFS reply readdir%s: %d\n",
644 plus? "plus" : "", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 return status;
646}
647
648static int
649nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
650 dev_t rdev)
651{
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800652 struct posix_acl *default_acl, *acl;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400653 struct nfs3_createdata *data;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400654 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Al Viro6de14722013-09-16 10:53:17 -0400656 dprintk("NFS call mknod %pd %u:%u\n", dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 MAJOR(rdev), MINOR(rdev));
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000658
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400659 data = nfs3_alloc_createdata();
660 if (data == NULL)
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000661 goto out;
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400662
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800663 status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
664 if (status)
665 goto out;
666
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400667 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD];
668 data->arg.mknod.fh = NFS_FH(dir);
669 data->arg.mknod.name = dentry->d_name.name;
670 data->arg.mknod.len = dentry->d_name.len;
671 data->arg.mknod.sattr = sattr;
672 data->arg.mknod.rdev = rdev;
673
674 switch (sattr->ia_mode & S_IFMT) {
675 case S_IFBLK:
676 data->arg.mknod.type = NF3BLK;
677 break;
678 case S_IFCHR:
679 data->arg.mknod.type = NF3CHR;
680 break;
681 case S_IFIFO:
682 data->arg.mknod.type = NF3FIFO;
683 break;
684 case S_IFSOCK:
685 data->arg.mknod.type = NF3SOCK;
686 break;
687 default:
688 status = -EINVAL;
689 goto out;
690 }
691
692 status = nfs3_do_create(dir, dentry, data);
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000693 if (status != 0)
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800694 goto out_release_acls;
695
David Howells2b0143b2015-03-17 22:25:59 +0000696 status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800697
698out_release_acls:
699 posix_acl_release(acl);
700 posix_acl_release(default_acl);
Andreas Gruenbacher055ffbe2005-06-22 17:16:27 +0000701out:
Trond Myklebust0b4aae72008-06-20 17:00:23 -0400702 nfs3_free_createdata(data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 dprintk("NFS reply mknod: %d\n", status);
704 return status;
705}
706
707static int
708nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
709 struct nfs_fsstat *stat)
710{
Chuck Leverdead28d2006-03-20 13:44:23 -0500711 struct rpc_message msg = {
712 .rpc_proc = &nfs3_procedures[NFS3PROC_FSSTAT],
713 .rpc_argp = fhandle,
714 .rpc_resp = stat,
715 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 int status;
717
718 dprintk("NFS call fsstat\n");
Trond Myklebust0e574af2005-10-27 22:12:38 -0400719 nfs_fattr_init(stat->fattr);
Chuck Leverdead28d2006-03-20 13:44:23 -0500720 status = rpc_call_sync(server->client, &msg, 0);
Chuck Leverd141d972010-09-21 16:55:47 -0400721 dprintk("NFS reply fsstat: %d\n", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 return status;
723}
724
725static int
EG Keizer37ca8f52008-08-19 16:34:36 -0400726do_proc_fsinfo(struct rpc_clnt *client, struct nfs_fh *fhandle,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 struct nfs_fsinfo *info)
728{
Chuck Leverdead28d2006-03-20 13:44:23 -0500729 struct rpc_message msg = {
730 .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
731 .rpc_argp = fhandle,
732 .rpc_resp = info,
733 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 int status;
735
736 dprintk("NFS call fsinfo\n");
Trond Myklebust0e574af2005-10-27 22:12:38 -0400737 nfs_fattr_init(info->fattr);
EG Keizer37ca8f52008-08-19 16:34:36 -0400738 status = rpc_call_sync(client, &msg, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 dprintk("NFS reply fsinfo: %d\n", status);
740 return status;
741}
742
EG Keizer37ca8f52008-08-19 16:34:36 -0400743/*
744 * Bare-bones access to fsinfo: this is for nfs_get_root/nfs_get_sb via
745 * nfs_create_server
746 */
747static int
748nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
749 struct nfs_fsinfo *info)
750{
751 int status;
752
753 status = do_proc_fsinfo(server->client, fhandle, info);
754 if (status && server->nfs_client->cl_rpcclient != server->client)
755 status = do_proc_fsinfo(server->nfs_client->cl_rpcclient, fhandle, info);
756 return status;
757}
758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759static int
760nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
761 struct nfs_pathconf *info)
762{
Chuck Leverdead28d2006-03-20 13:44:23 -0500763 struct rpc_message msg = {
764 .rpc_proc = &nfs3_procedures[NFS3PROC_PATHCONF],
765 .rpc_argp = fhandle,
766 .rpc_resp = info,
767 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 int status;
769
770 dprintk("NFS call pathconf\n");
Trond Myklebust0e574af2005-10-27 22:12:38 -0400771 nfs_fattr_init(info->fattr);
Chuck Leverdead28d2006-03-20 13:44:23 -0500772 status = rpc_call_sync(server->client, &msg, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 dprintk("NFS reply pathconf: %d\n", status);
774 return status;
775}
776
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400777static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778{
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400779 struct inode *inode = hdr->inode;
Fred Isamancd841602012-04-20 14:47:44 -0400780
Trond Myklebust16cecdf2014-06-22 12:55:11 -0400781 if (hdr->pgio_done_cb != NULL)
782 return hdr->pgio_done_cb(task, hdr);
783
Fred Isamancd841602012-04-20 14:47:44 -0400784 if (nfs3_async_handle_jukebox(task, inode))
Trond Myklebustec06c092006-03-20 13:44:27 -0500785 return -EAGAIN;
Trond Myklebust8850df92007-09-28 17:20:07 -0400786
Fred Isamancd841602012-04-20 14:47:44 -0400787 nfs_invalidate_atime(inode);
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400788 nfs_refresh_inode(inode, &hdr->fattr);
Trond Myklebustec06c092006-03-20 13:44:27 -0500789 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790}
791
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400792static void nfs3_proc_read_setup(struct nfs_pgio_header *hdr,
793 struct rpc_message *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794{
Trond Myklebustbdc7f022007-07-14 15:40:00 -0400795 msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796}
797
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400798static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task,
799 struct nfs_pgio_header *hdr)
Bryan Schumakerea7c3302012-03-19 14:54:40 -0400800{
801 rpc_call_start(task);
NeilBrownef1820f2013-09-04 17:04:49 +1000802 return 0;
Bryan Schumakerea7c3302012-03-19 14:54:40 -0400803}
804
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400805static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400807 struct inode *inode = hdr->inode;
Fred Isamancd841602012-04-20 14:47:44 -0400808
Trond Myklebust16cecdf2014-06-22 12:55:11 -0400809 if (hdr->pgio_done_cb != NULL)
810 return hdr->pgio_done_cb(task, hdr);
811
Fred Isamancd841602012-04-20 14:47:44 -0400812 if (nfs3_async_handle_jukebox(task, inode))
Trond Myklebust788e7a82006-03-20 13:44:27 -0500813 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 if (task->tk_status >= 0)
Trond Myklebusta08a8cd2015-02-26 17:36:09 -0500815 nfs_writeback_update_inode(hdr);
Trond Myklebust788e7a82006-03-20 13:44:27 -0500816 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817}
818
Weston Andros Adamsond45f60c2014-06-09 11:48:35 -0400819static void nfs3_proc_write_setup(struct nfs_pgio_header *hdr,
820 struct rpc_message *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821{
Trond Myklebustbdc7f022007-07-14 15:40:00 -0400822 msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823}
824
Fred Isaman0b7c0152012-04-20 14:47:39 -0400825static void nfs3_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
826{
827 rpc_call_start(task);
828}
829
830static int nfs3_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
Trond Myklebust16cecdf2014-06-22 12:55:11 -0400832 if (data->commit_done_cb != NULL)
833 return data->commit_done_cb(task, data);
834
Chuck Lever006ea732006-03-20 13:44:14 -0500835 if (nfs3_async_handle_jukebox(task, data->inode))
Trond Myklebust788e7a82006-03-20 13:44:27 -0500836 return -EAGAIN;
Trond Myklebust9e08a3c2007-10-08 14:10:31 -0400837 nfs_refresh_inode(data->inode, data->res.fattr);
Trond Myklebust788e7a82006-03-20 13:44:27 -0500838 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839}
840
Fred Isaman0b7c0152012-04-20 14:47:39 -0400841static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842{
Trond Myklebustbdc7f022007-07-14 15:40:00 -0400843 msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844}
845
Trond Myklebustbb3393d2017-04-25 16:25:06 -0400846static void nfs3_nlm_alloc_call(void *data)
Benjamin Coddingtonf30cb752017-04-11 12:50:12 -0400847{
848 struct nfs_lock_context *l_ctx = data;
849 if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags)) {
850 get_nfs_open_context(l_ctx->open_context);
851 nfs_get_lock_context(l_ctx->open_context);
852 }
853}
854
Trond Myklebustbb3393d2017-04-25 16:25:06 -0400855static bool nfs3_nlm_unlock_prepare(struct rpc_task *task, void *data)
Benjamin Coddingtonf30cb752017-04-11 12:50:12 -0400856{
857 struct nfs_lock_context *l_ctx = data;
858 if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags))
859 return nfs_async_iocounter_wait(task, l_ctx);
860 return false;
861
862}
863
Trond Myklebustbb3393d2017-04-25 16:25:06 -0400864static void nfs3_nlm_release_call(void *data)
Benjamin Coddingtonf30cb752017-04-11 12:50:12 -0400865{
866 struct nfs_lock_context *l_ctx = data;
867 struct nfs_open_context *ctx;
868 if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags)) {
869 ctx = l_ctx->open_context;
870 nfs_put_lock_context(l_ctx);
871 put_nfs_open_context(ctx);
872 }
873}
874
875const struct nlmclnt_operations nlmclnt_fl_close_lock_ops = {
876 .nlmclnt_alloc_call = nfs3_nlm_alloc_call,
877 .nlmclnt_unlock_prepare = nfs3_nlm_unlock_prepare,
878 .nlmclnt_release_call = nfs3_nlm_release_call,
879};
880
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881static int
882nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
883{
Al Viro496ad9a2013-01-23 17:07:38 -0500884 struct inode *inode = file_inode(filp);
Benjamin Coddingtonf30cb752017-04-11 12:50:12 -0400885 struct nfs_lock_context *l_ctx = NULL;
886 struct nfs_open_context *ctx = nfs_file_open_context(filp);
887 int status;
Chuck Lever1093a602008-01-11 17:09:59 -0500888
Benjamin Coddingtonf30cb752017-04-11 12:50:12 -0400889 if (fl->fl_flags & FL_CLOSE) {
890 l_ctx = nfs_get_lock_context(ctx);
891 if (IS_ERR(l_ctx))
892 l_ctx = NULL;
893 else
894 set_bit(NFS_CONTEXT_UNLOCK, &ctx->flags);
895 }
896
897 status = nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, l_ctx);
898
899 if (l_ctx)
900 nfs_put_lock_context(l_ctx);
901
902 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903}
904
Bryan Schumaker011e2a72012-06-20 15:53:43 -0400905static int nfs3_have_delegation(struct inode *inode, fmode_t flags)
906{
907 return 0;
908}
909
Bryan Schumaker57ec14c2012-06-20 15:53:44 -0400910static int nfs3_return_delegation(struct inode *inode)
911{
912 nfs_wb_all(inode);
913 return 0;
914}
915
Bryan Schumakerab962912012-07-16 16:39:11 -0400916static const struct inode_operations nfs3_dir_inode_operations = {
917 .create = nfs_create,
918 .lookup = nfs_lookup,
919 .link = nfs_link,
920 .unlink = nfs_unlink,
921 .symlink = nfs_symlink,
922 .mkdir = nfs_mkdir,
923 .rmdir = nfs_rmdir,
924 .mknod = nfs_mknod,
925 .rename = nfs_rename,
926 .permission = nfs_permission,
927 .getattr = nfs_getattr,
928 .setattr = nfs_setattr,
Christoph Hellwig5f13ee92014-01-30 06:01:52 -0800929#ifdef CONFIG_NFS_V3_ACL
Christoph Hellwig74adf832014-06-18 11:07:03 +0200930 .listxattr = nfs3_listxattr,
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800931 .get_acl = nfs3_get_acl,
932 .set_acl = nfs3_set_acl,
933#endif
Bryan Schumakerab962912012-07-16 16:39:11 -0400934};
935
936static const struct inode_operations nfs3_file_inode_operations = {
937 .permission = nfs_permission,
938 .getattr = nfs_getattr,
939 .setattr = nfs_setattr,
Christoph Hellwig5f13ee92014-01-30 06:01:52 -0800940#ifdef CONFIG_NFS_V3_ACL
Christoph Hellwig74adf832014-06-18 11:07:03 +0200941 .listxattr = nfs3_listxattr,
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800942 .get_acl = nfs3_get_acl,
943 .set_acl = nfs3_set_acl,
944#endif
Bryan Schumakerab962912012-07-16 16:39:11 -0400945};
946
David Howells509de812006-08-22 20:06:11 -0400947const struct nfs_rpc_ops nfs_v3_clientops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 .version = 3, /* protocol version */
949 .dentry_ops = &nfs_dentry_operations,
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +0000950 .dir_inode_ops = &nfs3_dir_inode_operations,
951 .file_inode_ops = &nfs3_file_inode_operations,
Jeff Layton1788ea62011-11-04 13:31:21 -0400952 .file_ops = &nfs_file_operations,
Benjamin Coddingtonf30cb752017-04-11 12:50:12 -0400953 .nlmclnt_ops = &nlmclnt_fl_close_lock_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 .getroot = nfs3_proc_get_root,
Bryan Schumaker281cad42012-04-27 13:27:45 -0400955 .submount = nfs_submount,
Bryan Schumakerff9099f22012-07-30 16:05:18 -0400956 .try_mount = nfs_try_mount,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 .getattr = nfs3_proc_getattr,
958 .setattr = nfs3_proc_setattr,
959 .lookup = nfs3_proc_lookup,
960 .access = nfs3_proc_access,
961 .readlink = nfs3_proc_readlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 .create = nfs3_proc_create,
963 .remove = nfs3_proc_remove,
964 .unlink_setup = nfs3_proc_unlink_setup,
Bryan Schumaker34e137c2012-03-19 14:54:41 -0400965 .unlink_rpc_prepare = nfs3_proc_unlink_rpc_prepare,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 .unlink_done = nfs3_proc_unlink_done,
Jeff Laytond3d41522010-09-17 17:31:57 -0400967 .rename_setup = nfs3_proc_rename_setup,
Bryan Schumakerc6bfa1a2012-03-19 14:54:42 -0400968 .rename_rpc_prepare = nfs3_proc_rename_rpc_prepare,
Jeff Laytond3d41522010-09-17 17:31:57 -0400969 .rename_done = nfs3_proc_rename_done,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 .link = nfs3_proc_link,
971 .symlink = nfs3_proc_symlink,
972 .mkdir = nfs3_proc_mkdir,
973 .rmdir = nfs3_proc_rmdir,
974 .readdir = nfs3_proc_readdir,
975 .mknod = nfs3_proc_mknod,
976 .statfs = nfs3_proc_statfs,
977 .fsinfo = nfs3_proc_fsinfo,
978 .pathconf = nfs3_proc_pathconf,
979 .decode_dirent = nfs3_decode_dirent,
Anna Schumakera4cdda52014-05-06 09:12:31 -0400980 .pgio_rpc_prepare = nfs3_proc_pgio_rpc_prepare,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 .read_setup = nfs3_proc_read_setup,
Trond Myklebustec06c092006-03-20 13:44:27 -0500982 .read_done = nfs3_read_done,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 .write_setup = nfs3_proc_write_setup,
Trond Myklebust788e7a82006-03-20 13:44:27 -0500984 .write_done = nfs3_write_done,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 .commit_setup = nfs3_proc_commit_setup,
Fred Isaman0b7c0152012-04-20 14:47:39 -0400986 .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare,
Trond Myklebust788e7a82006-03-20 13:44:27 -0500987 .commit_done = nfs3_commit_done,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 .lock = nfs3_proc_lock,
Christoph Hellwig013cdf12013-12-20 05:16:53 -0800989 .clear_acl_cache = forget_all_cached_acls,
Trond Myklebust7fe5c392009-03-19 15:35:50 -0400990 .close_context = nfs_close_context,
Bryan Schumaker011e2a72012-06-20 15:53:43 -0400991 .have_delegation = nfs3_have_delegation,
Bryan Schumaker57ec14c2012-06-20 15:53:44 -0400992 .return_delegation = nfs3_return_delegation,
Bryan Schumaker6663ee72012-06-20 15:53:46 -0400993 .alloc_client = nfs_alloc_client,
Andy Adamson45a52a02011-03-01 01:34:08 +0000994 .init_client = nfs_init_client,
Bryan Schumakercdb7ece2012-06-20 15:53:45 -0400995 .free_client = nfs_free_client,
Bryan Schumaker1179acc2012-07-30 16:05:19 -0400996 .create_server = nfs3_create_server,
997 .clone_server = nfs3_clone_server,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998};