diff options
-rw-r--r-- | fs/nfs/idmap.c | 10 | ||||
-rw-r--r-- | include/linux/sunrpc/clnt.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/rpc_pipe_fs.h | 9 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 9 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 53 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 268 |
6 files changed, 209 insertions, 142 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 1d0a5bf0d264..ffb8df91dc34 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -66,6 +66,7 @@ struct idmap_hashtable { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct idmap { | 68 | struct idmap { |
69 | char idmap_path[48]; | ||
69 | struct dentry *idmap_dentry; | 70 | struct dentry *idmap_dentry; |
70 | wait_queue_head_t idmap_wq; | 71 | wait_queue_head_t idmap_wq; |
71 | struct idmap_msg idmap_im; | 72 | struct idmap_msg idmap_im; |
@@ -101,8 +102,11 @@ nfs_idmap_new(struct nfs4_client *clp) | |||
101 | 102 | ||
102 | memset(idmap, 0, sizeof(*idmap)); | 103 | memset(idmap, 0, sizeof(*idmap)); |
103 | 104 | ||
104 | idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry, | 105 | snprintf(idmap->idmap_path, sizeof(idmap->idmap_path), |
105 | "idmap", idmap, &idmap_upcall_ops, 0); | 106 | "%s/idmap", clp->cl_rpcclient->cl_pathname); |
107 | |||
108 | idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path, | ||
109 | idmap, &idmap_upcall_ops, 0); | ||
106 | if (IS_ERR(idmap->idmap_dentry)) { | 110 | if (IS_ERR(idmap->idmap_dentry)) { |
107 | kfree(idmap); | 111 | kfree(idmap); |
108 | return; | 112 | return; |
@@ -124,7 +128,7 @@ nfs_idmap_delete(struct nfs4_client *clp) | |||
124 | 128 | ||
125 | if (!idmap) | 129 | if (!idmap) |
126 | return; | 130 | return; |
127 | rpc_unlink(idmap->idmap_dentry); | 131 | rpc_unlink(idmap->idmap_path); |
128 | clp->cl_idmap = NULL; | 132 | clp->cl_idmap = NULL; |
129 | kfree(idmap); | 133 | kfree(idmap); |
130 | } | 134 | } |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index b5b51c196690..ab151bbb66df 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -59,7 +59,7 @@ struct rpc_clnt { | |||
59 | 59 | ||
60 | int cl_nodelen; /* nodename length */ | 60 | int cl_nodelen; /* nodename length */ |
61 | char cl_nodename[UNX_MAXNODENAME]; | 61 | char cl_nodename[UNX_MAXNODENAME]; |
62 | struct dentry * __cl_parent_dentry; | 62 | char cl_pathname[30];/* Path in rpc_pipe_fs */ |
63 | struct dentry * cl_dentry; /* inode */ | 63 | struct dentry * cl_dentry; /* inode */ |
64 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ | 64 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ |
65 | struct rpc_rtt cl_rtt_default; | 65 | struct rpc_rtt cl_rtt_default; |
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index 63878d05c9a9..63929349571f 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h | |||
@@ -41,11 +41,10 @@ RPC_I(struct inode *inode) | |||
41 | 41 | ||
42 | extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); | 42 | extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); |
43 | 43 | ||
44 | extern struct dentry *rpc_mkdir(struct dentry *, char *, struct rpc_clnt *); | 44 | extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *); |
45 | extern void rpc_rmdir(struct dentry *); | 45 | extern int rpc_rmdir(char *); |
46 | extern struct dentry *rpc_mkpipe(struct dentry *, char *, void *, | 46 | extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); |
47 | struct rpc_pipe_ops *, int flags); | 47 | extern int rpc_unlink(char *); |
48 | extern void rpc_unlink(struct dentry *); | ||
49 | 48 | ||
50 | #endif | 49 | #endif |
51 | #endif | 50 | #endif |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index bd2555139fa9..d2b08f16c257 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -87,6 +87,7 @@ struct gss_auth { | |||
87 | struct list_head upcalls; | 87 | struct list_head upcalls; |
88 | struct rpc_clnt *client; | 88 | struct rpc_clnt *client; |
89 | struct dentry *dentry; | 89 | struct dentry *dentry; |
90 | char path[48]; | ||
90 | spinlock_t lock; | 91 | spinlock_t lock; |
91 | }; | 92 | }; |
92 | 93 | ||
@@ -689,8 +690,10 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
689 | if (err) | 690 | if (err) |
690 | goto err_put_mech; | 691 | goto err_put_mech; |
691 | 692 | ||
692 | gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, | 693 | snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s", |
693 | clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); | 694 | clnt->cl_pathname, |
695 | gss_auth->mech->gm_name); | ||
696 | gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); | ||
694 | if (IS_ERR(gss_auth->dentry)) { | 697 | if (IS_ERR(gss_auth->dentry)) { |
695 | err = PTR_ERR(gss_auth->dentry); | 698 | err = PTR_ERR(gss_auth->dentry); |
696 | goto err_put_mech; | 699 | goto err_put_mech; |
@@ -715,7 +718,7 @@ gss_destroy(struct rpc_auth *auth) | |||
715 | auth, auth->au_flavor); | 718 | auth, auth->au_flavor); |
716 | 719 | ||
717 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 720 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
718 | rpc_unlink(gss_auth->dentry); | 721 | rpc_unlink(gss_auth->path); |
719 | gss_mech_put(gss_auth->mech); | 722 | gss_mech_put(gss_auth->mech); |
720 | 723 | ||
721 | rpcauth_free_credcache(auth); | 724 | rpcauth_free_credcache(auth); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 63bf591310e0..5a8f01d726e9 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -67,42 +67,26 @@ static u32 * call_verify(struct rpc_task *task); | |||
67 | static int | 67 | static int |
68 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | 68 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) |
69 | { | 69 | { |
70 | static unsigned int clntid; | 70 | static uint32_t clntid; |
71 | char name[128]; | ||
72 | int error; | 71 | int error; |
73 | 72 | ||
74 | if (dir_name == NULL) | 73 | if (dir_name == NULL) |
75 | return 0; | 74 | return 0; |
76 | 75 | for (;;) { | |
77 | retry_parent: | 76 | snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname), |
78 | clnt->__cl_parent_dentry = rpc_mkdir(NULL, dir_name, NULL); | 77 | "%s/clnt%x", dir_name, |
79 | if (IS_ERR(clnt->__cl_parent_dentry)) { | 78 | (unsigned int)clntid++); |
80 | error = PTR_ERR(clnt->__cl_parent_dentry); | 79 | clnt->cl_pathname[sizeof(clnt->cl_pathname) - 1] = '\0'; |
81 | if (error == -EEXIST) | 80 | clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt); |
82 | goto retry_parent; /* XXX(hch): WTF? */ | 81 | if (!IS_ERR(clnt->cl_dentry)) |
83 | 82 | return 0; | |
84 | printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", | ||
85 | dir_name, error); | ||
86 | return error; | ||
87 | } | ||
88 | |||
89 | |||
90 | retry_child: | ||
91 | snprintf(name, sizeof(name), "clnt%x", clntid++); | ||
92 | name[sizeof(name) - 1] = '\0'; | ||
93 | |||
94 | clnt->cl_dentry = rpc_mkdir(clnt->__cl_parent_dentry, name, clnt); | ||
95 | if (IS_ERR(clnt->cl_dentry)) { | ||
96 | error = PTR_ERR(clnt->cl_dentry); | 83 | error = PTR_ERR(clnt->cl_dentry); |
97 | if (error == -EEXIST) | 84 | if (error != -EEXIST) { |
98 | goto retry_child; | 85 | printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", |
99 | printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", | 86 | clnt->cl_pathname, error); |
100 | name, error); | 87 | return error; |
101 | rpc_rmdir(clnt->__cl_parent_dentry); | 88 | } |
102 | return error; | ||
103 | } | 89 | } |
104 | |||
105 | return 0; | ||
106 | } | 90 | } |
107 | 91 | ||
108 | /* | 92 | /* |
@@ -190,8 +174,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
190 | return clnt; | 174 | return clnt; |
191 | 175 | ||
192 | out_no_auth: | 176 | out_no_auth: |
193 | rpc_rmdir(clnt->cl_dentry); | 177 | rpc_rmdir(clnt->cl_pathname); |
194 | rpc_rmdir(clnt->__cl_parent_dentry); | ||
195 | out_no_path: | 178 | out_no_path: |
196 | if (clnt->cl_server != clnt->cl_inline_name) | 179 | if (clnt->cl_server != clnt->cl_inline_name) |
197 | kfree(clnt->cl_server); | 180 | kfree(clnt->cl_server); |
@@ -319,10 +302,8 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
319 | rpc_destroy_client(clnt->cl_parent); | 302 | rpc_destroy_client(clnt->cl_parent); |
320 | goto out_free; | 303 | goto out_free; |
321 | } | 304 | } |
322 | if (clnt->cl_dentry) | 305 | if (clnt->cl_pathname[0]) |
323 | rpc_rmdir(clnt->cl_dentry); | 306 | rpc_rmdir(clnt->cl_pathname); |
324 | if (clnt->__cl_parent_dentry) | ||
325 | rpc_rmdir(clnt->__cl_parent_dentry); | ||
326 | if (clnt->cl_xprt) { | 307 | if (clnt->cl_xprt) { |
327 | xprt_destroy(clnt->cl_xprt); | 308 | xprt_destroy(clnt->cl_xprt); |
328 | clnt->cl_xprt = NULL; | 309 | clnt->cl_xprt = NULL; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index b382809726d8..ded6c63f11ec 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -414,6 +414,38 @@ rpc_put_mount(void) | |||
414 | simple_release_fs(&rpc_mount, &rpc_mount_count); | 414 | simple_release_fs(&rpc_mount, &rpc_mount_count); |
415 | } | 415 | } |
416 | 416 | ||
417 | static int | ||
418 | rpc_lookup_parent(char *path, struct nameidata *nd) | ||
419 | { | ||
420 | if (path[0] == '\0') | ||
421 | return -ENOENT; | ||
422 | if (rpc_get_mount()) { | ||
423 | printk(KERN_WARNING "%s: %s failed to mount " | ||
424 | "pseudofilesystem \n", __FILE__, __FUNCTION__); | ||
425 | return -ENODEV; | ||
426 | } | ||
427 | nd->mnt = mntget(rpc_mount); | ||
428 | nd->dentry = dget(rpc_mount->mnt_root); | ||
429 | nd->last_type = LAST_ROOT; | ||
430 | nd->flags = LOOKUP_PARENT; | ||
431 | nd->depth = 0; | ||
432 | |||
433 | if (path_walk(path, nd)) { | ||
434 | printk(KERN_WARNING "%s: %s failed to find path %s\n", | ||
435 | __FILE__, __FUNCTION__, path); | ||
436 | rpc_put_mount(); | ||
437 | return -ENOENT; | ||
438 | } | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static void | ||
443 | rpc_release_path(struct nameidata *nd) | ||
444 | { | ||
445 | path_release(nd); | ||
446 | rpc_put_mount(); | ||
447 | } | ||
448 | |||
417 | static struct inode * | 449 | static struct inode * |
418 | rpc_get_inode(struct super_block *sb, int mode) | 450 | rpc_get_inode(struct super_block *sb, int mode) |
419 | { | 451 | { |
@@ -518,149 +550,197 @@ out_bad: | |||
518 | return -ENOMEM; | 550 | return -ENOMEM; |
519 | } | 551 | } |
520 | 552 | ||
521 | struct dentry * | 553 | static int |
522 | rpc_mkdir(struct dentry *parent, char *name, struct rpc_clnt *rpc_client) | 554 | __rpc_mkdir(struct inode *dir, struct dentry *dentry) |
523 | { | 555 | { |
524 | struct inode *dir; | ||
525 | struct dentry *dentry; | ||
526 | struct inode *inode; | 556 | struct inode *inode; |
557 | |||
558 | inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR); | ||
559 | if (!inode) | ||
560 | goto out_err; | ||
561 | inode->i_ino = iunique(dir->i_sb, 100); | ||
562 | d_instantiate(dentry, inode); | ||
563 | dir->i_nlink++; | ||
564 | inode_dir_notify(dir, DN_CREATE); | ||
565 | rpc_get_mount(); | ||
566 | return 0; | ||
567 | out_err: | ||
568 | printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", | ||
569 | __FILE__, __FUNCTION__, dentry->d_name.name); | ||
570 | return -ENOMEM; | ||
571 | } | ||
572 | |||
573 | static int | ||
574 | __rpc_rmdir(struct inode *dir, struct dentry *dentry) | ||
575 | { | ||
527 | int error; | 576 | int error; |
528 | 577 | ||
529 | if (!parent) | 578 | shrink_dcache_parent(dentry); |
530 | parent = rpc_mount->mnt_root; | 579 | if (dentry->d_inode) { |
580 | rpc_close_pipes(dentry->d_inode); | ||
581 | rpc_inode_setowner(dentry->d_inode, NULL); | ||
582 | } | ||
583 | if ((error = simple_rmdir(dir, dentry)) != 0) | ||
584 | return error; | ||
585 | if (!error) { | ||
586 | inode_dir_notify(dir, DN_DELETE); | ||
587 | d_drop(dentry); | ||
588 | rpc_put_mount(); | ||
589 | } | ||
590 | return 0; | ||
591 | } | ||
531 | 592 | ||
532 | dir = parent->d_inode; | 593 | static struct dentry * |
533 | 594 | rpc_lookup_negative(char *path, struct nameidata *nd) | |
534 | error = rpc_get_mount(); | 595 | { |
535 | if (error) | 596 | struct dentry *dentry; |
536 | return ERR_PTR(error); | 597 | struct inode *dir; |
598 | int error; | ||
537 | 599 | ||
600 | if ((error = rpc_lookup_parent(path, nd)) != 0) | ||
601 | return ERR_PTR(error); | ||
602 | dir = nd->dentry->d_inode; | ||
538 | down(&dir->i_sem); | 603 | down(&dir->i_sem); |
539 | dentry = lookup_one_len(name, parent, strlen(name)); | 604 | dentry = lookup_hash(&nd->last, nd->dentry); |
540 | if (IS_ERR(dentry)) | 605 | if (IS_ERR(dentry)) |
541 | goto out_unlock; | 606 | goto out_err; |
542 | if (dentry->d_inode) { | 607 | if (dentry->d_inode) { |
608 | dput(dentry); | ||
543 | dentry = ERR_PTR(-EEXIST); | 609 | dentry = ERR_PTR(-EEXIST); |
544 | goto out_dput; | 610 | goto out_err; |
545 | } | 611 | } |
546 | 612 | return dentry; | |
547 | inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR); | 613 | out_err: |
548 | if (!inode) | ||
549 | goto out_dput; | ||
550 | inode->i_ino = iunique(dir->i_sb, 100); | ||
551 | dir->i_nlink++; | ||
552 | RPC_I(dentry->d_inode)->private = rpc_client; | ||
553 | |||
554 | d_instantiate(dentry, inode); | ||
555 | dget(dentry); | ||
556 | up(&dir->i_sem); | 614 | up(&dir->i_sem); |
615 | rpc_release_path(nd); | ||
616 | return dentry; | ||
617 | } | ||
557 | 618 | ||
558 | inode_dir_notify(dir, DN_CREATE); | ||
559 | 619 | ||
620 | struct dentry * | ||
621 | rpc_mkdir(char *path, struct rpc_clnt *rpc_client) | ||
622 | { | ||
623 | struct nameidata nd; | ||
624 | struct dentry *dentry; | ||
625 | struct inode *dir; | ||
626 | int error; | ||
627 | |||
628 | dentry = rpc_lookup_negative(path, &nd); | ||
629 | if (IS_ERR(dentry)) | ||
630 | return dentry; | ||
631 | dir = nd.dentry->d_inode; | ||
632 | if ((error = __rpc_mkdir(dir, dentry)) != 0) | ||
633 | goto err_dput; | ||
634 | RPC_I(dentry->d_inode)->private = rpc_client; | ||
560 | error = rpc_populate(dentry, authfiles, | 635 | error = rpc_populate(dentry, authfiles, |
561 | RPCAUTH_info, RPCAUTH_EOF); | 636 | RPCAUTH_info, RPCAUTH_EOF); |
562 | if (error) | 637 | if (error) |
563 | goto out_depopulate; | 638 | goto err_depopulate; |
564 | 639 | out: | |
565 | return dentry; | ||
566 | |||
567 | out_depopulate: | ||
568 | rpc_rmdir(dentry); | ||
569 | out_dput: | ||
570 | dput(dentry); | ||
571 | out_unlock: | ||
572 | up(&dir->i_sem); | 640 | up(&dir->i_sem); |
573 | rpc_put_mount(); | 641 | rpc_release_path(&nd); |
574 | return dentry; | 642 | return dentry; |
643 | err_depopulate: | ||
644 | rpc_depopulate(dentry); | ||
645 | __rpc_rmdir(dir, dentry); | ||
646 | err_dput: | ||
647 | dput(dentry); | ||
648 | printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n", | ||
649 | __FILE__, __FUNCTION__, path, error); | ||
650 | dentry = ERR_PTR(error); | ||
651 | goto out; | ||
575 | } | 652 | } |
576 | 653 | ||
577 | void | 654 | int |
578 | rpc_rmdir(struct dentry *dentry) | 655 | rpc_rmdir(char *path) |
579 | { | 656 | { |
580 | struct dentry *parent = dentry->d_parent; | 657 | struct nameidata nd; |
581 | 658 | struct dentry *dentry; | |
582 | rpc_depopulate(dentry); | 659 | struct inode *dir; |
660 | int error; | ||
583 | 661 | ||
584 | down(&parent->d_inode->i_sem); | 662 | if ((error = rpc_lookup_parent(path, &nd)) != 0) |
585 | if (dentry->d_inode) { | 663 | return error; |
586 | rpc_close_pipes(dentry->d_inode); | 664 | dir = nd.dentry->d_inode; |
587 | rpc_inode_setowner(dentry->d_inode, NULL); | 665 | down(&dir->i_sem); |
588 | simple_rmdir(parent->d_inode, dentry); | 666 | dentry = lookup_hash(&nd.last, nd.dentry); |
667 | if (IS_ERR(dentry)) { | ||
668 | error = PTR_ERR(dentry); | ||
669 | goto out_release; | ||
589 | } | 670 | } |
590 | up(&parent->d_inode->i_sem); | 671 | rpc_depopulate(dentry); |
591 | 672 | error = __rpc_rmdir(dir, dentry); | |
592 | inode_dir_notify(parent->d_inode, DN_DELETE); | 673 | dput(dentry); |
593 | rpc_put_mount(); | 674 | out_release: |
675 | up(&dir->i_sem); | ||
676 | rpc_release_path(&nd); | ||
677 | return error; | ||
594 | } | 678 | } |
595 | 679 | ||
596 | struct dentry * | 680 | struct dentry * |
597 | rpc_mkpipe(struct dentry *parent, char *name, void *private, | 681 | rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) |
598 | struct rpc_pipe_ops *ops, int flags) | ||
599 | { | 682 | { |
600 | struct inode *dir = parent->d_inode; | 683 | struct nameidata nd; |
601 | struct dentry *dentry; | 684 | struct dentry *dentry; |
602 | struct inode *inode; | 685 | struct inode *dir, *inode; |
603 | struct rpc_inode *rpci; | 686 | struct rpc_inode *rpci; |
604 | int error; | ||
605 | |||
606 | error = rpc_get_mount(); | ||
607 | if (error) | ||
608 | return ERR_PTR(error); | ||
609 | 687 | ||
610 | down(&parent->d_inode->i_sem); | 688 | dentry = rpc_lookup_negative(path, &nd); |
611 | dentry = lookup_one_len(name, parent, strlen(name)); | ||
612 | if (IS_ERR(dentry)) | 689 | if (IS_ERR(dentry)) |
613 | goto out_unlock; | 690 | return dentry; |
614 | if (dentry->d_inode) { | 691 | dir = nd.dentry->d_inode; |
615 | dentry = ERR_PTR(-EEXIST); | 692 | inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR); |
616 | goto out_dput; | 693 | if (!inode) |
617 | } | 694 | goto err_dput; |
618 | |||
619 | inode = rpc_get_inode(parent->d_inode->i_sb, | ||
620 | S_IFSOCK | S_IRUSR | S_IWUSR); | ||
621 | if (!inode) { | ||
622 | dentry = ERR_PTR(-ENOMEM); | ||
623 | goto out_dput; | ||
624 | } | ||
625 | |||
626 | inode->i_ino = iunique(dir->i_sb, 100); | 695 | inode->i_ino = iunique(dir->i_sb, 100); |
627 | inode->i_fop = &rpc_pipe_fops; | 696 | inode->i_fop = &rpc_pipe_fops; |
628 | 697 | d_instantiate(dentry, inode); | |
629 | rpci = RPC_I(inode); | 698 | rpci = RPC_I(inode); |
630 | rpci->private = private; | 699 | rpci->private = private; |
631 | rpci->flags = flags; | 700 | rpci->flags = flags; |
632 | rpci->ops = ops; | 701 | rpci->ops = ops; |
633 | |||
634 | d_instantiate(dentry, inode); | ||
635 | dget(dentry); | ||
636 | up(&parent->d_inode->i_sem); | ||
637 | |||
638 | inode_dir_notify(dir, DN_CREATE); | 702 | inode_dir_notify(dir, DN_CREATE); |
703 | out: | ||
704 | up(&dir->i_sem); | ||
705 | rpc_release_path(&nd); | ||
639 | return dentry; | 706 | return dentry; |
640 | 707 | err_dput: | |
641 | out_dput: | ||
642 | dput(dentry); | 708 | dput(dentry); |
643 | out_unlock: | 709 | dentry = ERR_PTR(-ENOMEM); |
644 | up(&parent->d_inode->i_sem); | 710 | printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n", |
645 | rpc_put_mount(); | 711 | __FILE__, __FUNCTION__, path, -ENOMEM); |
646 | return dentry; | 712 | goto out; |
647 | } | 713 | } |
648 | 714 | ||
649 | void | 715 | int |
650 | rpc_unlink(struct dentry *dentry) | 716 | rpc_unlink(char *path) |
651 | { | 717 | { |
652 | struct dentry *parent = dentry->d_parent; | 718 | struct nameidata nd; |
719 | struct dentry *dentry; | ||
720 | struct inode *dir; | ||
721 | int error; | ||
653 | 722 | ||
654 | down(&parent->d_inode->i_sem); | 723 | if ((error = rpc_lookup_parent(path, &nd)) != 0) |
724 | return error; | ||
725 | dir = nd.dentry->d_inode; | ||
726 | down(&dir->i_sem); | ||
727 | dentry = lookup_hash(&nd.last, nd.dentry); | ||
728 | if (IS_ERR(dentry)) { | ||
729 | error = PTR_ERR(dentry); | ||
730 | goto out_release; | ||
731 | } | ||
732 | d_drop(dentry); | ||
655 | if (dentry->d_inode) { | 733 | if (dentry->d_inode) { |
656 | rpc_close_pipes(dentry->d_inode); | 734 | rpc_close_pipes(dentry->d_inode); |
657 | rpc_inode_setowner(dentry->d_inode, NULL); | 735 | rpc_inode_setowner(dentry->d_inode, NULL); |
658 | simple_unlink(parent->d_inode, dentry); | 736 | error = simple_unlink(dir, dentry); |
659 | } | 737 | } |
660 | up(&parent->d_inode->i_sem); | 738 | dput(dentry); |
661 | 739 | inode_dir_notify(dir, DN_DELETE); | |
662 | inode_dir_notify(parent->d_inode, DN_DELETE); | 740 | out_release: |
663 | rpc_put_mount(); | 741 | up(&dir->i_sem); |
742 | rpc_release_path(&nd); | ||
743 | return error; | ||
664 | } | 744 | } |
665 | 745 | ||
666 | /* | 746 | /* |