From 72fcea9367c3087c7701d705b9246fe7ba962607 Mon Sep 17 00:00:00 2001 From: Shuichi Ihara Date: Sun, 13 Apr 2014 23:11:03 +0900 Subject: [PATCH] LU-4257 clio: replace semaphore with mutex According https://www.kernel.org/doc/Documentation/mutex-design.txt: - the mutex subsystem is slightly faster and has better scalability for contended workloads. In terms of 'ops per CPU cycle', the semaphore kernel performed 551 ops/sec per 1% of CPU time used, while the mutex kernel performed 3825 ops/sec per 1% of CPU time used - it was 6.9 times more efficient. - there are no fastpath tradeoffs, the mutex fastpath is just as tight as the semaphore fastpath. On x86, the locking fastpath is 2 instructions. - 'struct mutex' semantics are well-defined and are enforced if CONFIG_DEBUG_MUTEXES is turned on. Semaphores on the other hand have virtually no debugging code or instrumentation. One more benefit of mutex is optimistic spinning. It try to spin for acquisition when there are no pending waiters and the lock owner is currently running on a (different) CPU. The rationale is that if the lock owner is running, it is likely to release the lock soon. This significantly reduce amount of context switches when locked region is small and we have high contention. Lustre commit: 96f482b509867bb70cc26e94e60903df82b09f30 Lustre change: http://review.whamcloud.com/9095 Signed-off-by: Dmitry Eremin Signed-off-by: Shuichi Ihara Change-Id: I29cb202468610636ebd45d49281c4e503930bde6 Reviewed-on: http://review.whamcloud.com/9943 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/llite_internal.h | 12 +++++------- lustre/llite/llite_lib.c | 22 ++++++++-------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 7084ec9..79f7f84 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -209,8 +209,7 @@ struct ll_inode_info { /* for non-directory */ struct { - struct semaphore f_size_sem; - void *f_size_sem_owner; + struct mutex f_size_mutex; char *f_symlink_name; __u64 f_maxbytes; /* @@ -245,10 +244,9 @@ struct ll_inode_info { * accurate if the file is shared by different jobs. */ char f_jobid[JOBSTATS_JOBID_SIZE]; - } f; + } f; -#define lli_size_sem u.f.f_size_sem -#define lli_size_sem_owner u.f.f_size_sem_owner +#define lli_size_mutex u.f.f_size_mutex #define lli_symlink_name u.f.f_symlink_name #define lli_maxbytes u.f.f_maxbytes #define lli_trunc_sem u.f.f_trunc_sem @@ -298,7 +296,7 @@ int ll_xattr_cache_get(struct inode *inode, * Locking to guarantee consistency of non-atomic updates to long long i_size, * consistency between file size and KMS. * - * Implemented by ->lli_size_sem and ->lsm_lock, nested in that order. + * Implemented by ->lli_size_mutex and ->lsm_lock, nested in that order. */ void ll_inode_size_lock(struct inode *inode); @@ -1462,7 +1460,7 @@ static inline void cl_isize_unlock(struct inode *inode) static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms) { - LASSERT(down_trylock(&ll_i2info(inode)->lli_size_sem) != 0); + LASSERT(mutex_is_locked(&ll_i2info(inode)->lli_size_mutex)); i_size_write(inode, kms); } diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 5564243..dfe933e 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -962,8 +962,7 @@ void ll_lli_init(struct ll_inode_info *lli) spin_lock_init(&lli->lli_sa_lock); lli->lli_opendir_pid = 0; } else { - sema_init(&lli->lli_size_sem, 1); - lli->lli_size_sem_owner = NULL; + mutex_init(&lli->lli_size_mutex); lli->lli_symlink_name = NULL; init_rwsem(&lli->lli_trunc_sem); mutex_init(&lli->lli_write_mutex); @@ -1687,25 +1686,20 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) void ll_inode_size_lock(struct inode *inode) { - struct ll_inode_info *lli; + struct ll_inode_info *lli; - LASSERT(!S_ISDIR(inode->i_mode)); + LASSERT(!S_ISDIR(inode->i_mode)); - lli = ll_i2info(inode); - LASSERT(lli->lli_size_sem_owner != current); - down(&lli->lli_size_sem); - LASSERT(lli->lli_size_sem_owner == NULL); - lli->lli_size_sem_owner = current; + lli = ll_i2info(inode); + mutex_lock(&lli->lli_size_mutex); } void ll_inode_size_unlock(struct inode *inode) { - struct ll_inode_info *lli; + struct ll_inode_info *lli; - lli = ll_i2info(inode); - LASSERT(lli->lli_size_sem_owner == current); - lli->lli_size_sem_owner = NULL; - up(&lli->lli_size_sem); + lli = ll_i2info(inode); + mutex_unlock(&lli->lli_size_mutex); } void ll_update_inode(struct inode *inode, struct lustre_md *md) -- 1.8.3.1