s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync) { s32 count; struct buffer_head *bh2; FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); #ifdef CONFIG_SDFAT_DBG_IOCTL struct sdfat_sb_info *sbi = SDFAT_SB(sb); long flags = sbi->debug_flags; if (flags & SDFAT_DEBUGFLAGS_ERROR_RW) return -EIO; #endif /* CONFIG_SDFAT_DBG_IOCTL */ if (!fsi->bd_opened) return -EIO; if (secno == bh->b_blocknr) { set_buffer_uptodate(bh); mark_buffer_dirty(bh); if (sync && (sync_dirty_buffer(bh) != 0)) return -EIO; } else { count = num_secs << sb->s_blocksize_bits; bh2 = __getblk(sb->s_bdev, secno, count); if (!bh2) goto no_bh; lock_buffer(bh2); memcpy(bh2->b_data, bh->b_data, count); set_buffer_uptodate(bh2); mark_buffer_dirty(bh2); unlock_buffer(bh2); if (sync && (sync_dirty_buffer(bh2) != 0)) { __brelse(bh2); goto no_bh; } __brelse(bh2); } return 0; no_bh: /* * patch 1.2.4 : reset ONCE warning message per volume. */ if(!(fsi->prev_eio & SDFAT_EIO_WRITE)) { fsi->prev_eio |= SDFAT_EIO_WRITE; sdfat_log_msg(sb, KERN_ERR, "%s: No bh. I/O error.", __func__); #ifdef CONFIG_SDFAT_DEBUG sdfat_debug_warn_on(1); #endif } return -EIO; }
static inline void fat_dir_readahead(struct inode *dir, sector_t iblock, sector_t phys) { struct super_block *sb = dir->i_sb; struct sdfat_sb_info *sbi = SDFAT_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_find_get_block(sb, phys); if (bh == NULL || !buffer_uptodate(bh)) { for (sec = 0; sec < sbi->sec_per_clus; sec++){ /* Modified by Panasonic (SAV), 2009-oct-5 */ meta_breadahead(sb, phys + sec, BH_Dirent); /*-----------------------------------------*/ } } brelse(bh); }
static inline loff_t fat_make_i_pos(struct super_block *sb, struct buffer_head *bh, struct msdos_dir_entry *de) { return ((loff_t)bh->b_blocknr << SDFAT_SB(sb)->dir_per_block_bits) | (de - (struct msdos_dir_entry *)bh->b_data); }
s32 bdev_close_dev(struct super_block *sb) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); fsi->bd_opened = false; return 0; }
s32 bdev_sync_all(struct super_block *sb) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); #ifdef CONFIG_SDFAT_DBG_IOCTL struct sdfat_sb_info *sbi = SDFAT_SB(sb); long flags = sbi->debug_flags; if (flags & SDFAT_DEBUGFLAGS_ERROR_RW) return -EIO; #endif /* CONFIG_SDFAT_DBG_IOCTL */ if (!fsi->bd_opened) return -EIO; return sync_blockdev(sb->s_bdev); }
/*======================================================================*/ s32 bdev_open_dev(struct super_block *sb) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); if (fsi->bd_opened) return 0; fsi->bd_opened = true; return 0; }
s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); u8 blksize_bits = sb->s_blocksize_bits; #ifdef CONFIG_SDFAT_DBG_IOCTL struct sdfat_sb_info *sbi = SDFAT_SB(sb); long flags = sbi->debug_flags; if (flags & SDFAT_DEBUGFLAGS_ERROR_RW) return -EIO; #endif /* CONFIG_SDFAT_DBG_IOCTL */ if (!fsi->bd_opened) return -EIO; brelse(*bh); if (read) *bh = __bread(sb->s_bdev, secno, num_secs << blksize_bits); else *bh = __getblk(sb->s_bdev, secno, num_secs << blksize_bits); /* read successfully */ if (*bh) return 0; /* * patch 1.2.4 : reset ONCE warning message per volume. */ if(!(fsi->prev_eio & SDFAT_EIO_READ)) { fsi->prev_eio |= SDFAT_EIO_READ; sdfat_log_msg(sb, KERN_ERR, "%s: No bh. I/O error.", __func__); #ifdef CONFIG_SDFAT_DEBUG sdfat_debug_warn_on(1); #endif } return -EIO; }
static inline int fat_get_entry(struct inode *dir, loff_t *pos, struct buffer_head **bh, struct msdos_dir_entry **de) { /* Fast stuff first */ if (*bh && *de && (*de - (struct msdos_dir_entry *)(*bh)->b_data) < SDFAT_SB(dir->i_sb)->dir_per_block - 1) { *pos += sizeof(struct msdos_dir_entry); (*de)++; return 0; } return fat__get_entry(dir, pos, bh, de); }
/* Make a readahead request */ s32 bdev_readahead(struct super_block *sb, u32 secno, u32 num_secs) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); int i; if (!fsi->bd_opened) return -EIO; for (i = 0; i < num_secs; i++) __breadahead(sb->s_bdev, secno + i, 1 << sb->s_blocksize_bits); return 0; }
s32 bdev_check_bdi_valid(struct super_block *sb) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); if (!sb->s_bdi || (sb->s_bdi == &default_backing_dev_info)) { if (!(fsi->prev_eio & SDFAT_EIO_BDI)) { fsi->prev_eio |= SDFAT_EIO_BDI; sdfat_log_msg(sb, KERN_ERR, "%s: block device is " "eliminated.(bdi:%p)", __func__, sb->s_bdi); #ifdef CONFIG_SDFAT_DEBUG sdfat_debug_warn_on(1); #endif } return -ENXIO; } return 0; }
s32 read_msect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); BUG_ON(!bh); if ( ((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0) ) { sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%d len:%d)", __func__ ,sec, num_secs); return -EIO; } if (bdev_mread(sb, sec, bh, num_secs, read)) { sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%d len:%d)", __func__,sec, num_secs); return -EIO; } return 0; } /* end of read_msect */
s32 write_sect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync) { FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi); BUG_ON(!bh); if ( (sec >= fsi->num_sectors) && (fsi->num_sectors > 0) ) { sdfat_fs_error_ratelimit(sb, "%s: out of range (sect:%d)", __func__, sec); return -EIO; } if (bdev_mwrite(sb, sec, bh, 1, sync)) { sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%d)", __func__, sec); return -EIO; } return 0; } /* end of write_sect */