Example #1
0
static int do_readahead(journal_t *journal, unsigned int start)
{
	int err;
	unsigned int max, nbufs, next;
	unsigned long long blocknr;
	struct buffer_head *bh;

	struct buffer_head * bufs[MAXBUF];

	/* Do up to 128K of readahead */
	max = start + (128 * 1024 / journal->j_blocksize);
	if (max > journal->j_maxlen)
		max = journal->j_maxlen;

	/* Do the readahead itself.  We'll submit MAXBUF buffer_heads at
	 * a time to the block device IO layer. */

	nbufs = 0;

	for (next = start; next < max; next++) {
		err = jbd2_journal_bmap(journal, next, &blocknr);

		if (err) {
			printk(KERN_ERR "JBD2: bad block at offset %u\n",
				next);
			goto failed;
		}

		bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
		if (!bh) {
			err = -ENOMEM;
			goto failed;
		}

		if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
			bufs[nbufs++] = bh;
			if (nbufs == MAXBUF) {
				ll_rw_block(READ, nbufs, bufs);
				journal_brelse_array(bufs, nbufs);
				nbufs = 0;
			}
		} else
			brelse(bh);
	}

	if (nbufs)
		ll_rw_block(READ, nbufs, bufs);
	err = 0;

failed:
	if (nbufs)
		journal_brelse_array(bufs, nbufs);
	return err;
}
static int ufs_fmp_run(struct device *dev, uint32_t mode, uint8_t *data,
			uint32_t len, uint32_t write)
{
	struct ufs_hba *hba;
	struct ufs_fmp_work *work;
	struct Scsi_Host *host;
	static struct buffer_head *bh;

	work = dev_get_drvdata(dev);
	if (!work) {
		dev_err(dev, "Fail to get work from platform device\n");
		return -ENODEV;
	}
	host = work->host;
	hba = shost_priv(host);
	hba->self_test_mode = mode;

	bh = __getblk(work->bdev, work->sector, FMP_BLK_SIZE);
	if (!bh) {
		dev_err(dev, "Fail to get block from bdev\n");
		return -ENODEV;
	}
	hba->self_test_bh = bh;

	get_bh(bh);
	if (write == WRITE_MODE) {
		memcpy(bh->b_data, data, len);
		bh->b_state &= ~(1 << BH_Uptodate);
		bh->b_state &= ~(1 << BH_Lock);
		ll_rw_block(WRITE_FLUSH_FUA, 1, &bh);
		wait_on_buffer(bh);

		memset(bh->b_data, 0, FMP_BLK_SIZE);
	} else {
		bh->b_state &= ~(1 << BH_Uptodate);
		bh->b_state &= ~(1 << BH_Lock);
		ll_rw_block(READ_SYNC, 1, &bh);
		wait_on_buffer(bh);

		memcpy(data, bh->b_data, len);
	}
	put_bh(bh);

	hba->self_test_mode = 0;
	hba->self_test_bh = NULL;

	return 0;
}
Example #3
0
static int read_bitmaps (struct super_block * s)
{
    int i, bmp;

    SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * SB_BMAP_NR(s), GFP_NOFS, s);
    if (SB_AP_BITMAP (s) == 0)
      return 1;
    for (i = 0, bmp = REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
 	 i < SB_BMAP_NR(s); i++, bmp = s->s_blocksize * 8 * i) {
      SB_AP_BITMAP (s)[i] = getblk (s->s_dev, bmp, s->s_blocksize);
      if (!buffer_uptodate(SB_AP_BITMAP(s)[i]))
	ll_rw_block(READ, 1, SB_AP_BITMAP(s) + i); 
    }
    for (i = 0; i < SB_BMAP_NR(s); i++) {
      wait_on_buffer(SB_AP_BITMAP (s)[i]);
      if (!buffer_uptodate(SB_AP_BITMAP(s)[i])) {
	reiserfs_warning("sh-2029: reiserfs read_bitmaps: "
			 "bitmap block (#%lu) reading failed\n",
			 SB_AP_BITMAP(s)[i]->b_blocknr);
	for (i = 0; i < SB_BMAP_NR(s); i++)
	  brelse(SB_AP_BITMAP(s)[i]);
	reiserfs_kfree(SB_AP_BITMAP(s), sizeof(struct buffer_head *) * SB_BMAP_NR(s), s);
	SB_AP_BITMAP(s) = NULL;
	return 1;
      }
    }   
    return 0;
}
Example #4
0
/**
 *  prepare the blocks and map them 
 * @param inode        inode    
 * @param page page pointer
 * @param from start offset within page        
 * @param to   last offset within page  
 * @param get_block    get_block funciton       
 * @return     return 0 on success, errno on failure
 */
