diff options
Diffstat (limited to 'fs/autofs4/root.c')
-rw-r--r-- | fs/autofs4/root.c | 126 |
1 files changed, 40 insertions, 86 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 2c676bd44acd..af9a4c6bbadf 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -30,7 +30,6 @@ static int autofs4_dir_close(struct inode *inode, struct file *file); | |||
30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); | 30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); |
31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); | 31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); |
32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
33 | static int autofs4_dcache_readdir(struct file *, void *, filldir_t); | ||
34 | 33 | ||
35 | struct file_operations autofs4_root_operations = { | 34 | struct file_operations autofs4_root_operations = { |
36 | .open = dcache_dir_open, | 35 | .open = dcache_dir_open, |
@@ -82,7 +81,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent, | |||
82 | 81 | ||
83 | DPRINTK("needs_reghost = %d", sbi->needs_reghost); | 82 | DPRINTK("needs_reghost = %d", sbi->needs_reghost); |
84 | 83 | ||
85 | return autofs4_dcache_readdir(file, dirent, filldir); | 84 | return dcache_readdir(file, dirent, filldir); |
86 | } | 85 | } |
87 | 86 | ||
88 | /* Update usage from here to top of tree, so that scan of | 87 | /* Update usage from here to top of tree, so that scan of |
@@ -103,75 +102,21 @@ static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry) | |||
103 | spin_unlock(&dcache_lock); | 102 | spin_unlock(&dcache_lock); |
104 | } | 103 | } |
105 | 104 | ||
106 | /* | ||
107 | * From 2.4 kernel readdir.c | ||
108 | */ | ||
109 | static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||
110 | { | ||
111 | int i; | ||
112 | struct dentry *dentry = filp->f_dentry; | ||
113 | |||
114 | i = filp->f_pos; | ||
115 | switch (i) { | ||
116 | case 0: | ||
117 | if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0) | ||
118 | break; | ||
119 | i++; | ||
120 | filp->f_pos++; | ||
121 | /* fallthrough */ | ||
122 | case 1: | ||
123 | if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) | ||
124 | break; | ||
125 | i++; | ||
126 | filp->f_pos++; | ||
127 | /* fallthrough */ | ||
128 | default: { | ||
129 | struct list_head *list; | ||
130 | int j = i-2; | ||
131 | |||
132 | spin_lock(&dcache_lock); | ||
133 | list = dentry->d_subdirs.next; | ||
134 | |||
135 | for (;;) { | ||
136 | if (list == &dentry->d_subdirs) { | ||
137 | spin_unlock(&dcache_lock); | ||
138 | return 0; | ||
139 | } | ||
140 | if (!j) | ||
141 | break; | ||
142 | j--; | ||
143 | list = list->next; | ||
144 | } | ||
145 | |||
146 | while(1) { | ||
147 | struct dentry *de = list_entry(list, | ||
148 | struct dentry, d_u.d_child); | ||
149 | |||
150 | if (!d_unhashed(de) && de->d_inode) { | ||
151 | spin_unlock(&dcache_lock); | ||
152 | if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0) | ||
153 | break; | ||
154 | spin_lock(&dcache_lock); | ||
155 | } | ||
156 | filp->f_pos++; | ||
157 | list = list->next; | ||
158 | if (list != &dentry->d_subdirs) | ||
159 | continue; | ||
160 | spin_unlock(&dcache_lock); | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int autofs4_dir_open(struct inode *inode, struct file *file) | 105 | static int autofs4_dir_open(struct inode *inode, struct file *file) |
169 | { | 106 | { |
170 | struct dentry *dentry = file->f_dentry; | 107 | struct dentry *dentry = file->f_dentry; |
171 | struct vfsmount *mnt = file->f_vfsmnt; | 108 | struct vfsmount *mnt = file->f_vfsmnt; |
172 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 109 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
110 | struct dentry *cursor; | ||
173 | int status; | 111 | int status; |
174 | 112 | ||
113 | status = dcache_dir_open(inode, file); | ||
114 | if (status) | ||
115 | goto out; | ||
116 | |||
117 | cursor = file->private_data; | ||
118 | cursor->d_fsdata = NULL; | ||
119 | |||
175 | DPRINTK("file=%p dentry=%p %.*s", | 120 | DPRINTK("file=%p dentry=%p %.*s", |
176 | file, dentry, dentry->d_name.len, dentry->d_name.name); | 121 | file, dentry, dentry->d_name.len, dentry->d_name.name); |
177 | 122 | ||
@@ -180,12 +125,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
180 | 125 | ||
181 | if (autofs4_ispending(dentry)) { | 126 | if (autofs4_ispending(dentry)) { |
182 | DPRINTK("dentry busy"); | 127 | DPRINTK("dentry busy"); |
183 | return -EBUSY; | 128 | dcache_dir_close(inode, file); |
129 | status = -EBUSY; | ||
130 | goto out; | ||
184 | } | 131 | } |
185 | 132 | ||
133 | status = -ENOENT; | ||
186 | if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { | 134 | if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { |
187 | struct nameidata nd; | 135 | struct nameidata nd; |
188 | int empty; | 136 | int empty, ret; |
189 | 137 | ||
190 | /* In case there are stale directory dentrys from a failed mount */ | 138 | /* In case there are stale directory dentrys from a failed mount */ |
191 | spin_lock(&dcache_lock); | 139 | spin_lock(&dcache_lock); |
@@ -195,13 +143,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
195 | if (!empty) | 143 | if (!empty) |
196 | d_invalidate(dentry); | 144 | d_invalidate(dentry); |
197 | 145 | ||
198 | nd.dentry = dentry; | ||
199 | nd.mnt = mnt; | ||
200 | nd.flags = LOOKUP_DIRECTORY; | 146 | nd.flags = LOOKUP_DIRECTORY; |
201 | status = (dentry->d_op->d_revalidate)(dentry, &nd); | 147 | ret = (dentry->d_op->d_revalidate)(dentry, &nd); |
202 | 148 | ||
203 | if (!status) | 149 | if (!ret) { |
204 | return -ENOENT; | 150 | dcache_dir_close(inode, file); |
151 | goto out; | ||
152 | } | ||
205 | } | 153 | } |
206 | 154 | ||
207 | if (d_mountpoint(dentry)) { | 155 | if (d_mountpoint(dentry)) { |
@@ -212,25 +160,29 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
212 | if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) { | 160 | if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) { |
213 | dput(fp_dentry); | 161 | dput(fp_dentry); |
214 | mntput(fp_mnt); | 162 | mntput(fp_mnt); |
215 | return -ENOENT; | 163 | dcache_dir_close(inode, file); |
164 | goto out; | ||
216 | } | 165 | } |
217 | 166 | ||
218 | fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); | 167 | fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); |
219 | status = PTR_ERR(fp); | 168 | status = PTR_ERR(fp); |
220 | if (IS_ERR(fp)) { | 169 | if (IS_ERR(fp)) { |
221 | file->private_data = NULL; | 170 | dcache_dir_close(inode, file); |
222 | return status; | 171 | goto out; |
223 | } | 172 | } |
224 | file->private_data = fp; | 173 | cursor->d_fsdata = fp; |
225 | } | 174 | } |
226 | out: | ||
227 | return 0; | 175 | return 0; |
176 | out: | ||
177 | return status; | ||
228 | } | 178 | } |
229 | 179 | ||
230 | static int autofs4_dir_close(struct inode *inode, struct file *file) | 180 | static int autofs4_dir_close(struct inode *inode, struct file *file) |
231 | { | 181 | { |
232 | struct dentry *dentry = file->f_dentry; | 182 | struct dentry *dentry = file->f_dentry; |
233 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 183 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
184 | struct dentry *cursor = file->private_data; | ||
185 | int status = 0; | ||
234 | 186 | ||
235 | DPRINTK("file=%p dentry=%p %.*s", | 187 | DPRINTK("file=%p dentry=%p %.*s", |
236 | file, dentry, dentry->d_name.len, dentry->d_name.name); | 188 | file, dentry, dentry->d_name.len, dentry->d_name.name); |
@@ -240,26 +192,28 @@ static int autofs4_dir_close(struct inode *inode, struct file *file) | |||
240 | 192 | ||
241 | if (autofs4_ispending(dentry)) { | 193 | if (autofs4_ispending(dentry)) { |
242 | DPRINTK("dentry busy"); | 194 | DPRINTK("dentry busy"); |
243 | return -EBUSY; | 195 | status = -EBUSY; |
196 | goto out; | ||
244 | } | 197 | } |
245 | 198 | ||
246 | if (d_mountpoint(dentry)) { | 199 | if (d_mountpoint(dentry)) { |
247 | struct file *fp = file->private_data; | 200 | struct file *fp = cursor->d_fsdata; |
248 | 201 | if (!fp) { | |
249 | if (!fp) | 202 | status = -ENOENT; |
250 | return -ENOENT; | 203 | goto out; |
251 | 204 | } | |
252 | filp_close(fp, current->files); | 205 | filp_close(fp, current->files); |
253 | file->private_data = NULL; | ||
254 | } | 206 | } |
255 | out: | 207 | out: |
256 | return 0; | 208 | dcache_dir_close(inode, file); |
209 | return status; | ||
257 | } | 210 | } |
258 | 211 | ||
259 | static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) | 212 | static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) |
260 | { | 213 | { |
261 | struct dentry *dentry = file->f_dentry; | 214 | struct dentry *dentry = file->f_dentry; |
262 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 215 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
216 | struct dentry *cursor = file->private_data; | ||
263 | int status; | 217 | int status; |
264 | 218 | ||
265 | DPRINTK("file=%p dentry=%p %.*s", | 219 | DPRINTK("file=%p dentry=%p %.*s", |
@@ -274,7 +228,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi | |||
274 | } | 228 | } |
275 | 229 | ||
276 | if (d_mountpoint(dentry)) { | 230 | if (d_mountpoint(dentry)) { |
277 | struct file *fp = file->private_data; | 231 | struct file *fp = cursor->d_fsdata; |
278 | 232 | ||
279 | if (!fp) | 233 | if (!fp) |
280 | return -ENOENT; | 234 | return -ENOENT; |
@@ -289,7 +243,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi | |||
289 | return status; | 243 | return status; |
290 | } | 244 | } |
291 | out: | 245 | out: |
292 | return autofs4_dcache_readdir(file, dirent, filldir); | 246 | return dcache_readdir(file, dirent, filldir); |
293 | } | 247 | } |
294 | 248 | ||
295 | static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags) | 249 | static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags) |