lock.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include "reiserfs.h"
  3. #include <linux/mutex.h>
  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. */
  21. void reiserfs_write_lock(struct super_block *s)
  22. {
  23. struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
  24. if (sb_i->lock_owner != current) {
  25. mutex_lock(&sb_i->lock);
  26. sb_i->lock_owner = current;
  27. }
  28. /* No need to protect it, only the current task touches it */
  29. sb_i->lock_depth++;
  30. }
  31. void reiserfs_write_unlock(struct super_block *s)
  32. {
  33. struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
  34. /*
  35. * Are we unlocking without even holding the lock?
  36. * Such a situation must raise a BUG() if we don't want
  37. * to corrupt the data.
  38. */
  39. BUG_ON(sb_i->lock_owner != current);
  40. if (--sb_i->lock_depth == -1) {
  41. sb_i->lock_owner = NULL;
  42. mutex_unlock(&sb_i->lock);
  43. }
  44. }
  45. int __must_check reiserfs_write_unlock_nested(struct super_block *s)
  46. {
  47. struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
  48. int depth;
  49. /* this can happen when the lock isn't always held */
  50. if (sb_i->lock_owner != current)
  51. return -1;
  52. depth = sb_i->lock_depth;
  53. sb_i->lock_depth = -1;
  54. sb_i->lock_owner = NULL;
  55. mutex_unlock(&sb_i->lock);
  56. return depth;
  57. }
  58. void reiserfs_write_lock_nested(struct super_block *s, int depth)
  59. {
  60. struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
  61. /* this can happen when the lock isn't always held */
  62. if (depth == -1)
  63. return;
  64. mutex_lock(&sb_i->lock);
  65. sb_i->lock_owner = current;
  66. sb_i->lock_depth = depth;
  67. }
  68. /*
  69. * Utility function to force a BUG if it is called without the superblock
  70. * write lock held. caller is the string printed just before calling BUG()
  71. */
  72. void reiserfs_check_lock_depth(struct super_block *sb, char *caller)
  73. {
  74. struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
  75. WARN_ON(sb_i->lock_depth < 0);
  76. }
  77. #ifdef CONFIG_REISERFS_CHECK
  78. void reiserfs_lock_check_recursive(struct super_block *sb)
  79. {
  80. struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
  81. WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n");
  82. }
  83. #endif