int rfs_block_prepare_write(struct inode * inode, struct page * page, unsigned from, unsigned to, get_block_t *get_block) 
{
       struct buffer_head *bh, *head;
       unsigned long block;
       unsigned block_start, block_end, blocksize, bbits; 
       int err = 0;
       char *kaddr = kmap(page);

       bbits = inode->i_blkbits;
       blocksize = 1 << bbits;

       if (!page->buffers) 
               create_empty_buffers(page, inode->i_dev, blocksize);
       head = page->buffers;

       block = page->index << (PAGE_CACHE_SHIFT - bbits); /* start block # */

       /* we allocate buffers and map them */
       for(bh = head, block_start = 0; bh != head || !block_start;
               block++, block_start = block_end + 1, bh = bh->b_this_page) {
               if (!bh) {
                       err = -EIO;
                       RFS_BUG("can't get buffer head\n");
                       goto out;
               }
               block_end = block_start + blocksize - 1;
               if (block_end < from) {
                       continue;
               } else if (block_start > to) { 
                       break;
               }
               clear_bit(BH_New, &bh->b_state);

               /* map new buffer if necessary*/        
               if (!buffer_mapped(bh) || (inode->i_size <= (block<<(inode->i_sb->s_blocksize_bits)))) {
                       err = get_block(inode, block, bh, 1);
                       if (err) {
                               DEBUG(DL1, "no block\n");       
                               goto out;
                       }
                       if (buffer_new(bh) && block_end > to) {
                               memset(kaddr+to+1, 0, block_end-to);
                               continue;
                       }
               }                       
               if (!buffer_uptodate(bh) && 
                       (block_start < from || block_end > to)) {
                       ll_rw_block(READ, 1, &bh);
                       wait_on_buffer(bh);
                       if (!buffer_uptodate(bh)) {
                               err = -EIO;
                               goto out;
                       }
               }
       }
out:
       flush_dcache_page(page);        
       kunmap_atomic(kaddr, KM_USER0);
       return err;     
}
Example #5
0
/*
 * Try to free up some pages by shrinking the buffer-cache
 *
 * Priority tells the routine how hard to try to shrink the
 * buffers: 3 means "don't bother too much", while a value
 * of 0 means "we'd better get some free pages now".
 */
