aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/f2fs.h
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2012-11-22 02:21:29 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-04-09 05:21:18 -0400
commit399368372ed9f3c396eadb5c2bbc98be8c774a39 (patch)
treeb496c910ebf04d95e5ad6cb1b65d8cbb45aeef89 /fs/f2fs/f2fs.h
parent1127a3d448bcf4de338e60a7cc695d54c5767433 (diff)
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types, such as directory operations, block allocation, block write, and so on. Reference the following lock types in f2fs.h. enum lock_type { RENAME, /* for renaming operations */ DENTRY_OPS, /* for directory operations */ DATA_WRITE, /* for data write */ DATA_NEW, /* for data allocation */ DATA_TRUNC, /* for data truncate */ NODE_NEW, /* for node allocation */ NODE_TRUNC, /* for node truncate */ NODE_WRITE, /* for node write */ NR_LOCK_TYPE, }; In that case, we lose the performance under the multi-threading environment, since every types of operations must be conducted one at a time. In order to address the problem, let's share the locks globally with a mutex array regardless of any types. So, let users grab a mutex and perform their jobs in parallel as much as possbile. For this, I propose a new global lock scheme as follows. 0. Data structure - f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS] - f2fs_sb_info -> node_write 1. mutex_lock_op(sbi) - try to get an avaiable lock from the array. - returns the index of the gottern lock variable. 2. mutex_unlock_op(sbi, index of the lock) - unlock the given index of the lock. 3. mutex_lock_all(sbi) - grab all the locks in the array before the checkpoint. 4. mutex_unlock_all(sbi) - release all the locks in the array after checkpoint. 5. block_operations() - call mutex_lock_all() - sync_dirty_dir_inodes() - grab node_write - sync_node_pages() Note that, the pairs of mutex_lock_op()/mutex_unlock_op() and mutex_lock_all()/mutex_unlock_all() should be used together. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/f2fs.h')
-rw-r--r--fs/f2fs/f2fs.h63
1 files changed, 40 insertions, 23 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 71eacd373916..06cc75c66c88 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -309,23 +309,12 @@ enum count_type {
309}; 309};
310 310
311/* 311/*
312 * FS_LOCK nesting subclasses for the lock validator: 312 * Uses as sbi->fs_lock[NR_GLOBAL_LOCKS].
313 * 313 * The checkpoint procedure blocks all the locks in this fs_lock array.
314 * The locking order between these classes is 314 * Some FS operations grab free locks, and if there is no free lock,
315 * RENAME -> DENTRY_OPS -> DATA_WRITE -> DATA_NEW 315 * then wait to grab a lock in a round-robin manner.
316 * -> DATA_TRUNC -> NODE_WRITE -> NODE_NEW -> NODE_TRUNC
317 */ 316 */
318enum lock_type { 317#define NR_GLOBAL_LOCKS 8
319 RENAME, /* for renaming operations */
320 DENTRY_OPS, /* for directory operations */
321 DATA_WRITE, /* for data write */
322 DATA_NEW, /* for data allocation */
323 DATA_TRUNC, /* for data truncate */
324 NODE_NEW, /* for node allocation */
325 NODE_TRUNC, /* for node truncate */
326 NODE_WRITE, /* for node write */
327 NR_LOCK_TYPE,
328};
329 318
330/* 319/*
331 * The below are the page types of bios used in submti_bio(). 320 * The below are the page types of bios used in submti_bio().
@@ -365,10 +354,11 @@ struct f2fs_sb_info {
365 /* for checkpoint */ 354 /* for checkpoint */
366 struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ 355 struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */
367 struct inode *meta_inode; /* cache meta blocks */ 356 struct inode *meta_inode; /* cache meta blocks */
368 struct mutex cp_mutex; /* for checkpoint procedure */ 357 struct mutex cp_mutex; /* checkpoint procedure lock */
369 struct mutex fs_lock[NR_LOCK_TYPE]; /* for blocking FS operations */ 358 struct mutex fs_lock[NR_GLOBAL_LOCKS]; /* blocking FS operations */
370 struct mutex write_inode; /* mutex for write inode */ 359 struct mutex node_write; /* locking node writes */
371 struct mutex writepages; /* mutex for writepages() */ 360 struct mutex writepages; /* mutex for writepages() */
361 unsigned char next_lock_num; /* round-robin global locks */
372 int por_doing; /* recovery is doing or not */ 362 int por_doing; /* recovery is doing or not */
373 363
374 /* for orphan inode management */ 364 /* for orphan inode management */
@@ -503,14 +493,40 @@ static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
503 cp->ckpt_flags = cpu_to_le32(ckpt_flags); 493 cp->ckpt_flags = cpu_to_le32(ckpt_flags);
504} 494}
505 495
506static inline void mutex_lock_op(struct f2fs_sb_info *sbi, enum lock_type t) 496static inline void mutex_lock_all(struct f2fs_sb_info *sbi)
497{
498 int i = 0;
499 for (; i < NR_GLOBAL_LOCKS; i++)
500 mutex_lock(&sbi->fs_lock[i]);
501}
502
503static inline void mutex_unlock_all(struct f2fs_sb_info *sbi)
507{ 504{
508 mutex_lock_nested(&sbi->fs_lock[t], t); 505 int i = 0;
506 for (; i < NR_GLOBAL_LOCKS; i++)
507 mutex_unlock(&sbi->fs_lock[i]);
509} 508}
510 509
511static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, enum lock_type t) 510static inline int mutex_lock_op(struct f2fs_sb_info *sbi)
512{ 511{
513 mutex_unlock(&sbi->fs_lock[t]); 512 unsigned char next_lock = sbi->next_lock_num % NR_GLOBAL_LOCKS;
513 int i = 0;
514
515 for (; i < NR_GLOBAL_LOCKS; i++)
516 if (mutex_trylock(&sbi->fs_lock[i]))
517 return i;
518
519 mutex_lock(&sbi->fs_lock[next_lock]);
520 sbi->next_lock_num++;
521 return next_lock;
522}
523
524static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, int ilock)
525{
526 if (ilock < 0)
527 return;
528 BUG_ON(ilock >= NR_GLOBAL_LOCKS);
529 mutex_unlock(&sbi->fs_lock[ilock]);
514} 530}
515 531
516/* 532/*
@@ -879,6 +895,7 @@ long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long);
879void f2fs_set_inode_flags(struct inode *); 895void f2fs_set_inode_flags(struct inode *);
880struct inode *f2fs_iget(struct super_block *, unsigned long); 896struct inode *f2fs_iget(struct super_block *, unsigned long);
881void update_inode(struct inode *, struct page *); 897void update_inode(struct inode *, struct page *);
898int update_inode_page(struct inode *);
882int f2fs_write_inode(struct inode *, struct writeback_control *); 899int f2fs_write_inode(struct inode *, struct writeback_control *);
883void f2fs_evict_inode(struct inode *); 900void f2fs_evict_inode(struct inode *);
884 901