Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include "reiserfs.h"
0003 #include <linux/mutex.h>
0004 
0005 /*
0006  * The previous reiserfs locking scheme was heavily based on
0007  * the tricky properties of the Bkl:
0008  *
0009  * - it was acquired recursively by a same task
0010  * - the performances relied on the release-while-schedule() property
0011  *
0012  * Now that we replace it by a mutex, we still want to keep the same
0013  * recursive property to avoid big changes in the code structure.
0014  * We use our own lock_owner here because the owner field on a mutex
0015  * is only available in SMP or mutex debugging, also we only need this field
0016  * for this mutex, no need for a system wide mutex facility.
0017  *
0018  * Also this lock is often released before a call that could block because
0019  * reiserfs performances were partially based on the release while schedule()
0020  * property of the Bkl.
0021  */
0022 void reiserfs_write_lock(struct super_block *s)
0023 {
0024     struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
0025 
0026     if (sb_i->lock_owner != current) {
0027         mutex_lock(&sb_i->lock);
0028         sb_i->lock_owner = current;
0029     }
0030 
0031     /* No need to protect it, only the current task touches it */
0032     sb_i->lock_depth++;
0033 }
0034 
0035 void reiserfs_write_unlock(struct super_block *s)
0036 {
0037     struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
0038 
0039     /*
0040      * Are we unlocking without even holding the lock?
0041      * Such a situation must raise a BUG() if we don't want
0042      * to corrupt the data.
0043      */
0044     BUG_ON(sb_i->lock_owner != current);
0045 
0046     if (--sb_i->lock_depth == -1) {
0047         sb_i->lock_owner = NULL;
0048         mutex_unlock(&sb_i->lock);
0049     }
0050 }
0051 
0052 int __must_check reiserfs_write_unlock_nested(struct super_block *s)
0053 {
0054     struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
0055     int depth;
0056 
0057     /* this can happen when the lock isn't always held */
0058     if (sb_i->lock_owner != current)
0059         return -1;
0060 
0061     depth = sb_i->lock_depth;
0062 
0063     sb_i->lock_depth = -1;
0064     sb_i->lock_owner = NULL;
0065     mutex_unlock(&sb_i->lock);
0066 
0067     return depth;
0068 }
0069 
0070 void reiserfs_write_lock_nested(struct super_block *s, int depth)
0071 {
0072     struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
0073 
0074     /* this can happen when the lock isn't always held */
0075     if (depth == -1)
0076         return;
0077 
0078     mutex_lock(&sb_i->lock);
0079     sb_i->lock_owner = current;
0080     sb_i->lock_depth = depth;
0081 }
0082 
0083 /*
0084  * Utility function to force a BUG if it is called without the superblock
0085  * write lock held.  caller is the string printed just before calling BUG()
0086  */
0087 void reiserfs_check_lock_depth(struct super_block *sb, char *caller)
0088 {
0089     struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
0090 
0091     WARN_ON(sb_i->lock_depth < 0);
0092 }
0093 
0094 #ifdef CONFIG_REISERFS_CHECK
0095 void reiserfs_lock_check_recursive(struct super_block *sb)
0096 {
0097     struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
0098 
0099     WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n");
0100 }
0101 #endif