aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/root.c149
1 files changed, 16 insertions, 133 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 87352654ff4e..51c873ca8e8d 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -25,8 +25,6 @@ static int autofs4_dir_rmdir(struct inode *,struct dentry *);
25static int autofs4_dir_mkdir(struct inode *,struct dentry *,int); 25static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
26static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); 26static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
27static int autofs4_dir_open(struct inode *inode, struct file *file); 27static int autofs4_dir_open(struct inode *inode, struct file *file);
28static int autofs4_dir_close(struct inode *inode, struct file *file);
29static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
30static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); 28static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
31static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); 29static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
32static void *autofs4_follow_link(struct dentry *, struct nameidata *); 30static void *autofs4_follow_link(struct dentry *, struct nameidata *);
@@ -44,9 +42,9 @@ const struct file_operations autofs4_root_operations = {
44 42
45const struct file_operations autofs4_dir_operations = { 43const struct file_operations autofs4_dir_operations = {
46 .open = autofs4_dir_open, 44 .open = autofs4_dir_open,
47 .release = autofs4_dir_close, 45 .release = dcache_dir_close,
48 .read = generic_read_dir, 46 .read = generic_read_dir,
49 .readdir = autofs4_dir_readdir, 47 .readdir = dcache_readdir,
50}; 48};
51 49
52const struct inode_operations autofs4_indirect_root_inode_operations = { 50const struct inode_operations autofs4_indirect_root_inode_operations = {
@@ -98,17 +96,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent,
98static int autofs4_dir_open(struct inode *inode, struct file *file) 96static int autofs4_dir_open(struct inode *inode, struct file *file)
99{ 97{
100 struct dentry *dentry = file->f_path.dentry; 98 struct dentry *dentry = file->f_path.dentry;
101 struct vfsmount *mnt = file->f_path.mnt;
102 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); 99 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
103 struct dentry *cursor;
104 int status;
105
106 status = dcache_dir_open(inode, file);
107 if (status)
108 goto out;
109
110 cursor = file->private_data;
111 cursor->d_fsdata = NULL;
112 100
113 DPRINTK("file=%p dentry=%p %.*s", 101 DPRINTK("file=%p dentry=%p %.*s",
114 file, dentry, dentry->d_name.len, dentry->d_name.name); 102 file, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -116,129 +104,24 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
116 if (autofs4_oz_mode(sbi)) 104 if (autofs4_oz_mode(sbi))
117 goto out; 105 goto out;
118 106
119 if (autofs4_ispending(dentry)) { 107 /*
120 DPRINTK("dentry busy"); 108 * An empty directory in an autofs file system is always a
121 dcache_dir_close(inode, file); 109 * mount point. The daemon must have failed to mount this
122 status = -EBUSY; 110 * during lookup so it doesn't exist. This can happen, for
123 goto out; 111 * example, if user space returns an incorrect status for a
124 } 112 * mount request. Otherwise we're doing a readdir on the
125 113 * autofs file system so just let the libfs routines handle
126 status = -ENOENT; 114 * it.
127 if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { 115 */
128 struct nameidata nd; 116 spin_lock(&dcache_lock);
129 int empty, ret; 117 if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
130
131 /* In case there are stale directory dentrys from a failed mount */
132 spin_lock(&dcache_lock);
133 empty = list_empty(&dentry->d_subdirs);
134 spin_unlock(&dcache_lock); 118 spin_unlock(&dcache_lock);
135 119 return -ENOENT;
136 if (!empty)
137 d_invalidate(dentry);
138
139 nd.flags = LOOKUP_DIRECTORY;
140 ret = (dentry->d_op->d_revalidate)(dentry, &nd);
141
142 if (ret <= 0) {
143 if (ret < 0)
144 status = ret;
145 dcache_dir_close(inode, file);
146 goto out;
147 }
148 } 120 }
121 spin_unlock(&dcache_lock);
149 122
150 if (d_mountpoint(dentry)) {
151 struct file *fp = NULL;
152 struct path fp_path = { .dentry = dentry, .mnt = mnt };
153
154 path_get(&fp_path);
155
156 if (!autofs4_follow_mount(&fp_path.mnt, &fp_path.dentry)) {
157 path_put(&fp_path);
158 dcache_dir_close(inode, file);
159 goto out;
160 }
161
162 fp = dentry_open(fp_path.dentry, fp_path.mnt, file->f_flags);
163 status = PTR_ERR(fp);
164 if (IS_ERR(fp)) {
165 dcache_dir_close(inode, file);
166 goto out;
167 }
168 cursor->d_fsdata = fp;
169 }
170 return 0;
171out:
172 return status;
173}
174
175static int autofs4_dir_close(struct inode *inode, struct file *file)
176{
177 struct dentry *dentry = file->f_path.dentry;
178 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
179 struct dentry *cursor = file->private_data;
180 int status = 0;
181
182 DPRINTK("file=%p dentry=%p %.*s",
183 file, dentry, dentry->d_name.len, dentry->d_name.name);
184
185 if (autofs4_oz_mode(sbi))
186 goto out;
187
188 if (autofs4_ispending(dentry)) {
189 DPRINTK("dentry busy");
190 status = -EBUSY;
191 goto out;
192 }
193
194 if (d_mountpoint(dentry)) {
195 struct file *fp = cursor->d_fsdata;
196 if (!fp) {
197 status = -ENOENT;
198 goto out;
199 }
200 filp_close(fp, current->files);
201 }
202out:
203 dcache_dir_close(inode, file);
204 return status;
205}
206
207static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
208{
209 struct dentry *dentry = file->f_path.dentry;
210 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
211 struct dentry *cursor = file->private_data;
212 int status;
213
214 DPRINTK("file=%p dentry=%p %.*s",
215 file, dentry, dentry->d_name.len, dentry->d_name.name);
216
217 if (autofs4_oz_mode(sbi))
218 goto out;
219
220 if (autofs4_ispending(dentry)) {
221 DPRINTK("dentry busy");
222 return -EBUSY;
223 }
224
225 if (d_mountpoint(dentry)) {
226 struct file *fp = cursor->d_fsdata;
227
228 if (!fp)
229 return -ENOENT;
230
231 if (!fp->f_op || !fp->f_op->readdir)
232 goto out;
233
234 status = vfs_readdir(fp, filldir, dirent);
235 file->f_pos = fp->f_pos;
236 if (status)
237 autofs4_copy_atime(file, fp);
238 return status;
239 }
240out: 123out:
241 return dcache_readdir(file, dirent, filldir); 124 return dcache_dir_open(inode, file);
242} 125}
243 126
244static int try_to_fill_dentry(struct dentry *dentry, int flags) 127static int try_to_fill_dentry(struct dentry *dentry, int flags)