return err;
}
+static int exfat_end_bh(struct super_block *sb, struct buffer_head *bh)
+{
+ int err;
+
+ exfat_update_bh(bh, sb->s_flags & SB_SYNCHRONOUS);
+ err = exfat_mirror_bh(sb, bh);
+ brelse(bh);
+
+ return err;
+}
+
static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
unsigned int *content, struct buffer_head **last)
{
return 0;
}
-int exfat_ent_set(struct super_block *sb, unsigned int loc,
- unsigned int content)
+static int __exfat_ent_set(struct super_block *sb, unsigned int loc,
+ unsigned int content, struct buffer_head **cache)
{
- unsigned int off;
sector_t sec;
__le32 *fat_entry;
- struct buffer_head *bh;
+ struct buffer_head *bh = cache ? *cache : NULL;
+ unsigned int off;
sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
- bh = sb_bread(sb, sec);
- if (!bh)
- return -EIO;
+ if (!bh || bh->b_blocknr != sec || !buffer_uptodate(bh)) {
+ if (bh)
+ exfat_end_bh(sb, bh);
+ bh = sb_bread(sb, sec);
+ if (cache)
+ *cache = bh;
+ if (unlikely(!bh))
+ return -EIO;
+ }
fat_entry = (__le32 *)&(bh->b_data[off]);
*fat_entry = cpu_to_le32(content);
- exfat_update_bh(bh, sb->s_flags & SB_SYNCHRONOUS);
- exfat_mirror_bh(sb, bh);
- brelse(bh);
+ if (!cache)
+ exfat_end_bh(sb, bh);
return 0;
}
+int exfat_ent_set(struct super_block *sb, unsigned int loc,
+ unsigned int content)
+{
+ return __exfat_ent_set(sb, loc, content, NULL);
+}
+
/*
* Caller must release the buffer_head if no error return.
*/
int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
unsigned int len)
{
+ struct buffer_head *bh = NULL;
sector_t sec, end, ra;
blkcnt_t ra_cnt = 0;
sec = FAT_ENT_OFFSET_SECTOR(sb, chain);
exfat_blk_readahead(sb, sec, &ra, &ra_cnt, end);
- if (exfat_ent_set(sb, chain, chain + 1))
+ if (__exfat_ent_set(sb, chain, chain + 1, &bh))
return -EIO;
chain++;
len--;
}
- if (exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER))
+ if (__exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER, &bh))
return -EIO;
+
+ exfat_end_bh(sb, bh);
return 0;
}