aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/autofs4/autofs_i.h1
-rw-r--r--fs/autofs4/expire.c34
-rw-r--r--fs/autofs4/inode.c12
-rw-r--r--fs/autofs4/root.c23
4 files changed, 59 insertions, 11 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index eea25934da62..00da71d0f32a 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -55,6 +55,7 @@ struct autofs_info {
55 55
56 struct autofs_sb_info *sbi; 56 struct autofs_sb_info *sbi;
57 unsigned long last_used; 57 unsigned long last_used;
58 atomic_t count;
58 59
59 mode_t mode; 60 mode_t mode;
60 size_t size; 61 size_t size;
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 165fe9e2d570..053d92a745b9 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -101,6 +101,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
101 unsigned long timeout, 101 unsigned long timeout,
102 int do_now) 102 int do_now)
103{ 103{
104 struct autofs_info *ino;
104 struct dentry *p; 105 struct dentry *p;
105 106
106 DPRINTK("top %p %.*s", 107 DPRINTK("top %p %.*s",
@@ -110,14 +111,6 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
110 if (!simple_positive(top)) 111 if (!simple_positive(top))
111 return 1; 112 return 1;
112 113
113 /* Timeout of a tree mount is determined by its top dentry */
114 if (!autofs4_can_expire(top, timeout, do_now))
115 return 1;
116
117 /* Is someone visiting anywhere in the tree ? */
118 if (may_umount_tree(mnt))
119 return 1;
120
121 spin_lock(&dcache_lock); 114 spin_lock(&dcache_lock);
122 for (p = top; p; p = next_dentry(p, top)) { 115 for (p = top; p; p = next_dentry(p, top)) {
123 /* Negative dentry - give up */ 116 /* Negative dentry - give up */
@@ -130,17 +123,40 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
130 p = dget(p); 123 p = dget(p);
131 spin_unlock(&dcache_lock); 124 spin_unlock(&dcache_lock);
132 125
126 /*
127 * Is someone visiting anywhere in the subtree ?
128 * If there's no mount we need to check the usage
129 * count for the autofs dentry.
130 */
131 ino = autofs4_dentry_ino(p);
133 if (d_mountpoint(p)) { 132 if (d_mountpoint(p)) {
134 /* First busy => tree busy */
135 if (autofs4_mount_busy(mnt, p)) { 133 if (autofs4_mount_busy(mnt, p)) {
136 dput(p); 134 dput(p);
137 return 1; 135 return 1;
138 } 136 }
137 } else {
138 unsigned int ino_count = atomic_read(&ino->count);
139
140 /* allow for dget above and top is already dgot */
141 if (p == top)
142 ino_count += 2;
143 else
144 ino_count++;
145
146 if (atomic_read(&p->d_count) > ino_count) {
147 dput(p);
148 return 1;
149 }
139 } 150 }
140 dput(p); 151 dput(p);
141 spin_lock(&dcache_lock); 152 spin_lock(&dcache_lock);
142 } 153 }
143 spin_unlock(&dcache_lock); 154 spin_unlock(&dcache_lock);
155
156 /* Timeout of a tree mount is ultimately determined by its top dentry */
157 if (!autofs4_can_expire(top, timeout, do_now))
158 return 1;
159
144 return 0; 160 return 0;
145} 161}
146 162
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 1ad98d48e550..2335b1d6490f 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -46,6 +46,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
46 ino->size = 0; 46 ino->size = 0;
47 47
48 ino->last_used = jiffies; 48 ino->last_used = jiffies;
49 atomic_set(&ino->count, 0);
49 50
50 ino->sbi = sbi; 51 ino->sbi = sbi;
51 52
@@ -64,10 +65,19 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
64 65
65void autofs4_free_ino(struct autofs_info *ino) 66void autofs4_free_ino(struct autofs_info *ino)
66{ 67{
68 struct autofs_info *p_ino;
69
67 if (ino->dentry) { 70 if (ino->dentry) {
68 ino->dentry->d_fsdata = NULL; 71 ino->dentry->d_fsdata = NULL;
69 if (ino->dentry->d_inode) 72 if (ino->dentry->d_inode) {
73 struct dentry *parent = ino->dentry->d_parent;
74 if (atomic_dec_and_test(&ino->count)) {
75 p_ino = autofs4_dentry_ino(parent);
76 if (p_ino && parent != ino->dentry)
77 atomic_dec(&p_ino->count);
78 }
70 dput(ino->dentry); 79 dput(ino->dentry);
80 }
71 ino->dentry = NULL; 81 ino->dentry = NULL;
72 } 82 }
73 if (ino->free) 83 if (ino->free)
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index c7ff35774344..d196712c4b94 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -490,6 +490,7 @@ static int autofs4_dir_symlink(struct inode *dir,
490{ 490{
491 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 491 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
492 struct autofs_info *ino = autofs4_dentry_ino(dentry); 492 struct autofs_info *ino = autofs4_dentry_ino(dentry);
493 struct autofs_info *p_ino;
493 struct inode *inode; 494 struct inode *inode;
494 char *cp; 495 char *cp;
495 496
@@ -523,6 +524,10 @@ static int autofs4_dir_symlink(struct inode *dir,
523 524
524 dentry->d_fsdata = ino; 525 dentry->d_fsdata = ino;
525 ino->dentry = dget(dentry); 526 ino->dentry = dget(dentry);
527 atomic_inc(&ino->count);
528 p_ino = autofs4_dentry_ino(dentry->d_parent);
529 if (p_ino && dentry->d_parent != dentry)
530 atomic_inc(&p_ino->count);
526 ino->inode = inode; 531 ino->inode = inode;
527 532
528 dir->i_mtime = CURRENT_TIME; 533 dir->i_mtime = CURRENT_TIME;
@@ -549,11 +554,17 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
549{ 554{
550 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 555 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
551 struct autofs_info *ino = autofs4_dentry_ino(dentry); 556 struct autofs_info *ino = autofs4_dentry_ino(dentry);
557 struct autofs_info *p_ino;
552 558
553 /* This allows root to remove symlinks */ 559 /* This allows root to remove symlinks */
554 if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) 560 if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
555 return -EACCES; 561 return -EACCES;
556 562
563 if (atomic_dec_and_test(&ino->count)) {
564 p_ino = autofs4_dentry_ino(dentry->d_parent);
565 if (p_ino && dentry->d_parent != dentry)
566 atomic_dec(&p_ino->count);
567 }
557 dput(ino->dentry); 568 dput(ino->dentry);
558 569
559 dentry->d_inode->i_size = 0; 570 dentry->d_inode->i_size = 0;
@@ -570,6 +581,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
570{ 581{
571 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 582 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
572 struct autofs_info *ino = autofs4_dentry_ino(dentry); 583 struct autofs_info *ino = autofs4_dentry_ino(dentry);
584 struct autofs_info *p_ino;
573 585
574 if (!autofs4_oz_mode(sbi)) 586 if (!autofs4_oz_mode(sbi))
575 return -EACCES; 587 return -EACCES;
@@ -584,8 +596,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
584 spin_unlock(&dentry->d_lock); 596 spin_unlock(&dentry->d_lock);
585 spin_unlock(&dcache_lock); 597 spin_unlock(&dcache_lock);
586 598
599 if (atomic_dec_and_test(&ino->count)) {
600 p_ino = autofs4_dentry_ino(dentry->d_parent);
601 if (p_ino && dentry->d_parent != dentry)
602 atomic_dec(&p_ino->count);
603 }
587 dput(ino->dentry); 604 dput(ino->dentry);
588
589 dentry->d_inode->i_size = 0; 605 dentry->d_inode->i_size = 0;
590 dentry->d_inode->i_nlink = 0; 606 dentry->d_inode->i_nlink = 0;
591 607
@@ -599,6 +615,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
599{ 615{
600 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 616 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
601 struct autofs_info *ino = autofs4_dentry_ino(dentry); 617 struct autofs_info *ino = autofs4_dentry_ino(dentry);
618 struct autofs_info *p_ino;
602 struct inode *inode; 619 struct inode *inode;
603 620
604 if ( !autofs4_oz_mode(sbi) ) 621 if ( !autofs4_oz_mode(sbi) )
@@ -621,6 +638,10 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
621 638
622 dentry->d_fsdata = ino; 639 dentry->d_fsdata = ino;
623 ino->dentry = dget(dentry); 640 ino->dentry = dget(dentry);
641 atomic_inc(&ino->count);
642 p_ino = autofs4_dentry_ino(dentry->d_parent);
643 if (p_ino && dentry->d_parent != dentry)
644 atomic_inc(&p_ino->count);
624 ino->inode = inode; 645 ino->inode = inode;
625 dir->i_nlink++; 646 dir->i_nlink++;
626 dir->i_mtime = CURRENT_TIME; 647 dir->i_mtime = CURRENT_TIME;