Date: Sun, 8 Jun 1997 14:20:01 -0700 (PDT) From: Dirk Keunecke <dk@panda.rhein-main.de> To: freebsd-bugs Subject: Re: kern/3571: Mounted ext2 prevents umount of filesystems during reboot Message-ID: <199706082120.OAA18225@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/3571; it has been noted by GNATS. From: Dirk Keunecke <dk@panda.rhein-main.de> To: FreeBSD-gnats@freebsd.org, freebsd-bugs@freebsd.org Cc: Subject: Re: kern/3571: Mounted ext2 prevents umount of filesystems during reboot Date: Sun, 8 Jun 1997 15:09:17 +0200 (CEST) [The following is related to the problem report 'kern/3571'] Hello, The 'ext2fs' stores group descriptors, inode and block bitmaps in buffers which it "reserves" by not brelse'ing them after the data is read in. The buffer is kept 'B_BUSY' until they are released at unmount time (this is not 100% accurate, some buffers may be released at other times). If one reboots the system, 'boot()' (in kern_shutdown.c') syncs and then waits for these buffers to become unbusy. This will never happen because they are brelse'ed in 'ext2_unmount()', which is called by 'boot()' only if all buffers of all filesystems have been successfully synced (as indicated by the non-busy state of all buffers). The 'B_LOCKED' flag also seems to prevent an buffer from being reused, but without keeping the buffer busy. I've made some minor changes to 'ext2' to use 'B_LOCKED' instead of 'B_BUSY' to reserve the buffers for 'ext2'. It seems to solve 'kern/3571'. If anybody cares enough, please review these changes. Comments, suggestions, corrections are welcome. Disclaimer: I am no filesystem-, kernel- or whatever kind of a guru, just someone who wants to learn something about the FreeBSD kernel. No warranty. Regards, Dirk [The following patch was created against CURRENT as of May 30] *** /sys/gnu/ext2fs/ext2_linux_balloc.c Tue Apr 1 22:31:32 1997 --- ext2_linux_balloc.c Sun Jun 1 16:44:13 1997 *************** *** 70,75 **** --- 70,76 ---- block_group, (unsigned long) gdp->bg_block_bitmap); sb->s_block_bitmap_number[bitmap_nr] = block_group; sb->s_block_bitmap[bitmap_nr] = bh; + LCK_BUF(bh) } /* *************** *** 130,136 **** if (sb->s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED) sb->s_loaded_block_bitmaps++; else ! brelse (sb->s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1]); for (j = sb->s_loaded_block_bitmaps - 1; j > 0; j--) { sb->s_block_bitmap_number[j] = sb->s_block_bitmap_number[j - 1]; --- 131,138 ---- if (sb->s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED) sb->s_loaded_block_bitmaps++; else ! ULCK_BUF(sb->s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1]) ! for (j = sb->s_loaded_block_bitmaps - 1; j > 0; j--) { sb->s_block_bitmap_number[j] = sb->s_block_bitmap_number[j - 1]; *** /sys/gnu/ext2fs/ext2_linux_ialloc.c Tue Apr 1 22:31:33 1997 --- ext2_linux_ialloc.c Sun Jun 1 16:42:27 1997 *************** *** 121,126 **** --- 121,127 ---- block_group, (unsigned long) gdp->bg_inode_bitmap); sb->s_inode_bitmap_number[bitmap_nr] = block_group; sb->s_inode_bitmap[bitmap_nr] = bh; + LCK_BUF(bh) } /* *************** *** 184,190 **** if (sb->s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED) sb->s_loaded_inode_bitmaps++; else ! brelse (sb->s_inode_bitmap[EXT2_MAX_GROUP_LOADED - 1]); for (j = sb->s_loaded_inode_bitmaps - 1; j > 0; j--) { sb->s_inode_bitmap_number[j] = sb->s_inode_bitmap_number[j - 1]; --- 185,191 ---- if (sb->s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED) sb->s_loaded_inode_bitmaps++; else ! ULCK_BUF(sb->s_inode_bitmap[EXT2_MAX_GROUP_LOADED - 1]) for (j = sb->s_loaded_inode_bitmaps - 1; j > 0; j--) { sb->s_inode_bitmap_number[j] = sb->s_inode_bitmap_number[j - 1]; *** /sys/gnu/ext2fs/ext2_vfsops.c Mon Mar 24 23:35:55 1997 --- ext2_vfsops.c Sun Jun 1 17:28:38 1997 *************** *** 415,424 **** printf("EXT2-fs: unable to read group descriptors (%d)\n", error); return EIO; } } if(!ext2_check_descriptors(fs)) { for (j = 0; j < db_count; j++) ! brelse(fs->s_group_desc[j]); bsd_free(fs->s_group_desc, M_UFSMNT); printf("EXT2-fs: (ext2_check_descriptors failure) " "unable to read group descriptors\n"); --- 415,426 ---- printf("EXT2-fs: unable to read group descriptors (%d)\n", error); return EIO; } + /* Set the B_LOCKED flag on the buffer, then brelse() it */ + LCK_BUF(fs->s_group_desc[i]) } if(!ext2_check_descriptors(fs)) { for (j = 0; j < db_count; j++) ! ULCK_BUF(fs->s_group_desc[j]) bsd_free(fs->s_group_desc, M_UFSMNT); printf("EXT2-fs: (ext2_check_descriptors failure) " "unable to read group descriptors\n"); *************** *** 694,709 **** fs->s_es->s_state |= EXT2_VALID_FS; /* was fs_clean = 1 */ ext2_sbupdate(ump, MNT_WAIT); } /* release buffers containing group descriptors */ for(i = 0; i < fs->s_db_per_group; i++) ! brelse(fs->s_group_desc[i]); /* release cached inode/block bitmaps */ for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) if (fs->s_inode_bitmap[i]) ! brelse (fs->s_inode_bitmap[i]); for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) if (fs->s_block_bitmap[i]) ! brelse (fs->s_block_bitmap[i]); ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, --- 696,714 ---- fs->s_es->s_state |= EXT2_VALID_FS; /* was fs_clean = 1 */ ext2_sbupdate(ump, MNT_WAIT); } + /* release buffers containing group descriptors */ for(i = 0; i < fs->s_db_per_group; i++) ! ULCK_BUF(fs->s_group_desc[i]) ! /* release cached inode/block bitmaps */ for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) if (fs->s_inode_bitmap[i]) ! ULCK_BUF(fs->s_inode_bitmap[i]) ! for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) if (fs->s_block_bitmap[i]) ! ULCK_BUF(fs->s_block_bitmap[i]) ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, *************** *** 1109,1128 **** else bawrite(bp); ! /* write group descriptors back on disk */ ! for(i = 0; i < fs->s_db_per_group; i++) ! /* Godmar thinks: we must avoid using any of the b*write ! * functions here: we want to keep the buffer locked ! * so we use my 'housemade' write routine: */ - error |= ll_w_block(fs->s_group_desc[i], waitfor == MNT_WAIT); - - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) - if (fs->s_inode_bitmap[i]) - ll_w_block (fs->s_inode_bitmap[i], 1); - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) - if (fs->s_block_bitmap[i]) - ll_w_block (fs->s_block_bitmap[i], 1); return (error); } --- 1115,1125 ---- else bawrite(bp); ! /* ! * The buffers for group descriptors, inode bitmaps and block bitmaps ! * are not busy at this point and are (hopefully) written by the ! * usual sync mechanism. No need to write them here */ return (error); } *** /sys/gnu/ext2fs/fs.h Mon Feb 10 04:19:21 1997 --- fs.h Sun Jun 1 16:40:19 1997 *************** *** 155,157 **** --- 155,177 ---- #define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curproc) #define unlock_super(devvp) VOP_UNLOCK(devvp, 0, curproc) + /* + * To lock a buffer, set the B_LOCKED flag and then brelse() it. To unlock, + * reset the B_LOCKED flag and brelse() the buffer back on the LRU list + */ + #define LCK_BUF(bp) { \ + int s; \ + s = splbio(); \ + (bp)->b_flags |= B_LOCKED; \ + splx(s); \ + brelse(bp); \ + } + + #define ULCK_BUF(bp) { \ + int s; \ + s = splbio(); \ + (bp)->b_flags &= ~B_LOCKED; \ + splx(s); \ + bremfree(bp); \ + brelse(bp); \ + }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199706082120.OAA18225>