aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2006-03-27 04:14:43 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:39 -0500
commitf360ce3be466d50de153b001b24561ca7593042b (patch)
treecad660d0143e02d3e949cd7c9483ea59da41b0ca
parent718c604a28e35848754a65b839e4877ec34b2fca (diff)
[PATCH] autofs4: use libfs routines for readdir
Change readdir routines to use the cursor based routines in libfs.c. This removes reliance on old readdir code from 2.4 and should improve efficiency of readdir in autofs4. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-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)