int shrink_buffers(unsigned int priority)
{
	struct buffer_head *bh;
	int i;

	if (priority < 2)
		sync_buffers(0);
	bh = free_list;
	i = nr_buffers >> priority;
	for ( ; i-- > 0 ; bh = bh->b_next_free) {
		if (bh->b_count || !bh->b_this_page)
			continue;
		if (bh->b_lock)
			if (priority)
				continue;
			else
				wait_on_buffer(bh);
		if (bh->b_dirt) {
			ll_rw_block(WRITEA,bh);
			continue;
		}
		if (try_to_free(bh))
			return 1;
	}
	return 0;
}
Example #6
0
static int sync_block (struct inode * inode, u32 * block, int wait)
{
	struct buffer_head * bh;
	int tmp;
	
	if (!*block)
		return 0;
	tmp = *block;
	bh = get_hash_table (inode->i_dev, *block, blocksize);
	if (!bh)
		return 0;
	if (*block != tmp) {
		brelse (bh);
		return 1;
	}
	if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
		brelse (bh);
		return -1;
	}
	if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
		brelse (bh);
		return 0;
	}
	ll_rw_block (WRITE, 1, &bh);
	bh->b_count--;
	return 0;
}
Example #7
0
void ubh_ll_rw_block(int rw, struct ufs_buffer_head *ubh)
{
	if (!ubh)
		return;

	ll_rw_block(rw, ubh->count, ubh->bh);
}
Example #8
0
static int read_bitmaps (struct super_block * s)
{
    int i, bmp;

    SB_AP_BITMAP (s) = vmalloc (sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
    if (SB_AP_BITMAP (s) == 0)
      return 1;
    memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s));

    for (i = 0, bmp = REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
 	 i < SB_BMAP_NR(s); i++, bmp = s->s_blocksize * 8 * i) {
      SB_AP_BITMAP (s)[i].bh = sb_getblk (s, bmp);
      if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
	ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh); 
    }
    for (i = 0; i < SB_BMAP_NR(s); i++) {
      wait_on_buffer(SB_AP_BITMAP (s)[i].bh);
      if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
	reiserfs_warning("sh-2029: reiserfs read_bitmaps: "
			 "bitmap block (#%lu) reading failed\n",
			 SB_AP_BITMAP(s)[i].bh->b_blocknr);
	for (i = 0; i < SB_BMAP_NR(s); i++)
	  brelse(SB_AP_BITMAP(s)[i].bh);
	vfree(SB_AP_BITMAP(s));
	SB_AP_BITMAP(s) = NULL;
	return 1;
      }
      load_bitmap_info_data (s, SB_AP_BITMAP (s) + i);
    }   
    return 0;
}
Example #9
0
void journal_sync_buffer(struct buffer_head *bh)
{
	transaction_t *transaction;
	journal_t *journal;
	long sequence;
	
	/* If the buffer isn't journaled, this is easy: just sync it to
	 * disk.  */

	if (bh->b_transaction == NULL) {
		/* If the buffer has already been journaled, then this
		 * is a noop. */
		if (bh->b_cp_transaction == NULL) 
			return;
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
		return;
	}
	
	/* Otherwise, just wait until the transaction is synced to disk. */
	transaction = bh->b_transaction;
	journal = transaction->t_journal;
	sequence = transaction->t_tid;
	
	jfs_debug(2, "requesting commit for bh %p\n", bh);
	log_start_commit (journal, transaction);
	
	while (tid_gt(sequence, journal->j_commit_sequence)) {
		wake_up(&journal->j_wait_done_commit);
		sleep_on(&journal->j_wait_done_commit);
	}
}
Example #10
0
/* Sync one block. The block number is
 * from_coh_ulong(*blockp) if convert=1, *blockp if convert=0.
 */
static int sync_block (struct inode * inode, u32 *blockp, int convert, int wait)
{
	struct buffer_head * bh;
	u32 tmp, block;
	struct super_block * sb;

	block = tmp = *blockp;
	if (convert)
		block = from_coh_ulong(block);
	if (!block)
		return 0;
	sb = inode->i_sb;
	bh = sv_get_hash_table(sb, inode->i_dev, block);
	if (!bh)
		return 0;
	if (*blockp != tmp) {
		brelse (bh);
		return 1;
	}
	if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
		brelse(bh);
		return -1;
	}
	if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
		brelse(bh);
		return 0;
	}
	ll_rw_block(WRITE, 1, &bh);
	atomic_dec(&bh->b_count);
	return 0;
}
Example #11
0
/*
 * Try to free up some pages by shrinking the buffer-cache
 *
 * Priority tells the routine how hard to try to shrink the
 * buffers: 3 means "don't bother too much", while a value
 * of 0 means "we'd better get some free pages now".
 */
