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

fs/9p: Move dotl inode operations into a seperate file

Source Code Reorganization

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>

authored by

Aneesh Kumar K.V and committed by
Eric Van Hensbergen
53c06f4e 255614c4

+916 -862
+1
fs/9p/Makefile
··· 3 3 9p-objs := \ 4 4 vfs_super.o \ 5 5 vfs_inode.o \ 6 + vfs_inode_dotl.o \ 6 7 vfs_addr.o \ 7 8 vfs_file.o \ 8 9 vfs_dir.o \
+39 -3
fs/9p/v9fs.h
··· 113 113 114 114 struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, 115 115 char *); 116 - void v9fs_session_close(struct v9fs_session_info *v9ses); 117 - void v9fs_session_cancel(struct v9fs_session_info *v9ses); 118 - void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); 116 + extern void v9fs_session_close(struct v9fs_session_info *v9ses); 117 + extern void v9fs_session_cancel(struct v9fs_session_info *v9ses); 118 + extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); 119 + extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, 120 + struct nameidata *nameidata); 121 + extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d); 122 + extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); 123 + extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 124 + struct inode *new_dir, struct dentry *new_dentry); 125 + extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, 126 + void *p); 127 + extern struct inode *v9fs_inode(struct v9fs_session_info *v9ses, 128 + struct p9_fid *fid, 129 + struct super_block *sb); 130 + 131 + extern const struct inode_operations v9fs_dir_inode_operations_dotl; 132 + extern const struct inode_operations v9fs_file_inode_operations_dotl; 133 + extern const struct inode_operations v9fs_symlink_inode_operations_dotl; 134 + extern struct inode *v9fs_inode_dotl(struct v9fs_session_info *v9ses, 135 + struct p9_fid *fid, 136 + struct super_block *sb); 119 137 120 138 /* other default globals */ 121 139 #define V9FS_PORT 564 ··· 155 137 static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) 156 138 { 157 139 return v9ses->flags & V9FS_PROTO_2000L; 140 + } 141 + 142 + /** 143 + * v9fs_inode_from_fid - Helper routine to populate an inode by 144 + * issuing a attribute request 145 + * @v9ses: session information 146 + * @fid: fid to issue attribute request for 147 + * @sb: superblock on which to create inode 148 + * 149 + */ 150 + static inline struct inode * 151 + v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, 152 + struct super_block *sb) 153 + { 154 + if (v9fs_proto_dotl(v9ses)) 155 + return v9fs_inode_dotl(v9ses, fid, sb); 156 + else 157 + return v9fs_inode(v9ses, fid, sb); 158 158 }
+6 -859
fs/9p/vfs_inode.c
··· 49 49 50 50 static const struct inode_operations v9fs_dir_inode_operations; 51 51 static const struct inode_operations v9fs_dir_inode_operations_dotu; 52 - static const struct inode_operations v9fs_dir_inode_operations_dotl; 53 52 static const struct inode_operations v9fs_file_inode_operations; 54 - static const struct inode_operations v9fs_file_inode_operations_dotl; 55 53 static const struct inode_operations v9fs_symlink_inode_operations; 56 - static const struct inode_operations v9fs_symlink_inode_operations_dotl; 57 - 58 - static int 59 - v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, 60 - dev_t rdev); 61 54 62 55 /** 63 56 * unixmode2p9mode - convert unix mode bits to plan 9 ··· 244 251 #endif 245 252 246 253 /** 247 - * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a 248 - * new file system object. This checks the S_ISGID to determine the owning 249 - * group of the new file system object. 250 - */ 251 - 252 - static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) 253 - { 254 - BUG_ON(dir_inode == NULL); 255 - 256 - if (dir_inode->i_mode & S_ISGID) { 257 - /* set_gid bit is set.*/ 258 - return dir_inode->i_gid; 259 - } 260 - return current_fsgid(); 261 - } 262 - 263 - /** 264 - * v9fs_dentry_from_dir_inode - helper function to get the dentry from 265 - * dir inode. 266 - * 267 - */ 268 - 269 - static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) 270 - { 271 - struct dentry *dentry; 272 - 273 - spin_lock(&inode->i_lock); 274 - /* Directory should have only one entry. */ 275 - BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); 276 - dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); 277 - spin_unlock(&inode->i_lock); 278 - return dentry; 279 - } 280 - 281 - /** 282 254 * v9fs_get_inode - helper function to setup an inode 283 255 * @sb: superblock 284 256 * @mode: mode to setup inode with ··· 412 454 #endif 413 455 } 414 456 415 - static struct inode * 457 + struct inode * 416 458 v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid, 417 459 struct super_block *sb) 418 460 { ··· 445 487 p9stat_free(st); 446 488 kfree(st); 447 489 return ERR_PTR(err); 448 - } 449 - 450 - static struct inode * 451 - v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, 452 - struct super_block *sb) 453 - { 454 - struct inode *ret = NULL; 455 - int err; 456 - struct p9_stat_dotl *st; 457 - 458 - st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 459 - if (IS_ERR(st)) 460 - return ERR_CAST(st); 461 - 462 - ret = v9fs_get_inode(sb, st->st_mode); 463 - if (IS_ERR(ret)) { 464 - err = PTR_ERR(ret); 465 - goto error; 466 - } 467 - 468 - v9fs_stat2inode_dotl(st, ret); 469 - ret->i_ino = v9fs_qid2ino(&st->qid); 470 - #ifdef CONFIG_9P_FSCACHE 471 - v9fs_vcookie_set_qid(ret, &st->qid); 472 - v9fs_cache_inode_get_cookie(ret); 473 - #endif 474 - err = v9fs_get_acl(ret, fid); 475 - if (err) { 476 - iput(ret); 477 - goto error; 478 - } 479 - kfree(st); 480 - return ret; 481 - error: 482 - kfree(st); 483 - return ERR_PTR(err); 484 - } 485 - 486 - /** 487 - * v9fs_inode_from_fid - Helper routine to populate an inode by 488 - * issuing a attribute request 489 - * @v9ses: session information 490 - * @fid: fid to issue attribute request for 491 - * @sb: superblock on which to create inode 492 - * 493 - */ 494 - static inline struct inode * 495 - v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, 496 - struct super_block *sb) 497 - { 498 - if (v9fs_proto_dotl(v9ses)) 499 - return v9fs_inode_dotl(v9ses, fid, sb); 500 - else 501 - return v9fs_inode(v9ses, fid, sb); 502 490 } 503 491 504 492 /** ··· 561 657 } 562 658 563 659 /** 564 - * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. 565 - * @dir: directory inode that is being created 566 - * @dentry: dentry that is being deleted 567 - * @mode: create permissions 568 - * @nd: path information 569 - * 570 - */ 571 - 572 - static int 573 - v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, 574 - struct nameidata *nd) 575 - { 576 - int err = 0; 577 - char *name = NULL; 578 - gid_t gid; 579 - int flags; 580 - mode_t mode; 581 - struct v9fs_session_info *v9ses; 582 - struct p9_fid *fid = NULL; 583 - struct p9_fid *dfid, *ofid; 584 - struct file *filp; 585 - struct p9_qid qid; 586 - struct inode *inode; 587 - struct posix_acl *pacl = NULL, *dacl = NULL; 588 - 589 - v9ses = v9fs_inode2v9ses(dir); 590 - if (nd && nd->flags & LOOKUP_OPEN) 591 - flags = nd->intent.open.flags - 1; 592 - else { 593 - /* 594 - * create call without LOOKUP_OPEN is due 595 - * to mknod of regular files. So use mknod 596 - * operation. 597 - */ 598 - return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); 599 - } 600 - 601 - name = (char *) dentry->d_name.name; 602 - P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " 603 - "mode:0x%x\n", name, flags, omode); 604 - 605 - dfid = v9fs_fid_lookup(dentry->d_parent); 606 - if (IS_ERR(dfid)) { 607 - err = PTR_ERR(dfid); 608 - P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 609 - return err; 610 - } 611 - 612 - /* clone a fid to use for creation */ 613 - ofid = p9_client_walk(dfid, 0, NULL, 1); 614 - if (IS_ERR(ofid)) { 615 - err = PTR_ERR(ofid); 616 - P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 617 - return err; 618 - } 619 - 620 - gid = v9fs_get_fsgid_for_create(dir); 621 - 622 - mode = omode; 623 - /* Update mode based on ACL value */ 624 - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 625 - if (err) { 626 - P9_DPRINTK(P9_DEBUG_VFS, 627 - "Failed to get acl values in creat %d\n", err); 628 - goto error; 629 - } 630 - err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); 631 - if (err < 0) { 632 - P9_DPRINTK(P9_DEBUG_VFS, 633 - "p9_client_open_dotl failed in creat %d\n", 634 - err); 635 - goto error; 636 - } 637 - /* instantiate inode and assign the unopened fid to the dentry */ 638 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE || 639 - (nd && nd->flags & LOOKUP_OPEN)) { 640 - fid = p9_client_walk(dfid, 1, &name, 1); 641 - if (IS_ERR(fid)) { 642 - err = PTR_ERR(fid); 643 - P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 644 - err); 645 - fid = NULL; 646 - goto error; 647 - } 648 - 649 - inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 650 - if (IS_ERR(inode)) { 651 - err = PTR_ERR(inode); 652 - P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 653 - err); 654 - goto error; 655 - } 656 - d_set_d_op(dentry, &v9fs_cached_dentry_operations); 657 - d_instantiate(dentry, inode); 658 - err = v9fs_fid_add(dentry, fid); 659 - if (err < 0) 660 - goto error; 661 - /* The fid would get clunked via a dput */ 662 - fid = NULL; 663 - } else { 664 - /* 665 - * Not in cached mode. No need to populate 666 - * inode with stat. We need to get an inode 667 - * so that we can set the acl with dentry 668 - */ 669 - inode = v9fs_get_inode(dir->i_sb, mode); 670 - if (IS_ERR(inode)) { 671 - err = PTR_ERR(inode); 672 - goto error; 673 - } 674 - d_set_d_op(dentry, &v9fs_dentry_operations); 675 - d_instantiate(dentry, inode); 676 - } 677 - /* Now set the ACL based on the default value */ 678 - v9fs_set_create_acl(dentry, dacl, pacl); 679 - 680 - /* if we are opening a file, assign the open fid to the file */ 681 - if (nd && nd->flags & LOOKUP_OPEN) { 682 - filp = lookup_instantiate_filp(nd, dentry, generic_file_open); 683 - if (IS_ERR(filp)) { 684 - p9_client_clunk(ofid); 685 - return PTR_ERR(filp); 686 - } 687 - filp->private_data = ofid; 688 - } else 689 - p9_client_clunk(ofid); 690 - 691 - return 0; 692 - 693 - error: 694 - if (ofid) 695 - p9_client_clunk(ofid); 696 - if (fid) 697 - p9_client_clunk(fid); 698 - return err; 699 - } 700 - 701 - /** 702 660 * v9fs_vfs_create - VFS hook to create files 703 661 * @dir: directory inode that is being created 704 662 * @dentry: dentry that is being deleted ··· 650 884 return err; 651 885 } 652 886 653 - 654 - /** 655 - * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory 656 - * @dir: inode that is being unlinked 657 - * @dentry: dentry that is being unlinked 658 - * @mode: mode for new directory 659 - * 660 - */ 661 - 662 - static int v9fs_vfs_mkdir_dotl(struct inode *dir, 663 - struct dentry *dentry, int omode) 664 - { 665 - int err; 666 - struct v9fs_session_info *v9ses; 667 - struct p9_fid *fid = NULL, *dfid = NULL; 668 - gid_t gid; 669 - char *name; 670 - mode_t mode; 671 - struct inode *inode; 672 - struct p9_qid qid; 673 - struct dentry *dir_dentry; 674 - struct posix_acl *dacl = NULL, *pacl = NULL; 675 - 676 - P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 677 - err = 0; 678 - v9ses = v9fs_inode2v9ses(dir); 679 - 680 - omode |= S_IFDIR; 681 - if (dir->i_mode & S_ISGID) 682 - omode |= S_ISGID; 683 - 684 - dir_dentry = v9fs_dentry_from_dir_inode(dir); 685 - dfid = v9fs_fid_lookup(dir_dentry); 686 - if (IS_ERR(dfid)) { 687 - err = PTR_ERR(dfid); 688 - P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 689 - dfid = NULL; 690 - goto error; 691 - } 692 - 693 - gid = v9fs_get_fsgid_for_create(dir); 694 - mode = omode; 695 - /* Update mode based on ACL value */ 696 - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 697 - if (err) { 698 - P9_DPRINTK(P9_DEBUG_VFS, 699 - "Failed to get acl values in mkdir %d\n", err); 700 - goto error; 701 - } 702 - name = (char *) dentry->d_name.name; 703 - err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); 704 - if (err < 0) 705 - goto error; 706 - 707 - /* instantiate inode and assign the unopened fid to the dentry */ 708 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 709 - fid = p9_client_walk(dfid, 1, &name, 1); 710 - if (IS_ERR(fid)) { 711 - err = PTR_ERR(fid); 712 - P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 713 - err); 714 - fid = NULL; 715 - goto error; 716 - } 717 - 718 - inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 719 - if (IS_ERR(inode)) { 720 - err = PTR_ERR(inode); 721 - P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 722 - err); 723 - goto error; 724 - } 725 - d_set_d_op(dentry, &v9fs_cached_dentry_operations); 726 - d_instantiate(dentry, inode); 727 - err = v9fs_fid_add(dentry, fid); 728 - if (err < 0) 729 - goto error; 730 - fid = NULL; 731 - } else { 732 - /* 733 - * Not in cached mode. No need to populate 734 - * inode with stat. We need to get an inode 735 - * so that we can set the acl with dentry 736 - */ 737 - inode = v9fs_get_inode(dir->i_sb, mode); 738 - if (IS_ERR(inode)) { 739 - err = PTR_ERR(inode); 740 - goto error; 741 - } 742 - d_set_d_op(dentry, &v9fs_dentry_operations); 743 - d_instantiate(dentry, inode); 744 - } 745 - /* Now set the ACL based on the default value */ 746 - v9fs_set_create_acl(dentry, dacl, pacl); 747 - 748 - error: 749 - if (fid) 750 - p9_client_clunk(fid); 751 - return err; 752 - } 753 - 754 887 /** 755 888 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode 756 889 * @dir: inode that is being walked from ··· 658 993 * 659 994 */ 660 995 661 - static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, 996 + struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, 662 997 struct nameidata *nameidata) 663 998 { 664 999 struct super_block *sb; ··· 728 1063 * 729 1064 */ 730 1065 731 - static int v9fs_vfs_unlink(struct inode *i, struct dentry *d) 1066 + int v9fs_vfs_unlink(struct inode *i, struct dentry *d) 732 1067 { 733 1068 return v9fs_remove(i, d, 0); 734 1069 } ··· 740 1075 * 741 1076 */ 742 1077 743 - static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) 1078 + int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) 744 1079 { 745 1080 return v9fs_remove(i, d, 1); 746 1081 } ··· 754 1089 * 755 1090 */ 756 1091 757 - static int 1092 + int 758 1093 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 759 1094 struct inode *new_dir, struct dentry *new_dentry) 760 1095 { ··· 861 1196 return 0; 862 1197 } 863 1198 864 - static int 865 - v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, 866 - struct kstat *stat) 867 - { 868 - int err; 869 - struct v9fs_session_info *v9ses; 870 - struct p9_fid *fid; 871 - struct p9_stat_dotl *st; 872 - 873 - P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 874 - err = -EPERM; 875 - v9ses = v9fs_inode2v9ses(dentry->d_inode); 876 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 877 - return simple_getattr(mnt, dentry, stat); 878 - 879 - fid = v9fs_fid_lookup(dentry); 880 - if (IS_ERR(fid)) 881 - return PTR_ERR(fid); 882 - 883 - /* Ask for all the fields in stat structure. Server will return 884 - * whatever it supports 885 - */ 886 - 887 - st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 888 - if (IS_ERR(st)) 889 - return PTR_ERR(st); 890 - 891 - v9fs_stat2inode_dotl(st, dentry->d_inode); 892 - generic_fillattr(dentry->d_inode, stat); 893 - /* Change block size to what the server returned */ 894 - stat->blksize = st->st_blksize; 895 - 896 - kfree(st); 897 - return 0; 898 - } 899 - 900 1199 /** 901 1200 * v9fs_vfs_setattr - set file metadata 902 1201 * @dentry: file whose metadata to set ··· 916 1287 917 1288 setattr_copy(dentry->d_inode, iattr); 918 1289 mark_inode_dirty(dentry->d_inode); 919 - return 0; 920 - } 921 - 922 - /** 923 - * v9fs_vfs_setattr_dotl - set file metadata 924 - * @dentry: file whose metadata to set 925 - * @iattr: metadata assignment structure 926 - * 927 - */ 928 - 929 - int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) 930 - { 931 - int retval; 932 - struct v9fs_session_info *v9ses; 933 - struct p9_fid *fid; 934 - struct p9_iattr_dotl p9attr; 935 - 936 - P9_DPRINTK(P9_DEBUG_VFS, "\n"); 937 - 938 - retval = inode_change_ok(dentry->d_inode, iattr); 939 - if (retval) 940 - return retval; 941 - 942 - p9attr.valid = iattr->ia_valid; 943 - p9attr.mode = iattr->ia_mode; 944 - p9attr.uid = iattr->ia_uid; 945 - p9attr.gid = iattr->ia_gid; 946 - p9attr.size = iattr->ia_size; 947 - p9attr.atime_sec = iattr->ia_atime.tv_sec; 948 - p9attr.atime_nsec = iattr->ia_atime.tv_nsec; 949 - p9attr.mtime_sec = iattr->ia_mtime.tv_sec; 950 - p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; 951 - 952 - retval = -EPERM; 953 - v9ses = v9fs_inode2v9ses(dentry->d_inode); 954 - fid = v9fs_fid_lookup(dentry); 955 - if (IS_ERR(fid)) 956 - return PTR_ERR(fid); 957 - 958 - retval = p9_client_setattr(fid, &p9attr); 959 - if (retval < 0) 960 - return retval; 961 - 962 - if ((iattr->ia_valid & ATTR_SIZE) && 963 - iattr->ia_size != i_size_read(dentry->d_inode)) { 964 - retval = vmtruncate(dentry->d_inode, iattr->ia_size); 965 - if (retval) 966 - return retval; 967 - } 968 - 969 - setattr_copy(dentry->d_inode, iattr); 970 - mark_inode_dirty(dentry->d_inode); 971 - if (iattr->ia_valid & ATTR_MODE) { 972 - /* We also want to update ACL when we update mode bits */ 973 - retval = v9fs_acl_chmod(dentry); 974 - if (retval < 0) 975 - return retval; 976 - } 977 1290 return 0; 978 1291 } 979 1292 ··· 994 1423 995 1424 /* not real number of blocks, but 512 byte ones ... */ 996 1425 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; 997 - } 998 - 999 - /** 1000 - * v9fs_stat2inode_dotl - populate an inode structure with stat info 1001 - * @stat: stat structure 1002 - * @inode: inode to populate 1003 - * @sb: superblock of filesystem 1004 - * 1005 - */ 1006 - 1007 - void 1008 - v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) 1009 - { 1010 - 1011 - if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { 1012 - inode->i_atime.tv_sec = stat->st_atime_sec; 1013 - inode->i_atime.tv_nsec = stat->st_atime_nsec; 1014 - inode->i_mtime.tv_sec = stat->st_mtime_sec; 1015 - inode->i_mtime.tv_nsec = stat->st_mtime_nsec; 1016 - inode->i_ctime.tv_sec = stat->st_ctime_sec; 1017 - inode->i_ctime.tv_nsec = stat->st_ctime_nsec; 1018 - inode->i_uid = stat->st_uid; 1019 - inode->i_gid = stat->st_gid; 1020 - inode->i_nlink = stat->st_nlink; 1021 - inode->i_mode = stat->st_mode; 1022 - inode->i_rdev = new_decode_dev(stat->st_rdev); 1023 - 1024 - if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) 1025 - init_special_inode(inode, inode->i_mode, inode->i_rdev); 1026 - 1027 - i_size_write(inode, stat->st_size); 1028 - inode->i_blocks = stat->st_blocks; 1029 - } else { 1030 - if (stat->st_result_mask & P9_STATS_ATIME) { 1031 - inode->i_atime.tv_sec = stat->st_atime_sec; 1032 - inode->i_atime.tv_nsec = stat->st_atime_nsec; 1033 - } 1034 - if (stat->st_result_mask & P9_STATS_MTIME) { 1035 - inode->i_mtime.tv_sec = stat->st_mtime_sec; 1036 - inode->i_mtime.tv_nsec = stat->st_mtime_nsec; 1037 - } 1038 - if (stat->st_result_mask & P9_STATS_CTIME) { 1039 - inode->i_ctime.tv_sec = stat->st_ctime_sec; 1040 - inode->i_ctime.tv_nsec = stat->st_ctime_nsec; 1041 - } 1042 - if (stat->st_result_mask & P9_STATS_UID) 1043 - inode->i_uid = stat->st_uid; 1044 - if (stat->st_result_mask & P9_STATS_GID) 1045 - inode->i_gid = stat->st_gid; 1046 - if (stat->st_result_mask & P9_STATS_NLINK) 1047 - inode->i_nlink = stat->st_nlink; 1048 - if (stat->st_result_mask & P9_STATS_MODE) { 1049 - inode->i_mode = stat->st_mode; 1050 - if ((S_ISBLK(inode->i_mode)) || 1051 - (S_ISCHR(inode->i_mode))) 1052 - init_special_inode(inode, inode->i_mode, 1053 - inode->i_rdev); 1054 - } 1055 - if (stat->st_result_mask & P9_STATS_RDEV) 1056 - inode->i_rdev = new_decode_dev(stat->st_rdev); 1057 - if (stat->st_result_mask & P9_STATS_SIZE) 1058 - i_size_write(inode, stat->st_size); 1059 - if (stat->st_result_mask & P9_STATS_BLOCKS) 1060 - inode->i_blocks = stat->st_blocks; 1061 - } 1062 - if (stat->st_result_mask & P9_STATS_GEN) 1063 - inode->i_generation = stat->st_gen; 1064 - 1065 - /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION 1066 - * because the inode structure does not have fields for them. 1067 - */ 1068 1426 } 1069 1427 1070 1428 /** ··· 1102 1602 * 1103 1603 */ 1104 1604 1105 - static void 1605 + void 1106 1606 v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) 1107 1607 { 1108 1608 char *s = nd_get_link(nd); ··· 1143 1643 1144 1644 p9_client_clunk(fid); 1145 1645 return 0; 1146 - } 1147 - 1148 - /** 1149 - * v9fs_vfs_symlink_dotl - helper function to create symlinks 1150 - * @dir: directory inode containing symlink 1151 - * @dentry: dentry for symlink 1152 - * @symname: symlink data 1153 - * 1154 - * See Also: 9P2000.L RFC for more information 1155 - * 1156 - */ 1157 - 1158 - static int 1159 - v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, 1160 - const char *symname) 1161 - { 1162 - struct v9fs_session_info *v9ses; 1163 - struct p9_fid *dfid; 1164 - struct p9_fid *fid = NULL; 1165 - struct inode *inode; 1166 - struct p9_qid qid; 1167 - char *name; 1168 - int err; 1169 - gid_t gid; 1170 - 1171 - name = (char *) dentry->d_name.name; 1172 - P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n", 1173 - dir->i_ino, name, symname); 1174 - v9ses = v9fs_inode2v9ses(dir); 1175 - 1176 - dfid = v9fs_fid_lookup(dentry->d_parent); 1177 - if (IS_ERR(dfid)) { 1178 - err = PTR_ERR(dfid); 1179 - P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 1180 - return err; 1181 - } 1182 - 1183 - gid = v9fs_get_fsgid_for_create(dir); 1184 - 1185 - /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ 1186 - err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); 1187 - 1188 - if (err < 0) { 1189 - P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err); 1190 - goto error; 1191 - } 1192 - 1193 - if (v9ses->cache) { 1194 - /* Now walk from the parent so we can get an unopened fid. */ 1195 - fid = p9_client_walk(dfid, 1, &name, 1); 1196 - if (IS_ERR(fid)) { 1197 - err = PTR_ERR(fid); 1198 - P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 1199 - err); 1200 - fid = NULL; 1201 - goto error; 1202 - } 1203 - 1204 - /* instantiate inode and assign the unopened fid to dentry */ 1205 - inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 1206 - if (IS_ERR(inode)) { 1207 - err = PTR_ERR(inode); 1208 - P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 1209 - err); 1210 - goto error; 1211 - } 1212 - d_set_d_op(dentry, &v9fs_cached_dentry_operations); 1213 - d_instantiate(dentry, inode); 1214 - err = v9fs_fid_add(dentry, fid); 1215 - if (err < 0) 1216 - goto error; 1217 - fid = NULL; 1218 - } else { 1219 - /* Not in cached mode. No need to populate inode with stat */ 1220 - inode = v9fs_get_inode(dir->i_sb, S_IFLNK); 1221 - if (IS_ERR(inode)) { 1222 - err = PTR_ERR(inode); 1223 - goto error; 1224 - } 1225 - d_set_d_op(dentry, &v9fs_dentry_operations); 1226 - d_instantiate(dentry, inode); 1227 - } 1228 - 1229 - error: 1230 - if (fid) 1231 - p9_client_clunk(fid); 1232 - 1233 - return err; 1234 1646 } 1235 1647 1236 1648 /** ··· 1204 1792 } 1205 1793 1206 1794 /** 1207 - * v9fs_vfs_link_dotl - create a hardlink for dotl 1208 - * @old_dentry: dentry for file to link to 1209 - * @dir: inode destination for new link 1210 - * @dentry: dentry for link 1211 - * 1212 - */ 1213 - 1214 - static int 1215 - v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, 1216 - struct dentry *dentry) 1217 - { 1218 - int err; 1219 - struct p9_fid *dfid, *oldfid; 1220 - char *name; 1221 - struct v9fs_session_info *v9ses; 1222 - struct dentry *dir_dentry; 1223 - 1224 - P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n", 1225 - dir->i_ino, old_dentry->d_name.name, 1226 - dentry->d_name.name); 1227 - 1228 - v9ses = v9fs_inode2v9ses(dir); 1229 - dir_dentry = v9fs_dentry_from_dir_inode(dir); 1230 - dfid = v9fs_fid_lookup(dir_dentry); 1231 - if (IS_ERR(dfid)) 1232 - return PTR_ERR(dfid); 1233 - 1234 - oldfid = v9fs_fid_lookup(old_dentry); 1235 - if (IS_ERR(oldfid)) 1236 - return PTR_ERR(oldfid); 1237 - 1238 - name = (char *) dentry->d_name.name; 1239 - 1240 - err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); 1241 - 1242 - if (err < 0) { 1243 - P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); 1244 - return err; 1245 - } 1246 - 1247 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 1248 - /* Get the latest stat info from server. */ 1249 - struct p9_fid *fid; 1250 - struct p9_stat_dotl *st; 1251 - 1252 - fid = v9fs_fid_lookup(old_dentry); 1253 - if (IS_ERR(fid)) 1254 - return PTR_ERR(fid); 1255 - 1256 - st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 1257 - if (IS_ERR(st)) 1258 - return PTR_ERR(st); 1259 - 1260 - v9fs_stat2inode_dotl(st, old_dentry->d_inode); 1261 - 1262 - kfree(st); 1263 - } else { 1264 - /* Caching disabled. No need to get upto date stat info. 1265 - * This dentry will be released immediately. So, just hold the 1266 - * inode 1267 - */ 1268 - ihold(old_dentry->d_inode); 1269 - } 1270 - 1271 - d_set_d_op(dentry, old_dentry->d_op); 1272 - d_instantiate(dentry, old_dentry->d_inode); 1273 - 1274 - return err; 1275 - } 1276 - 1277 - /** 1278 1795 * v9fs_vfs_mknod - create a special file 1279 1796 * @dir: inode destination for new link 1280 1797 * @dentry: dentry for file ··· 1248 1907 return retval; 1249 1908 } 1250 1909 1251 - /** 1252 - * v9fs_vfs_mknod_dotl - create a special file 1253 - * @dir: inode destination for new link 1254 - * @dentry: dentry for file 1255 - * @mode: mode for creation 1256 - * @rdev: device associated with special file 1257 - * 1258 - */ 1259 - static int 1260 - v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, 1261 - dev_t rdev) 1262 - { 1263 - int err; 1264 - char *name; 1265 - mode_t mode; 1266 - struct v9fs_session_info *v9ses; 1267 - struct p9_fid *fid = NULL, *dfid = NULL; 1268 - struct inode *inode; 1269 - gid_t gid; 1270 - struct p9_qid qid; 1271 - struct dentry *dir_dentry; 1272 - struct posix_acl *dacl = NULL, *pacl = NULL; 1273 - 1274 - P9_DPRINTK(P9_DEBUG_VFS, 1275 - " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1276 - dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev)); 1277 - 1278 - if (!new_valid_dev(rdev)) 1279 - return -EINVAL; 1280 - 1281 - v9ses = v9fs_inode2v9ses(dir); 1282 - dir_dentry = v9fs_dentry_from_dir_inode(dir); 1283 - dfid = v9fs_fid_lookup(dir_dentry); 1284 - if (IS_ERR(dfid)) { 1285 - err = PTR_ERR(dfid); 1286 - P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 1287 - dfid = NULL; 1288 - goto error; 1289 - } 1290 - 1291 - gid = v9fs_get_fsgid_for_create(dir); 1292 - mode = omode; 1293 - /* Update mode based on ACL value */ 1294 - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 1295 - if (err) { 1296 - P9_DPRINTK(P9_DEBUG_VFS, 1297 - "Failed to get acl values in mknod %d\n", err); 1298 - goto error; 1299 - } 1300 - name = (char *) dentry->d_name.name; 1301 - 1302 - err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); 1303 - if (err < 0) 1304 - goto error; 1305 - 1306 - /* instantiate inode and assign the unopened fid to the dentry */ 1307 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 1308 - fid = p9_client_walk(dfid, 1, &name, 1); 1309 - if (IS_ERR(fid)) { 1310 - err = PTR_ERR(fid); 1311 - P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 1312 - err); 1313 - fid = NULL; 1314 - goto error; 1315 - } 1316 - 1317 - inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 1318 - if (IS_ERR(inode)) { 1319 - err = PTR_ERR(inode); 1320 - P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 1321 - err); 1322 - goto error; 1323 - } 1324 - d_set_d_op(dentry, &v9fs_cached_dentry_operations); 1325 - d_instantiate(dentry, inode); 1326 - err = v9fs_fid_add(dentry, fid); 1327 - if (err < 0) 1328 - goto error; 1329 - fid = NULL; 1330 - } else { 1331 - /* 1332 - * Not in cached mode. No need to populate inode with stat. 1333 - * socket syscall returns a fd, so we need instantiate 1334 - */ 1335 - inode = v9fs_get_inode(dir->i_sb, mode); 1336 - if (IS_ERR(inode)) { 1337 - err = PTR_ERR(inode); 1338 - goto error; 1339 - } 1340 - d_set_d_op(dentry, &v9fs_dentry_operations); 1341 - d_instantiate(dentry, inode); 1342 - } 1343 - /* Now set the ACL based on the default value */ 1344 - v9fs_set_create_acl(dentry, dacl, pacl); 1345 - error: 1346 - if (fid) 1347 - p9_client_clunk(fid); 1348 - return err; 1349 - } 1350 - 1351 - static int 1352 - v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen) 1353 - { 1354 - int retval; 1355 - struct p9_fid *fid; 1356 - char *target = NULL; 1357 - 1358 - P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); 1359 - retval = -EPERM; 1360 - fid = v9fs_fid_lookup(dentry); 1361 - if (IS_ERR(fid)) 1362 - return PTR_ERR(fid); 1363 - 1364 - retval = p9_client_readlink(fid, &target); 1365 - if (retval < 0) 1366 - return retval; 1367 - 1368 - strncpy(buffer, target, buflen); 1369 - P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer); 1370 - 1371 - retval = strnlen(buffer, buflen); 1372 - return retval; 1373 - } 1374 - 1375 - /** 1376 - * v9fs_vfs_follow_link_dotl - follow a symlink path 1377 - * @dentry: dentry for symlink 1378 - * @nd: nameidata 1379 - * 1380 - */ 1381 - 1382 - static void * 1383 - v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) 1384 - { 1385 - int len = 0; 1386 - char *link = __getname(); 1387 - 1388 - P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); 1389 - 1390 - if (!link) 1391 - link = ERR_PTR(-ENOMEM); 1392 - else { 1393 - len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX); 1394 - if (len < 0) { 1395 - __putname(link); 1396 - link = ERR_PTR(len); 1397 - } else 1398 - link[min(len, PATH_MAX-1)] = 0; 1399 - } 1400 - nd_set_link(nd, link); 1401 - 1402 - return NULL; 1403 - } 1404 - 1405 1910 static const struct inode_operations v9fs_dir_inode_operations_dotu = { 1406 1911 .create = v9fs_vfs_create, 1407 1912 .lookup = v9fs_vfs_lookup, ··· 1260 2073 .rename = v9fs_vfs_rename, 1261 2074 .getattr = v9fs_vfs_getattr, 1262 2075 .setattr = v9fs_vfs_setattr, 1263 - }; 1264 - 1265 - static const struct inode_operations v9fs_dir_inode_operations_dotl = { 1266 - .create = v9fs_vfs_create_dotl, 1267 - .lookup = v9fs_vfs_lookup, 1268 - .link = v9fs_vfs_link_dotl, 1269 - .symlink = v9fs_vfs_symlink_dotl, 1270 - .unlink = v9fs_vfs_unlink, 1271 - .mkdir = v9fs_vfs_mkdir_dotl, 1272 - .rmdir = v9fs_vfs_rmdir, 1273 - .mknod = v9fs_vfs_mknod_dotl, 1274 - .rename = v9fs_vfs_rename, 1275 - .getattr = v9fs_vfs_getattr_dotl, 1276 - .setattr = v9fs_vfs_setattr_dotl, 1277 - .setxattr = generic_setxattr, 1278 - .getxattr = generic_getxattr, 1279 - .removexattr = generic_removexattr, 1280 - .listxattr = v9fs_listxattr, 1281 - .check_acl = v9fs_check_acl, 1282 2076 }; 1283 2077 1284 2078 static const struct inode_operations v9fs_dir_inode_operations = { ··· 1279 2111 .setattr = v9fs_vfs_setattr, 1280 2112 }; 1281 2113 1282 - static const struct inode_operations v9fs_file_inode_operations_dotl = { 1283 - .getattr = v9fs_vfs_getattr_dotl, 1284 - .setattr = v9fs_vfs_setattr_dotl, 1285 - .setxattr = generic_setxattr, 1286 - .getxattr = generic_getxattr, 1287 - .removexattr = generic_removexattr, 1288 - .listxattr = v9fs_listxattr, 1289 - .check_acl = v9fs_check_acl, 1290 - }; 1291 - 1292 2114 static const struct inode_operations v9fs_symlink_inode_operations = { 1293 2115 .readlink = generic_readlink, 1294 2116 .follow_link = v9fs_vfs_follow_link, ··· 1287 2129 .setattr = v9fs_vfs_setattr, 1288 2130 }; 1289 2131 1290 - static const struct inode_operations v9fs_symlink_inode_operations_dotl = { 1291 - .readlink = v9fs_vfs_readlink_dotl, 1292 - .follow_link = v9fs_vfs_follow_link_dotl, 1293 - .put_link = v9fs_vfs_put_link, 1294 - .getattr = v9fs_vfs_getattr_dotl, 1295 - .setattr = v9fs_vfs_setattr_dotl, 1296 - .setxattr = generic_setxattr, 1297 - .getxattr = generic_getxattr, 1298 - .removexattr = generic_removexattr, 1299 - .listxattr = v9fs_listxattr, 1300 - };
+870
fs/9p/vfs_inode_dotl.c
··· 1 + /* 2 + * linux/fs/9p/vfs_inode_dotl.c 3 + * 4 + * This file contains vfs inode ops for the 9P2000.L protocol. 5 + * 6 + * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 7 + * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 11 + * as published by the Free Software Foundation. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to: 20 + * Free Software Foundation 21 + * 51 Franklin Street, Fifth Floor 22 + * Boston, MA 02111-1301 USA 23 + * 24 + */ 25 + 26 + #include <linux/module.h> 27 + #include <linux/errno.h> 28 + #include <linux/fs.h> 29 + #include <linux/file.h> 30 + #include <linux/pagemap.h> 31 + #include <linux/stat.h> 32 + #include <linux/string.h> 33 + #include <linux/inet.h> 34 + #include <linux/namei.h> 35 + #include <linux/idr.h> 36 + #include <linux/sched.h> 37 + #include <linux/slab.h> 38 + #include <linux/xattr.h> 39 + #include <linux/posix_acl.h> 40 + #include <net/9p/9p.h> 41 + #include <net/9p/client.h> 42 + 43 + #include "v9fs.h" 44 + #include "v9fs_vfs.h" 45 + #include "fid.h" 46 + #include "cache.h" 47 + #include "xattr.h" 48 + #include "acl.h" 49 + 50 + static int 51 + v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, 52 + dev_t rdev); 53 + 54 + /** 55 + * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a 56 + * new file system object. This checks the S_ISGID to determine the owning 57 + * group of the new file system object. 58 + */ 59 + 60 + static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) 61 + { 62 + BUG_ON(dir_inode == NULL); 63 + 64 + if (dir_inode->i_mode & S_ISGID) { 65 + /* set_gid bit is set.*/ 66 + return dir_inode->i_gid; 67 + } 68 + return current_fsgid(); 69 + } 70 + 71 + /** 72 + * v9fs_dentry_from_dir_inode - helper function to get the dentry from 73 + * dir inode. 74 + * 75 + */ 76 + 77 + static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) 78 + { 79 + struct dentry *dentry; 80 + 81 + spin_lock(&inode->i_lock); 82 + /* Directory should have only one entry. */ 83 + BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); 84 + dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); 85 + spin_unlock(&inode->i_lock); 86 + return dentry; 87 + } 88 + 89 + struct inode * 90 + v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, 91 + struct super_block *sb) 92 + { 93 + struct inode *ret = NULL; 94 + int err; 95 + struct p9_stat_dotl *st; 96 + 97 + st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 98 + if (IS_ERR(st)) 99 + return ERR_CAST(st); 100 + 101 + ret = v9fs_get_inode(sb, st->st_mode); 102 + if (IS_ERR(ret)) { 103 + err = PTR_ERR(ret); 104 + goto error; 105 + } 106 + 107 + v9fs_stat2inode_dotl(st, ret); 108 + ret->i_ino = v9fs_qid2ino(&st->qid); 109 + #ifdef CONFIG_9P_FSCACHE 110 + v9fs_vcookie_set_qid(ret, &st->qid); 111 + v9fs_cache_inode_get_cookie(ret); 112 + #endif 113 + err = v9fs_get_acl(ret, fid); 114 + if (err) { 115 + iput(ret); 116 + goto error; 117 + } 118 + kfree(st); 119 + return ret; 120 + error: 121 + kfree(st); 122 + return ERR_PTR(err); 123 + } 124 + 125 + /** 126 + * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. 127 + * @dir: directory inode that is being created 128 + * @dentry: dentry that is being deleted 129 + * @mode: create permissions 130 + * @nd: path information 131 + * 132 + */ 133 + 134 + static int 135 + v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, 136 + struct nameidata *nd) 137 + { 138 + int err = 0; 139 + char *name = NULL; 140 + gid_t gid; 141 + int flags; 142 + mode_t mode; 143 + struct v9fs_session_info *v9ses; 144 + struct p9_fid *fid = NULL; 145 + struct p9_fid *dfid, *ofid; 146 + struct file *filp; 147 + struct p9_qid qid; 148 + struct inode *inode; 149 + struct posix_acl *pacl = NULL, *dacl = NULL; 150 + 151 + v9ses = v9fs_inode2v9ses(dir); 152 + if (nd && nd->flags & LOOKUP_OPEN) 153 + flags = nd->intent.open.flags - 1; 154 + else { 155 + /* 156 + * create call without LOOKUP_OPEN is due 157 + * to mknod of regular files. So use mknod 158 + * operation. 159 + */ 160 + return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); 161 + } 162 + 163 + name = (char *) dentry->d_name.name; 164 + P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " 165 + "mode:0x%x\n", name, flags, omode); 166 + 167 + dfid = v9fs_fid_lookup(dentry->d_parent); 168 + if (IS_ERR(dfid)) { 169 + err = PTR_ERR(dfid); 170 + P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 171 + return err; 172 + } 173 + 174 + /* clone a fid to use for creation */ 175 + ofid = p9_client_walk(dfid, 0, NULL, 1); 176 + if (IS_ERR(ofid)) { 177 + err = PTR_ERR(ofid); 178 + P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 179 + return err; 180 + } 181 + 182 + gid = v9fs_get_fsgid_for_create(dir); 183 + 184 + mode = omode; 185 + /* Update mode based on ACL value */ 186 + err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 187 + if (err) { 188 + P9_DPRINTK(P9_DEBUG_VFS, 189 + "Failed to get acl values in creat %d\n", err); 190 + goto error; 191 + } 192 + err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); 193 + if (err < 0) { 194 + P9_DPRINTK(P9_DEBUG_VFS, 195 + "p9_client_open_dotl failed in creat %d\n", 196 + err); 197 + goto error; 198 + } 199 + /* instantiate inode and assign the unopened fid to the dentry */ 200 + if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE || 201 + (nd && nd->flags & LOOKUP_OPEN)) { 202 + fid = p9_client_walk(dfid, 1, &name, 1); 203 + if (IS_ERR(fid)) { 204 + err = PTR_ERR(fid); 205 + P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 206 + err); 207 + fid = NULL; 208 + goto error; 209 + } 210 + 211 + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 212 + if (IS_ERR(inode)) { 213 + err = PTR_ERR(inode); 214 + P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 215 + err); 216 + goto error; 217 + } 218 + d_set_d_op(dentry, &v9fs_cached_dentry_operations); 219 + d_instantiate(dentry, inode); 220 + err = v9fs_fid_add(dentry, fid); 221 + if (err < 0) 222 + goto error; 223 + /* The fid would get clunked via a dput */ 224 + fid = NULL; 225 + } else { 226 + /* 227 + * Not in cached mode. No need to populate 228 + * inode with stat. We need to get an inode 229 + * so that we can set the acl with dentry 230 + */ 231 + inode = v9fs_get_inode(dir->i_sb, mode); 232 + if (IS_ERR(inode)) { 233 + err = PTR_ERR(inode); 234 + goto error; 235 + } 236 + d_set_d_op(dentry, &v9fs_dentry_operations); 237 + d_instantiate(dentry, inode); 238 + } 239 + /* Now set the ACL based on the default value */ 240 + v9fs_set_create_acl(dentry, dacl, pacl); 241 + 242 + /* if we are opening a file, assign the open fid to the file */ 243 + if (nd && nd->flags & LOOKUP_OPEN) { 244 + filp = lookup_instantiate_filp(nd, dentry, generic_file_open); 245 + if (IS_ERR(filp)) { 246 + p9_client_clunk(ofid); 247 + return PTR_ERR(filp); 248 + } 249 + filp->private_data = ofid; 250 + } else 251 + p9_client_clunk(ofid); 252 + 253 + return 0; 254 + 255 + error: 256 + if (ofid) 257 + p9_client_clunk(ofid); 258 + if (fid) 259 + p9_client_clunk(fid); 260 + return err; 261 + } 262 + 263 + /** 264 + * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory 265 + * @dir: inode that is being unlinked 266 + * @dentry: dentry that is being unlinked 267 + * @mode: mode for new directory 268 + * 269 + */ 270 + 271 + static int v9fs_vfs_mkdir_dotl(struct inode *dir, 272 + struct dentry *dentry, int omode) 273 + { 274 + int err; 275 + struct v9fs_session_info *v9ses; 276 + struct p9_fid *fid = NULL, *dfid = NULL; 277 + gid_t gid; 278 + char *name; 279 + mode_t mode; 280 + struct inode *inode; 281 + struct p9_qid qid; 282 + struct dentry *dir_dentry; 283 + struct posix_acl *dacl = NULL, *pacl = NULL; 284 + 285 + P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 286 + err = 0; 287 + v9ses = v9fs_inode2v9ses(dir); 288 + 289 + omode |= S_IFDIR; 290 + if (dir->i_mode & S_ISGID) 291 + omode |= S_ISGID; 292 + 293 + dir_dentry = v9fs_dentry_from_dir_inode(dir); 294 + dfid = v9fs_fid_lookup(dir_dentry); 295 + if (IS_ERR(dfid)) { 296 + err = PTR_ERR(dfid); 297 + P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 298 + dfid = NULL; 299 + goto error; 300 + } 301 + 302 + gid = v9fs_get_fsgid_for_create(dir); 303 + mode = omode; 304 + /* Update mode based on ACL value */ 305 + err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 306 + if (err) { 307 + P9_DPRINTK(P9_DEBUG_VFS, 308 + "Failed to get acl values in mkdir %d\n", err); 309 + goto error; 310 + } 311 + name = (char *) dentry->d_name.name; 312 + err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); 313 + if (err < 0) 314 + goto error; 315 + 316 + /* instantiate inode and assign the unopened fid to the dentry */ 317 + if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 318 + fid = p9_client_walk(dfid, 1, &name, 1); 319 + if (IS_ERR(fid)) { 320 + err = PTR_ERR(fid); 321 + P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 322 + err); 323 + fid = NULL; 324 + goto error; 325 + } 326 + 327 + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 328 + if (IS_ERR(inode)) { 329 + err = PTR_ERR(inode); 330 + P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 331 + err); 332 + goto error; 333 + } 334 + d_set_d_op(dentry, &v9fs_cached_dentry_operations); 335 + d_instantiate(dentry, inode); 336 + err = v9fs_fid_add(dentry, fid); 337 + if (err < 0) 338 + goto error; 339 + fid = NULL; 340 + } else { 341 + /* 342 + * Not in cached mode. No need to populate 343 + * inode with stat. We need to get an inode 344 + * so that we can set the acl with dentry 345 + */ 346 + inode = v9fs_get_inode(dir->i_sb, mode); 347 + if (IS_ERR(inode)) { 348 + err = PTR_ERR(inode); 349 + goto error; 350 + } 351 + d_set_d_op(dentry, &v9fs_dentry_operations); 352 + d_instantiate(dentry, inode); 353 + } 354 + /* Now set the ACL based on the default value */ 355 + v9fs_set_create_acl(dentry, dacl, pacl); 356 + 357 + error: 358 + if (fid) 359 + p9_client_clunk(fid); 360 + return err; 361 + } 362 + 363 + static int 364 + v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, 365 + struct kstat *stat) 366 + { 367 + int err; 368 + struct v9fs_session_info *v9ses; 369 + struct p9_fid *fid; 370 + struct p9_stat_dotl *st; 371 + 372 + P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 373 + err = -EPERM; 374 + v9ses = v9fs_inode2v9ses(dentry->d_inode); 375 + if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 376 + return simple_getattr(mnt, dentry, stat); 377 + 378 + fid = v9fs_fid_lookup(dentry); 379 + if (IS_ERR(fid)) 380 + return PTR_ERR(fid); 381 + 382 + /* Ask for all the fields in stat structure. Server will return 383 + * whatever it supports 384 + */ 385 + 386 + st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 387 + if (IS_ERR(st)) 388 + return PTR_ERR(st); 389 + 390 + v9fs_stat2inode_dotl(st, dentry->d_inode); 391 + generic_fillattr(dentry->d_inode, stat); 392 + /* Change block size to what the server returned */ 393 + stat->blksize = st->st_blksize; 394 + 395 + kfree(st); 396 + return 0; 397 + } 398 + 399 + /** 400 + * v9fs_vfs_setattr_dotl - set file metadata 401 + * @dentry: file whose metadata to set 402 + * @iattr: metadata assignment structure 403 + * 404 + */ 405 + 406 + int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) 407 + { 408 + int retval; 409 + struct v9fs_session_info *v9ses; 410 + struct p9_fid *fid; 411 + struct p9_iattr_dotl p9attr; 412 + 413 + P9_DPRINTK(P9_DEBUG_VFS, "\n"); 414 + 415 + retval = inode_change_ok(dentry->d_inode, iattr); 416 + if (retval) 417 + return retval; 418 + 419 + p9attr.valid = iattr->ia_valid; 420 + p9attr.mode = iattr->ia_mode; 421 + p9attr.uid = iattr->ia_uid; 422 + p9attr.gid = iattr->ia_gid; 423 + p9attr.size = iattr->ia_size; 424 + p9attr.atime_sec = iattr->ia_atime.tv_sec; 425 + p9attr.atime_nsec = iattr->ia_atime.tv_nsec; 426 + p9attr.mtime_sec = iattr->ia_mtime.tv_sec; 427 + p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; 428 + 429 + retval = -EPERM; 430 + v9ses = v9fs_inode2v9ses(dentry->d_inode); 431 + fid = v9fs_fid_lookup(dentry); 432 + if (IS_ERR(fid)) 433 + return PTR_ERR(fid); 434 + 435 + retval = p9_client_setattr(fid, &p9attr); 436 + if (retval < 0) 437 + return retval; 438 + 439 + if ((iattr->ia_valid & ATTR_SIZE) && 440 + iattr->ia_size != i_size_read(dentry->d_inode)) { 441 + retval = vmtruncate(dentry->d_inode, iattr->ia_size); 442 + if (retval) 443 + return retval; 444 + } 445 + 446 + setattr_copy(dentry->d_inode, iattr); 447 + mark_inode_dirty(dentry->d_inode); 448 + if (iattr->ia_valid & ATTR_MODE) { 449 + /* We also want to update ACL when we update mode bits */ 450 + retval = v9fs_acl_chmod(dentry); 451 + if (retval < 0) 452 + return retval; 453 + } 454 + return 0; 455 + } 456 + 457 + /** 458 + * v9fs_stat2inode_dotl - populate an inode structure with stat info 459 + * @stat: stat structure 460 + * @inode: inode to populate 461 + * @sb: superblock of filesystem 462 + * 463 + */ 464 + 465 + void 466 + v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) 467 + { 468 + 469 + if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { 470 + inode->i_atime.tv_sec = stat->st_atime_sec; 471 + inode->i_atime.tv_nsec = stat->st_atime_nsec; 472 + inode->i_mtime.tv_sec = stat->st_mtime_sec; 473 + inode->i_mtime.tv_nsec = stat->st_mtime_nsec; 474 + inode->i_ctime.tv_sec = stat->st_ctime_sec; 475 + inode->i_ctime.tv_nsec = stat->st_ctime_nsec; 476 + inode->i_uid = stat->st_uid; 477 + inode->i_gid = stat->st_gid; 478 + inode->i_nlink = stat->st_nlink; 479 + inode->i_mode = stat->st_mode; 480 + inode->i_rdev = new_decode_dev(stat->st_rdev); 481 + 482 + if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) 483 + init_special_inode(inode, inode->i_mode, inode->i_rdev); 484 + 485 + i_size_write(inode, stat->st_size); 486 + inode->i_blocks = stat->st_blocks; 487 + } else { 488 + if (stat->st_result_mask & P9_STATS_ATIME) { 489 + inode->i_atime.tv_sec = stat->st_atime_sec; 490 + inode->i_atime.tv_nsec = stat->st_atime_nsec; 491 + } 492 + if (stat->st_result_mask & P9_STATS_MTIME) { 493 + inode->i_mtime.tv_sec = stat->st_mtime_sec; 494 + inode->i_mtime.tv_nsec = stat->st_mtime_nsec; 495 + } 496 + if (stat->st_result_mask & P9_STATS_CTIME) { 497 + inode->i_ctime.tv_sec = stat->st_ctime_sec; 498 + inode->i_ctime.tv_nsec = stat->st_ctime_nsec; 499 + } 500 + if (stat->st_result_mask & P9_STATS_UID) 501 + inode->i_uid = stat->st_uid; 502 + if (stat->st_result_mask & P9_STATS_GID) 503 + inode->i_gid = stat->st_gid; 504 + if (stat->st_result_mask & P9_STATS_NLINK) 505 + inode->i_nlink = stat->st_nlink; 506 + if (stat->st_result_mask & P9_STATS_MODE) { 507 + inode->i_mode = stat->st_mode; 508 + if ((S_ISBLK(inode->i_mode)) || 509 + (S_ISCHR(inode->i_mode))) 510 + init_special_inode(inode, inode->i_mode, 511 + inode->i_rdev); 512 + } 513 + if (stat->st_result_mask & P9_STATS_RDEV) 514 + inode->i_rdev = new_decode_dev(stat->st_rdev); 515 + if (stat->st_result_mask & P9_STATS_SIZE) 516 + i_size_write(inode, stat->st_size); 517 + if (stat->st_result_mask & P9_STATS_BLOCKS) 518 + inode->i_blocks = stat->st_blocks; 519 + } 520 + if (stat->st_result_mask & P9_STATS_GEN) 521 + inode->i_generation = stat->st_gen; 522 + 523 + /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION 524 + * because the inode structure does not have fields for them. 525 + */ 526 + } 527 + 528 + static int 529 + v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, 530 + const char *symname) 531 + { 532 + struct v9fs_session_info *v9ses; 533 + struct p9_fid *dfid; 534 + struct p9_fid *fid = NULL; 535 + struct inode *inode; 536 + struct p9_qid qid; 537 + char *name; 538 + int err; 539 + gid_t gid; 540 + 541 + name = (char *) dentry->d_name.name; 542 + P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n", 543 + dir->i_ino, name, symname); 544 + v9ses = v9fs_inode2v9ses(dir); 545 + 546 + dfid = v9fs_fid_lookup(dentry->d_parent); 547 + if (IS_ERR(dfid)) { 548 + err = PTR_ERR(dfid); 549 + P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 550 + return err; 551 + } 552 + 553 + gid = v9fs_get_fsgid_for_create(dir); 554 + 555 + /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ 556 + err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); 557 + 558 + if (err < 0) { 559 + P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err); 560 + goto error; 561 + } 562 + 563 + if (v9ses->cache) { 564 + /* Now walk from the parent so we can get an unopened fid. */ 565 + fid = p9_client_walk(dfid, 1, &name, 1); 566 + if (IS_ERR(fid)) { 567 + err = PTR_ERR(fid); 568 + P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 569 + err); 570 + fid = NULL; 571 + goto error; 572 + } 573 + 574 + /* instantiate inode and assign the unopened fid to dentry */ 575 + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 576 + if (IS_ERR(inode)) { 577 + err = PTR_ERR(inode); 578 + P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 579 + err); 580 + goto error; 581 + } 582 + d_set_d_op(dentry, &v9fs_cached_dentry_operations); 583 + d_instantiate(dentry, inode); 584 + err = v9fs_fid_add(dentry, fid); 585 + if (err < 0) 586 + goto error; 587 + fid = NULL; 588 + } else { 589 + /* Not in cached mode. No need to populate inode with stat */ 590 + inode = v9fs_get_inode(dir->i_sb, S_IFLNK); 591 + if (IS_ERR(inode)) { 592 + err = PTR_ERR(inode); 593 + goto error; 594 + } 595 + d_set_d_op(dentry, &v9fs_dentry_operations); 596 + d_instantiate(dentry, inode); 597 + } 598 + 599 + error: 600 + if (fid) 601 + p9_client_clunk(fid); 602 + 603 + return err; 604 + } 605 + 606 + /** 607 + * v9fs_vfs_link_dotl - create a hardlink for dotl 608 + * @old_dentry: dentry for file to link to 609 + * @dir: inode destination for new link 610 + * @dentry: dentry for link 611 + * 612 + */ 613 + 614 + static int 615 + v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, 616 + struct dentry *dentry) 617 + { 618 + int err; 619 + struct p9_fid *dfid, *oldfid; 620 + char *name; 621 + struct v9fs_session_info *v9ses; 622 + struct dentry *dir_dentry; 623 + 624 + P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n", 625 + dir->i_ino, old_dentry->d_name.name, 626 + dentry->d_name.name); 627 + 628 + v9ses = v9fs_inode2v9ses(dir); 629 + dir_dentry = v9fs_dentry_from_dir_inode(dir); 630 + dfid = v9fs_fid_lookup(dir_dentry); 631 + if (IS_ERR(dfid)) 632 + return PTR_ERR(dfid); 633 + 634 + oldfid = v9fs_fid_lookup(old_dentry); 635 + if (IS_ERR(oldfid)) 636 + return PTR_ERR(oldfid); 637 + 638 + name = (char *) dentry->d_name.name; 639 + 640 + err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); 641 + 642 + if (err < 0) { 643 + P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); 644 + return err; 645 + } 646 + 647 + if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 648 + /* Get the latest stat info from server. */ 649 + struct p9_fid *fid; 650 + struct p9_stat_dotl *st; 651 + 652 + fid = v9fs_fid_lookup(old_dentry); 653 + if (IS_ERR(fid)) 654 + return PTR_ERR(fid); 655 + 656 + st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 657 + if (IS_ERR(st)) 658 + return PTR_ERR(st); 659 + 660 + v9fs_stat2inode_dotl(st, old_dentry->d_inode); 661 + 662 + kfree(st); 663 + } else { 664 + /* Caching disabled. No need to get upto date stat info. 665 + * This dentry will be released immediately. So, just hold the 666 + * inode 667 + */ 668 + ihold(old_dentry->d_inode); 669 + } 670 + 671 + d_set_d_op(dentry, old_dentry->d_op); 672 + d_instantiate(dentry, old_dentry->d_inode); 673 + 674 + return err; 675 + } 676 + 677 + /** 678 + * v9fs_vfs_mknod_dotl - create a special file 679 + * @dir: inode destination for new link 680 + * @dentry: dentry for file 681 + * @mode: mode for creation 682 + * @rdev: device associated with special file 683 + * 684 + */ 685 + static int 686 + v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, 687 + dev_t rdev) 688 + { 689 + int err; 690 + char *name; 691 + mode_t mode; 692 + struct v9fs_session_info *v9ses; 693 + struct p9_fid *fid = NULL, *dfid = NULL; 694 + struct inode *inode; 695 + gid_t gid; 696 + struct p9_qid qid; 697 + struct dentry *dir_dentry; 698 + struct posix_acl *dacl = NULL, *pacl = NULL; 699 + 700 + P9_DPRINTK(P9_DEBUG_VFS, 701 + " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 702 + dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev)); 703 + 704 + if (!new_valid_dev(rdev)) 705 + return -EINVAL; 706 + 707 + v9ses = v9fs_inode2v9ses(dir); 708 + dir_dentry = v9fs_dentry_from_dir_inode(dir); 709 + dfid = v9fs_fid_lookup(dir_dentry); 710 + if (IS_ERR(dfid)) { 711 + err = PTR_ERR(dfid); 712 + P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 713 + dfid = NULL; 714 + goto error; 715 + } 716 + 717 + gid = v9fs_get_fsgid_for_create(dir); 718 + mode = omode; 719 + /* Update mode based on ACL value */ 720 + err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 721 + if (err) { 722 + P9_DPRINTK(P9_DEBUG_VFS, 723 + "Failed to get acl values in mknod %d\n", err); 724 + goto error; 725 + } 726 + name = (char *) dentry->d_name.name; 727 + 728 + err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); 729 + if (err < 0) 730 + goto error; 731 + 732 + /* instantiate inode and assign the unopened fid to the dentry */ 733 + if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 734 + fid = p9_client_walk(dfid, 1, &name, 1); 735 + if (IS_ERR(fid)) { 736 + err = PTR_ERR(fid); 737 + P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 738 + err); 739 + fid = NULL; 740 + goto error; 741 + } 742 + 743 + inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 744 + if (IS_ERR(inode)) { 745 + err = PTR_ERR(inode); 746 + P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 747 + err); 748 + goto error; 749 + } 750 + d_set_d_op(dentry, &v9fs_cached_dentry_operations); 751 + d_instantiate(dentry, inode); 752 + err = v9fs_fid_add(dentry, fid); 753 + if (err < 0) 754 + goto error; 755 + fid = NULL; 756 + } else { 757 + /* 758 + * Not in cached mode. No need to populate inode with stat. 759 + * socket syscall returns a fd, so we need instantiate 760 + */ 761 + inode = v9fs_get_inode(dir->i_sb, mode); 762 + if (IS_ERR(inode)) { 763 + err = PTR_ERR(inode); 764 + goto error; 765 + } 766 + d_set_d_op(dentry, &v9fs_dentry_operations); 767 + d_instantiate(dentry, inode); 768 + } 769 + /* Now set the ACL based on the default value */ 770 + v9fs_set_create_acl(dentry, dacl, pacl); 771 + error: 772 + if (fid) 773 + p9_client_clunk(fid); 774 + return err; 775 + } 776 + 777 + static int 778 + v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen) 779 + { 780 + int retval; 781 + struct p9_fid *fid; 782 + char *target = NULL; 783 + 784 + P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); 785 + retval = -EPERM; 786 + fid = v9fs_fid_lookup(dentry); 787 + if (IS_ERR(fid)) 788 + return PTR_ERR(fid); 789 + 790 + retval = p9_client_readlink(fid, &target); 791 + if (retval < 0) 792 + return retval; 793 + 794 + strncpy(buffer, target, buflen); 795 + P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer); 796 + 797 + retval = strnlen(buffer, buflen); 798 + return retval; 799 + } 800 + 801 + /** 802 + * v9fs_vfs_follow_link_dotl - follow a symlink path 803 + * @dentry: dentry for symlink 804 + * @nd: nameidata 805 + * 806 + */ 807 + 808 + static void * 809 + v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) 810 + { 811 + int len = 0; 812 + char *link = __getname(); 813 + 814 + P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); 815 + 816 + if (!link) 817 + link = ERR_PTR(-ENOMEM); 818 + else { 819 + len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX); 820 + if (len < 0) { 821 + __putname(link); 822 + link = ERR_PTR(len); 823 + } else 824 + link[min(len, PATH_MAX-1)] = 0; 825 + } 826 + nd_set_link(nd, link); 827 + 828 + return NULL; 829 + } 830 + 831 + const struct inode_operations v9fs_dir_inode_operations_dotl = { 832 + .create = v9fs_vfs_create_dotl, 833 + .lookup = v9fs_vfs_lookup, 834 + .link = v9fs_vfs_link_dotl, 835 + .symlink = v9fs_vfs_symlink_dotl, 836 + .unlink = v9fs_vfs_unlink, 837 + .mkdir = v9fs_vfs_mkdir_dotl, 838 + .rmdir = v9fs_vfs_rmdir, 839 + .mknod = v9fs_vfs_mknod_dotl, 840 + .rename = v9fs_vfs_rename, 841 + .getattr = v9fs_vfs_getattr_dotl, 842 + .setattr = v9fs_vfs_setattr_dotl, 843 + .setxattr = generic_setxattr, 844 + .getxattr = generic_getxattr, 845 + .removexattr = generic_removexattr, 846 + .listxattr = v9fs_listxattr, 847 + .check_acl = v9fs_check_acl, 848 + }; 849 + 850 + const struct inode_operations v9fs_file_inode_operations_dotl = { 851 + .getattr = v9fs_vfs_getattr_dotl, 852 + .setattr = v9fs_vfs_setattr_dotl, 853 + .setxattr = generic_setxattr, 854 + .getxattr = generic_getxattr, 855 + .removexattr = generic_removexattr, 856 + .listxattr = v9fs_listxattr, 857 + .check_acl = v9fs_check_acl, 858 + }; 859 + 860 + const struct inode_operations v9fs_symlink_inode_operations_dotl = { 861 + .readlink = v9fs_vfs_readlink_dotl, 862 + .follow_link = v9fs_vfs_follow_link_dotl, 863 + .put_link = v9fs_vfs_put_link, 864 + .getattr = v9fs_vfs_getattr_dotl, 865 + .setattr = v9fs_vfs_setattr_dotl, 866 + .setxattr = generic_setxattr, 867 + .getxattr = generic_getxattr, 868 + .removexattr = generic_removexattr, 869 + .listxattr = v9fs_listxattr, 870 + };