linux/fs/reiserfs/lock.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include "reiserfs.h"
   3#include <linux/mutex.h>
   4
   5/*
   6 * The previous reiserfs locking scheme was heavily based on
   7 * the tricky properties of the Bkl:
   8 *
   9 * - it was acquired recursively by a same task
  10 * - the performances relied on the release-while-schedule() property
  11 *
  12 * Now that we replace it by a mutex, we still want to keep the same
  13 * recursive property to avoid big changes in the code structure.
  14 * We use our own lock_owner here because the owner field on a mutex
  15 * is only available in SMP or mutex debugging, also we only need this field
  16 * 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 because
  19 * 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 want
  42         * 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 superblock
  85 * 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_CHECK
  95void 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#endif
 102