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