diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 258 |
1 files changed, 187 insertions, 71 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 9e670d527646..34bf71b56542 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/xattr.h> | 38 | #include <linux/xattr.h> |
39 | #include <linux/posix_acl.h> | ||
39 | #include <net/9p/9p.h> | 40 | #include <net/9p/9p.h> |
40 | #include <net/9p/client.h> | 41 | #include <net/9p/client.h> |
41 | 42 | ||
@@ -44,6 +45,7 @@ | |||
44 | #include "fid.h" | 45 | #include "fid.h" |
45 | #include "cache.h" | 46 | #include "cache.h" |
46 | #include "xattr.h" | 47 | #include "xattr.h" |
48 | #include "acl.h" | ||
47 | 49 | ||
48 | static const struct inode_operations v9fs_dir_inode_operations; | 50 | static const struct inode_operations v9fs_dir_inode_operations; |
49 | static const struct inode_operations v9fs_dir_inode_operations_dotu; | 51 | static const struct inode_operations v9fs_dir_inode_operations_dotu; |
@@ -53,6 +55,10 @@ static const struct inode_operations v9fs_file_inode_operations_dotl; | |||
53 | static const struct inode_operations v9fs_symlink_inode_operations; | 55 | static const struct inode_operations v9fs_symlink_inode_operations; |
54 | static const struct inode_operations v9fs_symlink_inode_operations_dotl; | 56 | static const struct inode_operations v9fs_symlink_inode_operations_dotl; |
55 | 57 | ||
58 | static int | ||
59 | v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, | ||
60 | dev_t rdev); | ||
61 | |||
56 | /** | 62 | /** |
57 | * unixmode2p9mode - convert unix mode bits to plan 9 | 63 | * unixmode2p9mode - convert unix mode bits to plan 9 |
58 | * @v9ses: v9fs session information | 64 | * @v9ses: v9fs session information |
@@ -500,6 +506,11 @@ v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, | |||
500 | v9fs_vcookie_set_qid(ret, &st->qid); | 506 | v9fs_vcookie_set_qid(ret, &st->qid); |
501 | v9fs_cache_inode_get_cookie(ret); | 507 | v9fs_cache_inode_get_cookie(ret); |
502 | #endif | 508 | #endif |
509 | err = v9fs_get_acl(ret, fid); | ||
510 | if (err) { | ||
511 | iput(ret); | ||
512 | goto error; | ||
513 | } | ||
503 | kfree(st); | 514 | kfree(st); |
504 | return ret; | 515 | return ret; |
505 | error: | 516 | error: |
@@ -553,13 +564,6 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
553 | return retval; | 564 | return retval; |
554 | } | 565 | } |
555 | 566 | ||
556 | static int | ||
557 | v9fs_open_created(struct inode *inode, struct file *file) | ||
558 | { | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | |||
563 | /** | 567 | /** |
564 | * v9fs_create - Create a file | 568 | * v9fs_create - Create a file |
565 | * @v9ses: session information | 569 | * @v9ses: session information |
@@ -655,29 +659,37 @@ error: | |||
655 | */ | 659 | */ |
656 | 660 | ||
657 | static int | 661 | static int |
658 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | 662 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, |
659 | struct nameidata *nd) | 663 | struct nameidata *nd) |
660 | { | 664 | { |
661 | int err = 0; | 665 | int err = 0; |
662 | char *name = NULL; | 666 | char *name = NULL; |
663 | gid_t gid; | 667 | gid_t gid; |
664 | int flags; | 668 | int flags; |
669 | mode_t mode; | ||
665 | struct v9fs_session_info *v9ses; | 670 | struct v9fs_session_info *v9ses; |
666 | struct p9_fid *fid = NULL; | 671 | struct p9_fid *fid = NULL; |
667 | struct p9_fid *dfid, *ofid; | 672 | struct p9_fid *dfid, *ofid; |
668 | struct file *filp; | 673 | struct file *filp; |
669 | struct p9_qid qid; | 674 | struct p9_qid qid; |
670 | struct inode *inode; | 675 | struct inode *inode; |
676 | struct posix_acl *pacl = NULL, *dacl = NULL; | ||
671 | 677 | ||
672 | v9ses = v9fs_inode2v9ses(dir); | 678 | v9ses = v9fs_inode2v9ses(dir); |
673 | if (nd && nd->flags & LOOKUP_OPEN) | 679 | if (nd && nd->flags & LOOKUP_OPEN) |
674 | flags = nd->intent.open.flags - 1; | 680 | flags = nd->intent.open.flags - 1; |
675 | else | 681 | else { |
676 | flags = O_RDWR; | 682 | /* |
683 | * create call without LOOKUP_OPEN is due | ||
684 | * to mknod of regular files. So use mknod | ||
685 | * operation. | ||
686 | */ | ||
687 | return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); | ||
688 | } | ||
677 | 689 | ||
678 | name = (char *) dentry->d_name.name; | 690 | name = (char *) dentry->d_name.name; |
679 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " | 691 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " |
680 | "mode:0x%x\n", name, flags, mode); | 692 | "mode:0x%x\n", name, flags, omode); |
681 | 693 | ||
682 | dfid = v9fs_fid_lookup(dentry->d_parent); | 694 | dfid = v9fs_fid_lookup(dentry->d_parent); |
683 | if (IS_ERR(dfid)) { | 695 | if (IS_ERR(dfid)) { |
@@ -695,6 +707,15 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
695 | } | 707 | } |
696 | 708 | ||
697 | gid = v9fs_get_fsgid_for_create(dir); | 709 | gid = v9fs_get_fsgid_for_create(dir); |
710 | |||
711 | mode = omode; | ||
712 | /* Update mode based on ACL value */ | ||
713 | err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); | ||
714 | if (err) { | ||
715 | P9_DPRINTK(P9_DEBUG_VFS, | ||
716 | "Failed to get acl values in creat %d\n", err); | ||
717 | goto error; | ||
718 | } | ||
698 | err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); | 719 | err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); |
699 | if (err < 0) { | 720 | if (err < 0) { |
700 | P9_DPRINTK(P9_DEBUG_VFS, | 721 | P9_DPRINTK(P9_DEBUG_VFS, |
@@ -702,46 +723,52 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
702 | err); | 723 | err); |
703 | goto error; | 724 | goto error; |
704 | } | 725 | } |
726 | /* instantiate inode and assign the unopened fid to the dentry */ | ||
727 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE || | ||
728 | (nd && nd->flags & LOOKUP_OPEN)) { | ||
729 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
730 | if (IS_ERR(fid)) { | ||
731 | err = PTR_ERR(fid); | ||
732 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", | ||
733 | err); | ||
734 | fid = NULL; | ||
735 | goto error; | ||
736 | } | ||
705 | 737 | ||
706 | /* No need to populate the inode if we are not opening the file AND | 738 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); |
707 | * not in cached mode. | 739 | if (IS_ERR(inode)) { |
708 | */ | 740 | err = PTR_ERR(inode); |
709 | if (!v9ses->cache && !(nd && nd->flags & LOOKUP_OPEN)) { | 741 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", |
710 | /* Not in cached mode. No need to populate inode with stat */ | 742 | err); |
711 | dentry->d_op = &v9fs_dentry_operations; | 743 | goto error; |
712 | p9_client_clunk(ofid); | 744 | } |
713 | d_instantiate(dentry, NULL); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | /* Now walk from the parent so we can get an unopened fid. */ | ||
718 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
719 | if (IS_ERR(fid)) { | ||
720 | err = PTR_ERR(fid); | ||
721 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | ||
722 | fid = NULL; | ||
723 | goto error; | ||
724 | } | ||
725 | |||
726 | /* instantiate inode and assign the unopened fid to dentry */ | ||
727 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | ||
728 | if (IS_ERR(inode)) { | ||
729 | err = PTR_ERR(inode); | ||
730 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | ||
731 | goto error; | ||
732 | } | ||
733 | if (v9ses->cache) | ||
734 | dentry->d_op = &v9fs_cached_dentry_operations; | 745 | dentry->d_op = &v9fs_cached_dentry_operations; |
735 | else | 746 | d_instantiate(dentry, inode); |
747 | err = v9fs_fid_add(dentry, fid); | ||
748 | if (err < 0) | ||
749 | goto error; | ||
750 | /* The fid would get clunked via a dput */ | ||
751 | fid = NULL; | ||
752 | } else { | ||
753 | /* | ||
754 | * Not in cached mode. No need to populate | ||
755 | * inode with stat. We need to get an inode | ||
756 | * so that we can set the acl with dentry | ||
757 | */ | ||
758 | inode = v9fs_get_inode(dir->i_sb, mode); | ||
759 | if (IS_ERR(inode)) { | ||
760 | err = PTR_ERR(inode); | ||
761 | goto error; | ||
762 | } | ||
736 | dentry->d_op = &v9fs_dentry_operations; | 763 | dentry->d_op = &v9fs_dentry_operations; |
737 | d_instantiate(dentry, inode); | 764 | d_instantiate(dentry, inode); |
738 | err = v9fs_fid_add(dentry, fid); | 765 | } |
739 | if (err < 0) | 766 | /* Now set the ACL based on the default value */ |
740 | goto error; | 767 | v9fs_set_create_acl(dentry, dacl, pacl); |
741 | 768 | ||
742 | /* if we are opening a file, assign the open fid to the file */ | 769 | /* if we are opening a file, assign the open fid to the file */ |
743 | if (nd && nd->flags & LOOKUP_OPEN) { | 770 | if (nd && nd->flags & LOOKUP_OPEN) { |
744 | filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); | 771 | filp = lookup_instantiate_filp(nd, dentry, generic_file_open); |
745 | if (IS_ERR(filp)) { | 772 | if (IS_ERR(filp)) { |
746 | p9_client_clunk(ofid); | 773 | p9_client_clunk(ofid); |
747 | return PTR_ERR(filp); | 774 | return PTR_ERR(filp); |
@@ -800,7 +827,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
800 | 827 | ||
801 | /* if we are opening a file, assign the open fid to the file */ | 828 | /* if we are opening a file, assign the open fid to the file */ |
802 | if (nd && nd->flags & LOOKUP_OPEN) { | 829 | if (nd && nd->flags & LOOKUP_OPEN) { |
803 | filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); | 830 | filp = lookup_instantiate_filp(nd, dentry, generic_file_open); |
804 | if (IS_ERR(filp)) { | 831 | if (IS_ERR(filp)) { |
805 | err = PTR_ERR(filp); | 832 | err = PTR_ERR(filp); |
806 | goto error; | 833 | goto error; |
@@ -859,23 +886,28 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
859 | * | 886 | * |
860 | */ | 887 | */ |
861 | 888 | ||
862 | static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, | 889 | static int v9fs_vfs_mkdir_dotl(struct inode *dir, |
863 | int mode) | 890 | struct dentry *dentry, int omode) |
864 | { | 891 | { |
865 | int err; | 892 | int err; |
866 | struct v9fs_session_info *v9ses; | 893 | struct v9fs_session_info *v9ses; |
867 | struct p9_fid *fid = NULL, *dfid = NULL; | 894 | struct p9_fid *fid = NULL, *dfid = NULL; |
868 | gid_t gid; | 895 | gid_t gid; |
869 | char *name; | 896 | char *name; |
897 | mode_t mode; | ||
870 | struct inode *inode; | 898 | struct inode *inode; |
871 | struct p9_qid qid; | 899 | struct p9_qid qid; |
872 | struct dentry *dir_dentry; | 900 | struct dentry *dir_dentry; |
901 | struct posix_acl *dacl = NULL, *pacl = NULL; | ||
873 | 902 | ||
874 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); | 903 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); |
875 | err = 0; | 904 | err = 0; |
876 | v9ses = v9fs_inode2v9ses(dir); | 905 | v9ses = v9fs_inode2v9ses(dir); |
877 | 906 | ||
878 | mode |= S_IFDIR; | 907 | omode |= S_IFDIR; |
908 | if (dir->i_mode & S_ISGID) | ||
909 | omode |= S_ISGID; | ||
910 | |||
879 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | 911 | dir_dentry = v9fs_dentry_from_dir_inode(dir); |
880 | dfid = v9fs_fid_lookup(dir_dentry); | 912 | dfid = v9fs_fid_lookup(dir_dentry); |
881 | if (IS_ERR(dfid)) { | 913 | if (IS_ERR(dfid)) { |
@@ -886,11 +918,14 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, | |||
886 | } | 918 | } |
887 | 919 | ||
888 | gid = v9fs_get_fsgid_for_create(dir); | 920 | gid = v9fs_get_fsgid_for_create(dir); |
889 | if (gid < 0) { | 921 | mode = omode; |
890 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); | 922 | /* Update mode based on ACL value */ |
923 | err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); | ||
924 | if (err) { | ||
925 | P9_DPRINTK(P9_DEBUG_VFS, | ||
926 | "Failed to get acl values in mkdir %d\n", err); | ||
891 | goto error; | 927 | goto error; |
892 | } | 928 | } |
893 | |||
894 | name = (char *) dentry->d_name.name; | 929 | name = (char *) dentry->d_name.name; |
895 | err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); | 930 | err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); |
896 | if (err < 0) | 931 | if (err < 0) |
@@ -920,7 +955,23 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, | |||
920 | if (err < 0) | 955 | if (err < 0) |
921 | goto error; | 956 | goto error; |
922 | fid = NULL; | 957 | fid = NULL; |
958 | } else { | ||
959 | /* | ||
960 | * Not in cached mode. No need to populate | ||
961 | * inode with stat. We need to get an inode | ||
962 | * so that we can set the acl with dentry | ||
963 | */ | ||
964 | inode = v9fs_get_inode(dir->i_sb, mode); | ||
965 | if (IS_ERR(inode)) { | ||
966 | err = PTR_ERR(inode); | ||
967 | goto error; | ||
968 | } | ||
969 | dentry->d_op = &v9fs_dentry_operations; | ||
970 | d_instantiate(dentry, inode); | ||
923 | } | 971 | } |
972 | /* Now set the ACL based on the default value */ | ||
973 | v9fs_set_create_acl(dentry, dacl, pacl); | ||
974 | |||
924 | error: | 975 | error: |
925 | if (fid) | 976 | if (fid) |
926 | p9_client_clunk(fid); | 977 | p9_client_clunk(fid); |
@@ -979,7 +1030,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
979 | 1030 | ||
980 | result = v9fs_fid_add(dentry, fid); | 1031 | result = v9fs_fid_add(dentry, fid); |
981 | if (result < 0) | 1032 | if (result < 0) |
982 | goto error; | 1033 | goto error_iput; |
983 | 1034 | ||
984 | inst_out: | 1035 | inst_out: |
985 | if (v9ses->cache) | 1036 | if (v9ses->cache) |
@@ -990,6 +1041,8 @@ inst_out: | |||
990 | d_add(dentry, inode); | 1041 | d_add(dentry, inode); |
991 | return NULL; | 1042 | return NULL; |
992 | 1043 | ||
1044 | error_iput: | ||
1045 | iput(inode); | ||
993 | error: | 1046 | error: |
994 | p9_client_clunk(fid); | 1047 | p9_client_clunk(fid); |
995 | 1048 | ||
@@ -1237,7 +1290,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
1237 | * | 1290 | * |
1238 | */ | 1291 | */ |
1239 | 1292 | ||
1240 | static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) | 1293 | int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) |
1241 | { | 1294 | { |
1242 | int retval; | 1295 | int retval; |
1243 | struct v9fs_session_info *v9ses; | 1296 | struct v9fs_session_info *v9ses; |
@@ -1279,6 +1332,12 @@ static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) | |||
1279 | 1332 | ||
1280 | setattr_copy(dentry->d_inode, iattr); | 1333 | setattr_copy(dentry->d_inode, iattr); |
1281 | mark_inode_dirty(dentry->d_inode); | 1334 | mark_inode_dirty(dentry->d_inode); |
1335 | if (iattr->ia_valid & ATTR_MODE) { | ||
1336 | /* We also want to update ACL when we update mode bits */ | ||
1337 | retval = v9fs_acl_chmod(dentry); | ||
1338 | if (retval < 0) | ||
1339 | return retval; | ||
1340 | } | ||
1282 | return 0; | 1341 | return 0; |
1283 | } | 1342 | } |
1284 | 1343 | ||
@@ -1473,7 +1532,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
1473 | if (IS_ERR(fid)) | 1532 | if (IS_ERR(fid)) |
1474 | return PTR_ERR(fid); | 1533 | return PTR_ERR(fid); |
1475 | 1534 | ||
1476 | if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) | 1535 | if (!v9fs_proto_dotu(v9ses)) |
1477 | return -EBADF; | 1536 | return -EBADF; |
1478 | 1537 | ||
1479 | st = p9_client_stat(fid); | 1538 | st = p9_client_stat(fid); |
@@ -1616,11 +1675,6 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, | |||
1616 | 1675 | ||
1617 | gid = v9fs_get_fsgid_for_create(dir); | 1676 | gid = v9fs_get_fsgid_for_create(dir); |
1618 | 1677 | ||
1619 | if (gid < 0) { | ||
1620 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_egid failed %d\n", gid); | ||
1621 | goto error; | ||
1622 | } | ||
1623 | |||
1624 | /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ | 1678 | /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ |
1625 | err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); | 1679 | err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); |
1626 | 1680 | ||
@@ -1789,9 +1843,10 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, | |||
1789 | kfree(st); | 1843 | kfree(st); |
1790 | } else { | 1844 | } else { |
1791 | /* Caching disabled. No need to get upto date stat info. | 1845 | /* Caching disabled. No need to get upto date stat info. |
1792 | * This dentry will be released immediately. So, just i_count++ | 1846 | * This dentry will be released immediately. So, just hold the |
1847 | * inode | ||
1793 | */ | 1848 | */ |
1794 | atomic_inc(&old_dentry->d_inode->i_count); | 1849 | ihold(old_dentry->d_inode); |
1795 | } | 1850 | } |
1796 | 1851 | ||
1797 | dentry->d_op = old_dentry->d_op; | 1852 | dentry->d_op = old_dentry->d_op; |
@@ -1854,21 +1909,23 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1854 | * | 1909 | * |
1855 | */ | 1910 | */ |
1856 | static int | 1911 | static int |
1857 | v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, | 1912 | v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, |
1858 | dev_t rdev) | 1913 | dev_t rdev) |
1859 | { | 1914 | { |
1860 | int err; | 1915 | int err; |
1861 | char *name; | 1916 | char *name; |
1917 | mode_t mode; | ||
1862 | struct v9fs_session_info *v9ses; | 1918 | struct v9fs_session_info *v9ses; |
1863 | struct p9_fid *fid = NULL, *dfid = NULL; | 1919 | struct p9_fid *fid = NULL, *dfid = NULL; |
1864 | struct inode *inode; | 1920 | struct inode *inode; |
1865 | gid_t gid; | 1921 | gid_t gid; |
1866 | struct p9_qid qid; | 1922 | struct p9_qid qid; |
1867 | struct dentry *dir_dentry; | 1923 | struct dentry *dir_dentry; |
1924 | struct posix_acl *dacl = NULL, *pacl = NULL; | ||
1868 | 1925 | ||
1869 | P9_DPRINTK(P9_DEBUG_VFS, | 1926 | P9_DPRINTK(P9_DEBUG_VFS, |
1870 | " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, | 1927 | " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, |
1871 | dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); | 1928 | dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev)); |
1872 | 1929 | ||
1873 | if (!new_valid_dev(rdev)) | 1930 | if (!new_valid_dev(rdev)) |
1874 | return -EINVAL; | 1931 | return -EINVAL; |
@@ -1884,11 +1941,14 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
1884 | } | 1941 | } |
1885 | 1942 | ||
1886 | gid = v9fs_get_fsgid_for_create(dir); | 1943 | gid = v9fs_get_fsgid_for_create(dir); |
1887 | if (gid < 0) { | 1944 | mode = omode; |
1888 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); | 1945 | /* Update mode based on ACL value */ |
1946 | err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); | ||
1947 | if (err) { | ||
1948 | P9_DPRINTK(P9_DEBUG_VFS, | ||
1949 | "Failed to get acl values in mknod %d\n", err); | ||
1889 | goto error; | 1950 | goto error; |
1890 | } | 1951 | } |
1891 | |||
1892 | name = (char *) dentry->d_name.name; | 1952 | name = (char *) dentry->d_name.name; |
1893 | 1953 | ||
1894 | err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); | 1954 | err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); |
@@ -1932,13 +1992,68 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
1932 | dentry->d_op = &v9fs_dentry_operations; | 1992 | dentry->d_op = &v9fs_dentry_operations; |
1933 | d_instantiate(dentry, inode); | 1993 | d_instantiate(dentry, inode); |
1934 | } | 1994 | } |
1935 | 1995 | /* Now set the ACL based on the default value */ | |
1996 | v9fs_set_create_acl(dentry, dacl, pacl); | ||
1936 | error: | 1997 | error: |
1937 | if (fid) | 1998 | if (fid) |
1938 | p9_client_clunk(fid); | 1999 | p9_client_clunk(fid); |
1939 | return err; | 2000 | return err; |
1940 | } | 2001 | } |
1941 | 2002 | ||
2003 | static int | ||
2004 | v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen) | ||
2005 | { | ||
2006 | int retval; | ||
2007 | struct p9_fid *fid; | ||
2008 | char *target = NULL; | ||
2009 | |||
2010 | P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); | ||
2011 | retval = -EPERM; | ||
2012 | fid = v9fs_fid_lookup(dentry); | ||
2013 | if (IS_ERR(fid)) | ||
2014 | return PTR_ERR(fid); | ||
2015 | |||
2016 | retval = p9_client_readlink(fid, &target); | ||
2017 | if (retval < 0) | ||
2018 | return retval; | ||
2019 | |||
2020 | strncpy(buffer, target, buflen); | ||
2021 | P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer); | ||
2022 | |||
2023 | retval = strnlen(buffer, buflen); | ||
2024 | return retval; | ||
2025 | } | ||
2026 | |||
2027 | /** | ||
2028 | * v9fs_vfs_follow_link_dotl - follow a symlink path | ||
2029 | * @dentry: dentry for symlink | ||
2030 | * @nd: nameidata | ||
2031 | * | ||
2032 | */ | ||
2033 | |||
2034 | static void * | ||
2035 | v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) | ||
2036 | { | ||
2037 | int len = 0; | ||
2038 | char *link = __getname(); | ||
2039 | |||
2040 | P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); | ||
2041 | |||
2042 | if (!link) | ||
2043 | link = ERR_PTR(-ENOMEM); | ||
2044 | else { | ||
2045 | len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX); | ||
2046 | if (len < 0) { | ||
2047 | __putname(link); | ||
2048 | link = ERR_PTR(len); | ||
2049 | } else | ||
2050 | link[min(len, PATH_MAX-1)] = 0; | ||
2051 | } | ||
2052 | nd_set_link(nd, link); | ||
2053 | |||
2054 | return NULL; | ||
2055 | } | ||
2056 | |||
1942 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 2057 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { |
1943 | .create = v9fs_vfs_create, | 2058 | .create = v9fs_vfs_create, |
1944 | .lookup = v9fs_vfs_lookup, | 2059 | .lookup = v9fs_vfs_lookup, |
@@ -1969,7 +2084,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotl = { | |||
1969 | .getxattr = generic_getxattr, | 2084 | .getxattr = generic_getxattr, |
1970 | .removexattr = generic_removexattr, | 2085 | .removexattr = generic_removexattr, |
1971 | .listxattr = v9fs_listxattr, | 2086 | .listxattr = v9fs_listxattr, |
1972 | 2087 | .check_acl = v9fs_check_acl, | |
1973 | }; | 2088 | }; |
1974 | 2089 | ||
1975 | static const struct inode_operations v9fs_dir_inode_operations = { | 2090 | static const struct inode_operations v9fs_dir_inode_operations = { |
@@ -1996,6 +2111,7 @@ static const struct inode_operations v9fs_file_inode_operations_dotl = { | |||
1996 | .getxattr = generic_getxattr, | 2111 | .getxattr = generic_getxattr, |
1997 | .removexattr = generic_removexattr, | 2112 | .removexattr = generic_removexattr, |
1998 | .listxattr = v9fs_listxattr, | 2113 | .listxattr = v9fs_listxattr, |
2114 | .check_acl = v9fs_check_acl, | ||
1999 | }; | 2115 | }; |
2000 | 2116 | ||
2001 | static const struct inode_operations v9fs_symlink_inode_operations = { | 2117 | static const struct inode_operations v9fs_symlink_inode_operations = { |
@@ -2007,8 +2123,8 @@ static const struct inode_operations v9fs_symlink_inode_operations = { | |||
2007 | }; | 2123 | }; |
2008 | 2124 | ||
2009 | static const struct inode_operations v9fs_symlink_inode_operations_dotl = { | 2125 | static const struct inode_operations v9fs_symlink_inode_operations_dotl = { |
2010 | .readlink = generic_readlink, | 2126 | .readlink = v9fs_vfs_readlink_dotl, |
2011 | .follow_link = v9fs_vfs_follow_link, | 2127 | .follow_link = v9fs_vfs_follow_link_dotl, |
2012 | .put_link = v9fs_vfs_put_link, | 2128 | .put_link = v9fs_vfs_put_link, |
2013 | .getattr = v9fs_vfs_getattr_dotl, | 2129 | .getattr = v9fs_vfs_getattr_dotl, |
2014 | .setattr = v9fs_vfs_setattr_dotl, | 2130 | .setattr = v9fs_vfs_setattr_dotl, |