aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-03 03:55:08 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-06 14:58:41 -0500
commite56e0b78eb1097a8e06512b9ed4be94d7538e7ac (patch)
treefe2b82993dd62323f9891f28bdb79c7cb2b01442 /fs/nfs/nfs4proc.c
parent06f814a3ad0ddfe19e6e4f44e3da5d490547faf3 (diff)
NFSv4: Allocate OPEN call RPC arguments using kmalloc()
Cleanup in preparation for making OPEN calls interruptible by the user. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c213
1 files changed, 117 insertions, 96 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c7bec4319236..4a5cc8402110 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -194,6 +194,76 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
194 spin_unlock(&inode->i_lock); 194 spin_unlock(&inode->i_lock);
195} 195}
196 196
197struct nfs4_opendata {
198 struct nfs_openargs o_arg;
199 struct nfs_openres o_res;
200 struct nfs_fattr f_attr;
201 struct nfs_fattr dir_attr;
202 struct dentry *dentry;
203 struct dentry *dir;
204 struct nfs4_state_owner *owner;
205 struct iattr attrs;
206};
207
208static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
209 struct nfs4_state_owner *sp, int flags,
210 const struct iattr *attrs)
211{
212 struct dentry *parent = dget_parent(dentry);
213 struct inode *dir = parent->d_inode;
214 struct nfs_server *server = NFS_SERVER(dir);
215 struct nfs4_opendata *p;
216
217 p = kzalloc(sizeof(*p), GFP_KERNEL);
218 if (p == NULL)
219 goto err;
220 p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
221 if (p->o_arg.seqid == NULL)
222 goto err_free;
223 p->dentry = dget(dentry);
224 p->dir = parent;
225 p->owner = sp;
226 atomic_inc(&sp->so_count);
227 p->o_arg.fh = NFS_FH(dir);
228 p->o_arg.open_flags = flags,
229 p->o_arg.clientid = server->nfs4_state->cl_clientid;
230 p->o_arg.id = sp->so_id;
231 p->o_arg.name = &dentry->d_name;
232 p->o_arg.server = server;
233 p->o_arg.bitmask = server->attr_bitmask;
234 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
235 p->o_res.f_attr = &p->f_attr;
236 p->o_res.dir_attr = &p->dir_attr;
237 p->o_res.server = server;
238 nfs_fattr_init(&p->f_attr);
239 nfs_fattr_init(&p->dir_attr);
240 if (flags & O_EXCL) {
241 u32 *s = (u32 *) p->o_arg.u.verifier.data;
242 s[0] = jiffies;
243 s[1] = current->pid;
244 } else if (flags & O_CREAT) {
245 p->o_arg.u.attrs = &p->attrs;
246 memcpy(&p->attrs, attrs, sizeof(p->attrs));
247 }
248 return p;
249err_free:
250 kfree(p);
251err:
252 dput(parent);
253 return NULL;
254}
255
256static void nfs4_opendata_free(struct nfs4_opendata *p)
257{
258 if (p != NULL) {
259 nfs_free_seqid(p->o_arg.seqid);
260 nfs4_put_state_owner(p->owner);
261 dput(p->dir);
262 dput(p->dentry);
263 kfree(p);
264 }
265}
266
197/* Helper for asynchronous RPC calls */ 267/* Helper for asynchronous RPC calls */
198static int nfs4_call_async(struct rpc_clnt *clnt, 268static int nfs4_call_async(struct rpc_clnt *clnt,
199 const struct rpc_call_ops *tk_ops, void *calldata) 269 const struct rpc_call_ops *tk_ops, void *calldata)
@@ -314,57 +384,45 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state
314 struct nfs4_state_owner *sp = state->owner; 384 struct nfs4_state_owner *sp = state->owner;
315 struct inode *inode = dentry->d_inode; 385 struct inode *inode = dentry->d_inode;
316 struct nfs_server *server = NFS_SERVER(inode); 386 struct nfs_server *server = NFS_SERVER(inode);
317 struct dentry *parent = dget_parent(dentry);
318 struct nfs_openargs arg = {
319 .fh = NFS_FH(parent->d_inode),
320 .clientid = server->nfs4_state->cl_clientid,
321 .name = &dentry->d_name,
322 .id = sp->so_id,
323 .server = server,
324 .bitmask = server->attr_bitmask,
325 .claim = NFS4_OPEN_CLAIM_DELEGATE_CUR,
326 };
327 struct nfs_openres res = {
328 .server = server,
329 };
330 struct rpc_message msg = { 387 struct rpc_message msg = {
331 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR], 388 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
332 .rpc_argp = &arg,
333 .rpc_resp = &res,
334 .rpc_cred = sp->so_cred, 389 .rpc_cred = sp->so_cred,
335 }; 390 };
391 struct nfs4_opendata *opendata;
336 int status = 0; 392 int status = 0;
337 393
338 if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) 394 if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
339 goto out; 395 goto out;
340 if (state->state == 0) 396 if (state->state == 0)
341 goto out; 397 goto out;
342 arg.seqid = nfs_alloc_seqid(&sp->so_seqid); 398 opendata = nfs4_opendata_alloc(dentry, sp, state->state, NULL);
343 status = -ENOMEM; 399 status = -ENOMEM;
344 if (arg.seqid == NULL) 400 if (opendata == NULL)
345 goto out; 401 goto out;
346 arg.open_flags = state->state; 402 opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
347 memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); 403 msg.rpc_argp = &opendata->o_arg;
404 msg.rpc_resp = &opendata->o_res;
405 memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
406 sizeof(opendata->o_arg.u.delegation.data));
348 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); 407 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
349 nfs_increment_open_seqid(status, arg.seqid); 408 nfs_increment_open_seqid(status, opendata->o_arg.seqid);
350 if (status != 0) 409 if (status != 0)
351 goto out_free; 410 goto out_free;
352 if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) { 411 if(opendata->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
353 status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode), 412 status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode),
354 sp, &res.stateid, arg.seqid); 413 sp, &opendata->o_res.stateid, opendata->o_arg.seqid);
355 if (status != 0) 414 if (status != 0)
356 goto out_free; 415 goto out_free;
357 } 416 }
358 nfs_confirm_seqid(&sp->so_seqid, 0); 417 nfs_confirm_seqid(&sp->so_seqid, 0);
359 if (status >= 0) { 418 if (status >= 0) {
360 memcpy(state->stateid.data, res.stateid.data, 419 memcpy(state->stateid.data, opendata->o_res.stateid.data,
361 sizeof(state->stateid.data)); 420 sizeof(state->stateid.data));
362 clear_bit(NFS_DELEGATED_STATE, &state->flags); 421 clear_bit(NFS_DELEGATED_STATE, &state->flags);
363 } 422 }
364out_free: 423out_free:
365 nfs_free_seqid(arg.seqid); 424 nfs4_opendata_free(opendata);
366out: 425out:
367 dput(parent);
368 return status; 426 return status;
369} 427}
370 428
@@ -506,21 +564,8 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
506 struct dentry *parent = dget_parent(dentry); 564 struct dentry *parent = dget_parent(dentry);
507 struct inode *dir = parent->d_inode; 565 struct inode *dir = parent->d_inode;
508 struct inode *inode = state->inode; 566 struct inode *inode = state->inode;
509 struct nfs_server *server = NFS_SERVER(dir);
510 struct nfs_delegation *delegation = NFS_I(inode)->delegation; 567 struct nfs_delegation *delegation = NFS_I(inode)->delegation;
511 struct nfs_fattr f_attr, dir_attr; 568 struct nfs4_opendata *opendata;
512 struct nfs_openargs o_arg = {
513 .fh = NFS_FH(dir),
514 .open_flags = state->state,
515 .name = &dentry->d_name,
516 .bitmask = server->attr_bitmask,
517 .claim = NFS4_OPEN_CLAIM_NULL,
518 };
519 struct nfs_openres o_res = {
520 .f_attr = &f_attr,
521 .dir_attr = &dir_attr,
522 .server = server,
523 };
524 int status = 0; 569 int status = 0;
525 570
526 if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) { 571 if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
@@ -531,38 +576,38 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
531 set_bit(NFS_DELEGATED_STATE, &state->flags); 576 set_bit(NFS_DELEGATED_STATE, &state->flags);
532 goto out; 577 goto out;
533 } 578 }
534 o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
535 status = -ENOMEM; 579 status = -ENOMEM;
536 if (o_arg.seqid == NULL) 580 opendata = nfs4_opendata_alloc(dentry, sp, state->state, NULL);
581 if (opendata == NULL)
537 goto out; 582 goto out;
538 nfs_fattr_init(&f_attr); 583 status = _nfs4_proc_open(dir, sp, &opendata->o_arg, &opendata->o_res);
539 nfs_fattr_init(&dir_attr);
540 status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
541 if (status != 0) 584 if (status != 0)
542 goto out_nodeleg; 585 goto out_nodeleg;
543 /* Check if files differ */ 586 /* Check if files differ */
544 if ((f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT)) 587 if ((opendata->f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT))
545 goto out_stale; 588 goto out_stale;
546 /* Has the file handle changed? */ 589 /* Has the file handle changed? */
547 if (nfs_compare_fh(&o_res.fh, NFS_FH(inode)) != 0) { 590 if (nfs_compare_fh(&opendata->o_res.fh, NFS_FH(inode)) != 0) {
548 /* Verify if the change attributes are the same */ 591 /* Verify if the change attributes are the same */
549 if (f_attr.change_attr != NFS_I(inode)->change_attr) 592 if (opendata->f_attr.change_attr != NFS_I(inode)->change_attr)
550 goto out_stale; 593 goto out_stale;
551 if (nfs_size_to_loff_t(f_attr.size) != inode->i_size) 594 if (nfs_size_to_loff_t(opendata->f_attr.size) != inode->i_size)
552 goto out_stale; 595 goto out_stale;
553 /* Lets just pretend that this is the same file */ 596 /* Lets just pretend that this is the same file */
554 nfs_copy_fh(NFS_FH(inode), &o_res.fh); 597 nfs_copy_fh(NFS_FH(inode), &opendata->o_res.fh);
555 NFS_I(inode)->fileid = f_attr.fileid; 598 NFS_I(inode)->fileid = opendata->f_attr.fileid;
556 } 599 }
557 memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); 600 memcpy(&state->stateid, &opendata->o_res.stateid, sizeof(state->stateid));
558 if (o_res.delegation_type != 0) { 601 if (opendata->o_res.delegation_type != 0) {
559 if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) 602 if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM))
560 nfs_inode_set_delegation(inode, sp->so_cred, &o_res); 603 nfs_inode_set_delegation(inode, sp->so_cred,
604 &opendata->o_res);
561 else 605 else
562 nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); 606 nfs_inode_reclaim_delegation(inode, sp->so_cred,
607 &opendata->o_res);
563 } 608 }
564out_nodeleg: 609out_nodeleg:
565 nfs_free_seqid(o_arg.seqid); 610 nfs4_opendata_free(opendata);
566 clear_bit(NFS_DELEGATED_STATE, &state->flags); 611 clear_bit(NFS_DELEGATED_STATE, &state->flags);
567out: 612out:
568 dput(parent); 613 dput(parent);
@@ -706,21 +751,8 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
706 struct nfs_server *server = NFS_SERVER(dir); 751 struct nfs_server *server = NFS_SERVER(dir);
707 struct nfs4_client *clp = server->nfs4_state; 752 struct nfs4_client *clp = server->nfs4_state;
708 struct inode *inode = NULL; 753 struct inode *inode = NULL;
754 struct nfs4_opendata *opendata;
709 int status; 755 int status;
710 struct nfs_fattr f_attr, dir_attr;
711 struct nfs_openargs o_arg = {
712 .fh = NFS_FH(dir),
713 .open_flags = flags,
714 .name = &dentry->d_name,
715 .server = server,
716 .bitmask = server->attr_bitmask,
717 .claim = NFS4_OPEN_CLAIM_NULL,
718 };
719 struct nfs_openres o_res = {
720 .f_attr = &f_attr,
721 .dir_attr = &dir_attr,
722 .server = server,
723 };
724 756
725 /* Protect against reboot recovery conflicts */ 757 /* Protect against reboot recovery conflicts */
726 down_read(&clp->cl_sem); 758 down_read(&clp->cl_sem);
@@ -729,45 +761,34 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
729 dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n"); 761 dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
730 goto out_err; 762 goto out_err;
731 } 763 }
732 if (flags & O_EXCL) { 764 opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
733 u32 *p = (u32 *) o_arg.u.verifier.data; 765 if (opendata == NULL)
734 p[0] = jiffies; 766 goto err_put_state_owner;
735 p[1] = current->pid;
736 } else
737 o_arg.u.attrs = sattr;
738 /* Serialization for the sequence id */
739 767
740 o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); 768 status = _nfs4_proc_open(dir, sp, &opendata->o_arg, &opendata->o_res);
741 if (o_arg.seqid == NULL)
742 return -ENOMEM;
743 nfs_fattr_init(&f_attr);
744 nfs_fattr_init(&dir_attr);
745 status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
746 if (status != 0) 769 if (status != 0)
747 goto out_err; 770 goto err_opendata_free;
748 771
749 status = -ENOMEM; 772 status = -ENOMEM;
750 inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr); 773 inode = nfs_fhget(dir->i_sb, &opendata->o_res.fh, &opendata->f_attr);
751 if (!inode) 774 if (!inode)
752 goto out_err; 775 goto err_opendata_free;
753 state = nfs4_get_open_state(inode, sp); 776 state = nfs4_get_open_state(inode, sp);
754 if (!state) 777 if (!state)
755 goto out_err; 778 goto err_opendata_free;
756 update_open_stateid(state, &o_res.stateid, flags); 779 update_open_stateid(state, &opendata->o_res.stateid, flags);
757 if (o_res.delegation_type != 0) 780 if (opendata->o_res.delegation_type != 0)
758 nfs_inode_set_delegation(inode, cred, &o_res); 781 nfs_inode_set_delegation(inode, cred, &opendata->o_res);
759 nfs_free_seqid(o_arg.seqid); 782 nfs4_opendata_free(opendata);
760 nfs4_put_state_owner(sp); 783 nfs4_put_state_owner(sp);
761 up_read(&clp->cl_sem); 784 up_read(&clp->cl_sem);
762 *res = state; 785 *res = state;
763 return 0; 786 return 0;
787err_opendata_free:
788 nfs4_opendata_free(opendata);
789err_put_state_owner:
790 nfs4_put_state_owner(sp);
764out_err: 791out_err:
765 if (sp != NULL) {
766 if (state != NULL)
767 nfs4_put_open_state(state);
768 nfs_free_seqid(o_arg.seqid);
769 nfs4_put_state_owner(sp);
770 }
771 /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ 792 /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */
772 up_read(&clp->cl_sem); 793 up_read(&clp->cl_sem);
773 if (inode != NULL) 794 if (inode != NULL)