int shrink_buffers(unsigned int priority)
{
	struct buffer_head *bh;
	int i;

	if (priority < 2)
		sync_buffers(0,0);
	bh = free_list;
	i = nr_buffers >> priority;
	for ( ; i-- > 0 ; bh = bh->b_next_free) {
		if (bh->b_count ||
		    (priority >= 5 &&
		     mem_map[MAP_NR((unsigned long) bh->b_data)] > 1)) {
			put_last_free(bh);
			continue;
		}
		if (!bh->b_this_page)
			continue;
		if (bh->b_lock)
			if (priority)
				continue;
			else
				wait_on_buffer(bh);
		if (bh->b_dirt) {
			bh->b_count++;
			ll_rw_block(WRITEA, 1, &bh);
			bh->b_count--;
			continue;
		}
		if (try_to_free(bh, &bh))
			return 1;
	}
	return 0;
}
Example #12
0
//// 从指定设备上读取指定的数据块。
struct buffer_head *
bread( int dev, int block )
{
	struct buffer_head *bh;

// 在高速缓冲中申请一块缓冲区。如果返回值是NULL 指针,表示内核出错,死机。
	if( !( bh = getblk( dev, block ) ) )
	{
		panic( "bread: getblk returned NULL\n" );
	}
// 如果该缓冲区中的数据是有效的(已更新的)可以直接使用,则返回。
	if( bh->b_uptodate )
	{
		return bh;
	}
// 否则调用ll_rw_block()函数,产生读设备块请求。并等待缓冲区解锁。
	ll_rw_block( READ, bh );
	wait_on_buffer( bh );
// 如果该缓冲区已更新,则返回缓冲区头指针,退出。
	if( bh->b_uptodate )
	{
		return bh;
	}
// 否则表明读设备操作失败,释放该缓冲区,返回NULL 指针,退出。
	brelse( bh );
	return NULL;
}
Example #13
0
void msdos_ll_rw_block (
	struct super_block *sb,
	int opr,
	int nbreq,
	struct buffer_head *bh[32])
{
	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);
	}
}
Example #14
0
void default_fat_ll_rw_block (
    struct super_block *sb,
    int opr,
    int nbreq,
    struct buffer_head *bh[32])
{
    ll_rw_block(opr,nbreq,bh);
}
Example #15
0
static inline void dirty_indirect(struct buffer_head *bh, struct inode *inode)
{
	mark_buffer_dirty_inode(bh, inode);
	if (IS_SYNC(inode)) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}
}
Example #16
0
static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
{
	es->s_wtime = cpu_to_le32(CURRENT_TIME);
	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
	ll_rw_block(WRITE, 1, &EXT2_SB(sb)->s_sbh);
	wait_on_buffer(EXT2_SB(sb)->s_sbh);
	sb->s_dirt = 0;
}
Example #17
0
void brelse(struct buffer_head *bh)
{
	if (bh->b_dirty)
		ll_rw_block(WRITE, 1, &bh);
	jfs_debug(3, "freeing block %lu/%p (total %d)\n",
		  (unsigned long) bh->b_blocknr, (void *) bh, --bh_count);
	ext2fs_free_mem(&bh);
}
Example #18
0
/* after journal replay, reread all bitmap and super blocks */
static int reread_meta_blocks(struct super_block *s) {
  int i ;
  ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))) ;
  wait_on_buffer(SB_BUFFER_WITH_SB(s)) ;
  if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
    printk("reread_meta_blocks, error reading the super\n") ;
    return 1 ;
  }

  for (i = 0; i < SB_BMAP_NR(s) ; i++) {
    ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh)) ;
    wait_on_buffer(SB_AP_BITMAP(s)[i].bh) ;
    if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
      printk("reread_meta_blocks, error reading bitmap block number %d at
      %ld\n", i, SB_AP_BITMAP(s)[i].bh->b_blocknr) ;
      return 1 ;
    }
  }
