blob: f57dba8150991439c2e175832c99cbd17304205b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/nfs/nfs4proc.c
3 *
4 * Client-side procedure declarations for NFSv4.
5 *
6 * Copyright (c) 2002 The Regents of the University of Michigan.
7 * All rights reserved.
8 *
9 * Kendrick Smith <kmsmith@umich.edu>
10 * Andy Adamson <andros@umich.edu>
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <linux/mm.h>
39#include <linux/utsname.h>
40#include <linux/delay.h>
41#include <linux/errno.h>
42#include <linux/string.h>
43#include <linux/sunrpc/clnt.h>
44#include <linux/nfs.h>
45#include <linux/nfs4.h>
46#include <linux/nfs_fs.h>
47#include <linux/nfs_page.h>
48#include <linux/smp_lock.h>
49#include <linux/namei.h>
50
Trond Myklebust4ce79712005-06-22 17:16:21 +000051#include "nfs4_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include "delegation.h"
53
54#define NFSDBG_FACILITY NFSDBG_PROC
55
56#define NFS4_POLL_RETRY_MIN (1*HZ)
57#define NFS4_POLL_RETRY_MAX (15*HZ)
58
Trond Myklebust0a8838f2005-10-18 14:20:14 -070059static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
61static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
62static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
63static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
64extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
65extern struct rpc_procinfo nfs4_procedures[];
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067/* Prevent leaks of NFSv4 errors into userland */
68int nfs4_map_errors(int err)
69{
70 if (err < -1000) {
71 dprintk("%s could not handle NFSv4 error %d\n",
72 __FUNCTION__, -err);
73 return -EIO;
74 }
75 return err;
76}
77
78/*
79 * This is our standard bitmap for GETATTR requests.
80 */
81const u32 nfs4_fattr_bitmap[2] = {
82 FATTR4_WORD0_TYPE
83 | FATTR4_WORD0_CHANGE
84 | FATTR4_WORD0_SIZE
85 | FATTR4_WORD0_FSID
86 | FATTR4_WORD0_FILEID,
87 FATTR4_WORD1_MODE
88 | FATTR4_WORD1_NUMLINKS
89 | FATTR4_WORD1_OWNER
90 | FATTR4_WORD1_OWNER_GROUP
91 | FATTR4_WORD1_RAWDEV
92 | FATTR4_WORD1_SPACE_USED
93 | FATTR4_WORD1_TIME_ACCESS
94 | FATTR4_WORD1_TIME_METADATA
95 | FATTR4_WORD1_TIME_MODIFY
96};
97
98const u32 nfs4_statfs_bitmap[2] = {
99 FATTR4_WORD0_FILES_AVAIL
100 | FATTR4_WORD0_FILES_FREE
101 | FATTR4_WORD0_FILES_TOTAL,
102 FATTR4_WORD1_SPACE_AVAIL
103 | FATTR4_WORD1_SPACE_FREE
104 | FATTR4_WORD1_SPACE_TOTAL
105};
106
Trond Myklebust4ce79712005-06-22 17:16:21 +0000107const u32 nfs4_pathconf_bitmap[2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 FATTR4_WORD0_MAXLINK
109 | FATTR4_WORD0_MAXNAME,
110 0
111};
112
113const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
114 | FATTR4_WORD0_MAXREAD
115 | FATTR4_WORD0_MAXWRITE
116 | FATTR4_WORD0_LEASE_TIME,
117 0
118};
119
120static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
121 struct nfs4_readdir_arg *readdir)
122{
123 u32 *start, *p;
124
125 BUG_ON(readdir->count < 80);
126 if (cookie > 2) {
Adrian Bunkb7ef1952005-06-22 17:16:28 +0000127 readdir->cookie = cookie;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
129 return;
130 }
131
132 readdir->cookie = 0;
133 memset(&readdir->verifier, 0, sizeof(readdir->verifier));
134 if (cookie == 2)
135 return;
136
137 /*
138 * NFSv4 servers do not return entries for '.' and '..'
139 * Therefore, we fake these entries here. We let '.'
140 * have cookie 0 and '..' have cookie 1. Note that
141 * when talking to the server, we always send cookie 0
142 * instead of 1 or 2.
143 */
144 start = p = (u32 *)kmap_atomic(*readdir->pages, KM_USER0);
145
146 if (cookie == 0) {
147 *p++ = xdr_one; /* next */
148 *p++ = xdr_zero; /* cookie, first word */
149 *p++ = xdr_one; /* cookie, second word */
150 *p++ = xdr_one; /* entry len */
151 memcpy(p, ".\0\0\0", 4); /* entry */
152 p++;
153 *p++ = xdr_one; /* bitmap length */
154 *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */
155 *p++ = htonl(8); /* attribute buffer length */
156 p = xdr_encode_hyper(p, dentry->d_inode->i_ino);
157 }
158
159 *p++ = xdr_one; /* next */
160 *p++ = xdr_zero; /* cookie, first word */
161 *p++ = xdr_two; /* cookie, second word */
162 *p++ = xdr_two; /* entry len */
163 memcpy(p, "..\0\0", 4); /* entry */
164 p++;
165 *p++ = xdr_one; /* bitmap length */
166 *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */
167 *p++ = htonl(8); /* attribute buffer length */
168 p = xdr_encode_hyper(p, dentry->d_parent->d_inode->i_ino);
169
170 readdir->pgbase = (char *)p - (char *)start;
171 readdir->count -= readdir->pgbase;
172 kunmap_atomic(start, KM_USER0);
173}
174
175static void
176renew_lease(struct nfs_server *server, unsigned long timestamp)
177{
178 struct nfs4_client *clp = server->nfs4_state;
179 spin_lock(&clp->cl_lock);
180 if (time_before(clp->cl_last_renewal,timestamp))
181 clp->cl_last_renewal = timestamp;
182 spin_unlock(&clp->cl_lock);
183}
184
185static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinfo)
186{
187 struct nfs_inode *nfsi = NFS_I(inode);
188
189 if (cinfo->before == nfsi->change_attr && cinfo->atomic)
190 nfsi->change_attr = cinfo->after;
191}
192
Trond Myklebust95121352005-10-18 14:20:12 -0700193/* Helper for asynchronous RPC calls */
194static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin,
195 rpc_action tk_exit, void *calldata)
196{
197 struct rpc_task *task;
198
199 if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC)))
200 return -ENOMEM;
201
202 task->tk_calldata = calldata;
203 task->tk_action = tk_begin;
204 rpc_execute(task);
205 return 0;
206}
207
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
209{
210 struct inode *inode = state->inode;
211
212 open_flags &= (FMODE_READ|FMODE_WRITE);
213 /* Protect against nfs4_find_state() */
214 spin_lock(&inode->i_lock);
215 state->state |= open_flags;
216 /* NB! List reordering - see the reclaim code for why. */
217 if ((open_flags & FMODE_WRITE) && 0 == state->nwriters++)
218 list_move(&state->open_states, &state->owner->so_states);
219 if (open_flags & FMODE_READ)
220 state->nreaders++;
221 memcpy(&state->stateid, stateid, sizeof(state->stateid));
222 spin_unlock(&inode->i_lock);
223}
224
225/*
226 * OPEN_RECLAIM:
227 * reclaim state on the server after a reboot.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 */
229static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
230{
231 struct inode *inode = state->inode;
232 struct nfs_server *server = NFS_SERVER(inode);
233 struct nfs_delegation *delegation = NFS_I(inode)->delegation;
234 struct nfs_openargs o_arg = {
235 .fh = NFS_FH(inode),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 .id = sp->so_id,
237 .open_flags = state->state,
238 .clientid = server->nfs4_state->cl_clientid,
239 .claim = NFS4_OPEN_CLAIM_PREVIOUS,
240 .bitmask = server->attr_bitmask,
241 };
242 struct nfs_openres o_res = {
243 .server = server, /* Grrr */
244 };
245 struct rpc_message msg = {
246 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
247 .rpc_argp = &o_arg,
248 .rpc_resp = &o_res,
249 .rpc_cred = sp->so_cred,
250 };
251 int status;
252
253 if (delegation != NULL) {
254 if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
255 memcpy(&state->stateid, &delegation->stateid,
256 sizeof(state->stateid));
257 set_bit(NFS_DELEGATED_STATE, &state->flags);
258 return 0;
259 }
260 o_arg.u.delegation_type = delegation->type;
261 }
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700262 o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
263 if (o_arg.seqid == NULL)
264 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700266 /* Confirm the sequence as being established */
267 nfs_confirm_seqid(&sp->so_seqid, status);
268 nfs_increment_open_seqid(status, o_arg.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 if (status == 0) {
270 memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
271 if (o_res.delegation_type != 0) {
272 nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
273 /* Did the server issue an immediate delegation recall? */
274 if (o_res.do_recall)
275 nfs_async_inode_return_delegation(inode, &o_res.stateid);
276 }
277 }
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700278 nfs_free_seqid(o_arg.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 clear_bit(NFS_DELEGATED_STATE, &state->flags);
280 /* Ensure we update the inode attributes */
281 NFS_CACHEINV(inode);
282 return status;
283}
284
285static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
286{
287 struct nfs_server *server = NFS_SERVER(state->inode);
288 struct nfs4_exception exception = { };
289 int err;
290 do {
291 err = _nfs4_open_reclaim(sp, state);
Trond Myklebust202b50d2005-06-22 17:16:29 +0000292 if (err != -NFS4ERR_DELAY)
293 break;
294 nfs4_handle_exception(server, err, &exception);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 } while (exception.retry);
296 return err;
297}
298
299static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
300{
301 struct nfs4_state_owner *sp = state->owner;
302 struct inode *inode = dentry->d_inode;
303 struct nfs_server *server = NFS_SERVER(inode);
304 struct dentry *parent = dget_parent(dentry);
305 struct nfs_openargs arg = {
306 .fh = NFS_FH(parent->d_inode),
307 .clientid = server->nfs4_state->cl_clientid,
308 .name = &dentry->d_name,
309 .id = sp->so_id,
310 .server = server,
311 .bitmask = server->attr_bitmask,
312 .claim = NFS4_OPEN_CLAIM_DELEGATE_CUR,
313 };
314 struct nfs_openres res = {
315 .server = server,
316 };
317 struct rpc_message msg = {
318 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
319 .rpc_argp = &arg,
320 .rpc_resp = &res,
321 .rpc_cred = sp->so_cred,
322 };
323 int status = 0;
324
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
326 goto out;
327 if (state->state == 0)
328 goto out;
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700329 arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
330 status = -ENOMEM;
331 if (arg.seqid == NULL)
332 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 arg.open_flags = state->state;
334 memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data));
335 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700336 nfs_increment_open_seqid(status, arg.seqid);
Trond Myklebust0a8838f2005-10-18 14:20:14 -0700337 if (status != 0)
338 goto out_free;
339 if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
340 status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode),
341 sp, &res.stateid, arg.seqid);
342 if (status != 0)
343 goto out_free;
344 }
345 nfs_confirm_seqid(&sp->so_seqid, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 if (status >= 0) {
347 memcpy(state->stateid.data, res.stateid.data,
348 sizeof(state->stateid.data));
349 clear_bit(NFS_DELEGATED_STATE, &state->flags);
350 }
Trond Myklebust0a8838f2005-10-18 14:20:14 -0700351out_free:
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700352 nfs_free_seqid(arg.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 dput(parent);
355 return status;
356}
357
358int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
359{
360 struct nfs4_exception exception = { };
361 struct nfs_server *server = NFS_SERVER(dentry->d_inode);
362 int err;
363 do {
364 err = _nfs4_open_delegation_recall(dentry, state);
365 switch (err) {
366 case 0:
367 return err;
368 case -NFS4ERR_STALE_CLIENTID:
369 case -NFS4ERR_STALE_STATEID:
370 case -NFS4ERR_EXPIRED:
371 /* Don't recall a delegation if it was lost */
372 nfs4_schedule_state_recovery(server->nfs4_state);
373 return err;
374 }
375 err = nfs4_handle_exception(server, err, &exception);
376 } while (exception.retry);
377 return err;
378}
379
Trond Myklebust0a8838f2005-10-18 14:20:14 -0700380static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
382 struct nfs_open_confirmargs arg = {
383 .fh = fh,
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700384 .seqid = seqid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 .stateid = *stateid,
386 };
387 struct nfs_open_confirmres res;
388 struct rpc_message msg = {
389 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
390 .rpc_argp = &arg,
391 .rpc_resp = &res,
392 .rpc_cred = sp->so_cred,
393 };
394 int status;
395
396 status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700397 /* Confirm the sequence as being established */
398 nfs_confirm_seqid(&sp->so_seqid, status);
399 nfs_increment_open_seqid(status, seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 if (status >= 0)
401 memcpy(stateid, &res.stateid, sizeof(*stateid));
402 return status;
403}
404
405static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, struct nfs_openargs *o_arg, struct nfs_openres *o_res)
406{
407 struct nfs_server *server = NFS_SERVER(dir);
408 struct rpc_message msg = {
409 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
410 .rpc_argp = o_arg,
411 .rpc_resp = o_res,
412 .rpc_cred = sp->so_cred,
413 };
414 int status;
415
416 /* Update sequence id. The caller must serialize! */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 o_arg->id = sp->so_id;
418 o_arg->clientid = sp->so_client->cl_clientid;
419
420 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700421 nfs_increment_open_seqid(status, o_arg->seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 if (status != 0)
423 goto out;
424 update_changeattr(dir, &o_res->cinfo);
425 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
426 status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700427 sp, &o_res->stateid, o_arg->seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 if (status != 0)
429 goto out;
430 }
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700431 nfs_confirm_seqid(&sp->so_seqid, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
433 status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
434out:
435 return status;
436}
437
438static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
439{
440 struct nfs_access_entry cache;
441 int mask = 0;
442 int status;
443
444 if (openflags & FMODE_READ)
445 mask |= MAY_READ;
446 if (openflags & FMODE_WRITE)
447 mask |= MAY_WRITE;
448 status = nfs_access_get_cached(inode, cred, &cache);
449 if (status == 0)
450 goto out;
451
452 /* Be clever: ask server to check for all possible rights */
453 cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
454 cache.cred = cred;
455 cache.jiffies = jiffies;
456 status = _nfs4_proc_access(inode, &cache);
457 if (status != 0)
458 return status;
459 nfs_access_add_cache(inode, &cache);
460out:
461 if ((cache.mask & mask) == mask)
462 return 0;
463 return -EACCES;
464}
465
466/*
467 * OPEN_EXPIRED:
468 * reclaim state on the server after a network partition.
469 * Assumes caller holds the appropriate lock
470 */
471static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
472{
473 struct dentry *parent = dget_parent(dentry);
474 struct inode *dir = parent->d_inode;
475 struct inode *inode = state->inode;
476 struct nfs_server *server = NFS_SERVER(dir);
477 struct nfs_delegation *delegation = NFS_I(inode)->delegation;
478 struct nfs_fattr f_attr = {
479 .valid = 0,
480 };
481 struct nfs_openargs o_arg = {
482 .fh = NFS_FH(dir),
483 .open_flags = state->state,
484 .name = &dentry->d_name,
485 .bitmask = server->attr_bitmask,
486 .claim = NFS4_OPEN_CLAIM_NULL,
487 };
488 struct nfs_openres o_res = {
489 .f_attr = &f_attr,
490 .server = server,
491 };
492 int status = 0;
493
494 if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
495 status = _nfs4_do_access(inode, sp->so_cred, state->state);
496 if (status < 0)
497 goto out;
498 memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
499 set_bit(NFS_DELEGATED_STATE, &state->flags);
500 goto out;
501 }
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700502 o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
503 status = -ENOMEM;
504 if (o_arg.seqid == NULL)
505 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
507 if (status != 0)
508 goto out_nodeleg;
509 /* Check if files differ */
510 if ((f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT))
511 goto out_stale;
512 /* Has the file handle changed? */
513 if (nfs_compare_fh(&o_res.fh, NFS_FH(inode)) != 0) {
514 /* Verify if the change attributes are the same */
515 if (f_attr.change_attr != NFS_I(inode)->change_attr)
516 goto out_stale;
517 if (nfs_size_to_loff_t(f_attr.size) != inode->i_size)
518 goto out_stale;
519 /* Lets just pretend that this is the same file */
520 nfs_copy_fh(NFS_FH(inode), &o_res.fh);
521 NFS_I(inode)->fileid = f_attr.fileid;
522 }
523 memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
524 if (o_res.delegation_type != 0) {
525 if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM))
526 nfs_inode_set_delegation(inode, sp->so_cred, &o_res);
527 else
528 nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
529 }
530out_nodeleg:
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700531 nfs_free_seqid(o_arg.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 clear_bit(NFS_DELEGATED_STATE, &state->flags);
533out:
534 dput(parent);
535 return status;
536out_stale:
537 status = -ESTALE;
538 /* Invalidate the state owner so we don't ever use it again */
539 nfs4_drop_state_owner(sp);
540 d_drop(dentry);
541 /* Should we be trying to close that stateid? */
542 goto out_nodeleg;
543}
544
Trond Myklebust202b50d2005-06-22 17:16:29 +0000545static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
546{
547 struct nfs_server *server = NFS_SERVER(dentry->d_inode);
548 struct nfs4_exception exception = { };
549 int err;
550
551 do {
552 err = _nfs4_open_expired(sp, state, dentry);
553 if (err == -NFS4ERR_DELAY)
554 nfs4_handle_exception(server, err, &exception);
555 } while (exception.retry);
556 return err;
557}
558
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
560{
561 struct nfs_inode *nfsi = NFS_I(state->inode);
562 struct nfs_open_context *ctx;
563 int status;
564
565 spin_lock(&state->inode->i_lock);
566 list_for_each_entry(ctx, &nfsi->open_files, list) {
567 if (ctx->state != state)
568 continue;
569 get_nfs_open_context(ctx);
570 spin_unlock(&state->inode->i_lock);
Trond Myklebust202b50d2005-06-22 17:16:29 +0000571 status = nfs4_do_open_expired(sp, state, ctx->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 put_nfs_open_context(ctx);
573 return status;
574 }
575 spin_unlock(&state->inode->i_lock);
576 return -ENOENT;
577}
578
579/*
580 * Returns an nfs4_state + an extra reference to the inode
581 */
582static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
583{
584 struct nfs_delegation *delegation;
585 struct nfs_server *server = NFS_SERVER(inode);
586 struct nfs4_client *clp = server->nfs4_state;
587 struct nfs_inode *nfsi = NFS_I(inode);
588 struct nfs4_state_owner *sp = NULL;
589 struct nfs4_state *state = NULL;
590 int open_flags = flags & (FMODE_READ|FMODE_WRITE);
591 int err;
592
593 /* Protect against reboot recovery - NOTE ORDER! */
594 down_read(&clp->cl_sem);
595 /* Protect against delegation recall */
596 down_read(&nfsi->rwsem);
597 delegation = NFS_I(inode)->delegation;
598 err = -ENOENT;
599 if (delegation == NULL || (delegation->type & open_flags) != open_flags)
600 goto out_err;
601 err = -ENOMEM;
602 if (!(sp = nfs4_get_state_owner(server, cred))) {
603 dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
604 goto out_err;
605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 state = nfs4_get_open_state(inode, sp);
607 if (state == NULL)
608 goto out_err;
609
610 err = -ENOENT;
611 if ((state->state & open_flags) == open_flags) {
612 spin_lock(&inode->i_lock);
613 if (open_flags & FMODE_READ)
614 state->nreaders++;
615 if (open_flags & FMODE_WRITE)
616 state->nwriters++;
617 spin_unlock(&inode->i_lock);
618 goto out_ok;
619 } else if (state->state != 0)
620 goto out_err;
621
622 lock_kernel();
623 err = _nfs4_do_access(inode, cred, open_flags);
624 unlock_kernel();
625 if (err != 0)
626 goto out_err;
627 set_bit(NFS_DELEGATED_STATE, &state->flags);
628 update_open_stateid(state, &delegation->stateid, open_flags);
629out_ok:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 nfs4_put_state_owner(sp);
631 up_read(&nfsi->rwsem);
632 up_read(&clp->cl_sem);
633 igrab(inode);
634 *res = state;
635 return 0;
636out_err:
637 if (sp != NULL) {
638 if (state != NULL)
639 nfs4_put_open_state(state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 nfs4_put_state_owner(sp);
641 }
642 up_read(&nfsi->rwsem);
643 up_read(&clp->cl_sem);
644 return err;
645}
646
647static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred)
648{
649 struct nfs4_exception exception = { };
650 struct nfs4_state *res;
651 int err;
652
653 do {
654 err = _nfs4_open_delegated(inode, flags, cred, &res);
655 if (err == 0)
656 break;
657 res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(inode),
658 err, &exception));
659 } while (exception.retry);
660 return res;
661}
662
663/*
664 * Returns an nfs4_state + an referenced inode
665 */
666static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
667{
668 struct nfs4_state_owner *sp;
669 struct nfs4_state *state = NULL;
670 struct nfs_server *server = NFS_SERVER(dir);
671 struct nfs4_client *clp = server->nfs4_state;
672 struct inode *inode = NULL;
673 int status;
674 struct nfs_fattr f_attr = {
675 .valid = 0,
676 };
677 struct nfs_openargs o_arg = {
678 .fh = NFS_FH(dir),
679 .open_flags = flags,
680 .name = &dentry->d_name,
681 .server = server,
682 .bitmask = server->attr_bitmask,
683 .claim = NFS4_OPEN_CLAIM_NULL,
684 };
685 struct nfs_openres o_res = {
686 .f_attr = &f_attr,
687 .server = server,
688 };
689
690 /* Protect against reboot recovery conflicts */
691 down_read(&clp->cl_sem);
692 status = -ENOMEM;
693 if (!(sp = nfs4_get_state_owner(server, cred))) {
694 dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
695 goto out_err;
696 }
697 if (flags & O_EXCL) {
698 u32 *p = (u32 *) o_arg.u.verifier.data;
699 p[0] = jiffies;
700 p[1] = current->pid;
701 } else
702 o_arg.u.attrs = sattr;
703 /* Serialization for the sequence id */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700705 o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
706 if (o_arg.seqid == NULL)
707 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
709 if (status != 0)
710 goto out_err;
711
712 status = -ENOMEM;
713 inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
714 if (!inode)
715 goto out_err;
716 state = nfs4_get_open_state(inode, sp);
717 if (!state)
718 goto out_err;
719 update_open_stateid(state, &o_res.stateid, flags);
720 if (o_res.delegation_type != 0)
721 nfs_inode_set_delegation(inode, cred, &o_res);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700722 nfs_free_seqid(o_arg.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 nfs4_put_state_owner(sp);
724 up_read(&clp->cl_sem);
725 *res = state;
726 return 0;
727out_err:
728 if (sp != NULL) {
729 if (state != NULL)
730 nfs4_put_open_state(state);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700731 nfs_free_seqid(o_arg.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 nfs4_put_state_owner(sp);
733 }
734 /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */
735 up_read(&clp->cl_sem);
736 if (inode != NULL)
737 iput(inode);
738 *res = NULL;
739 return status;
740}
741
742
743static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
744{
745 struct nfs4_exception exception = { };
746 struct nfs4_state *res;
747 int status;
748
749 do {
750 status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res);
751 if (status == 0)
752 break;
753 /* NOTE: BAD_SEQID means the server and client disagree about the
754 * book-keeping w.r.t. state-changing operations
755 * (OPEN/CLOSE/LOCK/LOCKU...)
756 * It is actually a sign of a bug on the client or on the server.
757 *
758 * If we receive a BAD_SEQID error in the particular case of
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700759 * doing an OPEN, we assume that nfs_increment_open_seqid() will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 * have unhashed the old state_owner for us, and that we can
761 * therefore safely retry using a new one. We should still warn
762 * the user though...
763 */
764 if (status == -NFS4ERR_BAD_SEQID) {
765 printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
766 exception.retry = 1;
767 continue;
768 }
769 res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
770 status, &exception));
771 } while (exception.retry);
772 return res;
773}
774
775static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
776 struct nfs_fh *fhandle, struct iattr *sattr,
777 struct nfs4_state *state)
778{
779 struct nfs_setattrargs arg = {
780 .fh = fhandle,
781 .iap = sattr,
782 .server = server,
783 .bitmask = server->attr_bitmask,
784 };
785 struct nfs_setattrres res = {
786 .fattr = fattr,
787 .server = server,
788 };
789 struct rpc_message msg = {
790 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
791 .rpc_argp = &arg,
792 .rpc_resp = &res,
793 };
Trond Myklebust65e43082005-08-16 11:49:44 -0400794 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
796 fattr->valid = 0;
797
Trond Myklebust08e9eac2005-06-22 17:16:29 +0000798 if (state != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 msg.rpc_cred = state->owner->so_cred;
Trond Myklebust08e9eac2005-06-22 17:16:29 +0000800 nfs4_copy_stateid(&arg.stateid, state, current->files);
801 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
803
Trond Myklebust65e43082005-08-16 11:49:44 -0400804 status = rpc_call_sync(server->client, &msg, 0);
805 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806}
807
808static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
809 struct nfs_fh *fhandle, struct iattr *sattr,
810 struct nfs4_state *state)
811{
812 struct nfs4_exception exception = { };
813 int err;
814 do {
815 err = nfs4_handle_exception(server,
816 _nfs4_do_setattr(server, fattr, fhandle, sattr,
817 state),
818 &exception);
819 } while (exception.retry);
820 return err;
821}
822
823struct nfs4_closedata {
824 struct inode *inode;
825 struct nfs4_state *state;
826 struct nfs_closeargs arg;
827 struct nfs_closeres res;
828};
829
Trond Myklebust95121352005-10-18 14:20:12 -0700830static void nfs4_free_closedata(struct nfs4_closedata *calldata)
831{
832 struct nfs4_state *state = calldata->state;
833 struct nfs4_state_owner *sp = state->owner;
Trond Myklebust95121352005-10-18 14:20:12 -0700834
835 nfs4_put_open_state(calldata->state);
836 nfs_free_seqid(calldata->arg.seqid);
Trond Myklebust95121352005-10-18 14:20:12 -0700837 nfs4_put_state_owner(sp);
Trond Myklebust95121352005-10-18 14:20:12 -0700838 kfree(calldata);
839}
840
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841static void nfs4_close_done(struct rpc_task *task)
842{
843 struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
844 struct nfs4_state *state = calldata->state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 struct nfs_server *server = NFS_SERVER(calldata->inode);
846
847 /* hmm. we are done with the inode, and in the process of freeing
848 * the state_owner. we keep this around to process errors
849 */
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700850 nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 switch (task->tk_status) {
852 case 0:
853 memcpy(&state->stateid, &calldata->res.stateid,
854 sizeof(state->stateid));
855 break;
856 case -NFS4ERR_STALE_STATEID:
857 case -NFS4ERR_EXPIRED:
858 state->state = calldata->arg.open_flags;
859 nfs4_schedule_state_recovery(server->nfs4_state);
860 break;
861 default:
862 if (nfs4_async_handle_error(task, server) == -EAGAIN) {
863 rpc_restart_call(task);
864 return;
865 }
866 }
867 state->state = calldata->arg.open_flags;
Trond Myklebust95121352005-10-18 14:20:12 -0700868 nfs4_free_closedata(calldata);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869}
870
Trond Myklebust95121352005-10-18 14:20:12 -0700871static void nfs4_close_begin(struct rpc_task *task)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872{
Trond Myklebust95121352005-10-18 14:20:12 -0700873 struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
874 struct nfs4_state *state = calldata->state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 struct rpc_message msg = {
876 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
877 .rpc_argp = &calldata->arg,
878 .rpc_resp = &calldata->res,
Trond Myklebust95121352005-10-18 14:20:12 -0700879 .rpc_cred = state->owner->so_cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 };
Trond Myklebust95121352005-10-18 14:20:12 -0700881 int mode = 0;
882 int status;
883
884 status = nfs_wait_on_sequence(calldata->arg.seqid, task);
885 if (status != 0)
886 return;
887 /* Don't reorder reads */
888 smp_rmb();
889 /* Recalculate the new open mode in case someone reopened the file
890 * while we were waiting in line to be scheduled.
891 */
892 if (state->nreaders != 0)
893 mode |= FMODE_READ;
894 if (state->nwriters != 0)
895 mode |= FMODE_WRITE;
896 if (test_bit(NFS_DELEGATED_STATE, &state->flags))
897 state->state = mode;
898 if (mode == state->state) {
899 nfs4_free_closedata(calldata);
900 task->tk_exit = NULL;
901 rpc_exit(task, 0);
902 return;
903 }
904 if (mode != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
Trond Myklebust95121352005-10-18 14:20:12 -0700906 calldata->arg.open_flags = mode;
907 rpc_call_setup(task, &msg, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908}
909
910/*
911 * It is possible for data to be read/written from a mem-mapped file
912 * after the sys_close call (which hits the vfs layer as a flush).
913 * This means that we can't safely call nfsv4 close on a file until
914 * the inode is cleared. This in turn means that we are not good
915 * NFSv4 citizens - we do not indicate to the server to update the file's
916 * share state even when we are done with one of the three share
917 * stateid's in the inode.
918 *
919 * NOTE: Caller must be holding the sp->so_owner semaphore!
920 */
921int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode)
922{
923 struct nfs4_closedata *calldata;
Trond Myklebust95121352005-10-18 14:20:12 -0700924 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Trond Myklebust95121352005-10-18 14:20:12 -0700926 calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (calldata == NULL)
Trond Myklebust95121352005-10-18 14:20:12 -0700928 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 calldata->inode = inode;
930 calldata->state = state;
931 calldata->arg.fh = NFS_FH(inode);
Trond Myklebust95121352005-10-18 14:20:12 -0700932 calldata->arg.stateid = &state->stateid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 /* Serialization for the sequence id */
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700934 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
Trond Myklebust95121352005-10-18 14:20:12 -0700935 if (calldata->arg.seqid == NULL)
936 goto out_free_calldata;
937
938 status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_close_begin,
939 nfs4_close_done, calldata);
940 if (status == 0)
941 goto out;
942
943 nfs_free_seqid(calldata->arg.seqid);
944out_free_calldata:
945 kfree(calldata);
946out:
947 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948}
949
950struct inode *
951nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
952{
953 struct iattr attr;
954 struct rpc_cred *cred;
955 struct nfs4_state *state;
956
957 if (nd->flags & LOOKUP_CREATE) {
958 attr.ia_mode = nd->intent.open.create_mode;
959 attr.ia_valid = ATTR_MODE;
960 if (!IS_POSIXACL(dir))
961 attr.ia_mode &= ~current->fs->umask;
962 } else {
963 attr.ia_valid = 0;
964 BUG_ON(nd->intent.open.flags & O_CREAT);
965 }
966
967 cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
968 if (IS_ERR(cred))
969 return (struct inode *)cred;
970 state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
971 put_rpccred(cred);
972 if (IS_ERR(state))
973 return (struct inode *)state;
974 return state->inode;
975}
976
977int
978nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
979{
980 struct rpc_cred *cred;
981 struct nfs4_state *state;
982 struct inode *inode;
983
984 cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
985 if (IS_ERR(cred))
986 return PTR_ERR(cred);
987 state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
988 if (IS_ERR(state))
989 state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
990 put_rpccred(cred);
991 if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0)
992 return 1;
993 if (IS_ERR(state))
994 return 0;
995 inode = state->inode;
996 if (inode == dentry->d_inode) {
997 iput(inode);
998 return 1;
999 }
1000 d_drop(dentry);
1001 nfs4_close_state(state, openflags);
1002 iput(inode);
1003 return 0;
1004}
1005
1006
1007static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
1008{
1009 struct nfs4_server_caps_res res = {};
1010 struct rpc_message msg = {
1011 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
1012 .rpc_argp = fhandle,
1013 .rpc_resp = &res,
1014 };
1015 int status;
1016
1017 status = rpc_call_sync(server->client, &msg, 0);
1018 if (status == 0) {
1019 memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
1020 if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
1021 server->caps |= NFS_CAP_ACLS;
1022 if (res.has_links != 0)
1023 server->caps |= NFS_CAP_HARDLINKS;
1024 if (res.has_symlinks != 0)
1025 server->caps |= NFS_CAP_SYMLINKS;
1026 server->acl_bitmask = res.acl_bitmask;
1027 }
1028 return status;
1029}
1030
1031static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
1032{
1033 struct nfs4_exception exception = { };
1034 int err;
1035 do {
1036 err = nfs4_handle_exception(server,
1037 _nfs4_server_capabilities(server, fhandle),
1038 &exception);
1039 } while (exception.retry);
1040 return err;
1041}
1042
1043static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
1044 struct nfs_fsinfo *info)
1045{
1046 struct nfs_fattr * fattr = info->fattr;
1047 struct nfs4_lookup_root_arg args = {
1048 .bitmask = nfs4_fattr_bitmap,
1049 };
1050 struct nfs4_lookup_res res = {
1051 .server = server,
1052 .fattr = fattr,
1053 .fh = fhandle,
1054 };
1055 struct rpc_message msg = {
1056 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP_ROOT],
1057 .rpc_argp = &args,
1058 .rpc_resp = &res,
1059 };
1060 fattr->valid = 0;
1061 return rpc_call_sync(server->client, &msg, 0);
1062}
1063
1064static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
1065 struct nfs_fsinfo *info)
1066{
1067 struct nfs4_exception exception = { };
1068 int err;
1069 do {
1070 err = nfs4_handle_exception(server,
1071 _nfs4_lookup_root(server, fhandle, info),
1072 &exception);
1073 } while (exception.retry);
1074 return err;
1075}
1076
1077static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
1078 struct nfs_fsinfo *info)
1079{
1080 struct nfs_fattr * fattr = info->fattr;
1081 unsigned char * p;
1082 struct qstr q;
1083 struct nfs4_lookup_arg args = {
1084 .dir_fh = fhandle,
1085 .name = &q,
1086 .bitmask = nfs4_fattr_bitmap,
1087 };
1088 struct nfs4_lookup_res res = {
1089 .server = server,
1090 .fattr = fattr,
1091 .fh = fhandle,
1092 };
1093 struct rpc_message msg = {
1094 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
1095 .rpc_argp = &args,
1096 .rpc_resp = &res,
1097 };
1098 int status;
1099
1100 /*
1101 * Now we do a separate LOOKUP for each component of the mount path.
1102 * The LOOKUPs are done separately so that we can conveniently
1103 * catch an ERR_WRONGSEC if it occurs along the way...
1104 */
1105 status = nfs4_lookup_root(server, fhandle, info);
1106 if (status)
1107 goto out;
1108
1109 p = server->mnt_path;
1110 for (;;) {
1111 struct nfs4_exception exception = { };
1112
1113 while (*p == '/')
1114 p++;
1115 if (!*p)
1116 break;
1117 q.name = p;
1118 while (*p && (*p != '/'))
1119 p++;
1120 q.len = p - q.name;
1121
1122 do {
1123 fattr->valid = 0;
1124 status = nfs4_handle_exception(server,
1125 rpc_call_sync(server->client, &msg, 0),
1126 &exception);
1127 } while (exception.retry);
1128 if (status == 0)
1129 continue;
1130 if (status == -ENOENT) {
1131 printk(KERN_NOTICE "NFS: mount path %s does not exist!\n", server->mnt_path);
1132 printk(KERN_NOTICE "NFS: suggestion: try mounting '/' instead.\n");
1133 }
1134 break;
1135 }
1136 if (status == 0)
1137 status = nfs4_server_capabilities(server, fhandle);
1138 if (status == 0)
1139 status = nfs4_do_fsinfo(server, fhandle, info);
1140out:
1141 return status;
1142}
1143
1144static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
1145{
1146 struct nfs4_getattr_arg args = {
1147 .fh = fhandle,
1148 .bitmask = server->attr_bitmask,
1149 };
1150 struct nfs4_getattr_res res = {
1151 .fattr = fattr,
1152 .server = server,
1153 };
1154 struct rpc_message msg = {
1155 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
1156 .rpc_argp = &args,
1157 .rpc_resp = &res,
1158 };
1159
1160 fattr->valid = 0;
1161 return rpc_call_sync(server->client, &msg, 0);
1162}
1163
1164static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
1165{
1166 struct nfs4_exception exception = { };
1167 int err;
1168 do {
1169 err = nfs4_handle_exception(server,
1170 _nfs4_proc_getattr(server, fhandle, fattr),
1171 &exception);
1172 } while (exception.retry);
1173 return err;
1174}
1175
1176/*
1177 * The file is not closed if it is opened due to the a request to change
1178 * the size of the file. The open call will not be needed once the
1179 * VFS layer lookup-intents are implemented.
1180 *
1181 * Close is called when the inode is destroyed.
1182 * If we haven't opened the file for O_WRONLY, we
1183 * need to in the size_change case to obtain a stateid.
1184 *
1185 * Got race?
1186 * Because OPEN is always done by name in nfsv4, it is
1187 * possible that we opened a different file by the same
1188 * name. We can recognize this race condition, but we
1189 * can't do anything about it besides returning an error.
1190 *
1191 * This will be fixed with VFS changes (lookup-intent).
1192 */
1193static int
1194nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1195 struct iattr *sattr)
1196{
Trond Myklebust08e9eac2005-06-22 17:16:29 +00001197 struct rpc_cred *cred;
1198 struct inode *inode = dentry->d_inode;
1199 struct nfs4_state *state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 int status;
1201
1202 fattr->valid = 0;
1203
Trond Myklebust08e9eac2005-06-22 17:16:29 +00001204 cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
1205 if (IS_ERR(cred))
1206 return PTR_ERR(cred);
1207 /* Search for an existing WRITE delegation first */
1208 state = nfs4_open_delegated(inode, FMODE_WRITE, cred);
1209 if (!IS_ERR(state)) {
1210 /* NB: nfs4_open_delegated() bumps the inode->i_count */
1211 iput(inode);
1212 } else {
1213 /* Search for an existing open(O_WRITE) stateid */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 state = nfs4_find_state(inode, cred, FMODE_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 }
Trond Myklebust08e9eac2005-06-22 17:16:29 +00001216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
1218 NFS_FH(inode), sattr, state);
Trond Myklebust65e43082005-08-16 11:49:44 -04001219 if (status == 0)
1220 nfs_setattr_update_inode(inode, sattr);
Trond Myklebust08e9eac2005-06-22 17:16:29 +00001221 if (state != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 nfs4_close_state(state, FMODE_WRITE);
Trond Myklebust08e9eac2005-06-22 17:16:29 +00001223 put_rpccred(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 return status;
1225}
1226
1227static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
1228 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
1229{
1230 int status;
1231 struct nfs_server *server = NFS_SERVER(dir);
1232 struct nfs4_lookup_arg args = {
1233 .bitmask = server->attr_bitmask,
1234 .dir_fh = NFS_FH(dir),
1235 .name = name,
1236 };
1237 struct nfs4_lookup_res res = {
1238 .server = server,
1239 .fattr = fattr,
1240 .fh = fhandle,
1241 };
1242 struct rpc_message msg = {
1243 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
1244 .rpc_argp = &args,
1245 .rpc_resp = &res,
1246 };
1247
1248 fattr->valid = 0;
1249
1250 dprintk("NFS call lookup %s\n", name->name);
1251 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1252 dprintk("NFS reply lookup: %d\n", status);
1253 return status;
1254}
1255
1256static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
1257{
1258 struct nfs4_exception exception = { };
1259 int err;
1260 do {
1261 err = nfs4_handle_exception(NFS_SERVER(dir),
1262 _nfs4_proc_lookup(dir, name, fhandle, fattr),
1263 &exception);
1264 } while (exception.retry);
1265 return err;
1266}
1267
1268static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
1269{
1270 struct nfs4_accessargs args = {
1271 .fh = NFS_FH(inode),
1272 };
1273 struct nfs4_accessres res = { 0 };
1274 struct rpc_message msg = {
1275 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
1276 .rpc_argp = &args,
1277 .rpc_resp = &res,
1278 .rpc_cred = entry->cred,
1279 };
1280 int mode = entry->mask;
1281 int status;
1282
1283 /*
1284 * Determine which access bits we want to ask for...
1285 */
1286 if (mode & MAY_READ)
1287 args.access |= NFS4_ACCESS_READ;
1288 if (S_ISDIR(inode->i_mode)) {
1289 if (mode & MAY_WRITE)
1290 args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE;
1291 if (mode & MAY_EXEC)
1292 args.access |= NFS4_ACCESS_LOOKUP;
1293 } else {
1294 if (mode & MAY_WRITE)
1295 args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND;
1296 if (mode & MAY_EXEC)
1297 args.access |= NFS4_ACCESS_EXECUTE;
1298 }
1299 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
1300 if (!status) {
1301 entry->mask = 0;
1302 if (res.access & NFS4_ACCESS_READ)
1303 entry->mask |= MAY_READ;
1304 if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
1305 entry->mask |= MAY_WRITE;
1306 if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
1307 entry->mask |= MAY_EXEC;
1308 }
1309 return status;
1310}
1311
1312static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
1313{
1314 struct nfs4_exception exception = { };
1315 int err;
1316 do {
1317 err = nfs4_handle_exception(NFS_SERVER(inode),
1318 _nfs4_proc_access(inode, entry),
1319 &exception);
1320 } while (exception.retry);
1321 return err;
1322}
1323
1324/*
1325 * TODO: For the time being, we don't try to get any attributes
1326 * along with any of the zero-copy operations READ, READDIR,
1327 * READLINK, WRITE.
1328 *
1329 * In the case of the first three, we want to put the GETATTR
1330 * after the read-type operation -- this is because it is hard
1331 * to predict the length of a GETATTR response in v4, and thus
1332 * align the READ data correctly. This means that the GETATTR
1333 * may end up partially falling into the page cache, and we should
1334 * shift it into the 'tail' of the xdr_buf before processing.
1335 * To do this efficiently, we need to know the total length
1336 * of data received, which doesn't seem to be available outside
1337 * of the RPC layer.
1338 *
1339 * In the case of WRITE, we also want to put the GETATTR after
1340 * the operation -- in this case because we want to make sure
1341 * we get the post-operation mtime and size. This means that
1342 * we can't use xdr_encode_pages() as written: we need a variant
1343 * of it which would leave room in the 'tail' iovec.
1344 *
1345 * Both of these changes to the XDR layer would in fact be quite
1346 * minor, but I decided to leave them for a subsequent patch.
1347 */
1348static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
1349 unsigned int pgbase, unsigned int pglen)
1350{
1351 struct nfs4_readlink args = {
1352 .fh = NFS_FH(inode),
1353 .pgbase = pgbase,
1354 .pglen = pglen,
1355 .pages = &page,
1356 };
1357 struct rpc_message msg = {
1358 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
1359 .rpc_argp = &args,
1360 .rpc_resp = NULL,
1361 };
1362
1363 return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
1364}
1365
1366static int nfs4_proc_readlink(struct inode *inode, struct page *page,
1367 unsigned int pgbase, unsigned int pglen)
1368{
1369 struct nfs4_exception exception = { };
1370 int err;
1371 do {
1372 err = nfs4_handle_exception(NFS_SERVER(inode),
1373 _nfs4_proc_readlink(inode, page, pgbase, pglen),
1374 &exception);
1375 } while (exception.retry);
1376 return err;
1377}
1378
1379static int _nfs4_proc_read(struct nfs_read_data *rdata)
1380{
1381 int flags = rdata->flags;
1382 struct inode *inode = rdata->inode;
1383 struct nfs_fattr *fattr = rdata->res.fattr;
1384 struct nfs_server *server = NFS_SERVER(inode);
1385 struct rpc_message msg = {
1386 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
1387 .rpc_argp = &rdata->args,
1388 .rpc_resp = &rdata->res,
1389 .rpc_cred = rdata->cred,
1390 };
1391 unsigned long timestamp = jiffies;
1392 int status;
1393
1394 dprintk("NFS call read %d @ %Ld\n", rdata->args.count,
1395 (long long) rdata->args.offset);
1396
1397 fattr->valid = 0;
1398 status = rpc_call_sync(server->client, &msg, flags);
1399 if (!status)
1400 renew_lease(server, timestamp);
1401 dprintk("NFS reply read: %d\n", status);
1402 return status;
1403}
1404
1405static int nfs4_proc_read(struct nfs_read_data *rdata)
1406{
1407 struct nfs4_exception exception = { };
1408 int err;
1409 do {
1410 err = nfs4_handle_exception(NFS_SERVER(rdata->inode),
1411 _nfs4_proc_read(rdata),
1412 &exception);
1413 } while (exception.retry);
1414 return err;
1415}
1416
1417static int _nfs4_proc_write(struct nfs_write_data *wdata)
1418{
1419 int rpcflags = wdata->flags;
1420 struct inode *inode = wdata->inode;
1421 struct nfs_fattr *fattr = wdata->res.fattr;
1422 struct nfs_server *server = NFS_SERVER(inode);
1423 struct rpc_message msg = {
1424 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
1425 .rpc_argp = &wdata->args,
1426 .rpc_resp = &wdata->res,
1427 .rpc_cred = wdata->cred,
1428 };
1429 int status;
1430
1431 dprintk("NFS call write %d @ %Ld\n", wdata->args.count,
1432 (long long) wdata->args.offset);
1433
1434 fattr->valid = 0;
1435 status = rpc_call_sync(server->client, &msg, rpcflags);
1436 dprintk("NFS reply write: %d\n", status);
1437 return status;
1438}
1439
1440static int nfs4_proc_write(struct nfs_write_data *wdata)
1441{
1442 struct nfs4_exception exception = { };
1443 int err;
1444 do {
1445 err = nfs4_handle_exception(NFS_SERVER(wdata->inode),
1446 _nfs4_proc_write(wdata),
1447 &exception);
1448 } while (exception.retry);
1449 return err;
1450}
1451
1452static int _nfs4_proc_commit(struct nfs_write_data *cdata)
1453{
1454 struct inode *inode = cdata->inode;
1455 struct nfs_fattr *fattr = cdata->res.fattr;
1456 struct nfs_server *server = NFS_SERVER(inode);
1457 struct rpc_message msg = {
1458 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
1459 .rpc_argp = &cdata->args,
1460 .rpc_resp = &cdata->res,
1461 .rpc_cred = cdata->cred,
1462 };
1463 int status;
1464
1465 dprintk("NFS call commit %d @ %Ld\n", cdata->args.count,
1466 (long long) cdata->args.offset);
1467
1468 fattr->valid = 0;
1469 status = rpc_call_sync(server->client, &msg, 0);
1470 dprintk("NFS reply commit: %d\n", status);
1471 return status;
1472}
1473
1474static int nfs4_proc_commit(struct nfs_write_data *cdata)
1475{
1476 struct nfs4_exception exception = { };
1477 int err;
1478 do {
1479 err = nfs4_handle_exception(NFS_SERVER(cdata->inode),
1480 _nfs4_proc_commit(cdata),
1481 &exception);
1482 } while (exception.retry);
1483 return err;
1484}
1485
1486/*
1487 * Got race?
1488 * We will need to arrange for the VFS layer to provide an atomic open.
1489 * Until then, this create/open method is prone to inefficiency and race
1490 * conditions due to the lookup, create, and open VFS calls from sys_open()
1491 * placed on the wire.
1492 *
1493 * Given the above sorry state of affairs, I'm simply sending an OPEN.
1494 * The file will be opened again in the subsequent VFS open call
1495 * (nfs4_proc_file_open).
1496 *
1497 * The open for read will just hang around to be used by any process that
1498 * opens the file O_RDONLY. This will all be resolved with the VFS changes.
1499 */
1500
1501static int
1502nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1503 int flags)
1504{
1505 struct nfs4_state *state;
1506 struct rpc_cred *cred;
1507 int status = 0;
1508
1509 cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
1510 if (IS_ERR(cred)) {
1511 status = PTR_ERR(cred);
1512 goto out;
1513 }
1514 state = nfs4_do_open(dir, dentry, flags, sattr, cred);
1515 put_rpccred(cred);
1516 if (IS_ERR(state)) {
1517 status = PTR_ERR(state);
1518 goto out;
1519 }
1520 d_instantiate(dentry, state->inode);
1521 if (flags & O_EXCL) {
1522 struct nfs_fattr fattr;
1523 status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
1524 NFS_FH(state->inode), sattr, state);
Trond Myklebust65e43082005-08-16 11:49:44 -04001525 if (status == 0) {
1526 nfs_setattr_update_inode(state->inode, sattr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 goto out;
Trond Myklebust65e43082005-08-16 11:49:44 -04001528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 } else if (flags != 0)
1530 goto out;
1531 nfs4_close_state(state, flags);
1532out:
1533 return status;
1534}
1535
1536static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
1537{
1538 struct nfs4_remove_arg args = {
1539 .fh = NFS_FH(dir),
1540 .name = name,
1541 };
1542 struct nfs4_change_info res;
1543 struct rpc_message msg = {
1544 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
1545 .rpc_argp = &args,
1546 .rpc_resp = &res,
1547 };
1548 int status;
1549
1550 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1551 if (status == 0)
1552 update_changeattr(dir, &res);
1553 return status;
1554}
1555
1556static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
1557{
1558 struct nfs4_exception exception = { };
1559 int err;
1560 do {
1561 err = nfs4_handle_exception(NFS_SERVER(dir),
1562 _nfs4_proc_remove(dir, name),
1563 &exception);
1564 } while (exception.retry);
1565 return err;
1566}
1567
1568struct unlink_desc {
1569 struct nfs4_remove_arg args;
1570 struct nfs4_change_info res;
1571};
1572
1573static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
1574 struct qstr *name)
1575{
1576 struct unlink_desc *up;
1577
1578 up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL);
1579 if (!up)
1580 return -ENOMEM;
1581
1582 up->args.fh = NFS_FH(dir->d_inode);
1583 up->args.name = name;
1584
1585 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
1586 msg->rpc_argp = &up->args;
1587 msg->rpc_resp = &up->res;
1588 return 0;
1589}
1590
1591static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
1592{
1593 struct rpc_message *msg = &task->tk_msg;
1594 struct unlink_desc *up;
1595
1596 if (msg->rpc_resp != NULL) {
1597 up = container_of(msg->rpc_resp, struct unlink_desc, res);
1598 update_changeattr(dir->d_inode, &up->res);
1599 kfree(up);
1600 msg->rpc_resp = NULL;
1601 msg->rpc_argp = NULL;
1602 }
1603 return 0;
1604}
1605
1606static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
1607 struct inode *new_dir, struct qstr *new_name)
1608{
1609 struct nfs4_rename_arg arg = {
1610 .old_dir = NFS_FH(old_dir),
1611 .new_dir = NFS_FH(new_dir),
1612 .old_name = old_name,
1613 .new_name = new_name,
1614 };
1615 struct nfs4_rename_res res = { };
1616 struct rpc_message msg = {
1617 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
1618 .rpc_argp = &arg,
1619 .rpc_resp = &res,
1620 };
1621 int status;
1622
1623 status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
1624
1625 if (!status) {
1626 update_changeattr(old_dir, &res.old_cinfo);
1627 update_changeattr(new_dir, &res.new_cinfo);
1628 }
1629 return status;
1630}
1631
1632static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
1633 struct inode *new_dir, struct qstr *new_name)
1634{
1635 struct nfs4_exception exception = { };
1636 int err;
1637 do {
1638 err = nfs4_handle_exception(NFS_SERVER(old_dir),
1639 _nfs4_proc_rename(old_dir, old_name,
1640 new_dir, new_name),
1641 &exception);
1642 } while (exception.retry);
1643 return err;
1644}
1645
1646static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
1647{
1648 struct nfs4_link_arg arg = {
1649 .fh = NFS_FH(inode),
1650 .dir_fh = NFS_FH(dir),
1651 .name = name,
1652 };
1653 struct nfs4_change_info cinfo = { };
1654 struct rpc_message msg = {
1655 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
1656 .rpc_argp = &arg,
1657 .rpc_resp = &cinfo,
1658 };
1659 int status;
1660
1661 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
1662 if (!status)
1663 update_changeattr(dir, &cinfo);
1664
1665 return status;
1666}
1667
1668static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
1669{
1670 struct nfs4_exception exception = { };
1671 int err;
1672 do {
1673 err = nfs4_handle_exception(NFS_SERVER(inode),
1674 _nfs4_proc_link(inode, dir, name),
1675 &exception);
1676 } while (exception.retry);
1677 return err;
1678}
1679
1680static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
1681 struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
1682 struct nfs_fattr *fattr)
1683{
1684 struct nfs_server *server = NFS_SERVER(dir);
1685 struct nfs4_create_arg arg = {
1686 .dir_fh = NFS_FH(dir),
1687 .server = server,
1688 .name = name,
1689 .attrs = sattr,
1690 .ftype = NF4LNK,
1691 .bitmask = server->attr_bitmask,
1692 };
1693 struct nfs4_create_res res = {
1694 .server = server,
1695 .fh = fhandle,
1696 .fattr = fattr,
1697 };
1698 struct rpc_message msg = {
1699 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
1700 .rpc_argp = &arg,
1701 .rpc_resp = &res,
1702 };
1703 int status;
1704
1705 if (path->len > NFS4_MAXPATHLEN)
1706 return -ENAMETOOLONG;
1707 arg.u.symlink = path;
1708 fattr->valid = 0;
1709
1710 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1711 if (!status)
1712 update_changeattr(dir, &res.dir_cinfo);
1713 return status;
1714}
1715
1716static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
1717 struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
1718 struct nfs_fattr *fattr)
1719{
1720 struct nfs4_exception exception = { };
1721 int err;
1722 do {
1723 err = nfs4_handle_exception(NFS_SERVER(dir),
1724 _nfs4_proc_symlink(dir, name, path, sattr,
1725 fhandle, fattr),
1726 &exception);
1727 } while (exception.retry);
1728 return err;
1729}
1730
1731static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
1732 struct iattr *sattr)
1733{
1734 struct nfs_server *server = NFS_SERVER(dir);
1735 struct nfs_fh fhandle;
1736 struct nfs_fattr fattr;
1737 struct nfs4_create_arg arg = {
1738 .dir_fh = NFS_FH(dir),
1739 .server = server,
1740 .name = &dentry->d_name,
1741 .attrs = sattr,
1742 .ftype = NF4DIR,
1743 .bitmask = server->attr_bitmask,
1744 };
1745 struct nfs4_create_res res = {
1746 .server = server,
1747 .fh = &fhandle,
1748 .fattr = &fattr,
1749 };
1750 struct rpc_message msg = {
1751 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
1752 .rpc_argp = &arg,
1753 .rpc_resp = &res,
1754 };
1755 int status;
1756
1757 fattr.valid = 0;
1758
1759 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1760 if (!status) {
1761 update_changeattr(dir, &res.dir_cinfo);
1762 status = nfs_instantiate(dentry, &fhandle, &fattr);
1763 }
1764 return status;
1765}
1766
1767static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
1768 struct iattr *sattr)
1769{
1770 struct nfs4_exception exception = { };
1771 int err;
1772 do {
1773 err = nfs4_handle_exception(NFS_SERVER(dir),
1774 _nfs4_proc_mkdir(dir, dentry, sattr),
1775 &exception);
1776 } while (exception.retry);
1777 return err;
1778}
1779
1780static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
1781 u64 cookie, struct page *page, unsigned int count, int plus)
1782{
1783 struct inode *dir = dentry->d_inode;
1784 struct nfs4_readdir_arg args = {
1785 .fh = NFS_FH(dir),
1786 .pages = &page,
1787 .pgbase = 0,
1788 .count = count,
1789 .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
1790 };
1791 struct nfs4_readdir_res res;
1792 struct rpc_message msg = {
1793 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READDIR],
1794 .rpc_argp = &args,
1795 .rpc_resp = &res,
1796 .rpc_cred = cred,
1797 };
1798 int status;
1799
Trond Myklebusteadf4592005-06-22 17:16:39 +00001800 dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __FUNCTION__,
1801 dentry->d_parent->d_name.name,
1802 dentry->d_name.name,
1803 (unsigned long long)cookie);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 lock_kernel();
1805 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
1806 res.pgbase = args.pgbase;
1807 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1808 if (status == 0)
1809 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
1810 unlock_kernel();
Trond Myklebusteadf4592005-06-22 17:16:39 +00001811 dprintk("%s: returns %d\n", __FUNCTION__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 return status;
1813}
1814
1815static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
1816 u64 cookie, struct page *page, unsigned int count, int plus)
1817{
1818 struct nfs4_exception exception = { };
1819 int err;
1820 do {
1821 err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
1822 _nfs4_proc_readdir(dentry, cred, cookie,
1823 page, count, plus),
1824 &exception);
1825 } while (exception.retry);
1826 return err;
1827}
1828
1829static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
1830 struct iattr *sattr, dev_t rdev)
1831{
1832 struct nfs_server *server = NFS_SERVER(dir);
1833 struct nfs_fh fh;
1834 struct nfs_fattr fattr;
1835 struct nfs4_create_arg arg = {
1836 .dir_fh = NFS_FH(dir),
1837 .server = server,
1838 .name = &dentry->d_name,
1839 .attrs = sattr,
1840 .bitmask = server->attr_bitmask,
1841 };
1842 struct nfs4_create_res res = {
1843 .server = server,
1844 .fh = &fh,
1845 .fattr = &fattr,
1846 };
1847 struct rpc_message msg = {
1848 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
1849 .rpc_argp = &arg,
1850 .rpc_resp = &res,
1851 };
1852 int status;
1853 int mode = sattr->ia_mode;
1854
1855 fattr.valid = 0;
1856
1857 BUG_ON(!(sattr->ia_valid & ATTR_MODE));
1858 BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
1859 if (S_ISFIFO(mode))
1860 arg.ftype = NF4FIFO;
1861 else if (S_ISBLK(mode)) {
1862 arg.ftype = NF4BLK;
1863 arg.u.device.specdata1 = MAJOR(rdev);
1864 arg.u.device.specdata2 = MINOR(rdev);
1865 }
1866 else if (S_ISCHR(mode)) {
1867 arg.ftype = NF4CHR;
1868 arg.u.device.specdata1 = MAJOR(rdev);
1869 arg.u.device.specdata2 = MINOR(rdev);
1870 }
1871 else
1872 arg.ftype = NF4SOCK;
1873
1874 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1875 if (status == 0) {
1876 update_changeattr(dir, &res.dir_cinfo);
1877 status = nfs_instantiate(dentry, &fh, &fattr);
1878 }
1879 return status;
1880}
1881
1882static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
1883 struct iattr *sattr, dev_t rdev)
1884{
1885 struct nfs4_exception exception = { };
1886 int err;
1887 do {
1888 err = nfs4_handle_exception(NFS_SERVER(dir),
1889 _nfs4_proc_mknod(dir, dentry, sattr, rdev),
1890 &exception);
1891 } while (exception.retry);
1892 return err;
1893}
1894
1895static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
1896 struct nfs_fsstat *fsstat)
1897{
1898 struct nfs4_statfs_arg args = {
1899 .fh = fhandle,
1900 .bitmask = server->attr_bitmask,
1901 };
1902 struct rpc_message msg = {
1903 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
1904 .rpc_argp = &args,
1905 .rpc_resp = fsstat,
1906 };
1907
1908 fsstat->fattr->valid = 0;
1909 return rpc_call_sync(server->client, &msg, 0);
1910}
1911
1912static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
1913{
1914 struct nfs4_exception exception = { };
1915 int err;
1916 do {
1917 err = nfs4_handle_exception(server,
1918 _nfs4_proc_statfs(server, fhandle, fsstat),
1919 &exception);
1920 } while (exception.retry);
1921 return err;
1922}
1923
1924static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
1925 struct nfs_fsinfo *fsinfo)
1926{
1927 struct nfs4_fsinfo_arg args = {
1928 .fh = fhandle,
1929 .bitmask = server->attr_bitmask,
1930 };
1931 struct rpc_message msg = {
1932 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
1933 .rpc_argp = &args,
1934 .rpc_resp = fsinfo,
1935 };
1936
1937 return rpc_call_sync(server->client, &msg, 0);
1938}
1939
1940static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
1941{
1942 struct nfs4_exception exception = { };
1943 int err;
1944
1945 do {
1946 err = nfs4_handle_exception(server,
1947 _nfs4_do_fsinfo(server, fhandle, fsinfo),
1948 &exception);
1949 } while (exception.retry);
1950 return err;
1951}
1952
1953static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
1954{
1955 fsinfo->fattr->valid = 0;
1956 return nfs4_do_fsinfo(server, fhandle, fsinfo);
1957}
1958
1959static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
1960 struct nfs_pathconf *pathconf)
1961{
1962 struct nfs4_pathconf_arg args = {
1963 .fh = fhandle,
1964 .bitmask = server->attr_bitmask,
1965 };
1966 struct rpc_message msg = {
1967 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
1968 .rpc_argp = &args,
1969 .rpc_resp = pathconf,
1970 };
1971
1972 /* None of the pathconf attributes are mandatory to implement */
1973 if ((args.bitmask[0] & nfs4_pathconf_bitmap[0]) == 0) {
1974 memset(pathconf, 0, sizeof(*pathconf));
1975 return 0;
1976 }
1977
1978 pathconf->fattr->valid = 0;
1979 return rpc_call_sync(server->client, &msg, 0);
1980}
1981
1982static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
1983 struct nfs_pathconf *pathconf)
1984{
1985 struct nfs4_exception exception = { };
1986 int err;
1987
1988 do {
1989 err = nfs4_handle_exception(server,
1990 _nfs4_proc_pathconf(server, fhandle, pathconf),
1991 &exception);
1992 } while (exception.retry);
1993 return err;
1994}
1995
1996static void
1997nfs4_read_done(struct rpc_task *task)
1998{
1999 struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
2000 struct inode *inode = data->inode;
2001
2002 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
2003 rpc_restart_call(task);
2004 return;
2005 }
2006 if (task->tk_status > 0)
2007 renew_lease(NFS_SERVER(inode), data->timestamp);
2008 /* Call back common NFS readpage processing */
2009 nfs_readpage_result(task);
2010}
2011
2012static void
2013nfs4_proc_read_setup(struct nfs_read_data *data)
2014{
2015 struct rpc_task *task = &data->task;
2016 struct rpc_message msg = {
2017 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
2018 .rpc_argp = &data->args,
2019 .rpc_resp = &data->res,
2020 .rpc_cred = data->cred,
2021 };
2022 struct inode *inode = data->inode;
2023 int flags;
2024
2025 data->timestamp = jiffies;
2026
2027 /* N.B. Do we need to test? Never called for swapfile inode */
2028 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
2029
2030 /* Finalize the task. */
2031 rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags);
2032 rpc_call_setup(task, &msg, 0);
2033}
2034
2035static void
2036nfs4_write_done(struct rpc_task *task)
2037{
2038 struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
2039 struct inode *inode = data->inode;
2040
2041 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
2042 rpc_restart_call(task);
2043 return;
2044 }
2045 if (task->tk_status >= 0)
2046 renew_lease(NFS_SERVER(inode), data->timestamp);
2047 /* Call back common NFS writeback processing */
2048 nfs_writeback_done(task);
2049}
2050
2051static void
2052nfs4_proc_write_setup(struct nfs_write_data *data, int how)
2053{
2054 struct rpc_task *task = &data->task;
2055 struct rpc_message msg = {
2056 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
2057 .rpc_argp = &data->args,
2058 .rpc_resp = &data->res,
2059 .rpc_cred = data->cred,
2060 };
2061 struct inode *inode = data->inode;
2062 int stable;
2063 int flags;
2064
2065 if (how & FLUSH_STABLE) {
2066 if (!NFS_I(inode)->ncommit)
2067 stable = NFS_FILE_SYNC;
2068 else
2069 stable = NFS_DATA_SYNC;
2070 } else
2071 stable = NFS_UNSTABLE;
2072 data->args.stable = stable;
2073
2074 data->timestamp = jiffies;
2075
2076 /* Set the initial flags for the task. */
2077 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
2078
2079 /* Finalize the task. */
2080 rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags);
2081 rpc_call_setup(task, &msg, 0);
2082}
2083
2084static void
2085nfs4_commit_done(struct rpc_task *task)
2086{
2087 struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
2088 struct inode *inode = data->inode;
2089
2090 if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
2091 rpc_restart_call(task);
2092 return;
2093 }
2094 /* Call back common NFS writeback processing */
2095 nfs_commit_done(task);
2096}
2097
2098static void
2099nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
2100{
2101 struct rpc_task *task = &data->task;
2102 struct rpc_message msg = {
2103 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
2104 .rpc_argp = &data->args,
2105 .rpc_resp = &data->res,
2106 .rpc_cred = data->cred,
2107 };
2108 struct inode *inode = data->inode;
2109 int flags;
2110
2111 /* Set the initial flags for the task. */
2112 flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
2113
2114 /* Finalize the task. */
2115 rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags);
2116 rpc_call_setup(task, &msg, 0);
2117}
2118
2119/*
2120 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
2121 * standalone procedure for queueing an asynchronous RENEW.
2122 */
2123static void
2124renew_done(struct rpc_task *task)
2125{
2126 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
2127 unsigned long timestamp = (unsigned long)task->tk_calldata;
2128
2129 if (task->tk_status < 0) {
2130 switch (task->tk_status) {
2131 case -NFS4ERR_STALE_CLIENTID:
2132 case -NFS4ERR_EXPIRED:
2133 case -NFS4ERR_CB_PATH_DOWN:
2134 nfs4_schedule_state_recovery(clp);
2135 }
2136 return;
2137 }
2138 spin_lock(&clp->cl_lock);
2139 if (time_before(clp->cl_last_renewal,timestamp))
2140 clp->cl_last_renewal = timestamp;
2141 spin_unlock(&clp->cl_lock);
2142}
2143
2144int
2145nfs4_proc_async_renew(struct nfs4_client *clp)
2146{
2147 struct rpc_message msg = {
2148 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
2149 .rpc_argp = clp,
2150 .rpc_cred = clp->cl_cred,
2151 };
2152
2153 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
2154 renew_done, (void *)jiffies);
2155}
2156
2157int
2158nfs4_proc_renew(struct nfs4_client *clp)
2159{
2160 struct rpc_message msg = {
2161 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
2162 .rpc_argp = clp,
2163 .rpc_cred = clp->cl_cred,
2164 };
2165 unsigned long now = jiffies;
2166 int status;
2167
2168 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
2169 if (status < 0)
2170 return status;
2171 spin_lock(&clp->cl_lock);
2172 if (time_before(clp->cl_last_renewal,now))
2173 clp->cl_last_renewal = now;
2174 spin_unlock(&clp->cl_lock);
2175 return 0;
2176}
2177
2178/*
2179 * We will need to arrange for the VFS layer to provide an atomic open.
2180 * Until then, this open method is prone to inefficiency and race conditions
2181 * due to the lookup, potential create, and open VFS calls from sys_open()
2182 * placed on the wire.
2183 */
2184static int
2185nfs4_proc_file_open(struct inode *inode, struct file *filp)
2186{
2187 struct dentry *dentry = filp->f_dentry;
2188 struct nfs_open_context *ctx;
2189 struct nfs4_state *state = NULL;
2190 struct rpc_cred *cred;
2191 int status = -ENOMEM;
2192
2193 dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n",
2194 (int)dentry->d_parent->d_name.len,
2195 dentry->d_parent->d_name.name,
2196 (int)dentry->d_name.len, dentry->d_name.name);
2197
2198
2199 /* Find our open stateid */
2200 cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
2201 if (IS_ERR(cred))
2202 return PTR_ERR(cred);
2203 ctx = alloc_nfs_open_context(dentry, cred);
2204 put_rpccred(cred);
2205 if (unlikely(ctx == NULL))
2206 return -ENOMEM;
2207 status = -EIO; /* ERACE actually */
2208 state = nfs4_find_state(inode, cred, filp->f_mode);
2209 if (unlikely(state == NULL))
2210 goto no_state;
2211 ctx->state = state;
2212 nfs4_close_state(state, filp->f_mode);
2213 ctx->mode = filp->f_mode;
2214 nfs_file_set_open_context(filp, ctx);
2215 put_nfs_open_context(ctx);
2216 if (filp->f_mode & FMODE_WRITE)
2217 nfs_begin_data_update(inode);
2218 return 0;
2219no_state:
2220 printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
2221 put_nfs_open_context(ctx);
2222 return status;
2223}
2224
2225/*
2226 * Release our state
2227 */
2228static int
2229nfs4_proc_file_release(struct inode *inode, struct file *filp)
2230{
2231 if (filp->f_mode & FMODE_WRITE)
2232 nfs_end_data_update(inode);
2233 nfs_file_clear_open_context(filp);
2234 return 0;
2235}
2236
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00002237static inline int nfs4_server_supports_acls(struct nfs_server *server)
2238{
2239 return (server->caps & NFS_CAP_ACLS)
2240 && (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
2241 && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
2242}
2243
2244/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
2245 * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
2246 * the stack.
2247 */
2248#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
2249
2250static void buf_to_pages(const void *buf, size_t buflen,
2251 struct page **pages, unsigned int *pgbase)
2252{
2253 const void *p = buf;
2254
2255 *pgbase = offset_in_page(buf);
2256 p -= *pgbase;
2257 while (p < buf + buflen) {
2258 *(pages++) = virt_to_page(p);
2259 p += PAGE_CACHE_SIZE;
2260 }
2261}
2262
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00002263struct nfs4_cached_acl {
2264 int cached;
2265 size_t len;
Andrew Morton3e9d4152005-06-22 17:16:28 +00002266 char data[0];
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00002267};
2268
2269static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl)
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00002270{
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00002271 struct nfs_inode *nfsi = NFS_I(inode);
2272
2273 spin_lock(&inode->i_lock);
2274 kfree(nfsi->nfs4_acl);
2275 nfsi->nfs4_acl = acl;
2276 spin_unlock(&inode->i_lock);
2277}
2278
2279static void nfs4_zap_acl_attr(struct inode *inode)
2280{
2281 nfs4_set_cached_acl(inode, NULL);
2282}
2283
2284static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
2285{
2286 struct nfs_inode *nfsi = NFS_I(inode);
2287 struct nfs4_cached_acl *acl;
2288 int ret = -ENOENT;
2289
2290 spin_lock(&inode->i_lock);
2291 acl = nfsi->nfs4_acl;
2292 if (acl == NULL)
2293 goto out;
2294 if (buf == NULL) /* user is just asking for length */
2295 goto out_len;
2296 if (acl->cached == 0)
2297 goto out;
2298 ret = -ERANGE; /* see getxattr(2) man page */
2299 if (acl->len > buflen)
2300 goto out;
2301 memcpy(buf, acl->data, acl->len);
2302out_len:
2303 ret = acl->len;
2304out:
2305 spin_unlock(&inode->i_lock);
2306 return ret;
2307}
2308
2309static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
2310{
2311 struct nfs4_cached_acl *acl;
2312
2313 if (buf && acl_len <= PAGE_SIZE) {
2314 acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
2315 if (acl == NULL)
2316 goto out;
2317 acl->cached = 1;
2318 memcpy(acl->data, buf, acl_len);
2319 } else {
2320 acl = kmalloc(sizeof(*acl), GFP_KERNEL);
2321 if (acl == NULL)
2322 goto out;
2323 acl->cached = 0;
2324 }
2325 acl->len = acl_len;
2326out:
2327 nfs4_set_cached_acl(inode, acl);
2328}
2329
2330static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
2331{
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00002332 struct page *pages[NFS4ACL_MAXPAGES];
2333 struct nfs_getaclargs args = {
2334 .fh = NFS_FH(inode),
2335 .acl_pages = pages,
2336 .acl_len = buflen,
2337 };
2338 size_t resp_len = buflen;
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00002339 void *resp_buf;
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00002340 struct rpc_message msg = {
2341 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
2342 .rpc_argp = &args,
2343 .rpc_resp = &resp_len,
2344 };
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00002345 struct page *localpage = NULL;
2346 int ret;
2347
2348 if (buflen < PAGE_SIZE) {
2349 /* As long as we're doing a round trip to the server anyway,
2350 * let's be prepared for a page of acl data. */
2351 localpage = alloc_page(GFP_KERNEL);
2352 resp_buf = page_address(localpage);
2353 if (localpage == NULL)
2354 return -ENOMEM;
2355 args.acl_pages[0] = localpage;
2356 args.acl_pgbase = 0;
2357 args.acl_len = PAGE_SIZE;
2358 } else {
2359 resp_buf = buf;
2360 buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
2361 }
2362 ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
2363 if (ret)
2364 goto out_free;
2365 if (resp_len > args.acl_len)
2366 nfs4_write_cached_acl(inode, NULL, resp_len);
2367 else
2368 nfs4_write_cached_acl(inode, resp_buf, resp_len);
2369 if (buf) {
2370 ret = -ERANGE;
2371 if (resp_len > buflen)
2372 goto out_free;
2373 if (localpage)
2374 memcpy(buf, resp_buf, resp_len);
2375 }
2376 ret = resp_len;
2377out_free:
2378 if (localpage)
2379 __free_page(localpage);
2380 return ret;
2381}
2382
2383static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
2384{
2385 struct nfs_server *server = NFS_SERVER(inode);
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00002386 int ret;
2387
2388 if (!nfs4_server_supports_acls(server))
2389 return -EOPNOTSUPP;
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00002390 ret = nfs_revalidate_inode(server, inode);
2391 if (ret < 0)
2392 return ret;
2393 ret = nfs4_read_cached_acl(inode, buf, buflen);
2394 if (ret != -ENOENT)
2395 return ret;
2396 return nfs4_get_acl_uncached(inode, buf, buflen);
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00002397}
2398
J. Bruce Fields4b580ee2005-06-22 17:16:23 +00002399static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
2400{
2401 struct nfs_server *server = NFS_SERVER(inode);
2402 struct page *pages[NFS4ACL_MAXPAGES];
2403 struct nfs_setaclargs arg = {
2404 .fh = NFS_FH(inode),
2405 .acl_pages = pages,
2406 .acl_len = buflen,
2407 };
2408 struct rpc_message msg = {
2409 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
2410 .rpc_argp = &arg,
2411 .rpc_resp = NULL,
2412 };
2413 int ret;
2414
2415 if (!nfs4_server_supports_acls(server))
2416 return -EOPNOTSUPP;
2417 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
2418 ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00002419 if (ret == 0)
2420 nfs4_write_cached_acl(inode, buf, buflen);
J. Bruce Fields4b580ee2005-06-22 17:16:23 +00002421 return ret;
2422}
2423
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424static int
2425nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
2426{
2427 struct nfs4_client *clp = server->nfs4_state;
2428
2429 if (!clp || task->tk_status >= 0)
2430 return 0;
2431 switch(task->tk_status) {
2432 case -NFS4ERR_STALE_CLIENTID:
2433 case -NFS4ERR_STALE_STATEID:
2434 case -NFS4ERR_EXPIRED:
2435 rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
2436 nfs4_schedule_state_recovery(clp);
2437 if (test_bit(NFS4CLNT_OK, &clp->cl_state))
2438 rpc_wake_up_task(task);
2439 task->tk_status = 0;
2440 return -EAGAIN;
2441 case -NFS4ERR_GRACE:
2442 case -NFS4ERR_DELAY:
2443 rpc_delay(task, NFS4_POLL_RETRY_MAX);
2444 task->tk_status = 0;
2445 return -EAGAIN;
2446 case -NFS4ERR_OLD_STATEID:
2447 task->tk_status = 0;
2448 return -EAGAIN;
2449 }
2450 task->tk_status = nfs4_map_errors(task->tk_status);
2451 return 0;
2452}
2453
2454static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
2455{
2456 DEFINE_WAIT(wait);
2457 sigset_t oldset;
2458 int interruptible, res = 0;
2459
2460 might_sleep();
2461
2462 rpc_clnt_sigmask(clnt, &oldset);
2463 interruptible = TASK_UNINTERRUPTIBLE;
2464 if (clnt->cl_intr)
2465 interruptible = TASK_INTERRUPTIBLE;
2466 prepare_to_wait(&clp->cl_waitq, &wait, interruptible);
2467 nfs4_schedule_state_recovery(clp);
2468 if (clnt->cl_intr && signalled())
2469 res = -ERESTARTSYS;
2470 else if (!test_bit(NFS4CLNT_OK, &clp->cl_state))
2471 schedule();
2472 finish_wait(&clp->cl_waitq, &wait);
2473 rpc_clnt_sigunmask(clnt, &oldset);
2474 return res;
2475}
2476
2477static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
2478{
2479 sigset_t oldset;
2480 int res = 0;
2481
2482 might_sleep();
2483
2484 if (*timeout <= 0)
2485 *timeout = NFS4_POLL_RETRY_MIN;
2486 if (*timeout > NFS4_POLL_RETRY_MAX)
2487 *timeout = NFS4_POLL_RETRY_MAX;
2488 rpc_clnt_sigmask(clnt, &oldset);
2489 if (clnt->cl_intr) {
Nishanth Aravamudan041e0e32005-09-10 00:27:23 -07002490 schedule_timeout_interruptible(*timeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 if (signalled())
2492 res = -ERESTARTSYS;
Nishanth Aravamudan041e0e32005-09-10 00:27:23 -07002493 } else
2494 schedule_timeout_uninterruptible(*timeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 rpc_clnt_sigunmask(clnt, &oldset);
2496 *timeout <<= 1;
2497 return res;
2498}
2499
2500/* This is the error handling routine for processes that are allowed
2501 * to sleep.
2502 */
2503int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
2504{
2505 struct nfs4_client *clp = server->nfs4_state;
2506 int ret = errorcode;
2507
2508 exception->retry = 0;
2509 switch(errorcode) {
2510 case 0:
2511 return 0;
2512 case -NFS4ERR_STALE_CLIENTID:
2513 case -NFS4ERR_STALE_STATEID:
2514 case -NFS4ERR_EXPIRED:
2515 ret = nfs4_wait_clnt_recover(server->client, clp);
2516 if (ret == 0)
2517 exception->retry = 1;
2518 break;
2519 case -NFS4ERR_GRACE:
2520 case -NFS4ERR_DELAY:
2521 ret = nfs4_delay(server->client, &exception->timeout);
2522 if (ret == 0)
2523 exception->retry = 1;
2524 break;
2525 case -NFS4ERR_OLD_STATEID:
2526 if (ret == 0)
2527 exception->retry = 1;
2528 }
2529 /* We failed to handle the error */
2530 return nfs4_map_errors(ret);
2531}
2532
2533int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
2534{
2535 nfs4_verifier sc_verifier;
2536 struct nfs4_setclientid setclientid = {
2537 .sc_verifier = &sc_verifier,
2538 .sc_prog = program,
2539 };
2540 struct rpc_message msg = {
2541 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
2542 .rpc_argp = &setclientid,
2543 .rpc_resp = clp,
2544 .rpc_cred = clp->cl_cred,
2545 };
2546 u32 *p;
2547 int loop = 0;
2548 int status;
2549
2550 p = (u32*)sc_verifier.data;
2551 *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
2552 *p = htonl((u32)clp->cl_boot_time.tv_nsec);
2553
2554 for(;;) {
2555 setclientid.sc_name_len = scnprintf(setclientid.sc_name,
2556 sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
2557 clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
2558 clp->cl_cred->cr_ops->cr_name,
2559 clp->cl_id_uniquifier);
2560 setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
2561 sizeof(setclientid.sc_netid), "tcp");
2562 setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
2563 sizeof(setclientid.sc_uaddr), "%s.%d.%d",
2564 clp->cl_ipaddr, port >> 8, port & 255);
2565
2566 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
2567 if (status != -NFS4ERR_CLID_INUSE)
2568 break;
2569 if (signalled())
2570 break;
2571 if (loop++ & 1)
2572 ssleep(clp->cl_lease_time + 1);
2573 else
2574 if (++clp->cl_id_uniquifier == 0)
2575 break;
2576 }
2577 return status;
2578}
2579
2580int
2581nfs4_proc_setclientid_confirm(struct nfs4_client *clp)
2582{
2583 struct nfs_fsinfo fsinfo;
2584 struct rpc_message msg = {
2585 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
2586 .rpc_argp = clp,
2587 .rpc_resp = &fsinfo,
2588 .rpc_cred = clp->cl_cred,
2589 };
2590 unsigned long now;
2591 int status;
2592
2593 now = jiffies;
2594 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
2595 if (status == 0) {
2596 spin_lock(&clp->cl_lock);
2597 clp->cl_lease_time = fsinfo.lease_time * HZ;
2598 clp->cl_last_renewal = now;
2599 spin_unlock(&clp->cl_lock);
2600 }
2601 return status;
2602}
2603
2604static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
2605{
2606 struct nfs4_delegreturnargs args = {
2607 .fhandle = NFS_FH(inode),
2608 .stateid = stateid,
2609 };
2610 struct rpc_message msg = {
2611 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
2612 .rpc_argp = &args,
2613 .rpc_cred = cred,
2614 };
2615
2616 return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
2617}
2618
2619int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
2620{
2621 struct nfs_server *server = NFS_SERVER(inode);
2622 struct nfs4_exception exception = { };
2623 int err;
2624 do {
2625 err = _nfs4_proc_delegreturn(inode, cred, stateid);
2626 switch (err) {
2627 case -NFS4ERR_STALE_STATEID:
2628 case -NFS4ERR_EXPIRED:
2629 nfs4_schedule_state_recovery(server->nfs4_state);
2630 case 0:
2631 return 0;
2632 }
2633 err = nfs4_handle_exception(server, err, &exception);
2634 } while (exception.retry);
2635 return err;
2636}
2637
2638#define NFS4_LOCK_MINTIMEOUT (1 * HZ)
2639#define NFS4_LOCK_MAXTIMEOUT (30 * HZ)
2640
2641/*
2642 * sleep, with exponential backoff, and retry the LOCK operation.
2643 */
2644static unsigned long
2645nfs4_set_lock_task_retry(unsigned long timeout)
2646{
Nishanth Aravamudan041e0e32005-09-10 00:27:23 -07002647 schedule_timeout_interruptible(timeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 timeout <<= 1;
2649 if (timeout > NFS4_LOCK_MAXTIMEOUT)
2650 return NFS4_LOCK_MAXTIMEOUT;
2651 return timeout;
2652}
2653
2654static inline int
2655nfs4_lck_type(int cmd, struct file_lock *request)
2656{
2657 /* set lock type */
2658 switch (request->fl_type) {
2659 case F_RDLCK:
2660 return IS_SETLKW(cmd) ? NFS4_READW_LT : NFS4_READ_LT;
2661 case F_WRLCK:
2662 return IS_SETLKW(cmd) ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
2663 case F_UNLCK:
2664 return NFS4_WRITE_LT;
2665 }
2666 BUG();
2667 return 0;
2668}
2669
2670static inline uint64_t
2671nfs4_lck_length(struct file_lock *request)
2672{
2673 if (request->fl_end == OFFSET_MAX)
2674 return ~(uint64_t)0;
2675 return request->fl_end - request->fl_start + 1;
2676}
2677
2678static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
2679{
2680 struct inode *inode = state->inode;
2681 struct nfs_server *server = NFS_SERVER(inode);
2682 struct nfs4_client *clp = server->nfs4_state;
2683 struct nfs_lockargs arg = {
2684 .fh = NFS_FH(inode),
2685 .type = nfs4_lck_type(cmd, request),
2686 .offset = request->fl_start,
2687 .length = nfs4_lck_length(request),
2688 };
2689 struct nfs_lockres res = {
2690 .server = server,
2691 };
2692 struct rpc_message msg = {
2693 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKT],
2694 .rpc_argp = &arg,
2695 .rpc_resp = &res,
2696 .rpc_cred = state->owner->so_cred,
2697 };
2698 struct nfs_lowner nlo;
2699 struct nfs4_lock_state *lsp;
2700 int status;
2701
2702 down_read(&clp->cl_sem);
2703 nlo.clientid = clp->cl_clientid;
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002704 status = nfs4_set_lock_state(state, request);
2705 if (status != 0)
2706 goto out;
2707 lsp = request->fl_u.nfs4_fl.owner;
2708 nlo.id = lsp->ls_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 arg.u.lockt = &nlo;
2710 status = rpc_call_sync(server->client, &msg, 0);
2711 if (!status) {
2712 request->fl_type = F_UNLCK;
2713 } else if (status == -NFS4ERR_DENIED) {
2714 int64_t len, start, end;
2715 start = res.u.denied.offset;
2716 len = res.u.denied.length;
2717 end = start + len - 1;
2718 if (end < 0 || len == 0)
2719 request->fl_end = OFFSET_MAX;
2720 else
2721 request->fl_end = (loff_t)end;
2722 request->fl_start = (loff_t)start;
2723 request->fl_type = F_WRLCK;
2724 if (res.u.denied.type & 1)
2725 request->fl_type = F_RDLCK;
2726 request->fl_pid = 0;
2727 status = 0;
2728 }
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002729out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 up_read(&clp->cl_sem);
2731 return status;
2732}
2733
2734static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
2735{
2736 struct nfs4_exception exception = { };
2737 int err;
2738
2739 do {
2740 err = nfs4_handle_exception(NFS_SERVER(state->inode),
2741 _nfs4_proc_getlk(state, cmd, request),
2742 &exception);
2743 } while (exception.retry);
2744 return err;
2745}
2746
2747static int do_vfs_lock(struct file *file, struct file_lock *fl)
2748{
2749 int res = 0;
2750 switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
2751 case FL_POSIX:
2752 res = posix_lock_file_wait(file, fl);
2753 break;
2754 case FL_FLOCK:
2755 res = flock_lock_file_wait(file, fl);
2756 break;
2757 default:
2758 BUG();
2759 }
2760 if (res < 0)
2761 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
2762 __FUNCTION__);
2763 return res;
2764}
2765
2766static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
2767{
2768 struct inode *inode = state->inode;
2769 struct nfs_server *server = NFS_SERVER(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 struct nfs_lockargs arg = {
2771 .fh = NFS_FH(inode),
2772 .type = nfs4_lck_type(cmd, request),
2773 .offset = request->fl_start,
2774 .length = nfs4_lck_length(request),
2775 };
2776 struct nfs_lockres res = {
2777 .server = server,
2778 };
2779 struct rpc_message msg = {
2780 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
2781 .rpc_argp = &arg,
2782 .rpc_resp = &res,
2783 .rpc_cred = state->owner->so_cred,
2784 };
2785 struct nfs4_lock_state *lsp;
2786 struct nfs_locku_opargs luargs;
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002787 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002789 status = nfs4_set_lock_state(state, request);
2790 if (status != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 goto out;
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002792 lsp = request->fl_u.nfs4_fl.owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 /* We might have lost the locks! */
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002794 if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
2795 goto out;
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002796 luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid);
2797 status = -ENOMEM;
2798 if (luargs.seqid == NULL)
2799 goto out;
2800 memcpy(luargs.stateid.data, lsp->ls_stateid.data, sizeof(luargs.stateid.data));
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002801 arg.u.locku = &luargs;
2802 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002803 nfs_increment_lock_seqid(status, luargs.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002805 if (status == 0)
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002806 memcpy(lsp->ls_stateid.data, res.u.stateid.data,
2807 sizeof(lsp->ls_stateid.data));
2808 nfs_free_seqid(luargs.seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 if (status == 0)
2811 do_vfs_lock(request->fl_file, request);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 return status;
2813}
2814
2815static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
2816{
2817 struct nfs4_exception exception = { };
2818 int err;
2819
2820 do {
2821 err = nfs4_handle_exception(NFS_SERVER(state->inode),
2822 _nfs4_proc_unlck(state, cmd, request),
2823 &exception);
2824 } while (exception.retry);
2825 return err;
2826}
2827
2828static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim)
2829{
2830 struct inode *inode = state->inode;
2831 struct nfs_server *server = NFS_SERVER(inode);
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002832 struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 struct nfs_lockargs arg = {
2834 .fh = NFS_FH(inode),
2835 .type = nfs4_lck_type(cmd, request),
2836 .offset = request->fl_start,
2837 .length = nfs4_lck_length(request),
2838 };
2839 struct nfs_lockres res = {
2840 .server = server,
2841 };
2842 struct rpc_message msg = {
2843 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
2844 .rpc_argp = &arg,
2845 .rpc_resp = &res,
2846 .rpc_cred = state->owner->so_cred,
2847 };
2848 struct nfs_lock_opargs largs = {
2849 .reclaim = reclaim,
2850 .new_lock_owner = 0,
2851 };
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002852 struct nfs_seqid *lock_seqid;
2853 int status = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002855 lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
2856 if (lock_seqid == NULL)
2857 return -ENOMEM;
2858 if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 struct nfs4_state_owner *owner = state->owner;
2860 struct nfs_open_to_lock otl = {
2861 .lock_owner = {
2862 .clientid = server->nfs4_state->cl_clientid,
2863 },
2864 };
2865
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002866 otl.lock_seqid = lock_seqid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 otl.lock_owner.id = lsp->ls_id;
2868 memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid));
2869 largs.u.open_lock = &otl;
2870 largs.new_lock_owner = 1;
2871 arg.u.lock = &largs;
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002872 otl.open_seqid = nfs_alloc_seqid(&owner->so_seqid);
2873 if (otl.open_seqid != NULL) {
2874 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
2875 /* increment seqid on success, and seqid mutating errors */
2876 nfs_increment_open_seqid(status, otl.open_seqid);
2877 nfs_free_seqid(otl.open_seqid);
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002878 }
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002879 if (status == 0)
2880 nfs_confirm_seqid(&lsp->ls_seqid, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 } else {
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002882 struct nfs_exist_lock el;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
2884 largs.u.exist_lock = &el;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 arg.u.lock = &largs;
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002886 el.seqid = lock_seqid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
2888 }
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002889 /* increment seqid on success, and seqid mutating errors*/
2890 nfs_increment_lock_seqid(status, lock_seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 /* save the returned stateid. */
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002892 if (status == 0) {
2893 memcpy(lsp->ls_stateid.data, res.u.stateid.data, sizeof(lsp->ls_stateid.data));
2894 lsp->ls_flags |= NFS_LOCK_INITIALIZED;
2895 } else if (status == -NFS4ERR_DENIED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 status = -EAGAIN;
Trond Myklebustcee54fc2005-10-18 14:20:12 -07002897 nfs_free_seqid(lock_seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 return status;
2899}
2900
2901static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
2902{
Trond Myklebust202b50d2005-06-22 17:16:29 +00002903 struct nfs_server *server = NFS_SERVER(state->inode);
2904 struct nfs4_exception exception = { };
2905 int err;
2906
2907 do {
2908 err = _nfs4_do_setlk(state, F_SETLK, request, 1);
2909 if (err != -NFS4ERR_DELAY)
2910 break;
2911 nfs4_handle_exception(server, err, &exception);
2912 } while (exception.retry);
2913 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914}
2915
2916static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
2917{
Trond Myklebust202b50d2005-06-22 17:16:29 +00002918 struct nfs_server *server = NFS_SERVER(state->inode);
2919 struct nfs4_exception exception = { };
2920 int err;
2921
2922 do {
2923 err = _nfs4_do_setlk(state, F_SETLK, request, 0);
2924 if (err != -NFS4ERR_DELAY)
2925 break;
2926 nfs4_handle_exception(server, err, &exception);
2927 } while (exception.retry);
2928 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929}
2930
2931static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
2932{
2933 struct nfs4_client *clp = state->owner->so_client;
2934 int status;
2935
2936 down_read(&clp->cl_sem);
Trond Myklebust8d0a8a92005-06-22 17:16:32 +00002937 status = nfs4_set_lock_state(state, request);
2938 if (status == 0)
2939 status = _nfs4_do_setlk(state, cmd, request, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 if (status == 0) {
2941 /* Note: we always want to sleep here! */
2942 request->fl_flags |= FL_SLEEP;
2943 if (do_vfs_lock(request->fl_file, request) < 0)
2944 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
2945 }
2946 up_read(&clp->cl_sem);
2947 return status;
2948}
2949
2950static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
2951{
2952 struct nfs4_exception exception = { };
2953 int err;
2954
2955 do {
2956 err = nfs4_handle_exception(NFS_SERVER(state->inode),
2957 _nfs4_proc_setlk(state, cmd, request),
2958 &exception);
2959 } while (exception.retry);
2960 return err;
2961}
2962
2963static int
2964nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
2965{
2966 struct nfs_open_context *ctx;
2967 struct nfs4_state *state;
2968 unsigned long timeout = NFS4_LOCK_MINTIMEOUT;
2969 int status;
2970
2971 /* verify open state */
2972 ctx = (struct nfs_open_context *)filp->private_data;
2973 state = ctx->state;
2974
2975 if (request->fl_start < 0 || request->fl_end < 0)
2976 return -EINVAL;
2977
2978 if (IS_GETLK(cmd))
2979 return nfs4_proc_getlk(state, F_GETLK, request);
2980
2981 if (!(IS_SETLK(cmd) || IS_SETLKW(cmd)))
2982 return -EINVAL;
2983
2984 if (request->fl_type == F_UNLCK)
2985 return nfs4_proc_unlck(state, cmd, request);
2986
2987 do {
2988 status = nfs4_proc_setlk(state, cmd, request);
2989 if ((status != -EAGAIN) || IS_SETLK(cmd))
2990 break;
2991 timeout = nfs4_set_lock_task_retry(timeout);
2992 status = -ERESTARTSYS;
2993 if (signalled())
2994 break;
2995 } while(status < 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 return status;
2997}
2998
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00002999
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00003000#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
3001
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00003002int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
3003 size_t buflen, int flags)
3004{
J. Bruce Fields4b580ee2005-06-22 17:16:23 +00003005 struct inode *inode = dentry->d_inode;
3006
3007 if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
3008 return -EOPNOTSUPP;
3009
3010 if (!S_ISREG(inode->i_mode) &&
3011 (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
3012 return -EPERM;
3013
3014 return nfs4_proc_set_acl(inode, buf, buflen);
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00003015}
3016
3017/* The getxattr man page suggests returning -ENODATA for unknown attributes,
3018 * and that's what we'll do for e.g. user attributes that haven't been set.
3019 * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
3020 * attributes in kernel-managed attribute namespaces. */
3021ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
3022 size_t buflen)
3023{
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00003024 struct inode *inode = dentry->d_inode;
3025
3026 if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
3027 return -EOPNOTSUPP;
3028
3029 return nfs4_proc_get_acl(inode, buf, buflen);
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00003030}
3031
3032ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
3033{
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00003034 size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00003035
3036 if (buf && buflen < len)
3037 return -ERANGE;
3038 if (buf)
J. Bruce Fieldsaa1870a2005-06-22 17:16:22 +00003039 memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
3040 return len;
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00003041}
3042
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
3044 .recover_open = nfs4_open_reclaim,
3045 .recover_lock = nfs4_lock_reclaim,
3046};
3047
3048struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
3049 .recover_open = nfs4_open_expired,
3050 .recover_lock = nfs4_lock_expired,
3051};
3052
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00003053static struct inode_operations nfs4_file_inode_operations = {
3054 .permission = nfs_permission,
3055 .getattr = nfs_getattr,
3056 .setattr = nfs_setattr,
3057 .getxattr = nfs4_getxattr,
3058 .setxattr = nfs4_setxattr,
3059 .listxattr = nfs4_listxattr,
3060};
3061
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062struct nfs_rpc_ops nfs_v4_clientops = {
3063 .version = 4, /* protocol version */
3064 .dentry_ops = &nfs4_dentry_operations,
3065 .dir_inode_ops = &nfs4_dir_inode_operations,
J. Bruce Fields6b3b5492005-06-22 17:16:22 +00003066 .file_inode_ops = &nfs4_file_inode_operations,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067 .getroot = nfs4_proc_get_root,
3068 .getattr = nfs4_proc_getattr,
3069 .setattr = nfs4_proc_setattr,
3070 .lookup = nfs4_proc_lookup,
3071 .access = nfs4_proc_access,
3072 .readlink = nfs4_proc_readlink,
3073 .read = nfs4_proc_read,
3074 .write = nfs4_proc_write,
3075 .commit = nfs4_proc_commit,
3076 .create = nfs4_proc_create,
3077 .remove = nfs4_proc_remove,
3078 .unlink_setup = nfs4_proc_unlink_setup,
3079 .unlink_done = nfs4_proc_unlink_done,
3080 .rename = nfs4_proc_rename,
3081 .link = nfs4_proc_link,
3082 .symlink = nfs4_proc_symlink,
3083 .mkdir = nfs4_proc_mkdir,
3084 .rmdir = nfs4_proc_remove,
3085 .readdir = nfs4_proc_readdir,
3086 .mknod = nfs4_proc_mknod,
3087 .statfs = nfs4_proc_statfs,
3088 .fsinfo = nfs4_proc_fsinfo,
3089 .pathconf = nfs4_proc_pathconf,
3090 .decode_dirent = nfs4_decode_dirent,
3091 .read_setup = nfs4_proc_read_setup,
3092 .write_setup = nfs4_proc_write_setup,
3093 .commit_setup = nfs4_proc_commit_setup,
3094 .file_open = nfs4_proc_file_open,
3095 .file_release = nfs4_proc_file_release,
3096 .lock = nfs4_proc_lock,
J. Bruce Fieldse50a1c22005-06-22 17:16:23 +00003097 .clear_acl_cache = nfs4_zap_acl_attr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098};
3099
3100/*
3101 * Local variables:
3102 * c-basic-offset: 8
3103 * End:
3104 */