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; }
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; }
/** * 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; }
/* * 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; }
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; }
void ubh_ll_rw_block(int rw, struct ufs_buffer_head *ubh) { if (!ubh) return; ll_rw_block(rw, ubh->count, ubh->bh); }
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; }
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); } }
/* 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; }
/* * 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; }
//// 从指定设备上读取指定的数据块。 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; }
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); } }
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); }
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); } }
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; }
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); }
/* 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 ; } }
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; }
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; }
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; }
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; }
//// 从指定设备读取指定的一些块。 // 成功时返回第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 ); }
/* * 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; }
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; }
/** * 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; }
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; }
/* * 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); }
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; }
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); } }