aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-03-03 16:23:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-03-03 16:23:03 -0500
commit56a79b7b021bf1b08334e63c2c14b280e2dbf47a (patch)
tree0419233e6194f4f12073c9284852885aa8984bec /fs/9p
parent1c82315a12144cde732636e259d39e3ee81b3c5b (diff)
parentdcf787f39162ce32ca325b3e784aba2d2444619a (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more VFS bits from Al Viro: "Unfortunately, it looks like xattr series will have to wait until the next cycle ;-/ This pile contains 9p cleanups and fixes (races in v9fs_fid_add() etc), fixup for nommu breakage in shmem.c, several cleanups and a bit more file_inode() work" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: constify path_get/path_put and fs_struct.c stuff fix nommu breakage in shmem.c cache the value of file_inode() in struct file 9p: if v9fs_fid_lookup() gets to asking server, it'd better have hashed dentry 9p: make sure ->lookup() adds fid to the right dentry 9p: untangle ->lookup() a bit 9p: double iput() in ->lookup() if d_materialise_unique() fails 9p: v9fs_fid_add() can't fail now v9fs: get rid of v9fs_dentry 9p: turn fid->dlist into hlist 9p: don't bother with private lock in ->d_fsdata; dentry->d_lock will do just fine more file_inode() open-coded instances selinux: opened file can't have NULL or negative ->f_path.dentry (In the meantime, the hlist traversal macros have changed, so this required a semantic conflict fixup for the newly hlistified fid->dlist)
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/fid.c54
-rw-r--r--fs/9p/fid.h22
-rw-r--r--fs/9p/vfs_dentry.c17
-rw-r--r--fs/9p/vfs_inode.c40
-rw-r--r--fs/9p/vfs_inode_dotl.c19
5 files changed, 51 insertions, 101 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index afd4724b2d92..d51ec9fafcc8 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -41,29 +41,16 @@
41 * 41 *
42 */ 42 */
43 43
44int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) 44static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid)
45{ 45{
46 struct v9fs_dentry *dent; 46 hlist_add_head(&fid->dlist, (struct hlist_head *)&dentry->d_fsdata);
47 47}
48 p9_debug(P9_DEBUG_VFS, "fid %d dentry %s\n",
49 fid->fid, dentry->d_name.name);
50
51 dent = dentry->d_fsdata;
52 if (!dent) {
53 dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);
54 if (!dent)
55 return -ENOMEM;
56
57 spin_lock_init(&dent->lock);
58 INIT_LIST_HEAD(&dent->fidlist);
59 dentry->d_fsdata = dent;
60 }
61
62 spin_lock(&dent->lock);
63 list_add(&fid->dlist, &dent->fidlist);
64 spin_unlock(&dent->lock);
65 48
66 return 0; 49void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
50{
51 spin_lock(&dentry->d_lock);
52 __add_fid(dentry, fid);
53 spin_unlock(&dentry->d_lock);
67} 54}
68 55
69/** 56/**
@@ -76,23 +63,23 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
76 63
77static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) 64static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
78{ 65{
79 struct v9fs_dentry *dent;
80 struct p9_fid *fid, *ret; 66 struct p9_fid *fid, *ret;
81 67
82 p9_debug(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n", 68 p9_debug(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n",
83 dentry->d_name.name, dentry, from_kuid(&init_user_ns, uid), 69 dentry->d_name.name, dentry, from_kuid(&init_user_ns, uid),
84 any); 70 any);
85 dent = (struct v9fs_dentry *) dentry->d_fsdata;
86 ret = NULL; 71 ret = NULL;
87 if (dent) { 72 /* we'll recheck under lock if there's anything to look in */
88 spin_lock(&dent->lock); 73 if (dentry->d_fsdata) {
89 list_for_each_entry(fid, &dent->fidlist, dlist) { 74 struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata;
75 spin_lock(&dentry->d_lock);
76 hlist_for_each_entry(fid, h, dlist) {
90 if (any || uid_eq(fid->uid, uid)) { 77 if (any || uid_eq(fid->uid, uid)) {
91 ret = fid; 78 ret = fid;
92 break; 79 break;
93 } 80 }
94 } 81 }
95 spin_unlock(&dent->lock); 82 spin_unlock(&dentry->d_lock);
96 } 83 }
97 84
98 return ret; 85 return ret;
@@ -215,8 +202,17 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
215 } 202 }
216 kfree(wnames); 203 kfree(wnames);
217fid_out: 204fid_out:
218 if (!IS_ERR(fid)) 205 if (!IS_ERR(fid)) {
219 v9fs_fid_add(dentry, fid); 206 spin_lock(&dentry->d_lock);
207 if (d_unhashed(dentry)) {
208 spin_unlock(&dentry->d_lock);
209 p9_client_clunk(fid);
210 fid = ERR_PTR(-ENOENT);
211 } else {
212 __add_fid(dentry, fid);
213 spin_unlock(&dentry->d_lock);
214 }
215 }
220err_out: 216err_out:
221 up_read(&v9ses->rename_sem); 217 up_read(&v9ses->rename_sem);
222 return fid; 218 return fid;
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index bb0b6e7f58fc..2b6787fcb626 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -23,28 +23,8 @@
23#define FS_9P_FID_H 23#define FS_9P_FID_H
24#include <linux/list.h> 24#include <linux/list.h>
25 25
26/**
27 * struct v9fs_dentry - 9p private data stored in dentry d_fsdata
28 * @lock: protects the fidlist
29 * @fidlist: list of FIDs currently associated with this dentry
30 *
31 * This structure defines the 9p private data associated with
32 * a particular dentry. In particular, this private data is used
33 * to lookup which 9P FID handle should be used for a particular VFS
34 * operation. FID handles are associated with dentries instead of
35 * inodes in order to more closely map functionality to the Plan 9
36 * expected behavior for FID reclaimation and tracking.
37 *
38 * See Also: Mapping FIDs to Linux VFS model in
39 * Design and Implementation of the Linux 9P File System documentation
40 */
41struct v9fs_dentry {
42 spinlock_t lock; /* protect fidlist */
43 struct list_head fidlist;
44};
45
46struct p9_fid *v9fs_fid_lookup(struct dentry *dentry); 26struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
47struct p9_fid *v9fs_fid_clone(struct dentry *dentry); 27struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
48int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid); 28void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
49struct p9_fid *v9fs_writeback_fid(struct dentry *dentry); 29struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
50#endif 30#endif
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 9ad68628522c..f039b104a98e 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -83,21 +83,12 @@ static int v9fs_cached_dentry_delete(const struct dentry *dentry)
83 83
84static void v9fs_dentry_release(struct dentry *dentry) 84static void v9fs_dentry_release(struct dentry *dentry)
85{ 85{
86 struct v9fs_dentry *dent; 86 struct hlist_node *p, *n;
87 struct p9_fid *temp, *current_fid;
88
89 p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n", 87 p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n",
90 dentry->d_name.name, dentry); 88 dentry->d_name.name, dentry);
91 dent = dentry->d_fsdata; 89 hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
92 if (dent) { 90 p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
93 list_for_each_entry_safe(current_fid, temp, &dent->fidlist, 91 dentry->d_fsdata = NULL;
94 dlist) {
95 p9_client_clunk(current_fid);
96 }
97
98 kfree(dent);
99 dentry->d_fsdata = NULL;
100 }
101} 92}
102 93
103static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) 94static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index b5340c829de1..d86edc8d3fd0 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -692,9 +692,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
692 "inode creation failed %d\n", err); 692 "inode creation failed %d\n", err);
693 goto error; 693 goto error;
694 } 694 }
695 err = v9fs_fid_add(dentry, fid); 695 v9fs_fid_add(dentry, fid);
696 if (err < 0)
697 goto error;
698 d_instantiate(dentry, inode); 696 d_instantiate(dentry, inode);
699 } 697 }
700 return ofid; 698 return ofid;
@@ -790,7 +788,6 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
790 struct p9_fid *dfid, *fid; 788 struct p9_fid *dfid, *fid;
791 struct inode *inode; 789 struct inode *inode;
792 char *name; 790 char *name;
793 int result = 0;
794 791
795 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n", 792 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n",
796 dir, dentry->d_name.name, dentry, flags); 793 dir, dentry->d_name.name, dentry, flags);
@@ -808,13 +805,11 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
808 name = (char *) dentry->d_name.name; 805 name = (char *) dentry->d_name.name;
809 fid = p9_client_walk(dfid, 1, &name, 1); 806 fid = p9_client_walk(dfid, 1, &name, 1);
810 if (IS_ERR(fid)) { 807 if (IS_ERR(fid)) {
811 result = PTR_ERR(fid); 808 if (fid == ERR_PTR(-ENOENT)) {
812 if (result == -ENOENT) { 809 d_add(dentry, NULL);
813 inode = NULL; 810 return NULL;
814 goto inst_out;
815 } 811 }
816 812 return ERR_CAST(fid);
817 return ERR_PTR(result);
818 } 813 }
819 /* 814 /*
820 * Make sure we don't use a wrong inode due to parallel 815 * Make sure we don't use a wrong inode due to parallel
@@ -826,14 +821,9 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
826 else 821 else
827 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); 822 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
828 if (IS_ERR(inode)) { 823 if (IS_ERR(inode)) {
829 result = PTR_ERR(inode); 824 p9_client_clunk(fid);
830 inode = NULL; 825 return ERR_CAST(inode);
831 goto error;
832 } 826 }
833 result = v9fs_fid_add(dentry, fid);
834 if (result < 0)
835 goto error_iput;
836inst_out:
837 /* 827 /*
838 * If we had a rename on the server and a parallel lookup 828 * If we had a rename on the server and a parallel lookup
839 * for the new name, then make sure we instantiate with 829 * for the new name, then make sure we instantiate with
@@ -842,15 +832,13 @@ inst_out:
842 * k/b. 832 * k/b.
843 */ 833 */
844 res = d_materialise_unique(dentry, inode); 834 res = d_materialise_unique(dentry, inode);
845 if (!IS_ERR(res)) 835 if (!res)
846 return res; 836 v9fs_fid_add(dentry, fid);
847 result = PTR_ERR(res); 837 else if (!IS_ERR(res))
848error_iput: 838 v9fs_fid_add(res, fid);
849 iput(inode); 839 else
850error: 840 p9_client_clunk(fid);
851 p9_client_clunk(fid); 841 return res;
852
853 return ERR_PTR(result);
854} 842}
855 843
856static int 844static int
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 61e4fa70a6fa..53687bbf2296 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -333,9 +333,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
333 /* Now set the ACL based on the default value */ 333 /* Now set the ACL based on the default value */
334 v9fs_set_create_acl(inode, fid, dacl, pacl); 334 v9fs_set_create_acl(inode, fid, dacl, pacl);
335 335
336 err = v9fs_fid_add(dentry, fid); 336 v9fs_fid_add(dentry, fid);
337 if (err < 0)
338 goto error;
339 d_instantiate(dentry, inode); 337 d_instantiate(dentry, inode);
340 338
341 v9inode = V9FS_I(inode); 339 v9inode = V9FS_I(inode);
@@ -453,12 +451,11 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
453 err); 451 err);
454 goto error; 452 goto error;
455 } 453 }
456 err = v9fs_fid_add(dentry, fid); 454 v9fs_fid_add(dentry, fid);
457 if (err < 0)
458 goto error;
459 v9fs_set_create_acl(inode, fid, dacl, pacl); 455 v9fs_set_create_acl(inode, fid, dacl, pacl);
460 d_instantiate(dentry, inode); 456 d_instantiate(dentry, inode);
461 fid = NULL; 457 fid = NULL;
458 err = 0;
462 } else { 459 } else {
463 /* 460 /*
464 * Not in cached mode. No need to populate 461 * Not in cached mode. No need to populate
@@ -747,11 +744,10 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
747 err); 744 err);
748 goto error; 745 goto error;
749 } 746 }
750 err = v9fs_fid_add(dentry, fid); 747 v9fs_fid_add(dentry, fid);
751 if (err < 0)
752 goto error;
753 d_instantiate(dentry, inode); 748 d_instantiate(dentry, inode);
754 fid = NULL; 749 fid = NULL;
750 err = 0;
755 } else { 751 } else {
756 /* Not in cached mode. No need to populate inode with stat */ 752 /* Not in cached mode. No need to populate inode with stat */
757 inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0); 753 inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0);
@@ -900,11 +896,10 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
900 goto error; 896 goto error;
901 } 897 }
902 v9fs_set_create_acl(inode, fid, dacl, pacl); 898 v9fs_set_create_acl(inode, fid, dacl, pacl);
903 err = v9fs_fid_add(dentry, fid); 899 v9fs_fid_add(dentry, fid);
904 if (err < 0)
905 goto error;
906 d_instantiate(dentry, inode); 900 d_instantiate(dentry, inode);
907 fid = NULL; 901 fid = NULL;
902 err = 0;
908 } else { 903 } else {
909 /* 904 /*
910 * Not in cached mode. No need to populate inode with stat. 905 * Not in cached mode. No need to populate inode with stat.