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

📄 io.c

📁 reiserfsprogs-3.6.19.tar.gz 源码 给有需要的人!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright 1996-2004 by Hans Reiser, licensing governed by  * reiserfsprogs/README */#include "io.h"#include <string.h>#include <errno.h>#include <asm/types.h>void check_memory_msg (void) {    fprintf(stderr, 	"\nThe problem has occurred looks like a hardware problem (perhaps\n"        "memory). Send us the bug report only if the second run dies at\n"	"the same place with the same block number.\n");}void check_hd_msg (void) {    fprintf(stderr, 	"\nThe problem has occurred looks like a hardware problem. If you have\n"	"bad blocks, we advise you to get a new hard drive, because once you\n"	"get one bad block  that the disk  drive internals  cannot hide from\n"        "your sight,the chances of getting more are generally said to become\n"        "much higher  (precise statistics are unknown to us), and  this disk\n"        "drive is probably not expensive enough  for you to you to risk your\n"        "time and  data on it.  If you don't want to follow that follow that\n"        "advice then  if you have just a few bad blocks,  try writing to the\n"	"bad blocks  and see if the drive remaps  the bad blocks (that means\n"	"it takes a block  it has  in reserve  and allocates  it for use for\n"	"of that block number).  If it cannot remap the block,  use badblock\n"	"option (-B) with  reiserfs utils to handle this block correctly.\n");}static int is_bad_block (unsigned long block){#ifdef IO_FAILURE_EMULATION        /* this array similates bad blocks on the device */    unsigned long bad_blocks [] =	{	    8208, 8209, 8210/*, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19*/	};    int i;        for (i = 0; i < sizeof (bad_blocks) / sizeof (bad_blocks[0]); i ++)	if (bad_blocks [i] == block)	    return 1;#endif    return 0;}/* All buffers are in double linked cycled list.  If getblk found buffer with   wanted block number in hash queue it moves buffer to the end of list. */static int g_nr_buffers;static unsigned long buffers_memory;/* create buffers until we spend this fraction of system memory, this** is a hard limit on the amount of buffer ram used*/#define BUFFER_MEMORY_FRACTION 10/* number of bytes in local buffer cache before we start forcing syncs** of dirty data and reusing unused buffers instead of allocating new** ones.  If a flush doesn't find reusable buffers, new ones are** still allocated up to the BUFFER_MEMORY_FRACTION percentage***/#define BUFFER_SOFT_LIMIT (500 * 1024)static unsigned long buffer_soft_limit = BUFFER_SOFT_LIMIT;#define NR_HASH_QUEUES 4096static struct buffer_head * g_a_hash_queues [NR_HASH_QUEUES];static struct buffer_head * Buffer_list_head;static struct buffer_head * g_free_buffers = NULL ;static struct buffer_head * g_buffer_heads;static int buffer_hits = 0 ;static int buffer_misses = 0 ;static int buffer_reads = 0 ;static int buffer_writes = 0 ;static void _show_buffers(struct buffer_head **list, int dev, unsigned long size) {    int all = 0;    int dirty = 0;    int in_use = 0; /* count != 0 */    int free = 0;    struct buffer_head * next;    next = *list;    if (!next)        return ;    for (;;) {	if (next->b_dev == dev && next->b_size == size) {	    all ++;	    if (next->b_count != 0) {		in_use ++;	    }	    if (buffer_dirty (next)) {		dirty ++;	    }	    if (buffer_clean (next) && next->b_count == 0) {		free ++;	    }	}	next = next->b_next;	if (next == *list)	    break;    }    printf("show_buffers (dev %d, size %lu): free %d, count != 0 %d, dirty %d, "	"all %d\n", dev, size, free, in_use, dirty, all);}static void show_buffers (int dev, int size){    _show_buffers(&Buffer_list_head, dev, size) ;    _show_buffers(&g_free_buffers, dev, size) ;}static void insert_into_hash_queue (struct buffer_head * bh){    int index = bh->b_blocknr % NR_HASH_QUEUES;    if (bh->b_hash_prev || bh->b_hash_next)	die ("insert_into_hash_queue: hash queue corrupted");    if (g_a_hash_queues[index]) {	g_a_hash_queues[index]->b_hash_prev = bh;	bh->b_hash_next = g_a_hash_queues[index];    }    g_a_hash_queues[index] = bh;}static void remove_from_hash_queue (struct buffer_head * bh){    if (bh->b_hash_next == 0 && bh->b_hash_prev == 0 && bh != g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES])	/* (b_dev == -1) ? */	return;    if (bh == g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES]) {	if (bh->b_hash_prev != 0)	    die ("remove_from_hash_queue: hash queue corrupted");	g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES] = bh->b_hash_next;    }    if (bh->b_hash_next)	bh->b_hash_next->b_hash_prev = bh->b_hash_prev;    if (bh->b_hash_prev)	bh->b_hash_prev->b_hash_next = bh->b_hash_next;    bh->b_hash_prev = bh->b_hash_next = 0;}static void put_buffer_list_end (struct buffer_head **list,                                 struct buffer_head * bh){    struct buffer_head * last = 0;    if (bh->b_prev || bh->b_next)	die ("put_buffer_list_end: buffer list corrupted");    if (*list == 0) {	bh->b_next = bh;	bh->b_prev = bh;	*list = bh;    } else {	last = (*list)->b_prev;	bh->b_next = last->b_next;	bh->b_prev = last;	last->b_next->b_prev = bh;	last->b_next = bh;    }}static void remove_from_buffer_list (struct buffer_head **list,                                     struct buffer_head * bh){    if (bh == bh->b_next) {	*list = 0;    } else {	bh->b_prev->b_next = bh->b_next;	bh->b_next->b_prev = bh->b_prev;	if (bh == *list)	    *list = bh->b_next;    }    bh->b_next = bh->b_prev = 0;}static void put_buffer_list_head (struct buffer_head **list,                                  struct buffer_head * bh){    put_buffer_list_end (list, bh);    *list = bh;}/*#include <sys/mman.h>static size_t estimate_memory_amount (void){    size_t len = 1;    size_t max = 0;    void * addr;    while (len > 0) {	addr = mmap (0, len, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);	if (addr == MAP_FAILED) {	    if (errno != ENOMEM)		die ("mmap failed: %s\n", strerror(errno));	    break;	}	if (mlock (addr, len) != 0) {	    if (errno == EPERM)		die ("No permission to run mlock");	    break;	}	munlock (addr, len);	munmap (addr, len);	max = len;	len *= 2;    }    // * If we've looped, we don't want to return 0, we want to return the    // * last successful len before we looped. In the event that mmap/mlock    // * failed for len = 1, max will still be 0, so we don't get an invalid    // * result    return max;}*/#define GROW_BUFFERS__NEW_BUFERS_PER_CALL 10/* creates number of new buffers and insert them into head of buffer list */static int grow_buffers (int size){    int i;    struct buffer_head * bh, * tmp;    /* get memory for array of buffer heads */    bh = (struct buffer_head *)getmem (GROW_BUFFERS__NEW_BUFERS_PER_CALL * 				       sizeof (struct buffer_head) + sizeof (struct buffer_head *));    if (g_buffer_heads == 0)	g_buffer_heads = bh;    else {	/* link new array to the end of array list */	tmp = g_buffer_heads;	while (*(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) != 0)	    tmp = *(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL);	*(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) = bh;    }    for (i = 0; i < GROW_BUFFERS__NEW_BUFERS_PER_CALL; i ++) {	tmp = bh + i;	memset (tmp, 0, sizeof (struct buffer_head));	tmp->b_data = getmem (size);	if (tmp->b_data == 0)	    die ("grow_buffers: no memory for new buffer data");	tmp->b_dev = -1;	tmp->b_size = size;	put_buffer_list_head (&g_free_buffers, tmp);    }    buffers_memory += GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;    g_nr_buffers += GROW_BUFFERS__NEW_BUFERS_PER_CALL;    return GROW_BUFFERS__NEW_BUFERS_PER_CALL;}struct buffer_head *find_buffer(int dev, unsigned long block, unsigned long size){		    struct buffer_head * next;    next = g_a_hash_queues[block % NR_HASH_QUEUES];    for (;;) {	struct buffer_head *tmp = next;	if (!next)	    break;	next = tmp->b_hash_next;	if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev)	    continue;	next = tmp;	break;    }    return next;}static struct buffer_head * get_free_buffer (struct buffer_head **list,                                             unsigned long size){    struct buffer_head * next;    next = *list;    if (!next)	return 0;    for (;;) {	if (!next)	    die ("get_free_buffer: buffer list is corrupted");	if (next->b_count == 0 && buffer_clean (next) && next->b_size == size) {	    remove_from_hash_queue (next);	    remove_from_buffer_list (list, next);	    return next;	}	next = next->b_next;	if (next == *list)	    break;    }    return 0;}/* to_write == 0 when all blocks have to be flushed. Otherwise - write only   buffers with b_count == 0 */static int sync_buffers (struct buffer_head **list, int dev, int to_write) {    struct buffer_head * next;    int written = 0;restart:    next = *list;    if (!next)	return 0;    for (;;) {	if (!next)	    die ("sync_buffers: buffer list is corrupted"); 	if (next->b_dev == dev && buffer_dirty (next) && buffer_uptodate (next)) {	    if ((to_write == 0 || next->b_count == 0) && !buffer_do_not_flush (next)) {		bwrite (next);	    }	}    	/* if this buffer is reusable, put it onto the end of the free list */	if (next->b_count == 0 && buffer_clean(next)) {	    remove_from_hash_queue (next);	    remove_from_buffer_list (list, next);	    put_buffer_list_end (&g_free_buffers, next);	    written++ ;	    if (written == to_write)		return written;	    goto restart;	}	if (to_write && written >= to_write)	    return written;	next = next->b_next;	if (next == *list)	    break;    }    return written;}void flush_buffers (int dev){    if (dev == -1)	die ("flush_buffers: device is not specified");    sync_buffers (&Buffer_list_head, dev, 0/*all*/);    buffer_soft_limit = BUFFER_SOFT_LIMIT;}struct buffer_head * getblk (int dev, unsigned long block, int size){    struct buffer_head * bh;    bh = find_buffer (dev, block, size);    if (bh) {	/* move the buffer to the end of list */	/*checkmem (bh->b_data, bh->b_size);*/	remove_from_buffer_list (&Buffer_list_head, bh);	put_buffer_list_end (&Buffer_list_head, bh);	bh->b_count ++;	buffer_hits++ ;	return bh;    }    buffer_misses++ ;    bh = get_free_buffer (&g_free_buffers, size);    if (bh == NULL) {	if (buffers_memory >= buffer_soft_limit) {	    if (sync_buffers (&Buffer_list_head, dev, 32) == 0) {		grow_buffers(size);		buffer_soft_limit = buffers_memory + 			GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;	    }	} else {	    if (grow_buffers(size) == 0)		sync_buffers (&Buffer_list_head, dev, 32);	}	bh = get_free_buffer (&g_free_buffers, size);	if (bh == NULL) {	    show_buffers (dev, size);	    die ("getblk: no free buffers after grow_buffers "		 "and refill (%d)", g_nr_buffers);	}    }    bh->b_count = 1;    bh->b_dev = dev;    bh->b_size = size;    bh->b_blocknr = block;    bh->b_end_io = NULL ;    memset (bh->b_data, 0, size);    misc_clear_bit(BH_Dirty, &bh->b_state);    misc_clear_bit(BH_Uptodate, &bh->b_state);    put_buffer_list_end (&Buffer_list_head, bh);    insert_into_hash_queue (bh);    /*checkmem (bh->b_data, bh->b_size);*/    return bh;}void brelse (struct buffer_head * bh){    if (bh == 0)	return;        if (bh->b_count == 0)	die ("brelse: can not free a free buffer %lu", bh->b_blocknr);        /*checkmem (bh->b_data, get_mem_size (bh->b_data));*/        bh->b_count --;}void bforget (struct buffer_head * bh){    if (bh) {	bh->b_state = 0;	brelse (bh);	remove_from_hash_queue (bh);	remove_from_buffer_list(&Buffer_list_head, bh);	put_buffer_list_head(&Buffer_list_head, bh);    }}/* Returns 0 on success; 1 - end of file; 0 - OK. */static int f_read(struct buffer_head * bh){    unsigned long long offset;    ssize_t bytes;    buffer_reads++ ;    offset = (unsigned long long)bh->b_size * bh->b_blocknr;    if (lseek (bh->b_dev, offset, SEEK_SET) < 0)	return -1;    bytes = read (bh->b_dev, bh->b_data, bh->b_size);

⌨️ 快捷键说明

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