diff options
Diffstat (limited to 'fs/hostfs')
-rw-r--r-- | fs/hostfs/hostfs_kern.c | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 2c0f148a49e6..d3244d949a4e 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -32,7 +32,7 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) | |||
32 | 32 | ||
33 | #define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode) | 33 | #define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode) |
34 | 34 | ||
35 | static int hostfs_d_delete(struct dentry *dentry) | 35 | static int hostfs_d_delete(const struct dentry *dentry) |
36 | { | 36 | { |
37 | return 1; | 37 | return 1; |
38 | } | 38 | } |
@@ -92,12 +92,10 @@ __uml_setup("hostfs=", hostfs_args, | |||
92 | 92 | ||
93 | static char *__dentry_name(struct dentry *dentry, char *name) | 93 | static char *__dentry_name(struct dentry *dentry, char *name) |
94 | { | 94 | { |
95 | char *p = __dentry_path(dentry, name, PATH_MAX); | 95 | char *p = dentry_path_raw(dentry, name, PATH_MAX); |
96 | char *root; | 96 | char *root; |
97 | size_t len; | 97 | size_t len; |
98 | 98 | ||
99 | spin_unlock(&dcache_lock); | ||
100 | |||
101 | root = dentry->d_sb->s_fs_info; | 99 | root = dentry->d_sb->s_fs_info; |
102 | len = strlen(root); | 100 | len = strlen(root); |
103 | if (IS_ERR(p)) { | 101 | if (IS_ERR(p)) { |
@@ -123,25 +121,23 @@ static char *dentry_name(struct dentry *dentry) | |||
123 | if (!name) | 121 | if (!name) |
124 | return NULL; | 122 | return NULL; |
125 | 123 | ||
126 | spin_lock(&dcache_lock); | ||
127 | return __dentry_name(dentry, name); /* will unlock */ | 124 | return __dentry_name(dentry, name); /* will unlock */ |
128 | } | 125 | } |
129 | 126 | ||
130 | static char *inode_name(struct inode *ino) | 127 | static char *inode_name(struct inode *ino) |
131 | { | 128 | { |
132 | struct dentry *dentry; | 129 | struct dentry *dentry; |
133 | char *name = __getname(); | 130 | char *name; |
134 | if (!name) | ||
135 | return NULL; | ||
136 | 131 | ||
137 | spin_lock(&dcache_lock); | 132 | dentry = d_find_alias(ino); |
138 | if (list_empty(&ino->i_dentry)) { | 133 | if (!dentry) |
139 | spin_unlock(&dcache_lock); | ||
140 | __putname(name); | ||
141 | return NULL; | 134 | return NULL; |
142 | } | 135 | |
143 | dentry = list_first_entry(&ino->i_dentry, struct dentry, d_alias); | 136 | name = dentry_name(dentry); |
144 | return __dentry_name(dentry, name); /* will unlock */ | 137 | |
138 | dput(dentry); | ||
139 | |||
140 | return name; | ||
145 | } | 141 | } |
146 | 142 | ||
147 | static char *follow_link(char *link) | 143 | static char *follow_link(char *link) |
@@ -251,11 +247,18 @@ static void hostfs_evict_inode(struct inode *inode) | |||
251 | } | 247 | } |
252 | } | 248 | } |
253 | 249 | ||
254 | static void hostfs_destroy_inode(struct inode *inode) | 250 | static void hostfs_i_callback(struct rcu_head *head) |
255 | { | 251 | { |
252 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
253 | INIT_LIST_HEAD(&inode->i_dentry); | ||
256 | kfree(HOSTFS_I(inode)); | 254 | kfree(HOSTFS_I(inode)); |
257 | } | 255 | } |
258 | 256 | ||
257 | static void hostfs_destroy_inode(struct inode *inode) | ||
258 | { | ||
259 | call_rcu(&inode->i_rcu, hostfs_i_callback); | ||
260 | } | ||
261 | |||
259 | static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | 262 | static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs) |
260 | { | 263 | { |
261 | const char *root_path = vfs->mnt_sb->s_fs_info; | 264 | const char *root_path = vfs->mnt_sb->s_fs_info; |
@@ -609,7 +612,7 @@ struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, | |||
609 | goto out_put; | 612 | goto out_put; |
610 | 613 | ||
611 | d_add(dentry, inode); | 614 | d_add(dentry, inode); |
612 | dentry->d_op = &hostfs_dentry_ops; | 615 | d_set_d_op(dentry, &hostfs_dentry_ops); |
613 | return NULL; | 616 | return NULL; |
614 | 617 | ||
615 | out_put: | 618 | out_put: |
@@ -746,11 +749,14 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, | |||
746 | return err; | 749 | return err; |
747 | } | 750 | } |
748 | 751 | ||
749 | int hostfs_permission(struct inode *ino, int desired) | 752 | int hostfs_permission(struct inode *ino, int desired, unsigned int flags) |
750 | { | 753 | { |
751 | char *name; | 754 | char *name; |
752 | int r = 0, w = 0, x = 0, err; | 755 | int r = 0, w = 0, x = 0, err; |
753 | 756 | ||
757 | if (flags & IPERM_FLAG_RCU) | ||
758 | return -ECHILD; | ||
759 | |||
754 | if (desired & MAY_READ) r = 1; | 760 | if (desired & MAY_READ) r = 1; |
755 | if (desired & MAY_WRITE) w = 1; | 761 | if (desired & MAY_WRITE) w = 1; |
756 | if (desired & MAY_EXEC) x = 1; | 762 | if (desired & MAY_EXEC) x = 1; |
@@ -765,7 +771,7 @@ int hostfs_permission(struct inode *ino, int desired) | |||
765 | err = access_file(name, r, w, x); | 771 | err = access_file(name, r, w, x); |
766 | __putname(name); | 772 | __putname(name); |
767 | if (!err) | 773 | if (!err) |
768 | err = generic_permission(ino, desired, NULL); | 774 | err = generic_permission(ino, desired, flags, NULL); |
769 | return err; | 775 | return err; |
770 | } | 776 | } |
771 | 777 | ||