mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
fs/exfat: implement errors=remount-ro
This patch implements errors=remount-ro for exfat. Port of cf4fa60 and 58ec900 on 8996 with minor change for updated submit_io() interface in kernel 4.9. Change-Id: Iee791a99216ecf9f710adffa681706e761f97d8f Signed-off-by: Shiyong Li <a22381@motorola.com> Reviewed-on: https://gerrit.mot.com/1102176 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Igor Kovalenko <igork@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
89b6111d7d
commit
982b6998ab
6 changed files with 67 additions and 11 deletions
|
|
@ -126,6 +126,50 @@ s32 bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh, u
|
|||
return FFS_MEDIAERR;
|
||||
}
|
||||
|
||||
void bdev_end_buffer_write(struct buffer_head *bh, int uptodate, int sync)
|
||||
{
|
||||
if (!uptodate)
|
||||
fs_error(bh->b_private);
|
||||
|
||||
if (sync)
|
||||
end_buffer_write_sync(bh, uptodate);
|
||||
else
|
||||
end_buffer_async_write(bh, uptodate);
|
||||
}
|
||||
|
||||
static void exfat_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
|
||||
{
|
||||
bdev_end_buffer_write(bh, uptodate, 1);
|
||||
}
|
||||
|
||||
s32 bdev_sync_dirty_buffer(struct buffer_head *bh,
|
||||
struct super_block *sb, int sync)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
WARN_ON(atomic_read(&bh->b_count) < 1);
|
||||
lock_buffer(bh);
|
||||
if (test_clear_buffer_dirty(bh)) {
|
||||
if (exfat_readonly(sb)) {
|
||||
unlock_buffer(bh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_bh(bh);
|
||||
bh->b_private = sb;
|
||||
bh->b_end_io = exfat_end_buffer_write_sync;
|
||||
ret = submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh);
|
||||
if (sync) {
|
||||
wait_on_buffer(bh);
|
||||
if (!ret && !buffer_uptodate(bh))
|
||||
ret = -EIO;
|
||||
}
|
||||
} else {
|
||||
unlock_buffer(bh);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, u32 num_secs, s32 sync)
|
||||
{
|
||||
s32 count;
|
||||
|
|
@ -148,7 +192,7 @@ s32 bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, u
|
|||
set_buffer_uptodate(bh);
|
||||
mark_buffer_dirty(bh);
|
||||
unlock_buffer(bh);
|
||||
if (sync && (sync_dirty_buffer(bh) != 0))
|
||||
if (bdev_sync_dirty_buffer(bh, sb, sync))
|
||||
return FFS_MEDIAERR;
|
||||
} else {
|
||||
count = num_secs << p_bd->sector_size_bits;
|
||||
|
|
@ -163,7 +207,7 @@ s32 bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, u
|
|||
set_buffer_uptodate(bh2);
|
||||
mark_buffer_dirty(bh2);
|
||||
unlock_buffer(bh2);
|
||||
if (sync && (sync_dirty_buffer(bh2) != 0)) {
|
||||
if (bdev_sync_dirty_buffer(bh2, sb, sync)) {
|
||||
__brelse(bh2);
|
||||
goto no_bh;
|
||||
}
|
||||
|
|
@ -193,5 +237,8 @@ s32 bdev_sync(struct super_block *sb)
|
|||
if (!p_bd->opened)
|
||||
return FFS_MEDIAERR;
|
||||
|
||||
if (exfat_readonly(sb))
|
||||
return FFS_MEDIAERR;
|
||||
|
||||
return sync_blockdev(sb->s_bdev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,5 +69,8 @@ s32 bdev_close(struct super_block *sb);
|
|||
s32 bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh, u32 num_secs, s32 read);
|
||||
s32 bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, u32 num_secs, s32 sync);
|
||||
s32 bdev_sync(struct super_block *sb);
|
||||
void bdev_end_buffer_write(struct buffer_head *bh, int uptodate, int sync);
|
||||
s32 bdev_sync_dirty_buffer(struct buffer_head *bh,
|
||||
struct super_block *sb, int sync);
|
||||
|
||||
#endif /* _EXFAT_BLKDEV_H */
|
||||
|
|
|
|||
|
|
@ -686,7 +686,7 @@ void buf_sync(struct super_block *sb)
|
|||
bp = p_fs->buf_cache_lru_list.next;
|
||||
while (bp != &p_fs->buf_cache_lru_list) {
|
||||
if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
|
||||
sync_dirty_buffer(bp->buf_bh);
|
||||
bdev_sync_dirty_buffer(bp->buf_bh, sb, 1);
|
||||
bp->flag &= ~(DIRTYBIT);
|
||||
}
|
||||
bp = bp->next;
|
||||
|
|
|
|||
|
|
@ -2314,7 +2314,7 @@ void sync_alloc_bitmap(struct super_block *sb)
|
|||
return;
|
||||
|
||||
for (i = 0; i < p_fs->map_sectors; i++)
|
||||
sync_dirty_buffer(p_fs->vol_amap[i]);
|
||||
bdev_sync_dirty_buffer(p_fs->vol_amap[i], sb, 1);
|
||||
} /* end of sync_alloc_bitmap */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1616,17 +1616,18 @@ static int exfat_readpages(struct file *file, struct address_space *mapping,
|
|||
|
||||
static int exfat_writepage(struct page *page, struct writeback_control *wbc)
|
||||
{
|
||||
int ret;
|
||||
ret = block_write_full_page(page, exfat_get_block, wbc);
|
||||
return ret;
|
||||
if (exfat_readonly(page->mapping->host->i_sb))
|
||||
return -EROFS;
|
||||
return block_write_full_page(page, exfat_get_block, wbc);
|
||||
}
|
||||
|
||||
static int exfat_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
int ret;
|
||||
ret = mpage_writepages(mapping, wbc, exfat_get_block);
|
||||
return ret;
|
||||
if (exfat_readonly(mapping->host->i_sb))
|
||||
return -EROFS;
|
||||
/* get_block should be NULL to call ->writepage and catch end_io */
|
||||
return mpage_writepages(mapping, wbc, NULL);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34)
|
||||
|
|
@ -2067,7 +2068,7 @@ static void exfat_write_super(struct super_block *sb)
|
|||
|
||||
__set_sb_clean(sb);
|
||||
|
||||
if (!(sb->s_flags & MS_RDONLY))
|
||||
if (!exfat_readonly(sb))
|
||||
FsSyncVol(sb, 1);
|
||||
|
||||
__unlock_super(sb);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,11 @@ static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
|
|||
return container_of(inode, struct exfat_inode_info, vfs_inode);
|
||||
}
|
||||
|
||||
static inline bool exfat_readonly(struct super_block *sb)
|
||||
{
|
||||
return sb->s_flags & MS_RDONLY;
|
||||
}
|
||||
|
||||
/*
|
||||
* If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to
|
||||
* save ATTR_RO instead of ->i_mode.
|
||||
|
|
|
|||
Loading…
Reference in a new issue