autofs4-2.6.12-rc1-mm4-tree-race.patch
For tree mount maps, a call to chdir or chroot, to a directory above the moint point directories at a certain time during the expire results in the expire incorrectly thinking the tree is not busy. This patch adds a check to see if the filesystem above the tree mount points is busy and also locks the filesystem during the tree mount expire to prevent the race.
Signed-off-by: Ian Kent <[EMAIL PROTECTED]>
--- linux-2.6.12-rc1-mm4/fs/autofs4/autofs_i.h.tree-race 2005-04-03 12:34:00.000000000 +0800 +++ linux-2.6.12-rc1-mm4/fs/autofs4/autofs_i.h 2005-04-03 12:38:09.000000000 +0800 @@ -102,6 +102,7 @@ struct autofs_sb_info { int needs_reghost; struct super_block *sb; struct semaphore wq_sem; + spinlock_t fs_lock; struct autofs_wait_queue *queues; /* Wait queue pointer */ };
@@ -127,9 +128,18 @@ static inline int autofs4_oz_mode(struct static inline int autofs4_ispending(struct dentry *dentry) { struct autofs_info *inf = autofs4_dentry_ino(dentry); + int pending;
- return (dentry->d_flags & DCACHE_AUTOFS_PENDING) || - (inf != NULL && inf->flags & AUTOFS_INF_EXPIRING); + if (dentry->d_flags & DCACHE_AUTOFS_PENDING) + return 1; + + if (inf) { + spin_lock(&inf->sbi->fs_lock); + pending = inf->flags & AUTOFS_INF_EXPIRING; + spin_unlock(&inf->sbi->fs_lock); + } + + return pending; }
static inline void autofs4_copy_atime(struct file *src, struct file *dst) --- linux-2.6.12-rc1-mm4/fs/autofs4/inode.c.tree-race 2005-04-03 12:34:10.000000000 +0800 +++ linux-2.6.12-rc1-mm4/fs/autofs4/inode.c 2005-04-03 12:34:54.000000000 +0800 @@ -206,6 +206,7 @@ int autofs4_fill_super(struct super_bloc sbi->version = 0; sbi->sub_version = 0; init_MUTEX(&sbi->wq_sem); + spin_lock_init(&sbi->fs_lock); sbi->queues = NULL; s->s_blocksize = 1024; s->s_blocksize_bits = 10; --- linux-2.6.12-rc1-mm4/fs/autofs4/expire.c.tree-race 2005-04-03 12:34:22.000000000 +0800 +++ linux-2.6.12-rc1-mm4/fs/autofs4/expire.c 2005-04-03 12:42:41.000000000 +0800 @@ -99,6 +99,10 @@ static int autofs4_check_tree(struct vfs if (!autofs4_can_expire(top, timeout, do_now)) return 0;
+ /* Is someone visiting anywhere in the tree ? */ + if (autofs4_may_umount(mnt)) + return 0; + spin_lock(&dcache_lock); repeat: next = this_parent->d_subdirs.next; @@ -270,10 +274,18 @@ static struct dentry *autofs4_expire(str
/* Case 2: tree mount, expire iff entire tree is not busy */ if (!exp_leaves) { + /* Lock the tree as we must expire as a whole */ + spin_lock(&sbi->fs_lock); if (autofs4_check_tree(mnt, dentry, timeout, do_now)) { - expired = dentry; - break; + struct autofs_info *inf = autofs4_dentry_ino(dentry); + + /* Set this flag early to catch sys_chdir and the like */ + inf->flags |= AUTOFS_INF_EXPIRING; + spin_unlock(&sbi->fs_lock); + expired = dentry; + break; } + spin_unlock(&sbi->fs_lock); /* Case 3: direct mount, expire individual leaves */ } else { expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html