Example #19
0
static int minix_file_write(struct inode * inode, struct file * filp, const char * buf, int count)
{
	off_t pos;
	int written,c;
	struct buffer_head * bh;
	char * p;

	if (!inode) {
		printk("minix_file_write: inode = NULL\n");
		return -EINVAL;
	}
	if (!S_ISREG(inode->i_mode)) {
		printk("minix_file_write: mode = %07o\n",inode->i_mode);
		return -EINVAL;
	}
	if (filp->f_flags & O_APPEND)
		pos = inode->i_size;
	else
		pos = filp->f_pos;
	written = 0;
	while (written < count) {
		bh = minix_getblk(inode,pos/BLOCK_SIZE,1);
		if (!bh) {
			if (!written)
				written = -ENOSPC;
			break;
		}
		c = BLOCK_SIZE - (pos % BLOCK_SIZE);
		if (c > count-written)
			c = count-written;
		if (c != BLOCK_SIZE && !buffer_uptodate(bh)) {
			ll_rw_block(READ, 1, &bh);
			wait_on_buffer(bh);
			if (!buffer_uptodate(bh)) {
				brelse(bh);
				if (!written)
					written = -EIO;
				break;
			}
		}
		p = (pos % BLOCK_SIZE) + bh->b_data;
		memcpy_fromfs(p,buf,c);
		update_vm_cache(inode, pos, p, c);
		mark_buffer_uptodate(bh, 1);
		mark_buffer_dirty(bh, 0);
		brelse(bh);
		pos += c;
		written += c;
		buf += c;
	}
	if (pos > inode->i_size)
		inode->i_size = pos;
	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
	filp->f_pos = pos;
	inode->i_dirt = 1;
	return written;
}
Example #20
0
static int sync_buffers(dev_t dev, int wait)
{
	int i, retry, pass = 0, err = 0;
	struct buffer_head * bh;

	/* One pass for no-wait, three for wait:
	   0) write out all dirty, unlocked buffers;
	   1) write out all dirty buffers, waiting if locked;
	   2) wait for completion by waiting for all buffers to unlock.
	 */
repeat:
	retry = 0;
	bh = free_list;
	for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) {
		if (dev && bh->b_dev != dev)
			continue;
#ifdef 0 /* Disable bad-block debugging code */
		if (bh->b_req && !bh->b_lock &&
		    !bh->b_dirt && !bh->b_uptodate)
			printk ("Warning (IO error) - orphaned block %08x on %04x\n",
				bh->b_blocknr, bh->b_dev);
#endif
		if (bh->b_lock)
		{
			/* Buffer is locked; skip it unless wait is
			   requested AND pass > 0. */
			if (!wait || !pass) {
				retry = 1;
				continue;
			}
			wait_on_buffer (bh);
		}
		/* If an unlocked buffer is not uptodate, there has been 
		   an IO error. Skip it. */
		if (wait && bh->b_req && !bh->b_lock &&
		    !bh->b_dirt && !bh->b_uptodate)
		{
			err = 1;
			continue;
		}
		/* Don't write clean buffers.  Don't write ANY buffers
		   on the third pass. */
		if (!bh->b_dirt || pass>=2)
			continue;
		bh->b_count++;
		ll_rw_block(WRITE, 1, &bh);
		bh->b_count--;
		retry = 1;
	}
	/* If we are waiting for the sync to succeed, and if any dirty
	   blocks were written, then repeat; on the second pass, only
	   wait for buffers being written (do not pass to write any
	   more buffers on the second pass). */
	if (wait && retry && ++pass<=2)
		goto repeat;
	return err;
}
Example #21
0
static struct buffer_head * block_getblk(struct inode * inode,
        struct buffer_head * bh, int nr, int create, char * *start)
{
    struct super_block *sb;
    unsigned long tmp, block;
    sysv_zone_t *p;
    struct buffer_head * result;

    if (!bh)
        return NULL;
    if (!bh->b_uptodate) {
        ll_rw_block(READ, 1, &bh);
        wait_on_buffer(bh);
        if (!bh->b_uptodate) {
            brelse(bh);
            return NULL;
        }
    }
    sb = inode->i_sb;
    p = nr + (sysv_zone_t *) *start;
repeat:
    block = tmp = *p;
    if (sb->sv_convert)
        block = from_coh_ulong(block);
    if (tmp) {
        result = getblk(bh->b_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
        if (tmp == *p) {
            brelse(bh);
            *start = result->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
            return result;
        }
        brelse(result);
        goto repeat;
    }
    if (!create) {
        brelse(bh);
        return NULL;
    }
    block = sysv_new_block(sb);
    if (!block) {
        brelse(bh);
        return NULL;
    }
    result = getblk(bh->b_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
    if (*p) {
        sysv_free_block(sb,block);
        brelse(result);
        goto repeat;
    }
    *p = (sb->sv_convert ? to_coh_ulong(block) : block);
    mark_buffer_dirty(bh, 1);
    brelse(bh);
    *start = result->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
    return result;
}
Example #22
0
static int journal_get_superblock(journal_t *journal)
{
    struct buffer_head *bh;
    journal_superblock_t *sb;
    int err = -EIO;

    bh = journal->j_sb_buffer;

    J_ASSERT(bh != NULL);
    if (!buffer_uptodate(bh)) {
        ll_rw_block(READ, 1, &bh);
        wait_on_buffer(bh);
        if (!buffer_uptodate(bh)) {
            printk (KERN_ERR
                    "JBD: IO error reading journal superblock\n");
            goto out;
        }
    }

    sb = journal->j_superblock;

    err = -EINVAL;

    if (sb->s_header.h_magic != cpu_to_be32(JFS_MAGIC_NUMBER) ||
            sb->s_blocksize != cpu_to_be32(journal->j_blocksize)) {
        printk(KERN_WARNING "JBD: no valid journal superblock found\n");
        goto out;
    }

    switch (be32_to_cpu(sb->s_header.h_blocktype)) {
    case JFS_SUPERBLOCK_V1:
        journal->j_format_version = 1;
        break;
    case JFS_SUPERBLOCK_V2:
        journal->j_format_version = 2;
        break;
    default:
        printk(KERN_WARNING "JBD: unrecognised superblock format ID\n");
        goto out;
    }

    if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen)
        journal->j_maxlen = be32_to_cpu(sb->s_maxlen);
    else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) {
        printk (KERN_WARNING "JBD: journal file too short\n");
        goto out;
    }

