Messages in this thread Patch in this message | | | From | "H. Peter Anvin" <> | Subject | Re: 2.2.0p6: autofs bug! unmountable filesystem | Date | Mon, 11 Jan 1999 11:35:25 -0800 (PST) |
| |
> Hi, > > I can reproduce a autofs bug whereby the autofs filesystem cannot be > unmounted. > > It is simple: first mount the autofs filesystem. I have RH5.2 so to do > this I use /etc/rc.d/init.d/autofs start > > Now I mount my CD rom drive by doing cd /misc/cd > > This next step seems to break things. _Manually_ umount /misc/cd, rather > than letting autofs timeout (before doing the the cwd will need to be > moved from /misc/cd :-) > > Now, /misc cannot be unmounted, it is permanently reported as busy. Not > good.
Hi there,
Try the following patch, please:
diff -ur stock/linux-2.2.0-pre6/fs/autofs/autofs_i.h linux-2.2.0-pre6/fs/autofs/autofs_i.h --- stock/linux-2.2.0-pre6/fs/autofs/autofs_i.h Fri Jan 8 15:53:20 1999 +++ linux-2.2.0-pre6/fs/autofs/autofs_i.h Mon Jan 11 11:02:16 1999 @@ -92,10 +92,6 @@ #define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) -#ifndef END_OF_TIME -#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1)) -#endif - #define AUTOFS_SBI_MAGIC 0x6d4a556d struct autofs_sb_info { @@ -111,6 +107,11 @@ u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; }; +extern inline struct autofs_sb_info *autofs_sbi(struct super_block *sb) +{ + return (struct autofs_sb_info *)(sb->u.generic_sbp); +} + /* autofs_oz_mode(): do we see the man behind the curtain? (The processes which do manipulations for us in user space sees the raw filesystem without "magic".) */ @@ -126,6 +127,7 @@ void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *); void autofs_hash_delete(struct autofs_dir_ent *); struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *); +void autofs_hash_dputall(struct autofs_dirhash *); void autofs_hash_nuke(struct autofs_dirhash *); /* Expiration-handling functions */ diff -ur stock/linux-2.2.0-pre6/fs/autofs/dirhash.c linux-2.2.0-pre6/fs/autofs/dirhash.c --- stock/linux-2.2.0-pre6/fs/autofs/dirhash.c Tue Oct 27 14:13:53 1998 +++ linux-2.2.0-pre6/fs/autofs/dirhash.c Mon Jan 11 11:06:40 1999 @@ -47,7 +47,7 @@ ent = dh->expiry_head.exp_next; - if ( ent == &(dh->expiry_head) ) + if ( ent == &(dh->expiry_head) || sbi->catatonic ) return NULL; /* No entries */ while ( jiffies - ent->last_usage >= timeout ) { @@ -62,8 +62,10 @@ dentry = ent->dentry; if ( !dentry ) { + /* Should only happen in catatonic mode */ printk("autofs: dentry == NULL but inode range is directory, entry %s\n", ent->name); autofs_delete_usage(ent); + continue; } if ( !dentry->d_inode ) { @@ -200,6 +202,23 @@ *ptr = ((bucket+1) << 16) + ecount; return ent; +} + +/* Iterate over all the ents, and remove all dentry pointers. Used on + entering catatonic mode, in order to make the filesystem unmountable. */ +void autofs_hash_dputall(struct autofs_dirhash *dh) +{ + int i; + struct autofs_dir_ent *ent, *nent; + + for ( i = 0 ; i < AUTOFS_HASH_SIZE ; i++ ) { + for ( ent = dh->h[i] ; ent ; ent = ent->next ) { + if ( ent->dentry ) { + dput(ent->dentry); + ent->dentry = NULL; + } + } + } } /* Delete everything. This is used on filesystem destruction, so we diff -ur stock/linux-2.2.0-pre6/fs/autofs/inode.c linux-2.2.0-pre6/fs/autofs/inode.c --- stock/linux-2.2.0-pre6/fs/autofs/inode.c Thu Dec 17 16:51:36 1998 +++ linux-2.2.0-pre6/fs/autofs/inode.c Mon Jan 11 10:46:26 1999 @@ -34,8 +34,7 @@ static void autofs_put_super(struct super_block *sb) { - struct autofs_sb_info *sbi = - (struct autofs_sb_info *) sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(sb); unsigned int n; if ( !sbi->catatonic ) @@ -297,8 +296,7 @@ { ino_t ino = inode->i_ino; unsigned int n; - struct autofs_sb_info *sbi = - (struct autofs_sb_info *) inode->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); /* Initialize to the default case (stub directory) */ diff -ur stock/linux-2.2.0-pre6/fs/autofs/root.c linux-2.2.0-pre6/fs/autofs/root.c --- stock/linux-2.2.0-pre6/fs/autofs/root.c Thu Dec 17 16:51:36 1998 +++ linux-2.2.0-pre6/fs/autofs/root.c Mon Jan 11 11:08:36 1999 @@ -68,13 +68,15 @@ { struct autofs_dir_ent *ent = NULL; struct autofs_dirhash *dirhash; + struct autofs_sb_info *sbi; struct inode * inode = filp->f_dentry->d_inode; off_t onr, nr; if (!inode || !S_ISDIR(inode->i_mode)) return -ENOTDIR; - dirhash = &((struct autofs_sb_info *)inode->i_sb->u.generic_sbp)->dirhash; + sbi = autofs_sbi(inode->i_sb); + dirhash = &sbi->dirhash; nr = filp->f_pos; switch(nr) @@ -168,12 +170,10 @@ */ static int autofs_revalidate(struct dentry * dentry) { - struct autofs_sb_info *sbi; struct inode * dir = dentry->d_parent->d_inode; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dir_ent *ent; - sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; - /* Pending dentry */ if ( dentry->d_flags & DCACHE_AUTOFS_PENDING ) { if (autofs_oz_mode(sbi)) @@ -220,7 +220,7 @@ if (!S_ISDIR(dir->i_mode)) return -ENOTDIR; - sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + sbi = autofs_sbi(dir->i_sb); oz_mode = autofs_oz_mode(sbi); DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", @@ -267,7 +267,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; unsigned int n; @@ -338,7 +338,7 @@ */ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; unsigned int n; @@ -365,7 +365,7 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; @@ -393,7 +393,7 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; ino_t ino; @@ -492,8 +492,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct autofs_sb_info *sbi = - (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); diff -ur stock/linux-2.2.0-pre6/fs/autofs/waitq.c linux-2.2.0-pre6/fs/autofs/waitq.c --- stock/linux-2.2.0-pre6/fs/autofs/waitq.c Mon Dec 28 00:47:48 1998 +++ linux-2.2.0-pre6/fs/autofs/waitq.c Mon Jan 11 11:03:03 1999 @@ -41,6 +41,7 @@ wq = nwq; } fput(sbi->pipe); /* Close the pipe */ + autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ } static int autofs_write(struct file *file, const void *addr, int bytes) - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |