Skip site navigation (1)Skip section navigation (2)
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>