    return 0;

out:
    journal_fail_superblock(journal);
    return err;
}
Example #23
0
//// 从指定设备读取指定的一些块。
// 成功时返回第1 块的缓冲区头指针,否则返回NULL。
struct buffer_head *
breada( int dev, int first, ... )
{
	va_list				args;
	struct buffer_head	*bh, *tmp;

// 取可变参数表中第1 个参数(块号)。
	va_start( args, first );
// 取高速缓冲中指定设备和块号的缓冲区。如果该缓冲区数据无效,则发出读设备数据块请求。
	if( !( bh = getblk( dev, first ) ) )
	{
		panic( "bread: getblk returned NULL\n" );
	}
	if( !bh->b_uptodate )
	{
		ll_rw_block( READ, bh );
	}
// 然后顺序取可变参数表中其它预读块号,并作与上面同样处理,但不引用。
	while( ( first = va_arg( args, int ) ) >= 0 )
	{
		tmp = getblk( dev, first );
		if( tmp )
		{
			if( !tmp->b_uptodate )
			{
				ll_rw_block( READA, bh );
			}
			tmp->b_count--;
		}
	}
// 可变参数表中所有参数处理完毕。等待第1 个缓冲区解锁(如果已被上锁)。
	va_end( args );
	wait_on_buffer( bh );
// 如果缓冲区中数据有效,则返回缓冲区头指针,退出。否则释放该缓冲区,返回NULL,退出。
	if( bh->b_uptodate )
	{
		return bh;
	}
	brelse( bh );
	return ( NULL );
}
Example #24
0
/*
 * floppy-change is never called from an interrupt, so we can relax a bit
 * here, sleep etc. Note that floppy-on tries to set current_DOR to point
 * to the desired drive, but it will probably not survive the sleep if
 * several floppies are used at the same time: thus the loop.
 */
