aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/root.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4/root.c')
-rw-r--r--fs/autofs4/root.c126
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);
30static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); 30static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
31static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); 31static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
32static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); 32static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
33static int autofs4_dcache_readdir(struct file *, void *, filldir_t);
34 33
35struct file_operations autofs4_root_operations = { 34struct 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 */
109static 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
168static int autofs4_dir_open(struct inode *inode, struct file *file) 105static 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 }
226out:
227 return 0; 175 return 0;
176out:
177 return status;
228} 178}
229 179
230static int autofs4_dir_close(struct inode *inode, struct file *file) 180static 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 }
255out: 207out:
256 return 0; 208 dcache_dir_close(inode, file);
209 return status;
257} 210}
258 211
259static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) 212static 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 }
291out: 245out:
292 return autofs4_dcache_readdir(file, dirent, filldir); 246 return dcache_readdir(file, dirent, filldir);
293} 247}
294 248
295static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags) 249static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags)