Skip to content

Commit 7646a75

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 73138cb commit 7646a75

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

exfat_fs.h

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

249249
struct mutex s_lock; /* superblock lock */
250+
struct mutex bitmap_lock; /* bitmap lock */
250251
struct exfat_mount_options options;
251252
struct nls_table *nls_io; /* Charset used for input and display */
252253
struct ratelimit_state ratelimit;

fatent.c

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

162-
int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
162+
/* This function must be called with bitmap_lock held */
163+
static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
163164
{
164-
unsigned int num_clusters = 0;
165-
unsigned int clu;
166165
struct super_block *sb = inode->i_sb;
167166
struct exfat_sb_info *sbi = EXFAT_SB(sb);
168167
int cur_cmap_i, next_cmap_i;
168+
unsigned int num_clusters = 0;
169+
unsigned int clu;
169170

170171
/* invalid cluster number */
171172
if (p_chain->dir == EXFAT_FREE_CLUSTER ||
@@ -238,6 +239,17 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
238239
return 0;
239240
}
240241

242+
int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
243+
{
244+
int ret = 0;
245+
246+
mutex_lock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
247+
ret = __exfat_free_cluster(inode, p_chain);
248+
mutex_unlock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
249+
250+
return ret;
251+
}
252+
241253
int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
242254
unsigned int *ret_clu)
243255
{
@@ -336,6 +348,8 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
336348
if (num_alloc > total_cnt - sbi->used_clusters)
337349
return -ENOSPC;
338350

351+
mutex_lock(&sbi->bitmap_lock);
352+
339353
hint_clu = p_chain->dir;
340354
/* find new cluster */
341355
if (hint_clu == EXFAT_EOF_CLUSTER) {
@@ -346,8 +360,10 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
346360
}
347361

348362
hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr);
349-
if (hint_clu == EXFAT_EOF_CLUSTER)
350-
return -ENOSPC;
363+
if (hint_clu == EXFAT_EOF_CLUSTER) {
364+
ret = -ENOSPC;
365+
goto unlock;
366+
}
351367
}
352368

353369
/* check cluster validation */
@@ -357,8 +373,10 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
357373
hint_clu = EXFAT_FIRST_CLUSTER;
358374
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
359375
if (exfat_chain_cont_cluster(sb, p_chain->dir,
360-
num_clusters))
361-
return -EIO;
376+
num_clusters)) {
377+
ret = -EIO;
378+
goto unlock;
379+
}
362380
p_chain->flags = ALLOC_FAT_CHAIN;
363381
}
364382
}
@@ -408,6 +426,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
408426
sbi->used_clusters += num_clusters;
409427

410428
p_chain->size += num_clusters;
429+
mutex_unlock(&sbi->bitmap_lock);
411430
return 0;
412431
}
413432

@@ -427,7 +446,9 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
427446
}
428447
free_cluster:
429448
if (num_clusters)
430-
exfat_free_cluster(inode, p_chain);
449+
__exfat_free_cluster(inode, p_chain);
450+
unlock:
451+
mutex_unlock(&sbi->bitmap_lock);
431452
return ret;
432453
}
433454

super.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,7 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
902902
return -ENOMEM;
903903

904904
mutex_init(&sbi->s_lock);
905+
mutex_init(&sbi->bitmap_lock);
905906
sb->s_fs_info = sbi;
906907
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
907908
DEFAULT_RATELIMIT_BURST);
@@ -1046,6 +1047,7 @@ static int exfat_init_fs_context(struct fs_context *fc)
10461047
return -ENOMEM;
10471048

10481049
mutex_init(&sbi->s_lock);
1050+
mutex_init(&sbi->bitmap_lock);
10491051
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
10501052
DEFAULT_RATELIMIT_BURST);
10511053

0 commit comments

Comments
 (0)