int floppy_change(struct buffer_head * bh)
{
	unsigned int mask = 1 << (bh->b_dev & 0x03);

	if (MAJOR(bh->b_dev) != 2) {
		printk("floppy_changed: not a floppy\r\n");
		return 0;
	}
	if (fake_change & mask) {
		fake_change &= ~mask;
/* omitting the next line breaks formatting in a horrible way ... */
		changed_floppies &= ~mask;
		return 1;
	}
	if (changed_floppies & mask) {
		changed_floppies &= ~mask;
		recalibrate = 1;
		return 1;
	}
	if (!bh)
		return 0;
	if (bh->b_dirt)
		ll_rw_block(WRITE,bh);
	else {
		buffer_track = -1;
		bh->b_uptodate = 0;
		ll_rw_block(READ,bh);
	}
	cli();
	while (bh->b_lock)
		sleep_on(&bh->b_wait);
	sti();
	if (changed_floppies & mask) {
		changed_floppies &= ~mask;
		recalibrate = 1;
		return 1;
	}
	return 0;
}
Example #25
0
struct buffer_head * getblk(int dev,int block)
{
	struct buffer_head * bh, * tmp;
	int buffers;

repeat:
	if (bh = get_hash_table(dev,block))
		return bh;
	buffers = NR_BUFFERS;
	tmp = free_list;
	do {
		tmp = tmp->b_next_free;
		if (tmp->b_count)
			continue;
		if (!bh || BADNESS(tmp)<BADNESS(bh)) {
			bh = tmp;
			if (!BADNESS(tmp))
				break;
		}
		if (tmp->b_dirt)
			ll_rw_block(WRITEA,tmp);
/* and repeat until we find something good */
	} while (buffers--);
	if (!bh) {
		sleep_on(&buffer_wait);
		goto repeat;
	}
	wait_on_buffer(bh);
	if (bh->b_count)
		goto repeat;
	while (bh->b_dirt) {
		sync_dev(bh->b_dev);
		wait_on_buffer(bh);
		if (bh->b_count)
			goto repeat;
	}
/* NOTE!! While we slept waiting for this block, somebody else might */
/* already have added "this" block to the cache. check it */
	if (find_buffer(dev,block))
		goto repeat;
/* OK, FINALLY we know that this buffer is the only one of it's kind, */
/* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
	bh->b_count=1;
	bh->b_dirt=0;
	bh->b_uptodate=0;
	remove_from_queues(bh);
	bh->b_dev=dev;
	bh->b_blocknr=block;
	insert_into_queues(bh);
	return bh;
}
Example #26
0
/**
 * floppy-change is never called from an interrupt, so we can relax a bit
 * here, sleep etc. Note that floppy-on tries to set current_DOR to point
 * to the desired drive, but it will probably not survive the sleep if
 * several floppies are used at the same time: thus the loop.
 */
static int floppy_change(struct buffer_head *bh) {

	unsigned int mask = 1 << (bh->b_dev & 0x03);
	if (MAJOR(bh->b_dev) != MAJOR_NR) {
		printk("floppy_changed: not a floppy\n");
		return 0;
	}
	if (fake_change & mask) {
		buffer_track = -1;
		fake_change &= ~mask;
		changed_floppies &= ~mask;
		return 1;
	}
	if (changed_floppies & mask) {
		buffer_track = -1;
		changed_floppies &= ~mask;
		recalibrate = 1;
		return 1;
	}
	if (!bh)
		return 0;

	if (bh->b_dirt)
		ll_rw_block(WRITE, 1, &bh);
	else {
		buffer_track = -1;
		bh->b_uptodate = 0;
		ll_rw_block(READ, 1, &bh);
	}

	//wait_on_buffer(bh);
	if (changed_floppies & mask) {
		changed_floppies &= ~mask;
		recalibrate = 1;
		return 1;
	}
	return 0;
}
Example #27
0
int sys_sync(void)
{
	int i;
	struct buffer_head * bh;

	sync_inodes();		/* write out inodes into buffers */
	bh = start_buffer;
	for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
		wait_on_buffer(bh);
		if (bh->b_dirt)
			ll_rw_block(WRITE,bh);
	}
	return 0;
}
Example #28
0
/*
 * bread() reads a specified block and returns the buffer that contains
 * it. It returns NULL if the block was unreadable.
 */
struct buffer_head * bread(int dev,int block)
{
	struct buffer_head * bh;

	if (!(bh=getblk(dev,block)))
		panic("bread: getblk returned NULL\n");
	if (bh->b_uptodate)
		return bh;
	ll_rw_block(READ,bh);
	if (bh->b_uptodate)
		return bh;
	brelse(bh);
	return (NULL);
}
Example #29
0
struct buffer_head * minix_bread(struct inode * inode, int block, int create)
{
	struct buffer_head * bh;

	bh = minix_getblk(inode,block,create);
	if (!bh || bh->b_uptodate)
		return bh;
	ll_rw_block(READ,bh);
	wait_on_buffer(bh);
	if (bh->b_uptodate)
		return bh;
	brelse(bh);
	return NULL;
}
Example #30
0
static void sync_buffers(int dev)
{
	int i;
	struct buffer_head * bh;

	bh = free_list;
	for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) {
		if (bh->b_lock)
			continue;
		if (!bh->b_dirt)
			continue;
		ll_rw_block(WRITE,bh);
	}
}