aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2010-09-27 14:57:40 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-10-28 10:08:46 -0400
commitad77dbce567128d59b37a14c9562c8af6f63aeca (patch)
treeb178b4766e568013c3f58446aca27b1771a3694b /fs/9p
parent6e8dc55550273084b7fb5846df2f44439f5d03d9 (diff)
fs/9p: Implement create time inheritance
Inherit default ACL on create 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>
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/acl.c52
-rw-r--r--fs/9p/acl.h17
-rw-r--r--fs/9p/vfs_inode.c141
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
155int 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
167int 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;
201cleanup:
202 posix_acl_release(acl);
203 return retval;
204
205}
206
155static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, 207static 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 @@
18extern int v9fs_get_acl(struct inode *, struct p9_fid *); 18extern int v9fs_get_acl(struct inode *, struct p9_fid *);
19extern int v9fs_check_acl(struct inode *inode, int mask); 19extern int v9fs_check_acl(struct inode *inode, int mask);
20extern int v9fs_acl_chmod(struct dentry *); 20extern int v9fs_acl_chmod(struct dentry *);
21extern int v9fs_set_create_acl(struct dentry *,
22 struct posix_acl *, struct posix_acl *);
23extern 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
23static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) 27static 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}
35static inline int v9fs_set_create_acl(struct dentry *dentry,
36 struct posix_acl *dpacl,
37 struct posix_acl *pacl)
38{
39 return 0;
40}
41static 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
664static int 664static int
665v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, 665v9fs_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
869static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, 886static 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
929error: 972error:
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 */
1863static int 1906static int
1864v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, 1907v9fs_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);
1939error: 1992error:
1940 if (fid) 1993 if (fid)
1941 p9_client_clunk(fid); 1994 p9_client_clunk(fid);