1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2f466c6fdSAl Viro #include "reiserfs.h" 38ebc4232SFrederic Weisbecker #include <linux/mutex.h> 48ebc4232SFrederic Weisbecker 58ebc4232SFrederic Weisbecker /* 68ebc4232SFrederic Weisbecker * The previous reiserfs locking scheme was heavily based on 78ebc4232SFrederic Weisbecker * the tricky properties of the Bkl: 88ebc4232SFrederic Weisbecker * 98ebc4232SFrederic Weisbecker * - it was acquired recursively by a same task 108ebc4232SFrederic Weisbecker * - the performances relied on the release-while-schedule() property 118ebc4232SFrederic Weisbecker * 128ebc4232SFrederic Weisbecker * Now that we replace it by a mutex, we still want to keep the same 138ebc4232SFrederic Weisbecker * recursive property to avoid big changes in the code structure. 148ebc4232SFrederic Weisbecker * We use our own lock_owner here because the owner field on a mutex 158ebc4232SFrederic Weisbecker * is only available in SMP or mutex debugging, also we only need this field 168ebc4232SFrederic Weisbecker * for this mutex, no need for a system wide mutex facility. 178ebc4232SFrederic Weisbecker * 188ebc4232SFrederic Weisbecker * Also this lock is often released before a call that could block because 1925985edcSLucas De Marchi * reiserfs performances were partially based on the release while schedule() 208ebc4232SFrederic Weisbecker * property of the Bkl. 218ebc4232SFrederic Weisbecker */ reiserfs_write_lock(struct super_block * s)228ebc4232SFrederic Weisbeckervoid reiserfs_write_lock(struct super_block *s) 238ebc4232SFrederic Weisbecker { 248ebc4232SFrederic Weisbecker struct reiserfs_sb_info *sb_i = REISERFS_SB(s); 258ebc4232SFrederic Weisbecker 268ebc4232SFrederic Weisbecker if (sb_i->lock_owner != current) { 278ebc4232SFrederic Weisbecker mutex_lock(&sb_i->lock); 288ebc4232SFrederic Weisbecker sb_i->lock_owner = current; 298ebc4232SFrederic Weisbecker } 308ebc4232SFrederic Weisbecker 318ebc4232SFrederic Weisbecker /* No need to protect it, only the current task touches it */ 328ebc4232SFrederic Weisbecker sb_i->lock_depth++; 338ebc4232SFrederic Weisbecker } 348ebc4232SFrederic Weisbecker reiserfs_write_unlock(struct super_block * s)358ebc4232SFrederic Weisbeckervoid reiserfs_write_unlock(struct super_block *s) 368ebc4232SFrederic Weisbecker { 378ebc4232SFrederic Weisbecker struct reiserfs_sb_info *sb_i = REISERFS_SB(s); 388ebc4232SFrederic Weisbecker 398ebc4232SFrederic Weisbecker /* 408ebc4232SFrederic Weisbecker * Are we unlocking without even holding the lock? 4180503185SFrederic Weisbecker * Such a situation must raise a BUG() if we don't want 4280503185SFrederic Weisbecker * to corrupt the data. 438ebc4232SFrederic Weisbecker */ 4480503185SFrederic Weisbecker BUG_ON(sb_i->lock_owner != current); 458ebc4232SFrederic Weisbecker 468ebc4232SFrederic Weisbecker if (--sb_i->lock_depth == -1) { 478ebc4232SFrederic Weisbecker sb_i->lock_owner = NULL; 488ebc4232SFrederic Weisbecker mutex_unlock(&sb_i->lock); 498ebc4232SFrederic Weisbecker } 508ebc4232SFrederic Weisbecker } 518ebc4232SFrederic Weisbecker reiserfs_write_unlock_nested(struct super_block * s)52278f6679SJeff Mahoneyint __must_check reiserfs_write_unlock_nested(struct super_block *s) 53278f6679SJeff Mahoney { 54278f6679SJeff Mahoney struct reiserfs_sb_info *sb_i = REISERFS_SB(s); 55278f6679SJeff Mahoney int depth; 56278f6679SJeff Mahoney 57278f6679SJeff Mahoney /* this can happen when the lock isn't always held */ 58278f6679SJeff Mahoney if (sb_i->lock_owner != current) 59278f6679SJeff Mahoney return -1; 60278f6679SJeff Mahoney 61278f6679SJeff Mahoney depth = sb_i->lock_depth; 62278f6679SJeff Mahoney 63278f6679SJeff Mahoney sb_i->lock_depth = -1; 64278f6679SJeff Mahoney sb_i->lock_owner = NULL; 65278f6679SJeff Mahoney mutex_unlock(&sb_i->lock); 66278f6679SJeff Mahoney 67278f6679SJeff Mahoney return depth; 68278f6679SJeff Mahoney } 69278f6679SJeff Mahoney reiserfs_write_lock_nested(struct super_block * s,int depth)70278f6679SJeff Mahoneyvoid reiserfs_write_lock_nested(struct super_block *s, int depth) 71daf88c89SFrederic Weisbecker { 72daf88c89SFrederic Weisbecker struct reiserfs_sb_info *sb_i = REISERFS_SB(s); 73daf88c89SFrederic Weisbecker 74278f6679SJeff Mahoney /* this can happen when the lock isn't always held */ 75278f6679SJeff Mahoney if (depth == -1) 76278f6679SJeff Mahoney return; 77278f6679SJeff Mahoney 78daf88c89SFrederic Weisbecker mutex_lock(&sb_i->lock); 79daf88c89SFrederic Weisbecker sb_i->lock_owner = current; 80278f6679SJeff Mahoney sb_i->lock_depth = depth; 81daf88c89SFrederic Weisbecker } 82daf88c89SFrederic Weisbecker 83daf88c89SFrederic Weisbecker /* 848ebc4232SFrederic Weisbecker * Utility function to force a BUG if it is called without the superblock 858ebc4232SFrederic Weisbecker * write lock held. caller is the string printed just before calling BUG() 868ebc4232SFrederic Weisbecker */ reiserfs_check_lock_depth(struct super_block * sb,char * caller)878ebc4232SFrederic Weisbeckervoid reiserfs_check_lock_depth(struct super_block *sb, char *caller) 888ebc4232SFrederic Weisbecker { 898ebc4232SFrederic Weisbecker struct reiserfs_sb_info *sb_i = REISERFS_SB(sb); 908ebc4232SFrederic Weisbecker 91278f6679SJeff Mahoney WARN_ON(sb_i->lock_depth < 0); 928ebc4232SFrederic Weisbecker } 93c4a62ca3SFrederic Weisbecker 94c4a62ca3SFrederic Weisbecker #ifdef CONFIG_REISERFS_CHECK reiserfs_lock_check_recursive(struct super_block * sb)95c4a62ca3SFrederic Weisbeckervoid reiserfs_lock_check_recursive(struct super_block *sb) 96c4a62ca3SFrederic Weisbecker { 97c4a62ca3SFrederic Weisbecker struct reiserfs_sb_info *sb_i = REISERFS_SB(sb); 98c4a62ca3SFrederic Weisbecker 99c4a62ca3SFrederic Weisbecker WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n"); 100c4a62ca3SFrederic Weisbecker } 101c4a62ca3SFrederic Weisbecker #endif 102