]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/staging/exfat/exfat_blkdev.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
[linux.git] / drivers / staging / exfat / exfat_blkdev.c
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
11 void exfat_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
26 void exfat_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
33 int exfat_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 -EIO;
44 #endif /* CONFIG_EXFAT_KERNEL_DEBUG */
45
46         if (!p_bd->opened)
47                 return -ENODEV;
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 -EIO;
66 }
67
68 int exfat_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 -EIO;
81 #endif /* CONFIG_EXFAT_KERNEL_DEBUG */
82
83         if (!p_bd->opened)
84                 return -ENODEV;
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 -EIO;
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
114 no_bh:
115         WARN(!p_fs->dev_ejected,
116              "[EXFAT] No bh, device seems wrong or to be ejected.\n");
117
118         return -EIO;
119 }
120
121 int exfat_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 -EIO;
130 #endif /* CONFIG_EXFAT_KERNEL_DEBUG */
131
132         if (!p_bd->opened)
133                 return -ENODEV;
134
135         return sync_blockdev(sb->s_bdev);
136 }