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); |