buffer.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 212 行

C
212
字号
/* * linux/fs/fat/buffer.c * * */#include <linux/mm.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/fs.h>#include <linux/msdos_fs.h>#include <linux/fat_cvf.h>#if 0#  define PRINTK(x) printk x#else#  define PRINTK(x)#endifstruct buffer_head *fat_bread (	struct super_block *sb,	int block){	struct buffer_head *ret = NULL;	PRINTK(("fat_bread: block=0x%x\n", block));	/*	 * Note that the blocksize is 512, 1024 or 2048, but the first read	 * is always of size 1024 (or 2048). Doing readahead may be	 * counterproductive or just plain wrong.	 */	if(MSDOS_SB(sb)->cvf_format &&	   MSDOS_SB(sb)->cvf_format->cvf_bread)		return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block);	if (sb->s_blocksize == 512) {		ret = bread (sb->s_dev,block,512);	} else {		struct buffer_head *real;		if (sb->s_blocksize == 1024){			real = bread (sb->s_dev,block>>1,1024);		} else {			real = bread (sb->s_dev,block>>2,2048);		}		if (real != NULL){			ret = (struct buffer_head *)				kmalloc (sizeof(struct buffer_head), GFP_KERNEL);			if (ret != NULL) {				/* #Specification: msdos / strategy / special device / dummy blocks				 * Many special device (Scsi optical disk for one) use				 * larger hardware sector size. This allows for higher				 * capacity.				 * Most of the time, the MS-DOS filesystem that sits				 * on this device is totally unaligned. It use logically				 * 512 bytes sector size, with logical sector starting				 * in the middle of a hardware block. The bad news is				 * that a hardware sector may hold data own by two				 * different files. This means that the hardware sector				 * must be read, patch and written almost all the time.				 * Needless to say that it kills write performance				 * on all OS.				 * Internally the linux msdos fs is using 512 bytes				 * logical sector. When accessing such a device, we				 * allocate dummy buffer cache blocks, that we stuff				 * with the information of a real one (1k large).				 * This strategy is used to hide this difference to				 * the core of the msdos fs. The slowdown is not				 * hidden though!				 */				/*				 * The memset is there only to catch errors. The msdos				 * fs is only using b_data				 */				memset (ret,0,sizeof(*ret));				ret->b_data = real->b_data;				if (sb->s_blocksize == 2048) {					if (block & 3) ret->b_data += (block & 3) << 9;				}else{					if (block & 1) ret->b_data += 512;				}				ret->b_next = real;			}else{				brelse (real);			}		}	}	return ret;}struct buffer_head *fat_getblk(struct super_block *sb, int block){	struct buffer_head *ret = NULL;	PRINTK(("fat_getblk: block=0x%x\n", block));	if (MSDOS_SB(sb)->cvf_format &&	    MSDOS_SB(sb)->cvf_format->cvf_getblk)		return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block);	if (sb->s_blocksize == 512){		ret = getblk (sb->s_dev,block,512);	} else {		/*		 * #Specification: msdos / special device / writing		 * A write is always preceded by a read of the complete block		 * (large hardware sector size). This defeat write performance.		 * There is a possibility to optimize this when writing large		 * chunk by making sure we are filling large block. Volunteer ?		 */		ret = fat_bread (sb,block);	}	return ret;}void fat_brelse (	struct super_block *sb,	struct buffer_head *bh){	if (bh != NULL) {		if (MSDOS_SB(sb)->cvf_format &&		    MSDOS_SB(sb)->cvf_format->cvf_brelse)			return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh);		if (sb->s_blocksize == 512){			brelse (bh);		}else{			brelse (bh->b_next);			/* We can free the dummy because a new one is allocated at				each fat_getblk() and fat_bread().			*/			kfree (bh);		}	}}	void fat_mark_buffer_dirty (	struct super_block *sb,	struct buffer_head *bh,	int dirty){	if (MSDOS_SB(sb)->cvf_format &&	    MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty) {		MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty);		return;	} 	if (sb->s_blocksize != 512){		bh = bh->b_next;	}	mark_buffer_dirty (bh,dirty);}void fat_set_uptodate (	struct super_block *sb,	struct buffer_head *bh,	int val){	if (MSDOS_SB(sb)->cvf_format && 	    MSDOS_SB(sb)->cvf_format->cvf_set_uptodate) {		MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val);		return;	} 	if (sb->s_blocksize != 512){		bh = bh->b_next;	}	mark_buffer_uptodate(bh, val);}int fat_is_uptodate (	struct super_block *sb,	struct buffer_head *bh){	if(MSDOS_SB(sb)->cvf_format &&	   MSDOS_SB(sb)->cvf_format->cvf_is_uptodate)		return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh); 	if (sb->s_blocksize != 512){		bh = bh->b_next;	}	return buffer_uptodate(bh);}void fat_ll_rw_block (	struct super_block *sb,	int opr,	int nbreq,	struct buffer_head *bh[32]){        if (MSDOS_SB(sb)->cvf_format &&	    MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block) {		MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh);		return;	} 	if (sb->s_blocksize == 512){		ll_rw_block(opr,nbreq,bh);	}else{		struct buffer_head *tmp[32];		int i;		for (i=0; i<nbreq; i++){			tmp[i] = bh[i]->b_next;		}		ll_rw_block(opr,nbreq,tmp);	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?