linux/drivers/staging/exfat/exfat_blkdev.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
   4 */
   5
   6#include <linux/blkdev.h>
   7#include <linux/buffer_head.h>
   8#include <linux/fs.h>
   9#include "exfat.h"
  10
  11void bdev_open(struct super_block *sb)
  12{
  13        struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
  14
  15        if (p_bd->opened)
  16                return;
  17
  18        p_bd->sector_size      = bdev_logical_block_size(sb->s_bdev);
  19        p_bd->sector_size_bits = ilog2(p_bd->sector_size);
  20        p_bd->sector_size_mask = p_bd->sector_size - 1;
  21        p_bd->num_sectors      = i_size_read(sb->s_bdev->bd_inode) >>
  22                                 p_bd->sector_size_bits;
  23        p_bd->opened = true;
  24}
  25
  26void bdev_close(struct super_block *sb)
  27{
  28        struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
  29
  30        p_bd->opened = false;
  31}
  32
  33int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
  34              u32 num_secs, bool read)
  35{
  36        struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
  37        struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
  38#ifdef CONFIG_EXFAT_KERNEL_DEBUG
  39        struct exfat_sb_info *sbi = EXFAT_SB(sb);
  40        long flags = sbi->debug_flags;
  41
  42        if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
  43                return FFS_MEDIAERR;
  44#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
  45
  46        if (!p_bd->opened)
  47                return FFS_MEDIAERR;
  48
  49        if (*bh)
  50                __brelse(*bh);
  51
  52        if (read)
  53                *bh = __bread(sb->s_bdev, secno,
  54                              num_secs << p_bd->sector_size_bits);
  55        else
  56                *bh = __getblk(sb->s_bdev, secno,
  57                               num_secs << p_bd->sector_size_bits);
  58
  59        if (*bh)
  60                return 0;
  61
  62        WARN(!p_fs->dev_ejected,
  63             "[EXFAT] No bh, device seems wrong or to be ejected.\n");
  64
  65        return FFS_MEDIAERR;
  66}
  67
  68int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
  69               u32 num_secs, bool sync)
  70{
  71        s32 count;
  72        struct buffer_head *bh2;
  73        struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
  74        struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
  75#ifdef CONFIG_EXFAT_KERNEL_DEBUG
  76        struct exfat_sb_info *sbi = EXFAT_SB(sb);
  77        long flags = sbi->debug_flags;
  78
  79        if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
  80                return FFS_MEDIAERR;
  81#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
  82
  83        if (!p_bd->opened)
  84                return FFS_MEDIAERR;
  85
  86        if (secno == bh->b_blocknr) {
  87                lock_buffer(bh);
  88                set_buffer_uptodate(bh);
  89                mark_buffer_dirty(bh);
  90                unlock_buffer(bh);
  91                if (sync && (sync_dirty_buffer(bh) != 0))
  92                        return FFS_MEDIAERR;
  93        } else {
  94                count = num_secs << p_bd->sector_size_bits;
  95
  96                bh2 = __getblk(sb->s_bdev, secno, count);
  97                if (!bh2)
  98                        goto no_bh;
  99
 100                lock_buffer(bh2);
 101                memcpy(bh2->b_data, bh->b_data, count);
 102                set_buffer_uptodate(bh2);
 103                mark_buffer_dirty(bh2);
 104                unlock_buffer(bh2);
 105                if (sync && (sync_dirty_buffer(bh2) != 0)) {
 106                        __brelse(bh2);
 107                        goto no_bh;
 108                }
 109                __brelse(bh2);
 110        }
 111
 112        return 0;
 113
 114no_bh:
 115        WARN(!p_fs->dev_ejected,
 116             "[EXFAT] No bh, device seems wrong or to be ejected.\n");
 117
 118        return FFS_MEDIAERR;
 119}
 120
 121int bdev_sync(struct super_block *sb)
 122{
 123        struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
 124#ifdef CONFIG_EXFAT_KERNEL_DEBUG
 125        struct exfat_sb_info *sbi = EXFAT_SB(sb);
 126        long flags = sbi->debug_flags;
 127
 128        if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
 129                return FFS_MEDIAERR;
 130#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
 131
 132        if (!p_bd->opened)
 133                return FFS_MEDIAERR;
 134
 135        return sync_blockdev(sb->s_bdev);
 136}
 137