Blame view
fs/autofs4/root.c
23.4 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* -*- c -*- --------------------------------------------------------------- * * * linux/fs/autofs/root.c * * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> |
34ca959cf [PATCH] autofs4: ... |
7 |
* Copyright 2001-2006 Ian Kent <raven@themaw.net> |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 12 13 |
* * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your * option, any later version, incorporated herein by reference. * * ------------------------------------------------------------------------- */ |
16f7e0fe2 [PATCH] capable/c... |
14 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
15 16 |
#include <linux/errno.h> #include <linux/stat.h> |
5a0e3ad6a include cleanup: ... |
17 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
#include <linux/param.h> #include <linux/time.h> |
c9243f5bd autofs/autofs4: M... |
20 |
#include <linux/compat.h> |
00e300e1b BKL: Remove BKL f... |
21 |
#include <linux/mutex.h> |
c9243f5bd autofs/autofs4: M... |
22 |
|
1da177e4c Linux-2.6.12-rc2 |
23 24 25 26 27 |
#include "autofs_i.h" static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *); static int autofs4_dir_unlink(struct inode *,struct dentry *); static int autofs4_dir_rmdir(struct inode *,struct dentry *); |
18bb1db3e switch vfs_mkdir(... |
28 |
static int autofs4_dir_mkdir(struct inode *,struct dentry *,umode_t); |
3663df70c autofs4: Pushdown... |
29 |
static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long); |
5a44a73b9 autofs4: Only dec... |
30 |
#ifdef CONFIG_COMPAT |
c9243f5bd autofs/autofs4: M... |
31 |
static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long); |
5a44a73b9 autofs4: Only dec... |
32 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
33 |
static int autofs4_dir_open(struct inode *inode, struct file *file); |
1da177e4c Linux-2.6.12-rc2 |
34 |
static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
71e469db2 autofs4: Clean up... |
35 |
static struct vfsmount *autofs4_d_automount(struct path *); |
1aed3e420 lose 'mounting_he... |
36 |
static int autofs4_d_manage(struct dentry *, bool); |
b89b12b46 autofs4: clean ->... |
37 |
static void autofs4_dentry_release(struct dentry *); |
1da177e4c Linux-2.6.12-rc2 |
38 |
|
4b6f5d20b [PATCH] Make most... |
39 |
const struct file_operations autofs4_root_operations = { |
1da177e4c Linux-2.6.12-rc2 |
40 41 42 |
.open = dcache_dir_open, .release = dcache_dir_close, .read = generic_read_dir, |
aa55ddf34 autofs4: remove u... |
43 |
.readdir = dcache_readdir, |
59af1584b [PATCH] fix ->lls... |
44 |
.llseek = dcache_dir_lseek, |
3663df70c autofs4: Pushdown... |
45 |
.unlocked_ioctl = autofs4_root_ioctl, |
c9243f5bd autofs/autofs4: M... |
46 47 48 |
#ifdef CONFIG_COMPAT .compat_ioctl = autofs4_root_compat_ioctl, #endif |
1da177e4c Linux-2.6.12-rc2 |
49 |
}; |
4b6f5d20b [PATCH] Make most... |
50 |
const struct file_operations autofs4_dir_operations = { |
1da177e4c Linux-2.6.12-rc2 |
51 |
.open = autofs4_dir_open, |
ff9cd499d autofs4: cleanup ... |
52 |
.release = dcache_dir_close, |
1da177e4c Linux-2.6.12-rc2 |
53 |
.read = generic_read_dir, |
ff9cd499d autofs4: cleanup ... |
54 |
.readdir = dcache_readdir, |
59af1584b [PATCH] fix ->lls... |
55 |
.llseek = dcache_dir_lseek, |
1da177e4c Linux-2.6.12-rc2 |
56 |
}; |
754661f14 [PATCH] mark stru... |
57 |
const struct inode_operations autofs4_dir_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
58 59 60 61 62 63 |
.lookup = autofs4_lookup, .unlink = autofs4_dir_unlink, .symlink = autofs4_dir_symlink, .mkdir = autofs4_dir_mkdir, .rmdir = autofs4_dir_rmdir, }; |
71e469db2 autofs4: Clean up... |
64 |
const struct dentry_operations autofs4_dentry_operations = { |
71e469db2 autofs4: Clean up... |
65 66 67 68 |
.d_automount = autofs4_d_automount, .d_manage = autofs4_d_manage, .d_release = autofs4_dentry_release, }; |
4f8427d19 autofs4: use help... |
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
static void autofs4_add_active(struct dentry *dentry) { struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); if (ino) { spin_lock(&sbi->lookup_lock); if (!ino->active_count) { if (list_empty(&ino->active)) list_add(&ino->active, &sbi->active_list); } ino->active_count++; spin_unlock(&sbi->lookup_lock); } return; } static void autofs4_del_active(struct dentry *dentry) { struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); if (ino) { spin_lock(&sbi->lookup_lock); ino->active_count--; if (!ino->active_count) { if (!list_empty(&ino->active)) list_del_init(&ino->active); } spin_unlock(&sbi->lookup_lock); } return; } |
1da177e4c Linux-2.6.12-rc2 |
100 101 |
static int autofs4_dir_open(struct inode *inode, struct file *file) { |
a4669ed8e [PATCH] autofs4: ... |
102 |
struct dentry *dentry = file->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
103 |
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
f360ce3be [PATCH] autofs4: ... |
104 |
|
1da177e4c Linux-2.6.12-rc2 |
105 106 107 108 109 |
DPRINTK("file=%p dentry=%p %.*s", file, dentry, dentry->d_name.len, dentry->d_name.name); if (autofs4_oz_mode(sbi)) goto out; |
ff9cd499d autofs4: cleanup ... |
110 111 112 113 114 115 116 117 118 |
/* * An empty directory in an autofs file system is always a * mount point. The daemon must have failed to mount this * during lookup so it doesn't exist. This can happen, for * example, if user space returns an incorrect status for a * mount request. Otherwise we're doing a readdir on the * autofs file system so just let the libfs routines handle * it. */ |
e7854723d autofs4 - remove ... |
119 |
spin_lock(&sbi->lookup_lock); |
2fd6b7f50 fs: dcache scale ... |
120 |
spin_lock(&dentry->d_lock); |
c42c7f7e6 autofs4: eliminat... |
121 |
if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { |
2fd6b7f50 fs: dcache scale ... |
122 |
spin_unlock(&dentry->d_lock); |
e7854723d autofs4 - remove ... |
123 |
spin_unlock(&sbi->lookup_lock); |
ff9cd499d autofs4: cleanup ... |
124 |
return -ENOENT; |
1da177e4c Linux-2.6.12-rc2 |
125 |
} |
2fd6b7f50 fs: dcache scale ... |
126 |
spin_unlock(&dentry->d_lock); |
e7854723d autofs4 - remove ... |
127 |
spin_unlock(&sbi->lookup_lock); |
1da177e4c Linux-2.6.12-rc2 |
128 |
|
1da177e4c Linux-2.6.12-rc2 |
129 |
out: |
ff9cd499d autofs4: cleanup ... |
130 |
return dcache_dir_open(inode, file); |
1da177e4c Linux-2.6.12-rc2 |
131 |
} |
b89b12b46 autofs4: clean ->... |
132 |
static void autofs4_dentry_release(struct dentry *de) |
1da177e4c Linux-2.6.12-rc2 |
133 |
{ |
b89b12b46 autofs4: clean ->... |
134 135 |
struct autofs_info *ino = autofs4_dentry_ino(de); struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); |
1da177e4c Linux-2.6.12-rc2 |
136 137 |
DPRINTK("releasing %p", de); |
b89b12b46 autofs4: clean ->... |
138 139 140 141 142 143 144 145 146 147 |
if (!ino) return; if (sbi) { spin_lock(&sbi->lookup_lock); if (!list_empty(&ino->active)) list_del(&ino->active); if (!list_empty(&ino->expiring)) list_del(&ino->expiring); spin_unlock(&sbi->lookup_lock); |
1da177e4c Linux-2.6.12-rc2 |
148 |
} |
b89b12b46 autofs4: clean ->... |
149 150 |
autofs4_free_ino(ino); |
1da177e4c Linux-2.6.12-rc2 |
151 |
} |
6510c9d85 autofs4: cleanup ... |
152 |
static struct dentry *autofs4_lookup_active(struct dentry *dentry) |
257673787 autofs4: use look... |
153 |
{ |
6510c9d85 autofs4: cleanup ... |
154 155 156 |
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *parent = dentry->d_parent; struct qstr *name = &dentry->d_name; |
257673787 autofs4: use look... |
157 158 159 160 |
unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; struct list_head *p, *head; |
257673787 autofs4: use look... |
161 162 163 164 |
spin_lock(&sbi->lookup_lock); head = &sbi->active_list; list_for_each(p, head) { struct autofs_info *ino; |
e4d5ade7b autofs4: rename d... |
165 |
struct dentry *active; |
257673787 autofs4: use look... |
166 167 168 |
struct qstr *qstr; ino = list_entry(p, struct autofs_info, active); |
e4d5ade7b autofs4: rename d... |
169 |
active = ino->dentry; |
257673787 autofs4: use look... |
170 |
|
e4d5ade7b autofs4: rename d... |
171 |
spin_lock(&active->d_lock); |
257673787 autofs4: use look... |
172 173 |
/* Already gone? */ |
b7ab39f63 fs: dcache scale ... |
174 |
if (active->d_count == 0) |
257673787 autofs4: use look... |
175 |
goto next; |
e4d5ade7b autofs4: rename d... |
176 |
qstr = &active->d_name; |
257673787 autofs4: use look... |
177 |
|
e4d5ade7b autofs4: rename d... |
178 |
if (active->d_name.hash != hash) |
257673787 autofs4: use look... |
179 |
goto next; |
e4d5ade7b autofs4: rename d... |
180 |
if (active->d_parent != parent) |
257673787 autofs4: use look... |
181 182 183 184 185 186 |
goto next; if (qstr->len != len) goto next; if (memcmp(qstr->name, str, len)) goto next; |
4b1ae27a9 Revert "autofs4: ... |
187 |
if (d_unhashed(active)) { |
b7ab39f63 fs: dcache scale ... |
188 |
dget_dlock(active); |
4b1ae27a9 Revert "autofs4: ... |
189 190 |
spin_unlock(&active->d_lock); spin_unlock(&sbi->lookup_lock); |
4b1ae27a9 Revert "autofs4: ... |
191 192 |
return active; } |
257673787 autofs4: use look... |
193 |
next: |
e4d5ade7b autofs4: rename d... |
194 |
spin_unlock(&active->d_lock); |
257673787 autofs4: use look... |
195 196 |
} spin_unlock(&sbi->lookup_lock); |
257673787 autofs4: use look... |
197 198 199 |
return NULL; } |
6510c9d85 autofs4: cleanup ... |
200 |
static struct dentry *autofs4_lookup_expiring(struct dentry *dentry) |
f50b6f869 [PATCH] autofs4: ... |
201 |
{ |
6510c9d85 autofs4: cleanup ... |
202 203 204 |
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *parent = dentry->d_parent; struct qstr *name = &dentry->d_name; |
f50b6f869 [PATCH] autofs4: ... |
205 206 207 208 |
unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; struct list_head *p, *head; |
5f6f4f28b autofs4: don't ma... |
209 210 |
spin_lock(&sbi->lookup_lock); head = &sbi->expiring_list; |
f50b6f869 [PATCH] autofs4: ... |
211 212 |
list_for_each(p, head) { struct autofs_info *ino; |
cb4b492ac autofs4: rename d... |
213 |
struct dentry *expiring; |
f50b6f869 [PATCH] autofs4: ... |
214 |
struct qstr *qstr; |
5f6f4f28b autofs4: don't ma... |
215 |
ino = list_entry(p, struct autofs_info, expiring); |
cb4b492ac autofs4: rename d... |
216 |
expiring = ino->dentry; |
f50b6f869 [PATCH] autofs4: ... |
217 |
|
cb4b492ac autofs4: rename d... |
218 |
spin_lock(&expiring->d_lock); |
f50b6f869 [PATCH] autofs4: ... |
219 220 |
/* Bad luck, we've already been dentry_iput */ |
cb4b492ac autofs4: rename d... |
221 |
if (!expiring->d_inode) |
f50b6f869 [PATCH] autofs4: ... |
222 |
goto next; |
cb4b492ac autofs4: rename d... |
223 |
qstr = &expiring->d_name; |
f50b6f869 [PATCH] autofs4: ... |
224 |
|
cb4b492ac autofs4: rename d... |
225 |
if (expiring->d_name.hash != hash) |
f50b6f869 [PATCH] autofs4: ... |
226 |
goto next; |
cb4b492ac autofs4: rename d... |
227 |
if (expiring->d_parent != parent) |
f50b6f869 [PATCH] autofs4: ... |
228 229 230 231 232 233 |
goto next; if (qstr->len != len) goto next; if (memcmp(qstr->name, str, len)) goto next; |
4b1ae27a9 Revert "autofs4: ... |
234 |
if (d_unhashed(expiring)) { |
b7ab39f63 fs: dcache scale ... |
235 |
dget_dlock(expiring); |
4b1ae27a9 Revert "autofs4: ... |
236 237 |
spin_unlock(&expiring->d_lock); spin_unlock(&sbi->lookup_lock); |
4b1ae27a9 Revert "autofs4: ... |
238 239 |
return expiring; } |
f50b6f869 [PATCH] autofs4: ... |
240 |
next: |
cb4b492ac autofs4: rename d... |
241 |
spin_unlock(&expiring->d_lock); |
f50b6f869 [PATCH] autofs4: ... |
242 |
} |
5f6f4f28b autofs4: don't ma... |
243 |
spin_unlock(&sbi->lookup_lock); |
f50b6f869 [PATCH] autofs4: ... |
244 245 246 |
return NULL; } |
10584211e autofs4: Add d_au... |
247 248 249 250 |
static int autofs4_mount_wait(struct dentry *dentry) { struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); |
3c3199852 autofs4 - reinsta... |
251 |
int status = 0; |
10584211e autofs4: Add d_au... |
252 253 254 255 256 257 |
if (ino->flags & AUTOFS_INF_PENDING) { DPRINTK("waiting for mount name=%.*s", dentry->d_name.len, dentry->d_name.name); status = autofs4_wait(sbi, dentry, NFY_MOUNT); DPRINTK("mount wait done status=%d", status); |
10584211e autofs4: Add d_au... |
258 |
} |
3c3199852 autofs4 - reinsta... |
259 260 |
ino->last_used = jiffies; return status; |
10584211e autofs4: Add d_au... |
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
} static int do_expire_wait(struct dentry *dentry) { struct dentry *expiring; expiring = autofs4_lookup_expiring(dentry); if (!expiring) return autofs4_expire_wait(dentry); else { /* * If we are racing with expire the request might not * be quite complete, but the directory has been removed * so it must have been successful, just wait for it. */ autofs4_expire_wait(expiring); autofs4_del_expiring(expiring); dput(expiring); } return 0; } static struct dentry *autofs4_mountpoint_changed(struct path *path) { struct dentry *dentry = path->dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); /* * If this is an indirect mount the dentry could have gone away * as a result of an expire and a new one created. */ if (autofs_type_indirect(sbi->type) && d_unhashed(dentry)) { struct dentry *parent = dentry->d_parent; |
3c3199852 autofs4 - reinsta... |
294 |
struct autofs_info *ino; |
10584211e autofs4: Add d_au... |
295 296 297 |
struct dentry *new = d_lookup(parent, &dentry->d_name); if (!new) return NULL; |
3c3199852 autofs4 - reinsta... |
298 299 |
ino = autofs4_dentry_ino(new); ino->last_used = jiffies; |
10584211e autofs4: Add d_au... |
300 301 302 303 304 |
dput(path->dentry); path->dentry = new; } return path->dentry; } |
71e469db2 autofs4: Clean up... |
305 |
static struct vfsmount *autofs4_d_automount(struct path *path) |
10584211e autofs4: Add d_au... |
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
{ struct dentry *dentry = path->dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); int status; DPRINTK("dentry=%p %.*s", dentry, dentry->d_name.len, dentry->d_name.name); /* The daemon never triggers a mount. */ if (autofs4_oz_mode(sbi)) return NULL; /* * If an expire request is pending everyone must wait. * If the expire fails we're still mounted so continue * the follow and return. A return of -EAGAIN (which only * happens with indirect mounts) means the expire completed * and the directory was removed, so just go ahead and try * the mount. */ status = do_expire_wait(dentry); if (status && status != -EAGAIN) return NULL; /* Callback to the daemon to perform the mount or wait */ spin_lock(&sbi->fs_lock); if (ino->flags & AUTOFS_INF_PENDING) { spin_unlock(&sbi->fs_lock); status = autofs4_mount_wait(dentry); if (status) return ERR_PTR(status); spin_lock(&sbi->fs_lock); goto done; } /* * If the dentry is a symlink it's equivalent to a directory |
b5b801779 autofs4: Add d_ma... |
344 |
* having d_mountpoint() true, so there's no need to call back |
10584211e autofs4: Add d_au... |
345 346 347 348 |
* to the daemon. */ if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) goto done; |
b5b801779 autofs4: Add d_ma... |
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
if (!d_mountpoint(dentry)) { /* * It's possible that user space hasn't removed directories * after umounting a rootless multi-mount, although it * should. For v5 have_submounts() is sufficient to handle * this because the leaves of the directory tree under the * mount never trigger mounts themselves (they have an autofs * trigger mount mounted on them). But v4 pseudo direct mounts * do need the leaves to to trigger mounts. In this case we * have no choice but to use the list_empty() check and * require user space behave. */ if (sbi->version > 4) { if (have_submounts(dentry)) goto done; } else { spin_lock(&dentry->d_lock); if (!list_empty(&dentry->d_subdirs)) { spin_unlock(&dentry->d_lock); goto done; } spin_unlock(&dentry->d_lock); } |
10584211e autofs4: Add d_au... |
372 |
ino->flags |= AUTOFS_INF_PENDING; |
10584211e autofs4: Add d_au... |
373 374 375 376 377 378 |
spin_unlock(&sbi->fs_lock); status = autofs4_mount_wait(dentry); if (status) return ERR_PTR(status); spin_lock(&sbi->fs_lock); ino->flags &= ~AUTOFS_INF_PENDING; |
10584211e autofs4: Add d_au... |
379 |
} |
10584211e autofs4: Add d_au... |
380 |
done: |
b5b801779 autofs4: Add d_ma... |
381 382 |
if (!(ino->flags & AUTOFS_INF_EXPIRING)) { /* |
3c3199852 autofs4 - reinsta... |
383 384 385 386 387 |
* Any needed mounting has been completed and the path * updated so clear DCACHE_NEED_AUTOMOUNT so we don't * call ->d_automount() on rootless multi-mounts since * it can lead to an incorrect ELOOP error return. * |
b5b801779 autofs4: Add d_ma... |
388 389 390 391 392 |
* Only clear DMANAGED_AUTOMOUNT for rootless multi-mounts and * symlinks as in all other cases the dentry will be covered by * an actual mount so ->d_automount() won't be called during * the follow. */ |
3c3199852 autofs4 - reinsta... |
393 |
spin_lock(&dentry->d_lock); |
b5b801779 autofs4: Add d_ma... |
394 395 396 397 398 399 |
if ((!d_mountpoint(dentry) && !list_empty(&dentry->d_subdirs)) || (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode))) __managed_dentry_clear_automount(dentry); spin_unlock(&dentry->d_lock); } |
10584211e autofs4: Add d_au... |
400 401 402 403 404 405 406 407 408 |
spin_unlock(&sbi->fs_lock); /* Mount succeeded, check if we ended up with a new dentry */ dentry = autofs4_mountpoint_changed(path); if (!dentry) return ERR_PTR(-ENOENT); return NULL; } |
1aed3e420 lose 'mounting_he... |
409 |
int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) |
b5b801779 autofs4: Add d_ma... |
410 411 412 413 414 415 416 |
{ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); DPRINTK("dentry=%p %.*s", dentry, dentry->d_name.len, dentry->d_name.name); /* The daemon never waits. */ |
1aed3e420 lose 'mounting_he... |
417 |
if (autofs4_oz_mode(sbi)) { |
83fb96bfc autofs4 - fix d_m... |
418 419 |
if (rcu_walk) return 0; |
b5b801779 autofs4: Add d_ma... |
420 421 422 423 |
if (!d_mountpoint(dentry)) return -EISDIR; return 0; } |
ab90911ff Allow d_manage() ... |
424 425 426 |
/* We need to sleep, so we need pathwalk to be in ref-mode */ if (rcu_walk) return -ECHILD; |
b5b801779 autofs4: Add d_ma... |
427 428 429 430 431 432 433 434 435 |
/* Wait for pending expires */ do_expire_wait(dentry); /* * This dentry may be under construction so wait on mount * completion. */ return autofs4_mount_wait(dentry); } |
1da177e4c Linux-2.6.12-rc2 |
436 437 438 439 |
/* Lookups in the root directory */ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct autofs_sb_info *sbi; |
257673787 autofs4: use look... |
440 |
struct autofs_info *ino; |
10584211e autofs4: Add d_au... |
441 |
struct dentry *active; |
1da177e4c Linux-2.6.12-rc2 |
442 |
|
10584211e autofs4: Add d_au... |
443 |
DPRINTK("name = %.*s", dentry->d_name.len, dentry->d_name.name); |
1da177e4c Linux-2.6.12-rc2 |
444 |
|
718c604a2 [PATCH] autofs4: ... |
445 |
/* File name too long to exist */ |
1da177e4c Linux-2.6.12-rc2 |
446 |
if (dentry->d_name.len > NAME_MAX) |
718c604a2 [PATCH] autofs4: ... |
447 |
return ERR_PTR(-ENAMETOOLONG); |
1da177e4c Linux-2.6.12-rc2 |
448 449 |
sbi = autofs4_sbi(dir->i_sb); |
718c604a2 [PATCH] autofs4: ... |
450 |
|
1da177e4c Linux-2.6.12-rc2 |
451 |
DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
c0bcc9d55 autofs4 - fix deb... |
452 453 |
current->pid, task_pgrp_nr(current), sbi->catatonic, autofs4_oz_mode(sbi)); |
1da177e4c Linux-2.6.12-rc2 |
454 |
|
6510c9d85 autofs4: cleanup ... |
455 |
active = autofs4_lookup_active(dentry); |
90387c9c1 autofs4: renamer ... |
456 |
if (active) { |
10584211e autofs4: Add d_au... |
457 |
return active; |
aa952eb26 autofs4: use auto... |
458 |
} else { |
4b1ae27a9 Revert "autofs4: ... |
459 |
/* |
10584211e autofs4: Add d_au... |
460 461 462 463 |
* A dentry that is not within the root can never trigger a * mount operation, unless the directory already exists, so we * can return fail immediately. The daemon however does need * to create directories within the file system. |
4b1ae27a9 Revert "autofs4: ... |
464 |
*/ |
10584211e autofs4: Add d_au... |
465 466 467 468 |
if (!autofs4_oz_mode(sbi) && !IS_ROOT(dentry->d_parent)) return ERR_PTR(-ENOENT); /* Mark entries in the root as mount triggers */ |
b650c858c autofs4: Merge th... |
469 |
if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) |
b5b801779 autofs4: Add d_ma... |
470 |
__managed_dentry_set_managed(dentry); |
10584211e autofs4: Add d_au... |
471 |
|
26e6c9106 autofs4: split au... |
472 |
ino = autofs4_new_ino(sbi); |
4b1ae27a9 Revert "autofs4: ... |
473 474 475 476 477 |
if (!ino) return ERR_PTR(-ENOMEM); dentry->d_fsdata = ino; ino->dentry = dentry; |
5f6f4f28b autofs4: don't ma... |
478 |
|
4b1ae27a9 Revert "autofs4: ... |
479 480 481 482 |
autofs4_add_active(dentry); d_instantiate(dentry, NULL); } |
1da177e4c Linux-2.6.12-rc2 |
483 484 485 486 487 488 489 490 491 |
return NULL; } static int autofs4_dir_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); |
1aff3c8b0 [PATCH] autofs4: ... |
492 |
struct autofs_info *p_ino; |
1da177e4c Linux-2.6.12-rc2 |
493 |
struct inode *inode; |
0bf71d4d0 autofs4: kill ->s... |
494 |
size_t size = strlen(symname); |
1da177e4c Linux-2.6.12-rc2 |
495 496 497 498 499 500 501 |
char *cp; DPRINTK("%s <- %.*s", symname, dentry->d_name.len, dentry->d_name.name); if (!autofs4_oz_mode(sbi)) return -EACCES; |
5a37db302 autofs4: mkdir an... |
502 |
BUG_ON(!ino); |
26e6c9106 autofs4: split au... |
503 |
autofs4_clean_ino(ino); |
1da177e4c Linux-2.6.12-rc2 |
504 |
|
4b1ae27a9 Revert "autofs4: ... |
505 |
autofs4_del_active(dentry); |
0bf71d4d0 autofs4: kill ->s... |
506 |
cp = kmalloc(size + 1, GFP_KERNEL); |
5a37db302 autofs4: mkdir an... |
507 |
if (!cp) |
257673787 autofs4: use look... |
508 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
509 510 |
strcpy(cp, symname); |
726a5e068 autofs4: autofs4_... |
511 |
inode = autofs4_get_inode(dir->i_sb, S_IFLNK | 0555); |
257673787 autofs4: use look... |
512 513 514 515 516 517 |
if (!inode) { kfree(cp); if (!dentry->d_fsdata) kfree(ino); return -ENOMEM; } |
292c5ee80 autofs4: keep sym... |
518 |
inode->i_private = cp; |
0bf71d4d0 autofs4: kill ->s... |
519 |
inode->i_size = size; |
1864f7bd5 autofs4: deadlock... |
520 |
d_add(dentry, inode); |
1da177e4c Linux-2.6.12-rc2 |
521 |
|
5a37db302 autofs4: mkdir an... |
522 |
dget(dentry); |
1aff3c8b0 [PATCH] autofs4: ... |
523 524 525 526 |
atomic_inc(&ino->count); p_ino = autofs4_dentry_ino(dentry->d_parent); if (p_ino && dentry->d_parent != dentry) atomic_inc(&p_ino->count); |
1da177e4c Linux-2.6.12-rc2 |
527 528 529 530 531 532 533 534 535 536 537 538 |
dir->i_mtime = CURRENT_TIME; return 0; } /* * NOTE! * * Normal filesystems would do a "d_delete()" to tell the VFS dcache * that the file no longer exists. However, doing that means that the * VFS layer can turn the dentry into a negative dentry. We don't want |
f50b6f869 [PATCH] autofs4: ... |
539 |
* this, because the unlink is probably the result of an expire. |
5f6f4f28b autofs4: don't ma... |
540 541 |
* We simply d_drop it and add it to a expiring list in the super block, * which allows the dentry lookup to check for an incomplete expire. |
1da177e4c Linux-2.6.12-rc2 |
542 543 544 545 546 547 548 549 550 551 |
* * If a process is blocked on the dentry waiting for the expire to finish, * it will invalidate the dentry and try to mount with a new one. * * Also see autofs4_dir_rmdir().. */ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) { struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); |
1aff3c8b0 [PATCH] autofs4: ... |
552 |
struct autofs_info *p_ino; |
1da177e4c Linux-2.6.12-rc2 |
553 554 |
/* This allows root to remove symlinks */ |
d78e53c89 Fix some coding-s... |
555 |
if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) |
1da177e4c Linux-2.6.12-rc2 |
556 |
return -EACCES; |
1aff3c8b0 [PATCH] autofs4: ... |
557 558 559 560 561 |
if (atomic_dec_and_test(&ino->count)) { p_ino = autofs4_dentry_ino(dentry->d_parent); if (p_ino && dentry->d_parent != dentry) atomic_dec(&p_ino->count); } |
1da177e4c Linux-2.6.12-rc2 |
562 563 564 |
dput(ino->dentry); dentry->d_inode->i_size = 0; |
ce71ec368 [PATCH] r/o bind ... |
565 |
clear_nlink(dentry->d_inode); |
1da177e4c Linux-2.6.12-rc2 |
566 567 |
dir->i_mtime = CURRENT_TIME; |
e7854723d autofs4 - remove ... |
568 569 |
spin_lock(&sbi->lookup_lock); __autofs4_add_expiring(dentry); |
f50b6f869 [PATCH] autofs4: ... |
570 571 572 |
spin_lock(&dentry->d_lock); __d_drop(dentry); spin_unlock(&dentry->d_lock); |
e7854723d autofs4 - remove ... |
573 |
spin_unlock(&sbi->lookup_lock); |
1da177e4c Linux-2.6.12-rc2 |
574 575 576 |
return 0; } |
dd89f90d2 autofs4: Add v4 p... |
577 578 579 580 581 582 583 |
/* * Version 4 of autofs provides a pseudo direct mount implementation * that relies on directories at the leaves of a directory tree under * an indirect mount to trigger mounts. To allow for this we need to * set the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags on the leaves * of the directory tree. There is no need to clear the automount flag * following a mount or restore it after an expire because these mounts |
25985edce Fix common misspe... |
584 |
* are always covered. However, it is necessary to ensure that these |
dd89f90d2 autofs4: Add v4 p... |
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
* flags are clear on non-empty directories to avoid unnecessary calls * during path walks. */ static void autofs_set_leaf_automount_flags(struct dentry *dentry) { struct dentry *parent; /* root and dentrys in the root are already handled */ if (IS_ROOT(dentry->d_parent)) return; managed_dentry_set_managed(dentry); parent = dentry->d_parent; /* only consider parents below dentrys in the root */ if (IS_ROOT(parent->d_parent)) return; managed_dentry_clear_managed(parent); return; } static void autofs_clear_leaf_automount_flags(struct dentry *dentry) { struct list_head *d_child; struct dentry *parent; /* flags for dentrys in the root are handled elsewhere */ if (IS_ROOT(dentry->d_parent)) return; managed_dentry_clear_managed(dentry); parent = dentry->d_parent; /* only consider parents below dentrys in the root */ if (IS_ROOT(parent->d_parent)) return; d_child = &dentry->d_u.d_child; /* Set parent managed if it's becoming empty */ if (d_child->next == &parent->d_subdirs && d_child->prev == &parent->d_subdirs) managed_dentry_set_managed(parent); return; } |
1da177e4c Linux-2.6.12-rc2 |
628 629 630 631 |
static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) { struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); |
1aff3c8b0 [PATCH] autofs4: ... |
632 |
struct autofs_info *p_ino; |
1da177e4c Linux-2.6.12-rc2 |
633 |
|
f50b6f869 [PATCH] autofs4: ... |
634 635 |
DPRINTK("dentry %p, removing %.*s", dentry, dentry->d_name.len, dentry->d_name.name); |
1da177e4c Linux-2.6.12-rc2 |
636 637 |
if (!autofs4_oz_mode(sbi)) return -EACCES; |
2fd6b7f50 fs: dcache scale ... |
638 639 |
spin_lock(&sbi->lookup_lock); spin_lock(&dentry->d_lock); |
1da177e4c Linux-2.6.12-rc2 |
640 |
if (!list_empty(&dentry->d_subdirs)) { |
2fd6b7f50 fs: dcache scale ... |
641 642 |
spin_unlock(&dentry->d_lock); spin_unlock(&sbi->lookup_lock); |
1da177e4c Linux-2.6.12-rc2 |
643 644 |
return -ENOTEMPTY; } |
2fd6b7f50 fs: dcache scale ... |
645 |
__autofs4_add_expiring(dentry); |
1da177e4c Linux-2.6.12-rc2 |
646 647 |
__d_drop(dentry); spin_unlock(&dentry->d_lock); |
e7854723d autofs4 - remove ... |
648 |
spin_unlock(&sbi->lookup_lock); |
1da177e4c Linux-2.6.12-rc2 |
649 |
|
dd89f90d2 autofs4: Add v4 p... |
650 651 |
if (sbi->version < 5) autofs_clear_leaf_automount_flags(dentry); |
1aff3c8b0 [PATCH] autofs4: ... |
652 653 654 655 656 |
if (atomic_dec_and_test(&ino->count)) { p_ino = autofs4_dentry_ino(dentry->d_parent); if (p_ino && dentry->d_parent != dentry) atomic_dec(&p_ino->count); } |
1da177e4c Linux-2.6.12-rc2 |
657 |
dput(ino->dentry); |
1da177e4c Linux-2.6.12-rc2 |
658 |
dentry->d_inode->i_size = 0; |
ce71ec368 [PATCH] r/o bind ... |
659 |
clear_nlink(dentry->d_inode); |
1da177e4c Linux-2.6.12-rc2 |
660 661 |
if (dir->i_nlink) |
9a53c3a78 [PATCH] r/o bind ... |
662 |
drop_nlink(dir); |
1da177e4c Linux-2.6.12-rc2 |
663 664 665 |
return 0; } |
18bb1db3e switch vfs_mkdir(... |
666 |
static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
667 668 669 |
{ struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); |
1aff3c8b0 [PATCH] autofs4: ... |
670 |
struct autofs_info *p_ino; |
1da177e4c Linux-2.6.12-rc2 |
671 |
struct inode *inode; |
d78e53c89 Fix some coding-s... |
672 |
if (!autofs4_oz_mode(sbi)) |
1da177e4c Linux-2.6.12-rc2 |
673 674 675 676 |
return -EACCES; DPRINTK("dentry %p, creating %.*s", dentry, dentry->d_name.len, dentry->d_name.name); |
5a37db302 autofs4: mkdir an... |
677 |
BUG_ON(!ino); |
26e6c9106 autofs4: split au... |
678 |
autofs4_clean_ino(ino); |
257673787 autofs4: use look... |
679 |
|
4b1ae27a9 Revert "autofs4: ... |
680 |
autofs4_del_active(dentry); |
726a5e068 autofs4: autofs4_... |
681 |
inode = autofs4_get_inode(dir->i_sb, S_IFDIR | 0555); |
5a37db302 autofs4: mkdir an... |
682 |
if (!inode) |
257673787 autofs4: use look... |
683 |
return -ENOMEM; |
1864f7bd5 autofs4: deadlock... |
684 |
d_add(dentry, inode); |
1da177e4c Linux-2.6.12-rc2 |
685 |
|
dd89f90d2 autofs4: Add v4 p... |
686 687 |
if (sbi->version < 5) autofs_set_leaf_automount_flags(dentry); |
5a37db302 autofs4: mkdir an... |
688 |
dget(dentry); |
1aff3c8b0 [PATCH] autofs4: ... |
689 690 691 692 |
atomic_inc(&ino->count); p_ino = autofs4_dentry_ino(dentry->d_parent); if (p_ino && dentry->d_parent != dentry) atomic_inc(&p_ino->count); |
d8c76e6f4 [PATCH] r/o bind ... |
693 |
inc_nlink(dir); |
1da177e4c Linux-2.6.12-rc2 |
694 695 696 697 698 699 |
dir->i_mtime = CURRENT_TIME; return 0; } /* Get/set timeout ioctl() operation */ |
c9243f5bd autofs/autofs4: M... |
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 |
#ifdef CONFIG_COMPAT static inline int autofs4_compat_get_set_timeout(struct autofs_sb_info *sbi, compat_ulong_t __user *p) { int rv; unsigned long ntimeout; if ((rv = get_user(ntimeout, p)) || (rv = put_user(sbi->exp_timeout/HZ, p))) return rv; if (ntimeout > UINT_MAX/HZ) sbi->exp_timeout = 0; else sbi->exp_timeout = ntimeout * HZ; return 0; } #endif |
1da177e4c Linux-2.6.12-rc2 |
719 720 721 722 723 |
static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi, unsigned long __user *p) { int rv; unsigned long ntimeout; |
d78e53c89 Fix some coding-s... |
724 725 |
if ((rv = get_user(ntimeout, p)) || (rv = put_user(sbi->exp_timeout/HZ, p))) |
1da177e4c Linux-2.6.12-rc2 |
726 |
return rv; |
d78e53c89 Fix some coding-s... |
727 |
if (ntimeout > ULONG_MAX/HZ) |
1da177e4c Linux-2.6.12-rc2 |
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 |
sbi->exp_timeout = 0; else sbi->exp_timeout = ntimeout * HZ; return 0; } /* Return protocol version */ static inline int autofs4_get_protover(struct autofs_sb_info *sbi, int __user *p) { return put_user(sbi->version, p); } /* Return protocol sub version */ static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi, int __user *p) { return put_user(sbi->sub_version, p); } /* |
1da177e4c Linux-2.6.12-rc2 |
748 749 750 751 752 |
* Tells the daemon whether it can umount the autofs mount. */ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p) { int status = 0; |
e3474a8eb [PATCH] autofs4: ... |
753 |
if (may_umount(mnt)) |
1da177e4c Linux-2.6.12-rc2 |
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 |
status = 1; DPRINTK("returning %d", status); status = put_user(status, p); return status; } /* Identify autofs4_dentries - this is so we can tell if there's an extra dentry refcount or not. We only hold a refcount on the dentry if its non-negative (ie, d_inode != NULL) */ int is_autofs4_dentry(struct dentry *dentry) { return dentry && dentry->d_inode && |
b650c858c autofs4: Merge th... |
770 |
dentry->d_op == &autofs4_dentry_operations && |
1da177e4c Linux-2.6.12-rc2 |
771 772 773 774 775 776 777 |
dentry->d_fsdata != NULL; } /* * ioctl()'s on the root directory is the chief method for the daemon to * generate kernel reactions */ |
3663df70c autofs4: Pushdown... |
778 779 |
static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
780 781 782 783 784 |
{ struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb); void __user *p = (void __user *)arg; DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u", |
a47afb0f9 pid namespaces: r... |
785 |
cmd,arg,sbi,task_pgrp_nr(current)); |
1da177e4c Linux-2.6.12-rc2 |
786 |
|
d78e53c89 Fix some coding-s... |
787 788 |
if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) |
1da177e4c Linux-2.6.12-rc2 |
789 790 |
return -ENOTTY; |
d78e53c89 Fix some coding-s... |
791 |
if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) |
1da177e4c Linux-2.6.12-rc2 |
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 |
return -EPERM; switch(cmd) { case AUTOFS_IOC_READY: /* Wait queue: go ahead and retry */ return autofs4_wait_release(sbi,(autofs_wqt_t)arg,0); case AUTOFS_IOC_FAIL: /* Wait queue: fail with ENOENT */ return autofs4_wait_release(sbi,(autofs_wqt_t)arg,-ENOENT); case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */ autofs4_catatonic_mode(sbi); return 0; case AUTOFS_IOC_PROTOVER: /* Get protocol version */ return autofs4_get_protover(sbi, p); case AUTOFS_IOC_PROTOSUBVER: /* Get protocol sub version */ return autofs4_get_protosubver(sbi, p); case AUTOFS_IOC_SETTIMEOUT: return autofs4_get_set_timeout(sbi, p); |
c9243f5bd autofs/autofs4: M... |
808 809 810 811 |
#ifdef CONFIG_COMPAT case AUTOFS_IOC_SETTIMEOUT32: return autofs4_compat_get_set_timeout(sbi, p); #endif |
1da177e4c Linux-2.6.12-rc2 |
812 |
|
1da177e4c Linux-2.6.12-rc2 |
813 |
case AUTOFS_IOC_ASKUMOUNT: |
a4669ed8e [PATCH] autofs4: ... |
814 |
return autofs4_ask_umount(filp->f_path.mnt, p); |
1da177e4c Linux-2.6.12-rc2 |
815 816 817 |
/* return a single thing to expire */ case AUTOFS_IOC_EXPIRE: |
a4669ed8e [PATCH] autofs4: ... |
818 |
return autofs4_expire_run(inode->i_sb,filp->f_path.mnt,sbi, p); |
1da177e4c Linux-2.6.12-rc2 |
819 820 |
/* same as above, but can send multiple expires through pipe */ case AUTOFS_IOC_EXPIRE_MULTI: |
a4669ed8e [PATCH] autofs4: ... |
821 |
return autofs4_expire_multi(inode->i_sb,filp->f_path.mnt,sbi, p); |
1da177e4c Linux-2.6.12-rc2 |
822 823 824 825 826 |
default: return -ENOSYS; } } |
3663df70c autofs4: Pushdown... |
827 828 829 830 |
static long autofs4_root_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { |
3663df70c autofs4: Pushdown... |
831 |
struct inode *inode = filp->f_dentry->d_inode; |
de47de740 autofs4 - remove ... |
832 |
return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); |
3663df70c autofs4: Pushdown... |
833 |
} |
c9243f5bd autofs/autofs4: M... |
834 835 836 837 838 839 840 |
#ifdef CONFIG_COMPAT static long autofs4_root_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = filp->f_path.dentry->d_inode; int ret; |
c9243f5bd autofs/autofs4: M... |
841 842 843 844 845 |
if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); else ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, (unsigned long)compat_ptr(arg)); |
c9243f5bd autofs/autofs4: M... |
846 847 848 849 |
return ret; } #endif |