static struct buffer_head *qnx4_getblk(struct inode *inode, int nr, int create) { struct buffer_head *result = NULL; if ( nr >= 0 ) nr = qnx4_block_map( inode, nr ); if (nr) { result = sb_getblk(inode->i_sb, nr); return result; } if (!create) { return NULL; } #if 0 tmp = qnx4_new_block(inode->i_sb); if (!tmp) { return NULL; } result = sb_getblk(inode->i_sb, tmp); if (tst) { qnx4_free_block(inode->i_sb, tmp); brelse(result); goto repeat; } tst = tmp; #endif inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); return result; }
struct buffer_head *udf_tgetblk(struct super_block *sb, int block) { if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) return sb_getblk(sb, udf_fixed_to_variable(block)); else return sb_getblk(sb, block); }
static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, ext4_fsblk_t mmp_block) { struct mmp_struct *mmp; if (*bh) clear_buffer_uptodate(*bh); if (!*bh) *bh = sb_getblk(sb, mmp_block); if (!*bh) return -ENOMEM; if (*bh) { get_bh(*bh); lock_buffer(*bh); (*bh)->b_end_io = end_buffer_read_sync; submit_bh(READ_SYNC, *bh); wait_on_buffer(*bh); if (!buffer_uptodate(*bh)) { brelse(*bh); *bh = NULL; } } if (!*bh) { ext4_warning(sb, "Error while reading MMP block %llu", mmp_block); return -EIO; } mmp = (struct mmp_struct *)((*bh)->b_data); if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) return -EINVAL; return 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; }
static struct buffer_head * read_block_bitmap(struct super_block *sb, unsigned int block_group) { struct ext2_group_desc * desc; struct buffer_head * bh = NULL; ext2_fsblk_t bitmap_blk; desc = ext2_get_group_desc(sb, block_group, NULL); if (!desc) return NULL; bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); bh = sb_getblk(sb, bitmap_blk); if (unlikely(!bh)) { ext2_error(sb, __func__, "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); return NULL; } if (likely(bh_uptodate_or_lock(bh))) return bh; if (bh_submit_read(bh) < 0) { brelse(bh); ext2_error(sb, __func__, "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); return NULL; } ext2_valid_block_bitmap(sb, desc, block_group, bh); return bh; }
/* * Nullify new chunk of inodes, * BSD people also set ui_gen field of inode * during nullification, but we not care about * that because of linux ufs do not support NFS */ static void ufs2_init_inodes_chunk(struct super_block *sb, struct ufs_cg_private_info *ucpi, struct ufs_cylinder_group *ucg) { struct buffer_head *bh; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; sector_t beg = uspi->s_sbbase + ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg + fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk)); sector_t end = beg + uspi->s_fpb; UFSD("ENTER cgno %d\n", ucpi->c_cgx); for (; beg < end; ++beg) { bh = sb_getblk(sb, beg); lock_buffer(bh); memset(bh->b_data, 0, sb->s_blocksize); set_buffer_uptodate(bh); mark_buffer_dirty(bh); unlock_buffer(bh); if (sb->s_flags & MS_SYNCHRONOUS) sync_dirty_buffer(bh); brelse(bh); } fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); if (sb->s_flags & MS_SYNCHRONOUS) { ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); ubh_wait_on_buffer(UCPI_UBH(ucpi)); } UFSD("EXIT\n"); }
void sysv_free_block(struct super_block * sb, sysv_zone_t nr) { struct sysv_sb_info * sbi = SYSV_SB(sb); struct buffer_head * bh; sysv_zone_t *blocks = sbi->s_bcache; unsigned count; unsigned block = fs32_to_cpu(sbi, nr); /* * This code does not work at all for AFS (it has a bitmap * free list). As AFS is supposed to be read-only no one * should call this for an AFS filesystem anyway... */ if (sbi->s_type == FSTYPE_AFS) return; if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { printk("sysv_free_block: trying to free block not in datazone\n"); return; } mutex_lock(&sbi->s_lock); count = fs16_to_cpu(sbi, *sbi->s_bcache_count); if (count > sbi->s_flc_size) { printk("sysv_free_block: flc_count %d > flc_size %d\n", count, sbi->s_flc_size); mutex_unlock(&sbi->s_lock); return; } /* If the free list head in super-block is full, it is copied * into this block being freed, ditto if it's completely empty * (applies only on Coherent). */ if (count == sbi->s_flc_size || count == 0) { block += sbi->s_block_base; bh = sb_getblk(sb, block); if (!bh) { printk("sysv_free_block: getblk() failed\n"); mutex_unlock(&sbi->s_lock); return; } memset(bh->b_data, 0, sb->s_blocksize); *(__fs16*)bh->b_data = cpu_to_fs16(sbi, count); memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t)); mark_buffer_dirty(bh); set_buffer_uptodate(bh); brelse(bh); count = 0; } sbi->s_bcache[count++] = nr; *sbi->s_bcache_count = cpu_to_fs16(sbi, count); fs32_add(sbi, sbi->s_free_blocks, 1); dirty_sb(sb); mutex_unlock(&sbi->s_lock); }
/** * nilfs_move_2nd_super - relocate secondary super block * @sb: super block instance * @sb2off: new offset of the secondary super block (in bytes) */ static int nilfs_move_2nd_super(struct super_block *sb, loff_t sb2off) { struct the_nilfs *nilfs = sb->s_fs_info; struct buffer_head *nsbh; struct nilfs_super_block *nsbp; sector_t blocknr, newblocknr; unsigned long offset; int sb2i; /* array index of the secondary superblock */ int ret = 0; /* nilfs->ns_sem must be locked by the caller. */ if (nilfs->ns_sbh[1] && nilfs->ns_sbh[1]->b_blocknr > nilfs->ns_first_data_block) { sb2i = 1; blocknr = nilfs->ns_sbh[1]->b_blocknr; } else if (nilfs->ns_sbh[0]->b_blocknr > nilfs->ns_first_data_block) { sb2i = 0; blocknr = nilfs->ns_sbh[0]->b_blocknr; } else { sb2i = -1; blocknr = 0; } if (sb2i >= 0 && (u64)blocknr << nilfs->ns_blocksize_bits == sb2off) goto out; /* super block location is unchanged */ /* Get new super block buffer */ newblocknr = sb2off >> nilfs->ns_blocksize_bits; offset = sb2off & (nilfs->ns_blocksize - 1); nsbh = sb_getblk(sb, newblocknr); if (!nsbh) { nilfs_msg(sb, KERN_WARNING, "unable to move secondary superblock to block %llu", (unsigned long long)newblocknr); ret = -EIO; goto out; } nsbp = (void *)nsbh->b_data + offset; memset(nsbp, 0, nilfs->ns_blocksize); if (sb2i >= 0) { memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize); brelse(nilfs->ns_sbh[sb2i]); nilfs->ns_sbh[sb2i] = nsbh; nilfs->ns_sbp[sb2i] = nsbp; } else if (nilfs->ns_sbh[0]->b_blocknr < nilfs->ns_first_data_block) { /* secondary super block will be restored to index 1 */ nilfs->ns_sbh[1] = nsbh; nilfs->ns_sbp[1] = nsbp; } else { brelse(nsbh); } out: return ret; }
/* Write to quotafile */ static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off) { struct inode *inode = sb_dqopt(sb)->files[type]; sector_t blk = off >> EXT2_BLOCK_SIZE_BITS(sb); int err = 0; int offset = off & (sb->s_blocksize - 1); int tocopy; size_t towrite = len; struct buffer_head tmp_bh; struct buffer_head *bh; mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); while (towrite > 0) { tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; tmp_bh.b_state = 0; err = ext2_get_block(inode, blk, &tmp_bh, 1); if (err < 0) goto out; if (offset || tocopy != EXT2_BLOCK_SIZE(sb)) bh = sb_bread(sb, tmp_bh.b_blocknr); else bh = sb_getblk(sb, tmp_bh.b_blocknr); if (!bh) { err = -EIO; goto out; } lock_buffer(bh); memcpy(bh->b_data+offset, data, tocopy); flush_dcache_page(bh->b_page); set_buffer_uptodate(bh); mark_buffer_dirty(bh); unlock_buffer(bh); brelse(bh); offset = 0; towrite -= tocopy; data += tocopy; blk++; } out: if (len == towrite) { mutex_unlock(&inode->i_mutex); return err; } if (inode->i_size < off+len-towrite) i_size_write(inode, off+len-towrite); inode->i_version++; inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); mutex_unlock(&inode->i_mutex); return len - towrite; }
static struct buffer_head *qnx4_getblk(struct inode *inode, int nr, int create) { struct buffer_head *result = NULL; if ( nr >= 0 ) nr = qnx4_block_map( inode, nr ); if (nr) { result = sb_getblk(inode->i_sb, nr); return result; } return NULL; }
// desperately need ERR_PTR return here to distinguish between // ENOMEM, which should be impossible but when it happens we // need to do something reasonable, or ENOSPC which we must // just report and keep going without a fuss. static struct buffer_head *new_block(struct btree *btree) { block_t block; int err = btree->ops->balloc(btree->sb, 1, &block); if (err) return NULL; // ERR_PTR me!!! struct buffer_head *buffer = sb_getblk(vfs_sb(btree->sb), block); if (!buffer) return NULL; memset(bufdata(buffer), 0, bufsize(buffer)); mark_buffer_dirty(buffer); return buffer; }
void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp) { struct buffer_head *bh; /*return hpfs_map_sector(s, secno, bhp, 0);*/ cond_resched(); if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { if (!buffer_uptodate(bh)) wait_on_buffer(bh); set_buffer_uptodate(bh); return bh->b_data; } else { printk("HPFS: hpfs_get_sector: getblk failed\n"); return NULL; } }
/* * Read the MMP block. It _must_ be read from disk and hence we clear the * uptodate flag on the buffer. */ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, ext4_fsblk_t mmp_block) { struct mmp_struct *mmp; int ret; if (*bh) clear_buffer_uptodate(*bh); /* This would be sb_bread(sb, mmp_block), except we need to be sure * that the MD RAID device cache has been bypassed, and that the read * is not blocked in the elevator. */ if (!*bh) { *bh = sb_getblk(sb, mmp_block); if (!*bh) { ret = -ENOMEM; goto warn_exit; } } get_bh(*bh); lock_buffer(*bh); (*bh)->b_end_io = end_buffer_read_sync; submit_bh(READ_SYNC | REQ_META | REQ_PRIO, *bh); wait_on_buffer(*bh); if (!buffer_uptodate(*bh)) { ret = -EIO; goto warn_exit; } mmp = (struct mmp_struct *)((*bh)->b_data); if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) { ret = -EFSCORRUPTED; goto warn_exit; } if (!ext4_mmp_csum_verify(sb, mmp)) { ret = -EFSBADCRC; goto warn_exit; } return 0; warn_exit: brelse(*bh); *bh = NULL; ext4_warning(sb, "Error %d while reading MMP block %llu", ret, mmp_block); return ret; }
void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp) { struct buffer_head *bh; /*return hpfs_map_sector(s, secno, bhp, 0);*/ hpfs_lock_assert(s); cond_resched(); if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { if (!buffer_uptodate(bh)) wait_on_buffer(bh); set_buffer_uptodate(bh); return bh->b_data; } else { pr_err("%s(): getblk failed\n", __func__); return NULL; } }
/* * hfs_buffer_get() * * Return a buffer for the 'block'th block of the media. * If ('read'==0) then the buffer is not read from disk. */ hfs_buffer hfs_buffer_get(hfs_sysmdb sys_mdb, int block, int read) { hfs_buffer tmp = HFS_BAD_BUFFER; if (read) { tmp = sb_bread(sys_mdb, block); } else { tmp = sb_getblk(sys_mdb, block); if (tmp) { mark_buffer_uptodate(tmp, 1); } } if (!tmp) { hfs_error("hfs_fs: unable to read block 0x%08x from dev %s\n", block, hfs_mdb_name(sys_mdb)); } return tmp; }
static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n, int sync) { struct buffer_head *bh; sector_t end = beg + n; for (; beg < end; ++beg) { bh = sb_getblk(inode->i_sb, beg); lock_buffer(bh); memset(bh->b_data, 0, inode->i_sb->s_blocksize); set_buffer_uptodate(bh); mark_buffer_dirty(bh); unlock_buffer(bh); if (IS_SYNC(inode) || sync) sync_dirty_buffer(bh); brelse(bh); } }
static struct buffer_head * ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle, struct inode *alloc_inode, struct ocfs2_alloc_context *ac, struct ocfs2_chain_list *cl) { int status; u32 bit_off, num_bits; u64 bg_blkno; struct buffer_head *bg_bh; unsigned int alloc_rec = ocfs2_find_smallest_chain(cl); status = ocfs2_claim_clusters(handle, ac, le16_to_cpu(cl->cl_cpg), &bit_off, &num_bits); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } /* setup the group */ bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); trace_ocfs2_block_group_alloc_contig( (unsigned long long)bg_blkno, alloc_rec); bg_bh = sb_getblk(osb->sb, bg_blkno); if (!bg_bh) { status = -EIO; mlog_errno(status); goto bail; } ocfs2_set_new_buffer_uptodate(INODE_CACHE(alloc_inode), bg_bh); status = ocfs2_block_group_fill(handle, alloc_inode, bg_bh, bg_blkno, num_bits, alloc_rec, cl); if (status < 0) { brelse(bg_bh); mlog_errno(status); } bail: return status ? ERR_PTR(status) : bg_bh; }
static int32_t lnx_bget(tarfs_io_t *iop, uint64_t blkno) { struct super_block *sb; struct buffer_head *bh; if (iop == NULL) { return -EINVAL; } sb = iop->io_dev; iop->io_blkno = blkno; bh = sb_getblk(sb, iop->io_blkno); if (bh == NULL) { return -EIO; } iop->io_bh = bh; iop->io_data = bh->b_data; return 0; }
/* * Read the MMP block. It _must_ be read from disk and hence we clear the * uptodate flag on the buffer. */ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, ext4_fsblk_t mmp_block) { struct mmp_struct *mmp; if (*bh) clear_buffer_uptodate(*bh); /* This would be sb_bread(sb, mmp_block), except we need to be sure * that the MD RAID device cache has been bypassed, and that the read * is not blocked in the elevator. */ if (!*bh) *bh = sb_getblk(sb, mmp_block); if (!*bh) return -ENOMEM; if (*bh) { get_bh(*bh); lock_buffer(*bh); (*bh)->b_end_io = end_buffer_read_sync; #ifdef FEATURE_STORAGE_META_LOG if( (*bh) && (*bh)->b_bdev && (*bh)->b_bdev->bd_disk) set_metadata_rw_status((*bh)->b_bdev->bd_disk->first_minor, WAIT_READ_CNT); #endif submit_bh(READ_SYNC | REQ_META | REQ_PRIO, *bh); wait_on_buffer(*bh); if (!buffer_uptodate(*bh)) { brelse(*bh); *bh = NULL; } } if (unlikely(!*bh)) { ext4_warning(sb, "Error while reading MMP block %llu", mmp_block); return -EIO; } mmp = (struct mmp_struct *)((*bh)->b_data); if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC || !ext4_mmp_csum_verify(sb, mmp)) return -EINVAL; return 0; }
static int alloc_branch(struct inode *inode, int num, int *offsets, Indirect *branch) { int n = 0; int i; int parent = minix_new_block(inode); printk("parent new block %d\n",parent); branch[0].key = cpu_to_block(parent); if (parent) for (n = 1; n < num; n++) { struct buffer_head *bh; /* Allocate the next block */ int nr = minix_new_block(inode); printk("loop new block %d",nr); if (!nr) break; branch[n].key = cpu_to_block(nr); bh = sb_getblk(inode->i_sb, parent); lock_buffer(bh); memset(bh->b_data, 0, bh->b_size); branch[n].bh = bh; branch[n].p = (block_t*) bh->b_data + offsets[n]; *branch[n].p = branch[n].key; set_buffer_uptodate(bh); unlock_buffer(bh); mark_buffer_dirty_inode(bh, inode); parent = nr; } if (n == num) return 0; /* Allocation failed, free what we already allocated */ for (i = 1; i < n; i++) bforget(branch[i].bh); for (i = 0; i < n; i++) minix_free_block(inode, block_to_cpu(branch[i].key)); return -ENOSPC; }
/* * Read the MMP block. It _must_ be read from disk and hence we clear the * uptodate flag on the buffer. */ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, ext4_fsblk_t mmp_block) { struct mmp_struct *mmp; if (*bh) clear_buffer_uptodate(*bh); /* This would be sb_bread(sb, mmp_block), except we need to be sure * that the MD RAID device cache has been bypassed, and that the read * is not blocked in the elevator. */ if (!*bh) *bh = sb_getblk(sb, mmp_block); if (!*bh) return -ENOMEM; if (*bh) { get_bh(*bh); lock_buffer(*bh); (*bh)->b_end_io = end_buffer_read_sync; submit_bh(READ_SYNC, *bh); wait_on_buffer(*bh); if (!buffer_uptodate(*bh)) { brelse(*bh); *bh = NULL; } } if (unlikely(!*bh)) { ext4_warning(sb, "Error while reading MMP block %llu", mmp_block); return -EIO; } mmp = (struct mmp_struct *)((*bh)->b_data); if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC || !ext4_mmp_csum_verify(sb, mmp)) return -EINVAL; return 0; }
static int __f2fs_commit_super(struct f2fs_sb_info *sbi, int block) { struct f2fs_super_block *super = F2FS_RAW_SUPER(sbi); struct buffer_head *bh; int err; bh = sb_getblk(sbi->sb, block); if (!bh) return -EIO; lock_buffer(bh); memcpy(bh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super)); set_buffer_uptodate(bh); set_buffer_dirty(bh); unlock_buffer(bh); /* it's rare case, we can do fua all the time */ err = __sync_dirty_buffer(bh, WRITE_FLUSH_FUA); brelse(bh); return err; }
static inline void fat_dir_readahead(struct inode *dir, sector_t iblock, sector_t phys) { struct super_block *sb = dir->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh; int sec; /* This is not a first sector of cluster, or sec_per_clus == 1 */ if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1) return; /* root dir of FAT12/FAT16 */ if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO)) return; bh = sb_getblk(sb, phys); if (bh && !buffer_uptodate(bh)) { for (sec = 0; sec < sbi->sec_per_clus; sec++) sb_breadahead(sb, phys + sec); } brelse(bh); }
/** * ext4_read_block_bitmap() * @sb: super block * @block_group: given block group * * Read the bitmap for a given block_group,and validate the * bits for block/inode/inode tables are set in the bitmaps * * Return buffer_head on success or NULL in case of failure. */ struct buffer_head * ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) { struct ext4_group_desc *desc; struct buffer_head *bh = NULL; ext4_fsblk_t bitmap_blk; desc = ext4_get_group_desc(sb, block_group, NULL); if (!desc) return NULL; bitmap_blk = ext4_block_bitmap(sb, desc); bh = sb_getblk(sb, bitmap_blk); if (unlikely(!bh)) { ext4_error(sb, __func__, "Cannot read block bitmap - " "block_group = %u, block_bitmap = %llu", block_group, bitmap_blk); return NULL; } if (bitmap_uptodate(bh)) return bh; lock_buffer(bh); if (bitmap_uptodate(bh)) { unlock_buffer(bh); return bh; } ext4_lock_group(sb, block_group); if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ext4_init_block_bitmap(sb, bh, block_group, desc); set_bitmap_uptodate(bh); set_buffer_uptodate(bh); ext4_unlock_group(sb, block_group); unlock_buffer(bh); return bh; } ext4_unlock_group(sb, block_group); if (buffer_uptodate(bh)) { /* * if not uninit if bh is uptodate, * bitmap is also uptodate */ set_bitmap_uptodate(bh); unlock_buffer(bh); return bh; } /* * submit the buffer_head for read. We can * safely mark the bitmap as uptodate now. * We do it here so the bitmap uptodate bit * get set with buffer lock held. */ set_bitmap_uptodate(bh); if (bh_submit_read(bh) < 0) { put_bh(bh); ext4_error(sb, __func__, "Cannot read block bitmap - " "block_group = %u, block_bitmap = %llu", block_group, bitmap_blk); return NULL; } ext4_valid_block_bitmap(sb, desc, block_group, bh); /* * file system mounted not to panic on error, * continue with corrupt bitmap */ return bh; }
int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, struct buffer_head *bhs[], int flags, int (*validate)(struct super_block *sb, struct buffer_head *bh)) { int status = 0; int i, ignore_cache = 0; struct buffer_head *bh; mlog_entry("(inode=%p, block=(%llu), nr=(%d), flags=%d)\n", inode, (unsigned long long)block, nr, flags); BUG_ON(!inode); BUG_ON((flags & OCFS2_BH_READAHEAD) && (flags & OCFS2_BH_IGNORE_CACHE)); if (bhs == NULL) { status = -EINVAL; mlog_errno(status); goto bail; } if (nr < 0) { mlog(ML_ERROR, "asked to read %d blocks!\n", nr); status = -EINVAL; mlog_errno(status); goto bail; } if (nr == 0) { mlog(ML_BH_IO, "No buffers will be read!\n"); status = 0; goto bail; } mutex_lock(&OCFS2_I(inode)->ip_io_mutex); for (i = 0 ; i < nr ; i++) { if (bhs[i] == NULL) { bhs[i] = sb_getblk(inode->i_sb, block++); if (bhs[i] == NULL) { mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); status = -EIO; mlog_errno(status); goto bail; } } bh = bhs[i]; ignore_cache = (flags & OCFS2_BH_IGNORE_CACHE); /* There are three read-ahead cases here which we need to * be concerned with. All three assume a buffer has * previously been submitted with OCFS2_BH_READAHEAD * and it hasn't yet completed I/O. * * 1) The current request is sync to disk. This rarely * happens these days, and never when performance * matters - the code can just wait on the buffer * lock and re-submit. * * 2) The current request is cached, but not * readahead. ocfs2_buffer_uptodate() will return * false anyway, so we'll wind up waiting on the * buffer lock to do I/O. We re-check the request * with after getting the lock to avoid a re-submit. * * 3) The current request is readahead (and so must * also be a caching one). We short circuit if the * buffer is locked (under I/O) and if it's in the * uptodate cache. The re-check from #2 catches the * case that the previous read-ahead completes just * before our is-it-in-flight check. */ if (!ignore_cache && !ocfs2_buffer_uptodate(inode, bh)) { mlog(ML_UPTODATE, "bh (%llu), inode %llu not uptodate\n", (unsigned long long)bh->b_blocknr, (unsigned long long)OCFS2_I(inode)->ip_blkno); /* We're using ignore_cache here to say * "go to disk" */ ignore_cache = 1; } if (buffer_jbd(bh)) { if (ignore_cache) mlog(ML_BH_IO, "trying to sync read a jbd " "managed bh (blocknr = %llu)\n", (unsigned long long)bh->b_blocknr); continue; } if (ignore_cache) { if (buffer_dirty(bh)) { /* This should probably be a BUG, or * at least return an error. */ mlog(ML_BH_IO, "asking me to sync read a dirty " "buffer! (blocknr = %llu)\n", (unsigned long long)bh->b_blocknr); continue; } /* A read-ahead request was made - if the * buffer is already under read-ahead from a * previously submitted request than we are * done here. */ if ((flags & OCFS2_BH_READAHEAD) && ocfs2_buffer_read_ahead(inode, bh)) continue; lock_buffer(bh); if (buffer_jbd(bh)) { #ifdef CATCH_BH_JBD_RACES mlog(ML_ERROR, "block %llu had the JBD bit set " "while I was in lock_buffer!", (unsigned long long)bh->b_blocknr); BUG(); #else unlock_buffer(bh); continue; #endif } /* Re-check ocfs2_buffer_uptodate() as a * previously read-ahead buffer may have * completed I/O while we were waiting for the * buffer lock. */ if (!(flags & OCFS2_BH_IGNORE_CACHE) && !(flags & OCFS2_BH_READAHEAD) && ocfs2_buffer_uptodate(inode, bh)) { unlock_buffer(bh); continue; } clear_buffer_uptodate(bh); get_bh(bh); /* for end_buffer_read_sync() */ if (validate) set_buffer_needs_validate(bh); bh->b_end_io = end_buffer_read_sync; submit_bh(READ, bh); continue; } } status = 0; for (i = (nr - 1); i >= 0; i--) { bh = bhs[i]; if (!(flags & OCFS2_BH_READAHEAD)) { /* We know this can't have changed as we hold the * inode sem. Avoid doing any work on the bh if the * journal has it. */ if (!buffer_jbd(bh)) wait_on_buffer(bh); if (!buffer_uptodate(bh)) { /* Status won't be cleared from here on out, * so we can safely record this and loop back * to cleanup the other buffers. Don't need to * remove the clustered uptodate information * for this bh as it's not marked locally * uptodate. */ status = -EIO; put_bh(bh); bhs[i] = NULL; continue; } if (buffer_needs_validate(bh)) { /* We never set NeedsValidate if the * buffer was held by the journal, so * that better not have changed */ BUG_ON(buffer_jbd(bh)); clear_buffer_needs_validate(bh); status = validate(inode->i_sb, bh); if (status) { put_bh(bh); bhs[i] = NULL; continue; } } } /* Always set the buffer in the cache, even if it was * a forced read, or read-ahead which hasn't yet * completed. */ ocfs2_set_buffer_uptodate(inode, bh); } mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", (unsigned long long)block, nr, ((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes", flags); bail: mlog_exit(status); return status; }
int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, unsigned int nr, struct buffer_head *bhs[]) { int status = 0; unsigned int i; struct buffer_head *bh; if (!nr) { mlog(ML_BH_IO, "No buffers will be read!\n"); goto bail; } for (i = 0 ; i < nr ; i++) { if (bhs[i] == NULL) { bhs[i] = sb_getblk(osb->sb, block++); if (bhs[i] == NULL) { status = -EIO; mlog_errno(status); goto bail; } } bh = bhs[i]; if (buffer_jbd(bh)) { mlog(ML_BH_IO, "trying to sync read a jbd " "managed bh (blocknr = %llu), skipping\n", (unsigned long long)bh->b_blocknr); continue; } if (buffer_dirty(bh)) { /* This should probably be a BUG, or * at least return an error. */ mlog(ML_ERROR, "trying to sync read a dirty " "buffer! (blocknr = %llu), skipping\n", (unsigned long long)bh->b_blocknr); continue; } lock_buffer(bh); if (buffer_jbd(bh)) { mlog(ML_ERROR, "block %llu had the JBD bit set " "while I was in lock_buffer!", (unsigned long long)bh->b_blocknr); BUG(); } clear_buffer_uptodate(bh); get_bh(bh); /* for end_buffer_read_sync() */ bh->b_end_io = end_buffer_read_sync; submit_bh(READ, bh); } for (i = nr; i > 0; i--) { bh = bhs[i - 1]; /* No need to wait on the buffer if it's managed by JBD. */ if (!buffer_jbd(bh)) wait_on_buffer(bh); if (!buffer_uptodate(bh)) { /* Status won't be cleared from here on out, * so we can safely record this and loop back * to cleanup the other buffers. */ status = -EIO; put_bh(bh); bhs[i - 1] = NULL; } } bail: return status; }
/* * Returns a pointer to a buffer containing at least LEN bytes of * filesystem starting at byte offset OFFSET into the filesystem. */ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len) { struct buffer_head * bh_array[BLKS_PER_BUF]; struct buffer_head * read_array[BLKS_PER_BUF]; unsigned i, blocknr, buffer, unread; unsigned long devsize; int major, minor; char *data; if (!len) return NULL; blocknr = offset >> PAGE_CACHE_SHIFT; offset &= PAGE_CACHE_SIZE - 1; /* Check if an existing buffer already has the data.. */ for (i = 0; i < READ_BUFFERS; i++) { unsigned int blk_offset; if (buffer_dev[i] != sb) continue; if (blocknr < buffer_blocknr[i]) continue; blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT; blk_offset += offset; if (blk_offset + len > BUFFER_SIZE) continue; return read_buffers[i] + blk_offset; } devsize = ~0UL; major = MAJOR(sb->s_dev); minor = MINOR(sb->s_dev); if (blk_size[major]) devsize = blk_size[major][minor] >> 2; /* Ok, read in BLKS_PER_BUF pages completely first. */ unread = 0; for (i = 0; i < BLKS_PER_BUF; i++) { struct buffer_head *bh; bh = NULL; if (blocknr + i < devsize) { bh = sb_getblk(sb, blocknr + i); if (!buffer_uptodate(bh)) read_array[unread++] = bh; } bh_array[i] = bh; } if (unread) { ll_rw_block(READ, unread, read_array); do { unread--; wait_on_buffer(read_array[unread]); } while (unread); } /* Ok, copy them to the staging area without sleeping. */ buffer = next_buffer; next_buffer = NEXT_BUFFER(buffer); buffer_blocknr[buffer] = blocknr; buffer_dev[buffer] = sb; data = read_buffers[buffer]; for (i = 0; i < BLKS_PER_BUF; i++) { struct buffer_head * bh = bh_array[i]; if (bh) { memcpy(data, bh->b_data, PAGE_CACHE_SIZE); brelse(bh); } else memset(data, 0, PAGE_CACHE_SIZE); data += PAGE_CACHE_SIZE; } return read_buffers[buffer] + offset; }
static int ext4_convert_inline_data_nolock(handle_t *handle, struct inode *inode, struct ext4_iloc *iloc) { int error; void *buf = NULL; struct buffer_head *data_bh = NULL; struct ext4_map_blocks map; int inline_size; inline_size = ext4_get_inline_size(inode); buf = kmalloc(inline_size, GFP_NOFS); if (!buf) { error = -ENOMEM; goto out; } error = ext4_read_inline_data(inode, buf, inline_size, iloc); if (error < 0) goto out; /* * Make sure the inline directory entries pass checks before we try to * convert them, so that we avoid touching stuff that needs fsck. */ if (S_ISDIR(inode->i_mode)) { error = ext4_check_all_de(inode, iloc->bh, buf + EXT4_INLINE_DOTDOT_SIZE, inline_size - EXT4_INLINE_DOTDOT_SIZE); if (error) goto out; } error = ext4_destroy_inline_data_nolock(handle, inode); if (error) goto out; map.m_lblk = 0; map.m_len = 1; map.m_flags = 0; error = ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_CREATE); if (error < 0) goto out_restore; if (!(map.m_flags & EXT4_MAP_MAPPED)) { error = -EIO; goto out_restore; } data_bh = sb_getblk(inode->i_sb, map.m_pblk); if (!data_bh) { error = -ENOMEM; goto out_restore; } lock_buffer(data_bh); error = ext4_journal_get_create_access(handle, data_bh); if (error) { unlock_buffer(data_bh); error = -EIO; goto out_restore; } memset(data_bh->b_data, 0, inode->i_sb->s_blocksize); if (!S_ISDIR(inode->i_mode)) { memcpy(data_bh->b_data, buf, inline_size); set_buffer_uptodate(data_bh); error = ext4_handle_dirty_metadata(handle, inode, data_bh); } else { error = ext4_finish_convert_inline_dir(handle, inode, data_bh, buf, inline_size); } unlock_buffer(data_bh); out_restore: if (error) ext4_restore_inline_data(handle, inode, iloc, buf, inline_size); out: brelse(data_bh); kfree(buf); return error; }
static int ufs_alloc_lastblock(struct inode *inode) { int err = 0; struct super_block *sb = inode->i_sb; struct address_space *mapping = inode->i_mapping; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; unsigned i, end; sector_t lastfrag; struct page *lastpage; struct buffer_head *bh; u64 phys64; lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; if (!lastfrag) goto out; lastfrag--; lastpage = ufs_get_locked_page(mapping, lastfrag >> (PAGE_CACHE_SHIFT - inode->i_blkbits)); if (IS_ERR(lastpage)) { err = -EIO; goto out; } end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1); bh = page_buffers(lastpage); for (i = 0; i < end; ++i) bh = bh->b_this_page; err = ufs_getfrag_block(inode, lastfrag, bh, 1); if (unlikely(err)) goto out_unlock; if (buffer_new(bh)) { clear_buffer_new(bh); unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); /* * we do not zeroize fragment, because of * if it maped to hole, it already contains zeroes */ set_buffer_uptodate(bh); mark_buffer_dirty(bh); set_page_dirty(lastpage); } if (lastfrag >= UFS_IND_FRAGMENT) { end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1; phys64 = bh->b_blocknr + 1; for (i = 0; i < end; ++i) { bh = sb_getblk(sb, i + phys64); lock_buffer(bh); memset(bh->b_data, 0, sb->s_blocksize); set_buffer_uptodate(bh); mark_buffer_dirty(bh); unlock_buffer(bh); sync_dirty_buffer(bh); brelse(bh); } } out_unlock: ufs_put_locked_page(lastpage); out: return err; }
int __microfs_read_blks(struct super_block* sb, struct address_space* mapping, void* data, microfs_read_blks_recycler recycler, microfs_read_blks_consumer consumer, __u32 offset, __u32 length) { __u32 i; __u32 n; __u32 dev_blks; int err = 0; __u32 blk_nr; __u32 blk_offset; __u32 nbhs; struct buffer_head** bhs; if (recycler(sb, data, offset, length, consumer) == 0) goto out_cachehit; blk_offset = offset - (offset & PAGE_MASK); nbhs = i_blks(blk_offset + length, PAGE_SIZE); bhs = kmalloc(nbhs * sizeof(void*), GFP_KERNEL); if (!bhs) { pr_err("__microfs_read_blks: failed to allocate bhs (%u slots)\n", nbhs); err = -ENOMEM; goto err_mem; } blk_nr = offset >> PAGE_SHIFT; dev_blks = sb->s_bdev->bd_inode->i_size >> PAGE_SHIFT; pr_spam("__microfs_read_blks: offset=0x%x, blk_offset=%u, length=%u\n", offset, blk_offset, length); pr_spam("__microfs_read_blks: nbhs=%u, blk_nr=%u, dev_blks=%u\n", nbhs, blk_nr, dev_blks); for (i = 0, n = 0; i < nbhs; ++i) { if (likely(blk_nr + i < dev_blks)) { bhs[n++] = sb_getblk(sb, blk_nr + i); if (unlikely(bhs[n - 1] == NULL)) { pr_err("__microfs_read_blks: failed to get a bh for block %u\n", blk_nr + i); err = -EIO; goto err_bhs; } else { pr_spam("__microfs_read_blks: got bh 0x%p for block %u\n", bhs[n - 1], blk_nr + i); } } else { /* It is not possible to fill the entire read buffer this * time. "Welcome to the end of the image." */ bhs[i] = NULL; } } ll_rw_block(REQ_OP_READ, 0, n, bhs); pr_spam("__microfs_read_blks: bhs submitted for reading\n"); for (i = 0; i < n; ++i) { wait_on_buffer(bhs[i]); if (unlikely(!buffer_uptodate(bhs[i]))) { pr_err("__microfs_read_blks: bh 0x%p (#%u) is not up-to-date\n", bhs[i], i); err = -EIO; goto err_bhs; } } pr_spam("__microfs_read_blks: reading complete\n"); err = consumer(sb, data, bhs, n, offset, length); pr_spam("__microfs_read_blks: processing complete\n"); err_bhs: for (i = 0; i < n; ++i) { pr_spam("__microfs_read_blks: releasing bh 0x%p\n", bhs[i]); put_bh(bhs[i]); } kfree(bhs); err_mem: out_cachehit: return err; }