aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/autofs4/autofs_i.h14
-rw-r--r--fs/autofs4/expire.c4
-rw-r--r--fs/autofs4/inode.c88
-rw-r--r--fs/autofs4/root.c74
-rw-r--r--fs/autofs4/symlink.c3
-rw-r--r--fs/namei.c4
6 files changed, 66 insertions, 121 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 1f016bfb42d5..54f923792728 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -88,14 +88,6 @@ struct autofs_info {
88 88
89 uid_t uid; 89 uid_t uid;
90 gid_t gid; 90 gid_t gid;
91
92 mode_t mode;
93 size_t size;
94
95 void (*free)(struct autofs_info *);
96 union {
97 const char *symlink;
98 } u;
99}; 91};
100 92
101#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ 93#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
@@ -175,7 +167,7 @@ static inline int autofs4_ispending(struct dentry *dentry)
175 return 0; 167 return 0;
176} 168}
177 169
178struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *); 170struct inode *autofs4_get_inode(struct super_block *, mode_t);
179void autofs4_free_ino(struct autofs_info *); 171void autofs4_free_ino(struct autofs_info *);
180 172
181/* Expiration */ 173/* Expiration */
@@ -285,7 +277,8 @@ static inline void managed_dentry_clear_managed(struct dentry *dentry)
285/* Initializing function */ 277/* Initializing function */
286 278
287int autofs4_fill_super(struct super_block *, void *, int); 279int autofs4_fill_super(struct super_block *, void *, int);
288struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info *sbi, mode_t mode); 280struct autofs_info *autofs4_new_ino(struct autofs_sb_info *);
281void autofs4_clean_ino(struct autofs_info *);
289 282
290/* Queue management functions */ 283/* Queue management functions */
291 284
@@ -345,5 +338,4 @@ static inline void autofs4_del_expiring(struct dentry *dentry)
345 return; 338 return;
346} 339}
347 340
348void autofs4_dentry_release(struct dentry *);
349extern void autofs4_kill_sb(struct super_block *); 341extern void autofs4_kill_sb(struct super_block *);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 3ed79d76c233..f43100b9662b 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -96,7 +96,7 @@ static struct dentry *get_next_positive_dentry(struct dentry *prev,
96 struct dentry *p, *ret; 96 struct dentry *p, *ret;
97 97
98 if (prev == NULL) 98 if (prev == NULL)
99 return dget(prev); 99 return dget(root);
100 100
101 spin_lock(&autofs4_lock); 101 spin_lock(&autofs4_lock);
102relock: 102relock:
@@ -133,7 +133,7 @@ again:
133 spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED); 133 spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
134 /* Negative dentry - try next */ 134 /* Negative dentry - try next */
135 if (!simple_positive(ret)) { 135 if (!simple_positive(ret)) {
136 spin_unlock(&ret->d_lock); 136 spin_unlock(&p->d_lock);
137 p = ret; 137 p = ret;
138 goto again; 138 goto again;
139 } 139 }
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 9e1a9dad23e1..180fa2425e49 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -22,65 +22,27 @@
22#include "autofs_i.h" 22#include "autofs_i.h"
23#include <linux/module.h> 23#include <linux/module.h>
24 24
25static void ino_lnkfree(struct autofs_info *ino) 25struct autofs_info *autofs4_new_ino(struct autofs_sb_info *sbi)
26{ 26{
27 if (ino->u.symlink) { 27 struct autofs_info *ino = kzalloc(sizeof(*ino), GFP_KERNEL);
28 kfree(ino->u.symlink); 28 if (ino) {
29 ino->u.symlink = NULL;
30 }
31}
32
33struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
34 struct autofs_sb_info *sbi, mode_t mode)
35{
36 int reinit = 1;
37
38 if (ino == NULL) {
39 reinit = 0;
40 ino = kmalloc(sizeof(*ino), GFP_KERNEL);
41 }
42
43 if (ino == NULL)
44 return NULL;
45
46 if (!reinit) {
47 ino->flags = 0;
48 ino->dentry = NULL;
49 ino->size = 0;
50 INIT_LIST_HEAD(&ino->active); 29 INIT_LIST_HEAD(&ino->active);
51 ino->active_count = 0;
52 INIT_LIST_HEAD(&ino->expiring); 30 INIT_LIST_HEAD(&ino->expiring);
53 atomic_set(&ino->count, 0); 31 ino->last_used = jiffies;
32 ino->sbi = sbi;
54 } 33 }
34 return ino;
35}
55 36
37void autofs4_clean_ino(struct autofs_info *ino)
38{
56 ino->uid = 0; 39 ino->uid = 0;
57 ino->gid = 0; 40 ino->gid = 0;
58 ino->mode = mode;
59 ino->last_used = jiffies; 41 ino->last_used = jiffies;
60
61 ino->sbi = sbi;
62
63 if (reinit && ino->free)
64 (ino->free)(ino);
65
66 memset(&ino->u, 0, sizeof(ino->u));
67
68 ino->free = NULL;
69
70 if (S_ISLNK(mode))
71 ino->free = ino_lnkfree;
72
73 return ino;
74} 42}
75 43
76void autofs4_free_ino(struct autofs_info *ino) 44void autofs4_free_ino(struct autofs_info *ino)
77{ 45{
78 if (ino->dentry) {
79 ino->dentry->d_fsdata = NULL;
80 ino->dentry = NULL;
81 }
82 if (ino->free)
83 (ino->free)(ino);
84 kfree(ino); 46 kfree(ino);
85} 47}
86 48
@@ -136,9 +98,16 @@ static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
136 return 0; 98 return 0;
137} 99}
138 100
101static void autofs4_evict_inode(struct inode *inode)
102{
103 end_writeback(inode);
104 kfree(inode->i_private);
105}
106
139static const struct super_operations autofs4_sops = { 107static const struct super_operations autofs4_sops = {
140 .statfs = simple_statfs, 108 .statfs = simple_statfs,
141 .show_options = autofs4_show_options, 109 .show_options = autofs4_show_options,
110 .evict_inode = autofs4_evict_inode,
142}; 111};
143 112
144enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto, 113enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto,
@@ -228,17 +197,6 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
228 return (*pipefd < 0); 197 return (*pipefd < 0);
229} 198}
230 199
231static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi)
232{
233 struct autofs_info *ino;
234
235 ino = autofs4_init_ino(NULL, sbi, S_IFDIR | 0755);
236 if (!ino)
237 return NULL;
238
239 return ino;
240}
241
242int autofs4_fill_super(struct super_block *s, void *data, int silent) 200int autofs4_fill_super(struct super_block *s, void *data, int silent)
243{ 201{
244 struct inode * root_inode; 202 struct inode * root_inode;
@@ -282,10 +240,10 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
282 /* 240 /*
283 * Get the root inode and dentry, but defer checking for errors. 241 * Get the root inode and dentry, but defer checking for errors.
284 */ 242 */
285 ino = autofs4_mkroot(sbi); 243 ino = autofs4_new_ino(sbi);
286 if (!ino) 244 if (!ino)
287 goto fail_free; 245 goto fail_free;
288 root_inode = autofs4_get_inode(s, ino); 246 root_inode = autofs4_get_inode(s, S_IFDIR | 0755);
289 if (!root_inode) 247 if (!root_inode)
290 goto fail_ino; 248 goto fail_ino;
291 249
@@ -368,15 +326,14 @@ fail_unlock:
368 return -EINVAL; 326 return -EINVAL;
369} 327}
370 328
371struct inode *autofs4_get_inode(struct super_block *sb, 329struct inode *autofs4_get_inode(struct super_block *sb, mode_t mode)
372 struct autofs_info *inf)
373{ 330{
374 struct inode *inode = new_inode(sb); 331 struct inode *inode = new_inode(sb);
375 332
376 if (inode == NULL) 333 if (inode == NULL)
377 return NULL; 334 return NULL;
378 335
379 inode->i_mode = inf->mode; 336 inode->i_mode = mode;
380 if (sb->s_root) { 337 if (sb->s_root) {
381 inode->i_uid = sb->s_root->d_inode->i_uid; 338 inode->i_uid = sb->s_root->d_inode->i_uid;
382 inode->i_gid = sb->s_root->d_inode->i_gid; 339 inode->i_gid = sb->s_root->d_inode->i_gid;
@@ -384,12 +341,11 @@ struct inode *autofs4_get_inode(struct super_block *sb,
384 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 341 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
385 inode->i_ino = get_next_ino(); 342 inode->i_ino = get_next_ino();
386 343
387 if (S_ISDIR(inf->mode)) { 344 if (S_ISDIR(mode)) {
388 inode->i_nlink = 2; 345 inode->i_nlink = 2;
389 inode->i_op = &autofs4_dir_inode_operations; 346 inode->i_op = &autofs4_dir_inode_operations;
390 inode->i_fop = &autofs4_dir_operations; 347 inode->i_fop = &autofs4_dir_operations;
391 } else if (S_ISLNK(inf->mode)) { 348 } else if (S_ISLNK(mode)) {
392 inode->i_size = inf->size;
393 inode->i_op = &autofs4_symlink_inode_operations; 349 inode->i_op = &autofs4_symlink_inode_operations;
394 } 350 }
395 351
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 1dba035fc376..014e7aba3b08 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -37,6 +37,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file);
37static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); 37static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
38static struct vfsmount *autofs4_d_automount(struct path *); 38static struct vfsmount *autofs4_d_automount(struct path *);
39static int autofs4_d_manage(struct dentry *, bool, bool); 39static int autofs4_d_manage(struct dentry *, bool, bool);
40static void autofs4_dentry_release(struct dentry *);
40 41
41const struct file_operations autofs4_root_operations = { 42const struct file_operations autofs4_root_operations = {
42 .open = dcache_dir_open, 43 .open = dcache_dir_open,
@@ -138,25 +139,26 @@ out:
138 return dcache_dir_open(inode, file); 139 return dcache_dir_open(inode, file);
139} 140}
140 141
141void autofs4_dentry_release(struct dentry *de) 142static void autofs4_dentry_release(struct dentry *de)
142{ 143{
143 struct autofs_info *inf; 144 struct autofs_info *ino = autofs4_dentry_ino(de);
145 struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb);
144 146
145 DPRINTK("releasing %p", de); 147 DPRINTK("releasing %p", de);
146 148
147 inf = autofs4_dentry_ino(de); 149 if (!ino)
148 if (inf) { 150 return;
149 struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); 151
150 if (sbi) { 152 if (sbi) {
151 spin_lock(&sbi->lookup_lock); 153 spin_lock(&sbi->lookup_lock);
152 if (!list_empty(&inf->active)) 154 if (!list_empty(&ino->active))
153 list_del(&inf->active); 155 list_del(&ino->active);
154 if (!list_empty(&inf->expiring)) 156 if (!list_empty(&ino->expiring))
155 list_del(&inf->expiring); 157 list_del(&ino->expiring);
156 spin_unlock(&sbi->lookup_lock); 158 spin_unlock(&sbi->lookup_lock);
157 }
158 autofs4_free_ino(inf);
159 } 159 }
160
161 autofs4_free_ino(ino);
160} 162}
161 163
162static struct dentry *autofs4_lookup_active(struct dentry *dentry) 164static struct dentry *autofs4_lookup_active(struct dentry *dentry)
@@ -488,7 +490,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
488 sbi = autofs4_sbi(dir->i_sb); 490 sbi = autofs4_sbi(dir->i_sb);
489 491
490 DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", 492 DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
491 current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); 493 current->pid, task_pgrp_nr(current), sbi->catatonic,
494 autofs4_oz_mode(sbi));
492 495
493 active = autofs4_lookup_active(dentry); 496 active = autofs4_lookup_active(dentry);
494 if (active) { 497 if (active) {
@@ -507,7 +510,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
507 if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) 510 if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent))
508 __managed_dentry_set_managed(dentry); 511 __managed_dentry_set_managed(dentry);
509 512
510 ino = autofs4_init_ino(NULL, sbi, 0555); 513 ino = autofs4_new_ino(sbi);
511 if (!ino) 514 if (!ino)
512 return ERR_PTR(-ENOMEM); 515 return ERR_PTR(-ENOMEM);
513 516
@@ -529,6 +532,7 @@ static int autofs4_dir_symlink(struct inode *dir,
529 struct autofs_info *ino = autofs4_dentry_ino(dentry); 532 struct autofs_info *ino = autofs4_dentry_ino(dentry);
530 struct autofs_info *p_ino; 533 struct autofs_info *p_ino;
531 struct inode *inode; 534 struct inode *inode;
535 size_t size = strlen(symname);
532 char *cp; 536 char *cp;
533 537
534 DPRINTK("%s <- %.*s", symname, 538 DPRINTK("%s <- %.*s", symname,
@@ -537,39 +541,35 @@ static int autofs4_dir_symlink(struct inode *dir,
537 if (!autofs4_oz_mode(sbi)) 541 if (!autofs4_oz_mode(sbi))
538 return -EACCES; 542 return -EACCES;
539 543
540 ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555); 544 BUG_ON(!ino);
541 if (!ino) 545
542 return -ENOMEM; 546 autofs4_clean_ino(ino);
543 547
544 autofs4_del_active(dentry); 548 autofs4_del_active(dentry);
545 549
546 ino->size = strlen(symname); 550 cp = kmalloc(size + 1, GFP_KERNEL);
547 cp = kmalloc(ino->size + 1, GFP_KERNEL); 551 if (!cp)
548 if (!cp) {
549 if (!dentry->d_fsdata)
550 kfree(ino);
551 return -ENOMEM; 552 return -ENOMEM;
552 }
553 553
554 strcpy(cp, symname); 554 strcpy(cp, symname);
555 555
556 inode = autofs4_get_inode(dir->i_sb, ino); 556 inode = autofs4_get_inode(dir->i_sb, S_IFLNK | 0555);
557 if (!inode) { 557 if (!inode) {
558 kfree(cp); 558 kfree(cp);
559 if (!dentry->d_fsdata) 559 if (!dentry->d_fsdata)
560 kfree(ino); 560 kfree(ino);
561 return -ENOMEM; 561 return -ENOMEM;
562 } 562 }
563 inode->i_private = cp;
564 inode->i_size = size;
563 d_add(dentry, inode); 565 d_add(dentry, inode);
564 566
565 dentry->d_fsdata = ino; 567 dget(dentry);
566 ino->dentry = dget(dentry);
567 atomic_inc(&ino->count); 568 atomic_inc(&ino->count);
568 p_ino = autofs4_dentry_ino(dentry->d_parent); 569 p_ino = autofs4_dentry_ino(dentry->d_parent);
569 if (p_ino && dentry->d_parent != dentry) 570 if (p_ino && dentry->d_parent != dentry)
570 atomic_inc(&p_ino->count); 571 atomic_inc(&p_ino->count);
571 572
572 ino->u.symlink = cp;
573 dir->i_mtime = CURRENT_TIME; 573 dir->i_mtime = CURRENT_TIME;
574 574
575 return 0; 575 return 0;
@@ -732,25 +732,21 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
732 DPRINTK("dentry %p, creating %.*s", 732 DPRINTK("dentry %p, creating %.*s",
733 dentry, dentry->d_name.len, dentry->d_name.name); 733 dentry, dentry->d_name.len, dentry->d_name.name);
734 734
735 ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555); 735 BUG_ON(!ino);
736 if (!ino) 736
737 return -ENOMEM; 737 autofs4_clean_ino(ino);
738 738
739 autofs4_del_active(dentry); 739 autofs4_del_active(dentry);
740 740
741 inode = autofs4_get_inode(dir->i_sb, ino); 741 inode = autofs4_get_inode(dir->i_sb, S_IFDIR | 0555);
742 if (!inode) { 742 if (!inode)
743 if (!dentry->d_fsdata)
744 kfree(ino);
745 return -ENOMEM; 743 return -ENOMEM;
746 }
747 d_add(dentry, inode); 744 d_add(dentry, inode);
748 745
749 if (sbi->version < 5) 746 if (sbi->version < 5)
750 autofs_set_leaf_automount_flags(dentry); 747 autofs_set_leaf_automount_flags(dentry);
751 748
752 dentry->d_fsdata = ino; 749 dget(dentry);
753 ino->dentry = dget(dentry);
754 atomic_inc(&ino->count); 750 atomic_inc(&ino->count);
755 p_ino = autofs4_dentry_ino(dentry->d_parent); 751 p_ino = autofs4_dentry_ino(dentry->d_parent);
756 if (p_ino && dentry->d_parent != dentry) 752 if (p_ino && dentry->d_parent != dentry)
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c
index b4ea82934d2e..f27c094a1919 100644
--- a/fs/autofs4/symlink.c
+++ b/fs/autofs4/symlink.c
@@ -14,8 +14,7 @@
14 14
15static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) 15static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
16{ 16{
17 struct autofs_info *ino = autofs4_dentry_ino(dentry); 17 nd_set_link(nd, dentry->d_inode->i_private);
18 nd_set_link(nd, (char *)ino->u.symlink);
19 return NULL; 18 return NULL;
20} 19}
21 20
diff --git a/fs/namei.c b/fs/namei.c
index b753192d8c3f..7d77f24d32a9 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1272,8 +1272,10 @@ done:
1272 path->mnt = mnt; 1272 path->mnt = mnt;
1273 path->dentry = dentry; 1273 path->dentry = dentry;
1274 err = follow_managed(path, nd->flags); 1274 err = follow_managed(path, nd->flags);
1275 if (unlikely(err < 0)) 1275 if (unlikely(err < 0)) {
1276 path_put_conditional(path, nd);
1276 return err; 1277 return err;
1278 }
1277 *inode = path->dentry->d_inode; 1279 *inode = path->dentry->d_inode;
1278 return 0; 1280 return 0;
1279 1281