1
2
3
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
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
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
131
132 if (!p_bd->opened)
133 return FFS_MEDIAERR;
134
135 return sync_blockdev(sb->s_bdev);
136}
137