123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /*
- * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- #include <linux/blkdev.h>
- #include "exfat_config.h"
- #include "exfat_global.h"
- #include "exfat_blkdev.h"
- #include "exfat_data.h"
- #include "exfat_api.h"
- #include "exfat_super.h"
- INT32 bdev_init(void)
- {
- return(FFS_SUCCESS);
- }
- INT32 bdev_shutdown(void)
- {
- return(FFS_SUCCESS);
- }
- INT32 bdev_open(struct super_block *sb)
- {
- BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
- if (p_bd->opened) return(FFS_SUCCESS);
- p_bd->sector_size = bdev_logical_block_size(sb->s_bdev);
- p_bd->sector_size_bits = my_log2(p_bd->sector_size);
- p_bd->sector_size_mask = p_bd->sector_size - 1;
- p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> p_bd->sector_size_bits;
- p_bd->opened = TRUE;
- return(FFS_SUCCESS);
- }
- INT32 bdev_close(struct super_block *sb)
- {
- BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
- if (!p_bd->opened) return(FFS_SUCCESS);
- p_bd->opened = FALSE;
- return(FFS_SUCCESS);
- }
- INT32 bdev_read(struct super_block *sb, UINT32 secno, struct buffer_head **bh, UINT32 num_secs, INT32 read)
- {
- BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
- FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
- #if EXFAT_CONFIG_KERNEL_DEBUG
- struct exfat_sb_info *sbi = EXFAT_SB(sb);
- long flags = sbi->debug_flags;
- if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR);
- #endif
- if (!p_bd->opened) return(FFS_MEDIAERR);
- if (*bh) __brelse(*bh);
- if (read)
- *bh = __bread(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits);
- else
- *bh = __getblk(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits);
- if (*bh) return(FFS_SUCCESS);
- WARN(!p_fs->dev_ejected,
- "[EXFAT] No bh, device seems wrong or to be ejected.\n");
- return(FFS_MEDIAERR);
- }
- INT32 bdev_write(struct super_block *sb, UINT32 secno, struct buffer_head *bh, UINT32 num_secs, INT32 sync)
- {
- INT32 count;
- struct buffer_head *bh2;
- BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
- FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
- #if EXFAT_CONFIG_KERNEL_DEBUG
- struct exfat_sb_info *sbi = EXFAT_SB(sb);
- long flags = sbi->debug_flags;
- if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR);
- #endif
- if (!p_bd->opened) return(FFS_MEDIAERR);
- if (secno == bh->b_blocknr) {
- set_buffer_uptodate(bh);
- mark_buffer_dirty(bh);
- if (sync && (sync_dirty_buffer(bh) != 0))
- return (FFS_MEDIAERR);
- } else {
- count = num_secs << p_bd->sector_size_bits;
- bh2 = __getblk(sb->s_bdev, secno, count);
- if (bh2 == NULL)
- 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(FFS_SUCCESS);
- no_bh:
- WARN(!p_fs->dev_ejected,
- "[EXFAT] No bh, device seems wrong or to be ejected.\n");
- return (FFS_MEDIAERR);
- }
- INT32 bdev_sync(struct super_block *sb)
- {
- BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
- #if EXFAT_CONFIG_KERNEL_DEBUG
- struct exfat_sb_info *sbi = EXFAT_SB(sb);
- long flags = sbi->debug_flags;
- if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR);
- #endif
- if (!p_bd->opened) return(FFS_MEDIAERR);
- return sync_blockdev(sb->s_bdev);
- }
- INT32 bdev_reada(struct super_block *sb, UINT32 secno, UINT32 num_secs)
- {
- BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
- UINT32 sects_per_page = (PAGE_SIZE >> sb->s_blocksize_bits);
- struct blk_plug plug;
- UINT32 i;
- if (!p_bd->opened)
- return (FFS_MEDIAERR);
- blk_start_plug(&plug);
- for (i = 0; i < num_secs; i++) {
- if (i && !(i & (sects_per_page - 1)))
- blk_flush_plug_list(&plug, false);
- sb_breadahead(sb, secno + i);
- }
- blk_finish_plug(&plug);
- return 0;
- }
|