Skip to content

Commit 5c2d728

Browse files
hyeongseok-kim901namjaejeon
authored andcommitted
exfat: introduce bitmap_lock for cluster bitmap access
s_lock which is for protecting concurrent access of file operations is too huge for cluster bitmap protection, so introduce a new bitmap_lock to narrow the lock range if only need to access cluster bitmap. Signed-off-by: Hyeongseok Kim <[email protected]> Acked-by: Sungjong Seo <[email protected]> Signed-off-by: Namjae Jeon <[email protected]>
1 parent 77edfc6 commit 5c2d728

File tree

3 files changed

+31
-8
lines changed

3 files changed

+31
-8
lines changed

fs/exfat/exfat_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ struct exfat_sb_info {
238238
unsigned int used_clusters; /* number of used clusters */
239239

240240
struct mutex s_lock; /* superblock lock */
241+
struct mutex bitmap_lock; /* bitmap lock */
241242
struct exfat_mount_options options;
242243
struct nls_table *nls_io; /* Charset used for input and display */
243244
struct ratelimit_state ratelimit;

fs/exfat/fatent.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,14 @@ int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
151151
return 0;
152152
}
153153

154-
int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
154+
/* This function must be called with bitmap_lock held */
155+
static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
155156
{
156-
unsigned int num_clusters = 0;
157-
unsigned int clu;
158157
struct super_block *sb = inode->i_sb;
159158
struct exfat_sb_info *sbi = EXFAT_SB(sb);
160159
int cur_cmap_i, next_cmap_i;
160+
unsigned int num_clusters = 0;
161+
unsigned int clu;
161162

162163
/* invalid cluster number */
163164
if (p_chain->dir == EXFAT_FREE_CLUSTER ||
@@ -230,6 +231,17 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
230231
return 0;
231232
}
232233

234+
int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
235+
{
236+
int ret = 0;
237+
238+
mutex_lock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
239+
ret = __exfat_free_cluster(inode, p_chain);
240+
mutex_unlock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
241+
242+
return ret;
243+
}
244+
233245
int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
234246
unsigned int *ret_clu)
235247
{
@@ -328,6 +340,8 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
328340
if (num_alloc > total_cnt - sbi->used_clusters)
329341
return -ENOSPC;
330342

343+
mutex_lock(&sbi->bitmap_lock);
344+
331345
hint_clu = p_chain->dir;
332346
/* find new cluster */
333347
if (hint_clu == EXFAT_EOF_CLUSTER) {
@@ -338,8 +352,10 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
338352
}
339353

340354
hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr);
341-
if (hint_clu == EXFAT_EOF_CLUSTER)
342-
return -ENOSPC;
355+
if (hint_clu == EXFAT_EOF_CLUSTER) {
356+
ret = -ENOSPC;
357+
goto unlock;
358+
}
343359
}
344360

345361
/* check cluster validation */
@@ -349,8 +365,10 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
349365
hint_clu = EXFAT_FIRST_CLUSTER;
350366
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
351367
if (exfat_chain_cont_cluster(sb, p_chain->dir,
352-
num_clusters))
353-
return -EIO;
368+
num_clusters)) {
369+
ret = -EIO;
370+
goto unlock;
371+
}
354372
p_chain->flags = ALLOC_FAT_CHAIN;
355373
}
356374
}
@@ -400,6 +418,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
400418
sbi->used_clusters += num_clusters;
401419

402420
p_chain->size += num_clusters;
421+
mutex_unlock(&sbi->bitmap_lock);
403422
return 0;
404423
}
405424

@@ -419,7 +438,9 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
419438
}
420439
free_cluster:
421440
if (num_clusters)
422-
exfat_free_cluster(inode, p_chain);
441+
__exfat_free_cluster(inode, p_chain);
442+
unlock:
443+
mutex_unlock(&sbi->bitmap_lock);
423444
return ret;
424445
}
425446

fs/exfat/super.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ static int exfat_init_fs_context(struct fs_context *fc)
752752
return -ENOMEM;
753753

754754
mutex_init(&sbi->s_lock);
755+
mutex_init(&sbi->bitmap_lock);
755756
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
756757
DEFAULT_RATELIMIT_BURST);
757758

0 commit comments

Comments
 (0)