diff options
| -rw-r--r-- | fs/9p/acl.c | 52 | ||||
| -rw-r--r-- | fs/9p/acl.h | 17 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 141 |
3 files changed, 166 insertions, 44 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 8f2acde74c05..8b3c54a4958c 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c | |||
| @@ -152,6 +152,58 @@ int v9fs_acl_chmod(struct dentry *dentry) | |||
| 152 | return retval; | 152 | return retval; |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | int v9fs_set_create_acl(struct dentry *dentry, | ||
| 156 | struct posix_acl *dpacl, struct posix_acl *pacl) | ||
| 157 | { | ||
| 158 | if (dpacl) | ||
| 159 | v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl); | ||
| 160 | if (pacl) | ||
| 161 | v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl); | ||
| 162 | posix_acl_release(dpacl); | ||
| 163 | posix_acl_release(pacl); | ||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | int v9fs_acl_mode(struct inode *dir, mode_t *modep, | ||
| 168 | struct posix_acl **dpacl, struct posix_acl **pacl) | ||
| 169 | { | ||
| 170 | int retval = 0; | ||
| 171 | mode_t mode = *modep; | ||
| 172 | struct posix_acl *acl = NULL; | ||
| 173 | |||
| 174 | if (!S_ISLNK(mode)) { | ||
| 175 | acl = v9fs_get_cached_acl(dir, ACL_TYPE_DEFAULT); | ||
| 176 | if (IS_ERR(acl)) | ||
| 177 | return PTR_ERR(acl); | ||
| 178 | if (!acl) | ||
| 179 | mode &= ~current_umask(); | ||
| 180 | } | ||
| 181 | if (acl) { | ||
| 182 | struct posix_acl *clone; | ||
| 183 | |||
| 184 | if (S_ISDIR(mode)) | ||
| 185 | *dpacl = acl; | ||
| 186 | clone = posix_acl_clone(acl, GFP_NOFS); | ||
| 187 | retval = -ENOMEM; | ||
| 188 | if (!clone) | ||
| 189 | goto cleanup; | ||
| 190 | |||
| 191 | retval = posix_acl_create_masq(clone, &mode); | ||
| 192 | if (retval < 0) { | ||
| 193 | posix_acl_release(clone); | ||
| 194 | goto cleanup; | ||
| 195 | } | ||
| 196 | if (retval > 0) | ||
| 197 | *pacl = clone; | ||
| 198 | } | ||
| 199 | *modep = mode; | ||
| 200 | return 0; | ||
| 201 | cleanup: | ||
| 202 | posix_acl_release(acl); | ||
| 203 | return retval; | ||
| 204 | |||
| 205 | } | ||
| 206 | |||
| 155 | static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, | 207 | static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, |
| 156 | void *buffer, size_t size, int type) | 208 | void *buffer, size_t size, int type) |
| 157 | { | 209 | { |
diff --git a/fs/9p/acl.h b/fs/9p/acl.h index 0adcc4326d18..59e18c2e8c7e 100644 --- a/fs/9p/acl.h +++ b/fs/9p/acl.h | |||
| @@ -18,6 +18,10 @@ | |||
| 18 | extern int v9fs_get_acl(struct inode *, struct p9_fid *); | 18 | extern int v9fs_get_acl(struct inode *, struct p9_fid *); |
| 19 | extern int v9fs_check_acl(struct inode *inode, int mask); | 19 | extern int v9fs_check_acl(struct inode *inode, int mask); |
| 20 | extern int v9fs_acl_chmod(struct dentry *); | 20 | extern int v9fs_acl_chmod(struct dentry *); |
| 21 | extern int v9fs_set_create_acl(struct dentry *, | ||
| 22 | struct posix_acl *, struct posix_acl *); | ||
| 23 | extern int v9fs_acl_mode(struct inode *dir, mode_t *modep, | ||
| 24 | struct posix_acl **dpacl, struct posix_acl **pacl); | ||
| 21 | #else | 25 | #else |
| 22 | #define v9fs_check_acl NULL | 26 | #define v9fs_check_acl NULL |
| 23 | static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) | 27 | static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) |
| @@ -28,5 +32,18 @@ static inline int v9fs_acl_chmod(struct dentry *dentry) | |||
| 28 | { | 32 | { |
| 29 | return 0; | 33 | return 0; |
| 30 | } | 34 | } |
| 35 | static inline int v9fs_set_create_acl(struct dentry *dentry, | ||
| 36 | struct posix_acl *dpacl, | ||
| 37 | struct posix_acl *pacl) | ||
| 38 | { | ||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | static inline int v9fs_acl_mode(struct inode *dir, mode_t *modep, | ||
| 42 | struct posix_acl **dpacl, | ||
| 43 | struct posix_acl **pacl) | ||
| 44 | { | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | |||
| 31 | #endif | 48 | #endif |
| 32 | #endif /* FS_9P_XATTR_H */ | 49 | #endif /* FS_9P_XATTR_H */ |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index bdc64d1c22fb..68f02973c338 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -662,19 +662,21 @@ error: | |||
| 662 | */ | 662 | */ |
| 663 | 663 | ||
| 664 | static int | 664 | static int |
| 665 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | 665 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, |
| 666 | struct nameidata *nd) | 666 | struct nameidata *nd) |
| 667 | { | 667 | { |
| 668 | int err = 0; | 668 | int err = 0; |
| 669 | char *name = NULL; | 669 | char *name = NULL; |
| 670 | gid_t gid; | 670 | gid_t gid; |
| 671 | int flags; | 671 | int flags; |
| 672 | mode_t mode; | ||
| 672 | struct v9fs_session_info *v9ses; | 673 | struct v9fs_session_info *v9ses; |
| 673 | struct p9_fid *fid = NULL; | 674 | struct p9_fid *fid = NULL; |
| 674 | struct p9_fid *dfid, *ofid; | 675 | struct p9_fid *dfid, *ofid; |
| 675 | struct file *filp; | 676 | struct file *filp; |
| 676 | struct p9_qid qid; | 677 | struct p9_qid qid; |
| 677 | struct inode *inode; | 678 | struct inode *inode; |
| 679 | struct posix_acl *pacl = NULL, *dacl = NULL; | ||
| 678 | 680 | ||
| 679 | v9ses = v9fs_inode2v9ses(dir); | 681 | v9ses = v9fs_inode2v9ses(dir); |
| 680 | if (nd && nd->flags & LOOKUP_OPEN) | 682 | if (nd && nd->flags & LOOKUP_OPEN) |
| @@ -684,7 +686,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
| 684 | 686 | ||
| 685 | name = (char *) dentry->d_name.name; | 687 | name = (char *) dentry->d_name.name; |
| 686 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " | 688 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " |
| 687 | "mode:0x%x\n", name, flags, mode); | 689 | "mode:0x%x\n", name, flags, omode); |
| 688 | 690 | ||
| 689 | dfid = v9fs_fid_lookup(dentry->d_parent); | 691 | dfid = v9fs_fid_lookup(dentry->d_parent); |
| 690 | if (IS_ERR(dfid)) { | 692 | if (IS_ERR(dfid)) { |
| @@ -702,6 +704,15 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
| 702 | } | 704 | } |
| 703 | 705 | ||
| 704 | gid = v9fs_get_fsgid_for_create(dir); | 706 | gid = v9fs_get_fsgid_for_create(dir); |
| 707 | |||
| 708 | mode = omode; | ||
| 709 | /* Update mode based on ACL value */ | ||
| 710 | err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); | ||
| 711 | if (err) { | ||
| 712 | P9_DPRINTK(P9_DEBUG_VFS, | ||
| 713 | "Failed to get acl values in creat %d\n", err); | ||
| 714 | goto error; | ||
| 715 | } | ||
| 705 | err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); | 716 | err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); |
| 706 | if (err < 0) { | 717 | if (err < 0) { |
| 707 | P9_DPRINTK(P9_DEBUG_VFS, | 718 | P9_DPRINTK(P9_DEBUG_VFS, |
| @@ -709,42 +720,48 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
| 709 | err); | 720 | err); |
| 710 | goto error; | 721 | goto error; |
| 711 | } | 722 | } |
| 723 | /* instantiate inode and assign the unopened fid to the dentry */ | ||
| 724 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE || | ||
| 725 | (nd && nd->flags & LOOKUP_OPEN)) { | ||
| 726 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
| 727 | if (IS_ERR(fid)) { | ||
| 728 | err = PTR_ERR(fid); | ||
| 729 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", | ||
| 730 | err); | ||
| 731 | fid = NULL; | ||
| 732 | goto error; | ||
| 733 | } | ||
| 712 | 734 | ||
| 713 | /* No need to populate the inode if we are not opening the file AND | 735 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); |
| 714 | * not in cached mode. | 736 | if (IS_ERR(inode)) { |
| 715 | */ | 737 | err = PTR_ERR(inode); |
| 716 | if (!v9ses->cache && !(nd && nd->flags & LOOKUP_OPEN)) { | 738 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", |
| 717 | /* Not in cached mode. No need to populate inode with stat */ | 739 | err); |
| 718 | dentry->d_op = &v9fs_dentry_operations; | 740 | goto error; |
| 719 | p9_client_clunk(ofid); | 741 | } |
| 720 | d_instantiate(dentry, NULL); | ||
| 721 | return 0; | ||
| 722 | } | ||
| 723 | |||
| 724 | /* Now walk from the parent so we can get an unopened fid. */ | ||
| 725 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
| 726 | if (IS_ERR(fid)) { | ||
| 727 | err = PTR_ERR(fid); | ||
| 728 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | ||
| 729 | fid = NULL; | ||
| 730 | goto error; | ||
| 731 | } | ||
| 732 | |||
| 733 | /* instantiate inode and assign the unopened fid to dentry */ | ||
| 734 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | ||
| 735 | if (IS_ERR(inode)) { | ||
| 736 | err = PTR_ERR(inode); | ||
| 737 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | ||
| 738 | goto error; | ||
| 739 | } | ||
| 740 | if (v9ses->cache) | ||
| 741 | dentry->d_op = &v9fs_cached_dentry_operations; | 742 | dentry->d_op = &v9fs_cached_dentry_operations; |
| 742 | else | 743 | d_instantiate(dentry, inode); |
| 744 | err = v9fs_fid_add(dentry, fid); | ||
| 745 | if (err < 0) | ||
| 746 | goto error; | ||
| 747 | /* The fid would get clunked via a dput */ | ||
| 748 | fid = NULL; | ||
| 749 | } else { | ||
| 750 | /* | ||
| 751 | * Not in cached mode. No need to populate | ||
| 752 | * inode with stat. We need to get an inode | ||
| 753 | * so that we can set the acl with dentry | ||
| 754 | */ | ||
| 755 | inode = v9fs_get_inode(dir->i_sb, mode); | ||
| 756 | if (IS_ERR(inode)) { | ||
| 757 | err = PTR_ERR(inode); | ||
| 758 | goto error; | ||
| 759 | } | ||
| 743 | dentry->d_op = &v9fs_dentry_operations; | 760 | dentry->d_op = &v9fs_dentry_operations; |
| 744 | d_instantiate(dentry, inode); | 761 | d_instantiate(dentry, inode); |
| 745 | err = v9fs_fid_add(dentry, fid); | 762 | } |
| 746 | if (err < 0) | 763 | /* Now set the ACL based on the default value */ |
| 747 | goto error; | 764 | v9fs_set_create_acl(dentry, dacl, pacl); |
| 748 | 765 | ||
| 749 | /* if we are opening a file, assign the open fid to the file */ | 766 | /* if we are opening a file, assign the open fid to the file */ |
| 750 | if (nd && nd->flags & LOOKUP_OPEN) { | 767 | if (nd && nd->flags & LOOKUP_OPEN) { |
| @@ -866,25 +883,28 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 866 | * | 883 | * |
| 867 | */ | 884 | */ |
| 868 | 885 | ||
| 869 | static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, | 886 | static int v9fs_vfs_mkdir_dotl(struct inode *dir, |
| 870 | int mode) | 887 | struct dentry *dentry, int omode) |
| 871 | { | 888 | { |
| 872 | int err; | 889 | int err; |
| 873 | struct v9fs_session_info *v9ses; | 890 | struct v9fs_session_info *v9ses; |
| 874 | struct p9_fid *fid = NULL, *dfid = NULL; | 891 | struct p9_fid *fid = NULL, *dfid = NULL; |
| 875 | gid_t gid; | 892 | gid_t gid; |
| 876 | char *name; | 893 | char *name; |
| 894 | mode_t mode; | ||
| 877 | struct inode *inode; | 895 | struct inode *inode; |
| 878 | struct p9_qid qid; | 896 | struct p9_qid qid; |
| 879 | struct dentry *dir_dentry; | 897 | struct dentry *dir_dentry; |
| 898 | struct posix_acl *dacl = NULL, *pacl = NULL; | ||
| 880 | 899 | ||
| 881 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); | 900 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); |
| 882 | err = 0; | 901 | err = 0; |
| 883 | v9ses = v9fs_inode2v9ses(dir); | 902 | v9ses = v9fs_inode2v9ses(dir); |
| 884 | 903 | ||
| 885 | mode |= S_IFDIR; | 904 | omode |= S_IFDIR; |
| 886 | if (dir->i_mode & S_ISGID) | 905 | if (dir->i_mode & S_ISGID) |
| 887 | mode |= S_ISGID; | 906 | omode |= S_ISGID; |
| 907 | |||
| 888 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | 908 | dir_dentry = v9fs_dentry_from_dir_inode(dir); |
| 889 | dfid = v9fs_fid_lookup(dir_dentry); | 909 | dfid = v9fs_fid_lookup(dir_dentry); |
| 890 | if (IS_ERR(dfid)) { | 910 | if (IS_ERR(dfid)) { |
| @@ -895,7 +915,14 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, | |||
| 895 | } | 915 | } |
| 896 | 916 | ||
| 897 | gid = v9fs_get_fsgid_for_create(dir); | 917 | gid = v9fs_get_fsgid_for_create(dir); |
| 898 | 918 | mode = omode; | |
| 919 | /* Update mode based on ACL value */ | ||
| 920 | err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); | ||
| 921 | if (err) { | ||
| 922 | P9_DPRINTK(P9_DEBUG_VFS, | ||
| 923 | "Failed to get acl values in mkdir %d\n", err); | ||
| 924 | goto error; | ||
| 925 | } | ||
| 899 | name = (char *) dentry->d_name.name; | 926 | name = (char *) dentry->d_name.name; |
| 900 | err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); | 927 | err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); |
| 901 | if (err < 0) | 928 | if (err < 0) |
| @@ -925,7 +952,23 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, | |||
| 925 | if (err < 0) | 952 | if (err < 0) |
| 926 | goto error; | 953 | goto error; |
| 927 | fid = NULL; | 954 | fid = NULL; |
| 955 | } else { | ||
| 956 | /* | ||
| 957 | * Not in cached mode. No need to populate | ||
| 958 | * inode with stat. We need to get an inode | ||
| 959 | * so that we can set the acl with dentry | ||
| 960 | */ | ||
| 961 | inode = v9fs_get_inode(dir->i_sb, mode); | ||
| 962 | if (IS_ERR(inode)) { | ||
| 963 | err = PTR_ERR(inode); | ||
| 964 | goto error; | ||
| 965 | } | ||
| 966 | dentry->d_op = &v9fs_dentry_operations; | ||
| 967 | d_instantiate(dentry, inode); | ||
| 928 | } | 968 | } |
| 969 | /* Now set the ACL based on the default value */ | ||
| 970 | v9fs_set_create_acl(dentry, dacl, pacl); | ||
| 971 | |||
| 929 | error: | 972 | error: |
| 930 | if (fid) | 973 | if (fid) |
| 931 | p9_client_clunk(fid); | 974 | p9_client_clunk(fid); |
| @@ -1861,21 +1904,23 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
| 1861 | * | 1904 | * |
| 1862 | */ | 1905 | */ |
| 1863 | static int | 1906 | static int |
| 1864 | v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, | 1907 | v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, |
| 1865 | dev_t rdev) | 1908 | dev_t rdev) |
| 1866 | { | 1909 | { |
| 1867 | int err; | 1910 | int err; |
| 1868 | char *name; | 1911 | char *name; |
| 1912 | mode_t mode; | ||
| 1869 | struct v9fs_session_info *v9ses; | 1913 | struct v9fs_session_info *v9ses; |
| 1870 | struct p9_fid *fid = NULL, *dfid = NULL; | 1914 | struct p9_fid *fid = NULL, *dfid = NULL; |
| 1871 | struct inode *inode; | 1915 | struct inode *inode; |
| 1872 | gid_t gid; | 1916 | gid_t gid; |
| 1873 | struct p9_qid qid; | 1917 | struct p9_qid qid; |
| 1874 | struct dentry *dir_dentry; | 1918 | struct dentry *dir_dentry; |
| 1919 | struct posix_acl *dacl = NULL, *pacl = NULL; | ||
| 1875 | 1920 | ||
| 1876 | P9_DPRINTK(P9_DEBUG_VFS, | 1921 | P9_DPRINTK(P9_DEBUG_VFS, |
| 1877 | " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, | 1922 | " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, |
| 1878 | dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); | 1923 | dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev)); |
| 1879 | 1924 | ||
| 1880 | if (!new_valid_dev(rdev)) | 1925 | if (!new_valid_dev(rdev)) |
| 1881 | return -EINVAL; | 1926 | return -EINVAL; |
| @@ -1891,7 +1936,14 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
| 1891 | } | 1936 | } |
| 1892 | 1937 | ||
| 1893 | gid = v9fs_get_fsgid_for_create(dir); | 1938 | gid = v9fs_get_fsgid_for_create(dir); |
| 1894 | 1939 | mode = omode; | |
| 1940 | /* Update mode based on ACL value */ | ||
| 1941 | err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); | ||
| 1942 | if (err) { | ||
| 1943 | P9_DPRINTK(P9_DEBUG_VFS, | ||
| 1944 | "Failed to get acl values in mknod %d\n", err); | ||
| 1945 | goto error; | ||
| 1946 | } | ||
| 1895 | name = (char *) dentry->d_name.name; | 1947 | name = (char *) dentry->d_name.name; |
| 1896 | 1948 | ||
| 1897 | err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); | 1949 | err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); |
| @@ -1935,7 +1987,8 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
| 1935 | dentry->d_op = &v9fs_dentry_operations; | 1987 | dentry->d_op = &v9fs_dentry_operations; |
| 1936 | d_instantiate(dentry, inode); | 1988 | d_instantiate(dentry, inode); |
| 1937 | } | 1989 | } |
| 1938 | 1990 | /* Now set the ACL based on the default value */ | |
| 1991 | v9fs_set_create_acl(dentry, dacl, pacl); | ||
| 1939 | error: | 1992 | error: |
| 1940 | if (fid) | 1993 | if (fid) |
| 1941 | p9_client_clunk(fid); | 1994 | p9_client_clunk(fid); |
