Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] RPC,NFS: new rpc_pipefs patch

Currently rpc_mkdir/rpc_rmdir and rpc_mkpipe/mk_unlink have an API that's
a little unfortunate. They take a path relative to the rpc_pipefs root and
thus need to perform a full lookup. If you look at debugfs or usbfs they
always store the dentry for directories they created and thus can pass in
a dentry + single pathname component pair into their equivalents of the
above functions.

And in fact rpc_pipefs actually stores a dentry for all but one component so
this change not only simplifies the core rpc_pipe code but also the callers.

Unfortuntately this code path is only used by the NFS4 idmapper and
AUTH_GSSAPI for which I don't have a test enviroment. Could someone give
it a spin? It's the last bit needed before we can rework the
lookup_hash API

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

authored by

Christoph Hellwig and committed by
Trond Myklebust
278c995c 470056c2

+149 -216
+3 -7
fs/nfs/idmap.c
··· 66 66 }; 67 67 68 68 struct idmap { 69 - char idmap_path[48]; 70 69 struct dentry *idmap_dentry; 71 70 wait_queue_head_t idmap_wq; 72 71 struct idmap_msg idmap_im; ··· 101 102 102 103 memset(idmap, 0, sizeof(*idmap)); 103 104 104 - snprintf(idmap->idmap_path, sizeof(idmap->idmap_path), 105 - "%s/idmap", clp->cl_rpcclient->cl_pathname); 106 - 107 - idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path, 108 - idmap, &idmap_upcall_ops, 0); 105 + idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry, 106 + "idmap", idmap, &idmap_upcall_ops, 0); 109 107 if (IS_ERR(idmap->idmap_dentry)) { 110 108 kfree(idmap); 111 109 return; ··· 124 128 125 129 if (!idmap) 126 130 return; 127 - rpc_unlink(idmap->idmap_path); 131 + rpc_unlink(idmap->idmap_dentry); 128 132 clp->cl_idmap = NULL; 129 133 kfree(idmap); 130 134 }
+1 -1
include/linux/sunrpc/clnt.h
··· 59 59 60 60 int cl_nodelen; /* nodename length */ 61 61 char cl_nodename[UNX_MAXNODENAME]; 62 - char cl_pathname[30];/* Path in rpc_pipe_fs */ 62 + struct dentry * __cl_parent_dentry; 63 63 struct dentry * cl_dentry; /* inode */ 64 64 struct rpc_clnt * cl_parent; /* Points to parent of clones */ 65 65 struct rpc_rtt cl_rtt_default;
+5 -4
include/linux/sunrpc/rpc_pipe_fs.h
··· 41 41 42 42 extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); 43 43 44 - extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *); 45 - extern int rpc_rmdir(char *); 46 - extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); 47 - extern int rpc_unlink(char *); 44 + extern struct dentry *rpc_mkdir(struct dentry *, char *, struct rpc_clnt *); 45 + extern void rpc_rmdir(struct dentry *); 46 + extern struct dentry *rpc_mkpipe(struct dentry *, char *, void *, 47 + struct rpc_pipe_ops *, int flags); 48 + extern void rpc_unlink(struct dentry *); 48 49 49 50 #endif 50 51 #endif
+3 -6
net/sunrpc/auth_gss/auth_gss.c
··· 87 87 struct list_head upcalls; 88 88 struct rpc_clnt *client; 89 89 struct dentry *dentry; 90 - char path[48]; 91 90 spinlock_t lock; 92 91 }; 93 92 ··· 689 690 if (err) 690 691 goto err_put_mech; 691 692 692 - snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s", 693 - clnt->cl_pathname, 694 - gss_auth->mech->gm_name); 695 - gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 693 + gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, 694 + clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 696 695 if (IS_ERR(gss_auth->dentry)) { 697 696 err = PTR_ERR(gss_auth->dentry); 698 697 goto err_put_mech; ··· 715 718 auth, auth->au_flavor); 716 719 717 720 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 718 - rpc_unlink(gss_auth->path); 721 + rpc_unlink(gss_auth->dentry); 719 722 gss_mech_put(gss_auth->mech); 720 723 721 724 rpcauth_free_credcache(auth);
+37 -18
net/sunrpc/clnt.c
··· 67 67 static int 68 68 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) 69 69 { 70 - static uint32_t clntid; 70 + static unsigned int clntid; 71 + char name[128]; 71 72 int error; 72 73 73 74 if (dir_name == NULL) 74 75 return 0; 75 - for (;;) { 76 - snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname), 77 - "%s/clnt%x", dir_name, 78 - (unsigned int)clntid++); 79 - clnt->cl_pathname[sizeof(clnt->cl_pathname) - 1] = '\0'; 80 - clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt); 81 - if (!IS_ERR(clnt->cl_dentry)) 82 - return 0; 83 - error = PTR_ERR(clnt->cl_dentry); 84 - if (error != -EEXIST) { 85 - printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", 86 - clnt->cl_pathname, error); 87 - return error; 88 - } 76 + 77 + retry_parent: 78 + clnt->__cl_parent_dentry = rpc_mkdir(NULL, dir_name, NULL); 79 + if (IS_ERR(clnt->__cl_parent_dentry)) { 80 + error = PTR_ERR(clnt->__cl_parent_dentry); 81 + if (error == -EEXIST) 82 + goto retry_parent; /* XXX(hch): WTF? */ 83 + 84 + printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", 85 + dir_name, error); 86 + return error; 89 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); 97 + if (error == -EEXIST) 98 + goto retry_child; 99 + printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", 100 + name, error); 101 + rpc_rmdir(clnt->__cl_parent_dentry); 102 + return error; 103 + } 104 + 105 + return 0; 90 106 } 91 107 92 108 /* ··· 190 174 return clnt; 191 175 192 176 out_no_auth: 193 - rpc_rmdir(clnt->cl_pathname); 177 + rpc_rmdir(clnt->cl_dentry); 178 + rpc_rmdir(clnt->__cl_parent_dentry); 194 179 out_no_path: 195 180 if (clnt->cl_server != clnt->cl_inline_name) 196 181 kfree(clnt->cl_server); ··· 319 302 rpc_destroy_client(clnt->cl_parent); 320 303 goto out_free; 321 304 } 322 - if (clnt->cl_pathname[0]) 323 - rpc_rmdir(clnt->cl_pathname); 305 + if (clnt->cl_dentry) 306 + rpc_rmdir(clnt->cl_dentry); 307 + if (clnt->__cl_parent_dentry) 308 + rpc_rmdir(clnt->__cl_parent_dentry); 324 309 if (clnt->cl_xprt) { 325 310 xprt_destroy(clnt->cl_xprt); 326 311 clnt->cl_xprt = NULL;
+100 -180
net/sunrpc/rpc_pipe.c
··· 414 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 - 449 417 static struct inode * 450 418 rpc_get_inode(struct super_block *sb, int mode) 451 419 { ··· 518 550 return -ENOMEM; 519 551 } 520 552 521 - static int 522 - __rpc_mkdir(struct inode *dir, struct dentry *dentry) 553 + struct dentry * 554 + rpc_mkdir(struct dentry *parent, char *name, struct rpc_clnt *rpc_client) 523 555 { 556 + struct inode *dir; 557 + struct dentry *dentry; 524 558 struct inode *inode; 559 + int error; 560 + 561 + if (!parent) 562 + parent = rpc_mount->mnt_root; 563 + 564 + dir = parent->d_inode; 565 + 566 + error = rpc_get_mount(); 567 + if (error) 568 + return ERR_PTR(error); 569 + 570 + down(&dir->i_sem); 571 + dentry = lookup_one_len(name, parent, strlen(name)); 572 + if (IS_ERR(dentry)) 573 + goto out_unlock; 574 + if (dentry->d_inode) { 575 + dentry = ERR_PTR(-EEXIST); 576 + goto out_dput; 577 + } 525 578 526 579 inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR); 527 580 if (!inode) 528 - goto out_err; 581 + goto out_dput; 529 582 inode->i_ino = iunique(dir->i_sb, 100); 530 - d_instantiate(dentry, inode); 531 583 dir->i_nlink++; 532 - inode_dir_notify(dir, DN_CREATE); 533 - rpc_get_mount(); 534 - return 0; 535 - out_err: 536 - printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", 537 - __FILE__, __FUNCTION__, dentry->d_name.name); 538 - return -ENOMEM; 539 - } 540 - 541 - static int 542 - __rpc_rmdir(struct inode *dir, struct dentry *dentry) 543 - { 544 - int error; 545 - 546 - shrink_dcache_parent(dentry); 547 - if (dentry->d_inode) { 548 - rpc_close_pipes(dentry->d_inode); 549 - rpc_inode_setowner(dentry->d_inode, NULL); 550 - } 551 - if ((error = simple_rmdir(dir, dentry)) != 0) 552 - return error; 553 - if (!error) { 554 - inode_dir_notify(dir, DN_DELETE); 555 - d_drop(dentry); 556 - rpc_put_mount(); 557 - } 558 - return 0; 559 - } 560 - 561 - static struct dentry * 562 - rpc_lookup_negative(char *path, struct nameidata *nd) 563 - { 564 - struct dentry *dentry; 565 - struct inode *dir; 566 - int error; 567 - 568 - if ((error = rpc_lookup_parent(path, nd)) != 0) 569 - return ERR_PTR(error); 570 - dir = nd->dentry->d_inode; 571 - down(&dir->i_sem); 572 - dentry = lookup_hash(&nd->last, nd->dentry); 573 - if (IS_ERR(dentry)) 574 - goto out_err; 575 - if (dentry->d_inode) { 576 - dput(dentry); 577 - dentry = ERR_PTR(-EEXIST); 578 - goto out_err; 579 - } 580 - return dentry; 581 - out_err: 582 - up(&dir->i_sem); 583 - rpc_release_path(nd); 584 - return dentry; 585 - } 586 - 587 - 588 - struct dentry * 589 - rpc_mkdir(char *path, struct rpc_clnt *rpc_client) 590 - { 591 - struct nameidata nd; 592 - struct dentry *dentry; 593 - struct inode *dir; 594 - int error; 595 - 596 - dentry = rpc_lookup_negative(path, &nd); 597 - if (IS_ERR(dentry)) 598 - return dentry; 599 - dir = nd.dentry->d_inode; 600 - if ((error = __rpc_mkdir(dir, dentry)) != 0) 601 - goto err_dput; 602 584 RPC_I(dentry->d_inode)->private = rpc_client; 585 + 586 + d_instantiate(dentry, inode); 587 + dget(dentry); 588 + up(&dir->i_sem); 589 + 590 + inode_dir_notify(dir, DN_CREATE); 591 + 603 592 error = rpc_populate(dentry, authfiles, 604 593 RPCAUTH_info, RPCAUTH_EOF); 605 594 if (error) 606 - goto err_depopulate; 607 - out: 608 - up(&dir->i_sem); 609 - rpc_release_path(&nd); 595 + goto out_depopulate; 596 + 610 597 return dentry; 611 - err_depopulate: 612 - rpc_depopulate(dentry); 613 - __rpc_rmdir(dir, dentry); 614 - err_dput: 598 + 599 + out_depopulate: 600 + rpc_rmdir(dentry); 601 + out_dput: 615 602 dput(dentry); 616 - printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n", 617 - __FILE__, __FUNCTION__, path, error); 618 - dentry = ERR_PTR(error); 619 - goto out; 603 + out_unlock: 604 + up(&dir->i_sem); 605 + rpc_put_mount(); 606 + return dentry; 620 607 } 621 608 622 - int 623 - rpc_rmdir(char *path) 609 + void 610 + rpc_rmdir(struct dentry *dentry) 624 611 { 625 - struct nameidata nd; 626 - struct dentry *dentry; 627 - struct inode *dir; 628 - int error; 612 + struct dentry *parent = dentry->d_parent; 629 613 630 - if ((error = rpc_lookup_parent(path, &nd)) != 0) 631 - return error; 632 - dir = nd.dentry->d_inode; 633 - down(&dir->i_sem); 634 - dentry = lookup_hash(&nd.last, nd.dentry); 635 - if (IS_ERR(dentry)) { 636 - error = PTR_ERR(dentry); 637 - goto out_release; 638 - } 639 614 rpc_depopulate(dentry); 640 - error = __rpc_rmdir(dir, dentry); 641 - dput(dentry); 642 - out_release: 643 - up(&dir->i_sem); 644 - rpc_release_path(&nd); 645 - return error; 615 + 616 + down(&parent->d_inode->i_sem); 617 + if (dentry->d_inode) { 618 + rpc_close_pipes(dentry->d_inode); 619 + rpc_inode_setowner(dentry->d_inode, NULL); 620 + simple_rmdir(parent->d_inode, dentry); 621 + } 622 + up(&parent->d_inode->i_sem); 623 + 624 + inode_dir_notify(parent->d_inode, DN_DELETE); 625 + rpc_put_mount(); 646 626 } 647 627 648 628 struct dentry * 649 - rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) 629 + rpc_mkpipe(struct dentry *parent, char *name, void *private, 630 + struct rpc_pipe_ops *ops, int flags) 650 631 { 651 - struct nameidata nd; 632 + struct inode *dir = parent->d_inode; 652 633 struct dentry *dentry; 653 - struct inode *dir, *inode; 634 + struct inode *inode; 654 635 struct rpc_inode *rpci; 636 + int error; 655 637 656 - dentry = rpc_lookup_negative(path, &nd); 638 + error = rpc_get_mount(); 639 + if (error) 640 + return ERR_PTR(error); 641 + 642 + down(&parent->d_inode->i_sem); 643 + dentry = lookup_one_len(name, parent, strlen(name)); 657 644 if (IS_ERR(dentry)) 658 - return dentry; 659 - dir = nd.dentry->d_inode; 660 - inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR); 661 - if (!inode) 662 - goto err_dput; 645 + goto out_unlock; 646 + if (dentry->d_inode) { 647 + dentry = ERR_PTR(-EEXIST); 648 + goto out_dput; 649 + } 650 + 651 + inode = rpc_get_inode(parent->d_inode->i_sb, 652 + S_IFSOCK | S_IRUSR | S_IWUSR); 653 + if (!inode) { 654 + dentry = ERR_PTR(-ENOMEM); 655 + goto out_dput; 656 + } 657 + 663 658 inode->i_ino = iunique(dir->i_sb, 100); 664 659 inode->i_fop = &rpc_pipe_fops; 665 - d_instantiate(dentry, inode); 660 + 666 661 rpci = RPC_I(inode); 667 662 rpci->private = private; 668 663 rpci->flags = flags; 669 664 rpci->ops = ops; 665 + 666 + d_instantiate(dentry, inode); 667 + dget(dentry); 668 + up(&parent->d_inode->i_sem); 669 + 670 670 inode_dir_notify(dir, DN_CREATE); 671 - out: 672 - up(&dir->i_sem); 673 - rpc_release_path(&nd); 674 671 return dentry; 675 - err_dput: 672 + 673 + out_dput: 676 674 dput(dentry); 677 - dentry = ERR_PTR(-ENOMEM); 678 - printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n", 679 - __FILE__, __FUNCTION__, path, -ENOMEM); 680 - goto out; 675 + out_unlock: 676 + up(&parent->d_inode->i_sem); 677 + rpc_put_mount(); 678 + return dentry; 681 679 } 682 680 683 - int 684 - rpc_unlink(char *path) 681 + void 682 + rpc_unlink(struct dentry *dentry) 685 683 { 686 - struct nameidata nd; 687 - struct dentry *dentry; 688 - struct inode *dir; 689 - int error; 684 + struct dentry *parent = dentry->d_parent; 690 685 691 - if ((error = rpc_lookup_parent(path, &nd)) != 0) 692 - return error; 693 - dir = nd.dentry->d_inode; 694 - down(&dir->i_sem); 695 - dentry = lookup_hash(&nd.last, nd.dentry); 696 - if (IS_ERR(dentry)) { 697 - error = PTR_ERR(dentry); 698 - goto out_release; 699 - } 700 - d_drop(dentry); 686 + down(&parent->d_inode->i_sem); 701 687 if (dentry->d_inode) { 702 688 rpc_close_pipes(dentry->d_inode); 703 689 rpc_inode_setowner(dentry->d_inode, NULL); 704 - error = simple_unlink(dir, dentry); 690 + simple_unlink(parent->d_inode, dentry); 705 691 } 706 - dput(dentry); 707 - inode_dir_notify(dir, DN_DELETE); 708 - out_release: 709 - up(&dir->i_sem); 710 - rpc_release_path(&nd); 711 - return error; 692 + up(&parent->d_inode->i_sem); 693 + 694 + inode_dir_notify(parent->d_inode, DN_DELETE); 695 + rpc_put_mount(); 712 696 } 713 697 714 698 /*