102 lines · c
1// SPDX-License-Identifier: GPL-2.02#include "reiserfs.h"3#include <linux/mutex.h>4 5/*6 * The previous reiserfs locking scheme was heavily based on7 * the tricky properties of the Bkl:8 *9 * - it was acquired recursively by a same task10 * - the performances relied on the release-while-schedule() property11 *12 * Now that we replace it by a mutex, we still want to keep the same13 * recursive property to avoid big changes in the code structure.14 * We use our own lock_owner here because the owner field on a mutex15 * is only available in SMP or mutex debugging, also we only need this field16 * for this mutex, no need for a system wide mutex facility.17 *18 * Also this lock is often released before a call that could block because19 * reiserfs performances were partially based on the release while schedule()20 * property of the Bkl.21 */22void reiserfs_write_lock(struct super_block *s)23{24 struct reiserfs_sb_info *sb_i = REISERFS_SB(s);25 26 if (sb_i->lock_owner != current) {27 mutex_lock(&sb_i->lock);28 sb_i->lock_owner = current;29 }30 31 /* No need to protect it, only the current task touches it */32 sb_i->lock_depth++;33}34 35void reiserfs_write_unlock(struct super_block *s)36{37 struct reiserfs_sb_info *sb_i = REISERFS_SB(s);38 39 /*40 * Are we unlocking without even holding the lock?41 * Such a situation must raise a BUG() if we don't want42 * to corrupt the data.43 */44 BUG_ON(sb_i->lock_owner != current);45 46 if (--sb_i->lock_depth == -1) {47 sb_i->lock_owner = NULL;48 mutex_unlock(&sb_i->lock);49 }50}51 52int __must_check reiserfs_write_unlock_nested(struct super_block *s)53{54 struct reiserfs_sb_info *sb_i = REISERFS_SB(s);55 int depth;56 57 /* this can happen when the lock isn't always held */58 if (sb_i->lock_owner != current)59 return -1;60 61 depth = sb_i->lock_depth;62 63 sb_i->lock_depth = -1;64 sb_i->lock_owner = NULL;65 mutex_unlock(&sb_i->lock);66 67 return depth;68}69 70void reiserfs_write_lock_nested(struct super_block *s, int depth)71{72 struct reiserfs_sb_info *sb_i = REISERFS_SB(s);73 74 /* this can happen when the lock isn't always held */75 if (depth == -1)76 return;77 78 mutex_lock(&sb_i->lock);79 sb_i->lock_owner = current;80 sb_i->lock_depth = depth;81}82 83/*84 * Utility function to force a BUG if it is called without the superblock85 * write lock held. caller is the string printed just before calling BUG()86 */87void reiserfs_check_lock_depth(struct super_block *sb, char *caller)88{89 struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);90 91 WARN_ON(sb_i->lock_depth < 0);92}93 94#ifdef CONFIG_REISERFS_CHECK95void reiserfs_lock_check_recursive(struct super_block *sb)96{97 struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);98 99 WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n");100}101#endif102