⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 balloc.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
字号:
/* *  linux/fs/sysv/balloc.c * *  minix/bitmap.c *  Copyright (C) 1991, 1992  Linus Torvalds * *  ext/freelists.c *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr) * *  xenix/alloc.c *  Copyright (C) 1992  Doug Evans * *  coh/alloc.c *  Copyright (C) 1993  Pascal Haible, Bruno Haible * *  sysv/balloc.c *  Copyright (C) 1993  Bruno Haible * *  This file contains code for allocating/freeing blocks. */#include <linux/kernel.h>#include <linux/fs.h>#include <linux/sysv_fs.h>#include <linux/string.h>#include <linux/locks.h>/* We don't trust the value of   sb->sv_sbd->s_tfree = *sb->sv_sb_total_free_blocks   but we nevertheless keep it up to date. */extern inline void memzero (void * s, size_t count){__asm__("cld\n\t"	"rep\n\t"	"stosl"	:	:"a" (0),"D" (s),"c" (count/4)	:"cx","di","memory");}void sysv_free_block(struct super_block * sb, unsigned int block){	struct buffer_head * bh;	char * bh_data;	if (!sb) {		printk("sysv_free_block: trying to free block on nonexistent device\n");		return;	}	if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {		printk("sysv_free_block: trying to free block not in datazone\n");		return;	}	lock_super(sb);	if (*sb->sv_sb_flc_count > sb->sv_flc_size) {		printk("sysv_free_block: flc_count > flc_size\n");		unlock_super(sb);		return;	}	/* If the free list head in super-block is full, it is copied	 * into this block being freed:	 */	if (*sb->sv_sb_flc_count == sb->sv_flc_size) {		unsigned short * flc_count;		unsigned long * flc_blocks;		if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */			bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);		else			bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);		if (!bh) {			printk("sysv_free_block: getblk() or bread() failed\n");			unlock_super(sb);			return;		}		bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);		switch (sb->sv_type) {			case FSTYPE_XENIX:				flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];				break;			case FSTYPE_SYSV4:				flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];				break;			case FSTYPE_SYSV2:				flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];				break;			case FSTYPE_COH:				flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];				break;			default: panic("sysv_free_block: invalid fs type\n");		}		*flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */		memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t));		bh->b_dirt = 1;		bh->b_uptodate = 1;		brelse(bh);		*sb->sv_sb_flc_count = 0;	} else	/* If the free list head in super-block is empty, create a new head	 * in this block being freed:	 */	if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */		if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */			bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);		else			bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);		if (!bh) {			printk("sysv_free_block: getblk() or bread() failed\n");			unlock_super(sb);			return;		}		bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);		memzero(bh_data, sb->sv_block_size);		/* this implies ((struct ..._freelist_chunk *) bh_data)->flc_count = 0; */		bh->b_dirt = 1;		bh->b_uptodate = 1;		brelse(bh);		/* still *sb->sv_sb_flc_count = 0 */	} else {		if (sb->sv_block_size_ratio_bits == 0) { /* block_size == BLOCK_SIZE ? */			/* Throw away block's contents */			bh = get_hash_table(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);			if (bh)				bh->b_dirt = 0;			brelse(bh);		}	}	if (sb->sv_convert)		block = to_coh_ulong(block);	sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)++] = block;	if (sb->sv_convert)		*sb->sv_sb_total_free_blocks =		  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);	else		*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;	sb->sv_bh->b_dirt = 1; /* super-block has been modified */	sb->s_dirt = 1; /* and needs time stamp */	unlock_super(sb);}int sysv_new_block(struct super_block * sb){	unsigned int block;	struct buffer_head * bh;	char * bh_data;	if (!sb) {		printk("sysv_new_block: trying to get new block from nonexistent device\n");		return 0;	}	lock_super(sb);	if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */		unlock_super(sb);		return 0;		/* no blocks available */	}	block = sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)-1];	if (sb->sv_convert)		block = from_coh_ulong(block);	if (block == 0) { /* Applies only to Xenix FS, SystemV FS */		unlock_super(sb);		return 0;		/* no blocks available */	}	(*sb->sv_sb_flc_count)--;	if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {		printk("sysv_new_block: new block %d is not in data zone\n",block);		unlock_super(sb);		return 0;	}	if (*sb->sv_sb_flc_count == 0) { /* the last block continues the free list */		unsigned short * flc_count;		unsigned long * flc_blocks;		if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) {			printk("sysv_new_block: cannot read free-list block\n");			/* retry this same block next time */			(*sb->sv_sb_flc_count)++;			unlock_super(sb);			return 0;		}		switch (sb->sv_type) {			case FSTYPE_XENIX:				flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];				break;			case FSTYPE_SYSV4:				flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];				break;			case FSTYPE_SYSV2:				flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];				break;			case FSTYPE_COH:				flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;				flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];				break;			default: panic("sysv_new_block: invalid fs type\n");		}		if (*flc_count > sb->sv_flc_size) {			printk("sysv_new_block: free-list block with >flc_size entries\n");			brelse(bh);			unlock_super(sb);			return 0;		}		*sb->sv_sb_flc_count = *flc_count;		memcpy(sb->sv_sb_flc_blocks, flc_blocks, *flc_count * sizeof(sysv_zone_t));		brelse(bh);	}	/* Now the free list head in the superblock is valid again. */	if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */		bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);	else		bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);	if (!bh) {		printk("sysv_new_block: getblk() or bread() failed\n");		unlock_super(sb);		return 0;	}	bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);	if (sb->sv_block_size_ratio_bits == 0) /* block_size == BLOCK_SIZE ? */		if (bh->b_count != 1) {			printk("sysv_new_block: block already in use\n");			unlock_super(sb);			return 0;		}	memzero(bh_data,sb->sv_block_size);	bh->b_dirt = 1;	bh->b_uptodate = 1;	brelse(bh);	if (sb->sv_convert)		*sb->sv_sb_total_free_blocks =		  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);	else		*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;	sb->sv_bh->b_dirt = 1; /* super-block has been modified */	sb->s_dirt = 1; /* and needs time stamp */	unlock_super(sb);	return block;}unsigned long sysv_count_free_blocks(struct super_block * sb){#if 1 /* test */	int count, old_count;	unsigned int block;	struct buffer_head * bh;	char * bh_data;	int i;	/* this causes a lot of disk traffic ... */	count = 0;	lock_super(sb);	if (*sb->sv_sb_flc_count > 0) {		for (i = *sb->sv_sb_flc_count ; /* i > 0 */ ; ) {			block = sb->sv_sb_flc_blocks[--i];			if (sb->sv_convert)				block = from_coh_ulong(block);			if (block == 0) /* block 0 terminates list */				goto done;			count++;			if (i == 0)				break;		}		/* block = sb->sv_sb_flc_blocks[0], the last block continues the free list */		while (1) {			unsigned short * flc_count;			unsigned long * flc_blocks;			if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {				printk("sysv_count_free_blocks: new block %d is not in data zone\n",block);				break;			}			if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) {				printk("sysv_count_free_blocks: cannot read free-list block\n");				break;			}			switch (sb->sv_type) {				case FSTYPE_XENIX:					flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;					flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];					break;				case FSTYPE_SYSV4:					flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;					flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];					break;				case FSTYPE_SYSV2:					flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;					flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];					break;				case FSTYPE_COH:					flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;					flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];					break;				default: panic("sysv_count_free_blocks: invalid fs type\n");			}			if (*flc_count > sb->sv_flc_size) {				printk("sysv_count_free_blocks: free-list block with >flc_size entries\n");				brelse(bh);				break;			}			if (*flc_count == 0) { /* Applies only to Coherent FS */				brelse(bh);				break;			}			for (i = *flc_count ; /* i > 0 */ ; ) {				block = flc_blocks[--i];				if (sb->sv_convert)					block = from_coh_ulong(block);				if (block == 0) /* block 0 terminates list */					break;				count++;				if (i == 0)					break;			}			/* block = flc_blocks[0], the last block continues the free list */			brelse(bh);			if (block == 0) /* Applies only to Xenix FS and SystemV FS */				break;		}		done: ;	}	old_count = *sb->sv_sb_total_free_blocks;	if (sb->sv_convert)		old_count = from_coh_ulong(old_count);	if (count != old_count) {		printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);		if (!(sb->s_flags & MS_RDONLY)) {			*sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);			sb->sv_bh->b_dirt = 1; /* super-block has been modified */			sb->s_dirt = 1; /* and needs time stamp */		}	}	unlock_super(sb);	return count;#else	int count;	count = *sb->sv_sb_total_free_blocks;	if (sb->sv_convert)		count = from_coh_ulong(count);	return count;#endif}

⌨️ 快捷键说明

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