ast.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /******************************************************************************
  3. *******************************************************************************
  4. **
  5. ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
  6. ** Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
  7. **
  8. **
  9. *******************************************************************************
  10. ******************************************************************************/
  11. #include <trace/events/dlm.h>
  12. #include "dlm_internal.h"
  13. #include "lock.h"
  14. #include "user.h"
  15. #include "ast.h"
  16. static uint64_t dlm_cb_seq;
  17. static DEFINE_SPINLOCK(dlm_cb_seq_spin);
  18. static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb)
  19. {
  20. int i;
  21. log_print("last_bast %x %llu flags %x mode %d sb %d %x",
  22. lkb->lkb_id,
  23. (unsigned long long)lkb->lkb_last_bast.seq,
  24. lkb->lkb_last_bast.flags,
  25. lkb->lkb_last_bast.mode,
  26. lkb->lkb_last_bast.sb_status,
  27. lkb->lkb_last_bast.sb_flags);
  28. log_print("last_cast %x %llu flags %x mode %d sb %d %x",
  29. lkb->lkb_id,
  30. (unsigned long long)lkb->lkb_last_cast.seq,
  31. lkb->lkb_last_cast.flags,
  32. lkb->lkb_last_cast.mode,
  33. lkb->lkb_last_cast.sb_status,
  34. lkb->lkb_last_cast.sb_flags);
  35. for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
  36. log_print("cb %x %llu flags %x mode %d sb %d %x",
  37. lkb->lkb_id,
  38. (unsigned long long)lkb->lkb_callbacks[i].seq,
  39. lkb->lkb_callbacks[i].flags,
  40. lkb->lkb_callbacks[i].mode,
  41. lkb->lkb_callbacks[i].sb_status,
  42. lkb->lkb_callbacks[i].sb_flags);
  43. }
  44. }
  45. int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
  46. int status, uint32_t sbflags, uint64_t seq)
  47. {
  48. struct dlm_ls *ls = lkb->lkb_resource->res_ls;
  49. uint64_t prev_seq;
  50. int prev_mode;
  51. int i, rv;
  52. for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
  53. if (lkb->lkb_callbacks[i].seq)
  54. continue;
  55. /*
  56. * Suppress some redundant basts here, do more on removal.
  57. * Don't even add a bast if the callback just before it
  58. * is a bast for the same mode or a more restrictive mode.
  59. * (the addional > PR check is needed for PR/CW inversion)
  60. */
  61. if ((i > 0) && (flags & DLM_CB_BAST) &&
  62. (lkb->lkb_callbacks[i-1].flags & DLM_CB_BAST)) {
  63. prev_seq = lkb->lkb_callbacks[i-1].seq;
  64. prev_mode = lkb->lkb_callbacks[i-1].mode;
  65. if ((prev_mode == mode) ||
  66. (prev_mode > mode && prev_mode > DLM_LOCK_PR)) {
  67. log_debug(ls, "skip %x add bast %llu mode %d "
  68. "for bast %llu mode %d",
  69. lkb->lkb_id,
  70. (unsigned long long)seq,
  71. mode,
  72. (unsigned long long)prev_seq,
  73. prev_mode);
  74. rv = 0;
  75. goto out;
  76. }
  77. }
  78. lkb->lkb_callbacks[i].seq = seq;
  79. lkb->lkb_callbacks[i].flags = flags;
  80. lkb->lkb_callbacks[i].mode = mode;
  81. lkb->lkb_callbacks[i].sb_status = status;
  82. lkb->lkb_callbacks[i].sb_flags = (sbflags & 0x000000FF);
  83. rv = 0;
  84. break;
  85. }
  86. if (i == DLM_CALLBACKS_SIZE) {
  87. log_error(ls, "no callbacks %x %llu flags %x mode %d sb %d %x",
  88. lkb->lkb_id, (unsigned long long)seq,
  89. flags, mode, status, sbflags);
  90. dlm_dump_lkb_callbacks(lkb);
  91. rv = -1;
  92. goto out;
  93. }
  94. out:
  95. return rv;
  96. }
  97. int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
  98. struct dlm_callback *cb, int *resid)
  99. {
  100. int i, rv;
  101. *resid = 0;
  102. if (!lkb->lkb_callbacks[0].seq) {
  103. rv = -ENOENT;
  104. goto out;
  105. }
  106. /* oldest undelivered cb is callbacks[0] */
  107. memcpy(cb, &lkb->lkb_callbacks[0], sizeof(struct dlm_callback));
  108. memset(&lkb->lkb_callbacks[0], 0, sizeof(struct dlm_callback));
  109. /* shift others down */
  110. for (i = 1; i < DLM_CALLBACKS_SIZE; i++) {
  111. if (!lkb->lkb_callbacks[i].seq)
  112. break;
  113. memcpy(&lkb->lkb_callbacks[i-1], &lkb->lkb_callbacks[i],
  114. sizeof(struct dlm_callback));
  115. memset(&lkb->lkb_callbacks[i], 0, sizeof(struct dlm_callback));
  116. (*resid)++;
  117. }
  118. /* if cb is a bast, it should be skipped if the blocking mode is
  119. compatible with the last granted mode */
  120. if ((cb->flags & DLM_CB_BAST) && lkb->lkb_last_cast.seq) {
  121. if (dlm_modes_compat(cb->mode, lkb->lkb_last_cast.mode)) {
  122. cb->flags |= DLM_CB_SKIP;
  123. log_debug(ls, "skip %x bast %llu mode %d "
  124. "for cast %llu mode %d",
  125. lkb->lkb_id,
  126. (unsigned long long)cb->seq,
  127. cb->mode,
  128. (unsigned long long)lkb->lkb_last_cast.seq,
  129. lkb->lkb_last_cast.mode);
  130. rv = 0;
  131. goto out;
  132. }
  133. }
  134. if (cb->flags & DLM_CB_CAST) {
  135. memcpy(&lkb->lkb_last_cast, cb, sizeof(struct dlm_callback));
  136. lkb->lkb_last_cast_time = ktime_get();
  137. }
  138. if (cb->flags & DLM_CB_BAST) {
  139. memcpy(&lkb->lkb_last_bast, cb, sizeof(struct dlm_callback));
  140. lkb->lkb_last_bast_time = ktime_get();
  141. }
  142. rv = 0;
  143. out:
  144. return rv;
  145. }
  146. void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
  147. uint32_t sbflags)
  148. {
  149. struct dlm_ls *ls = lkb->lkb_resource->res_ls;
  150. uint64_t new_seq, prev_seq;
  151. int rv;
  152. spin_lock(&dlm_cb_seq_spin);
  153. new_seq = ++dlm_cb_seq;
  154. if (!dlm_cb_seq)
  155. new_seq = ++dlm_cb_seq;
  156. spin_unlock(&dlm_cb_seq_spin);
  157. if (lkb->lkb_flags & DLM_IFL_USER) {
  158. dlm_user_add_ast(lkb, flags, mode, status, sbflags, new_seq);
  159. return;
  160. }
  161. mutex_lock(&lkb->lkb_cb_mutex);
  162. prev_seq = lkb->lkb_callbacks[0].seq;
  163. rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, new_seq);
  164. if (rv < 0)
  165. goto out;
  166. if (!prev_seq) {
  167. kref_get(&lkb->lkb_ref);
  168. mutex_lock(&ls->ls_cb_mutex);
  169. if (test_bit(LSFL_CB_DELAY, &ls->ls_flags)) {
  170. list_add(&lkb->lkb_cb_list, &ls->ls_cb_delay);
  171. } else {
  172. queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
  173. }
  174. mutex_unlock(&ls->ls_cb_mutex);
  175. }
  176. out:
  177. mutex_unlock(&lkb->lkb_cb_mutex);
  178. }
  179. void dlm_callback_work(struct work_struct *work)
  180. {
  181. struct dlm_lkb *lkb = container_of(work, struct dlm_lkb, lkb_cb_work);
  182. struct dlm_ls *ls = lkb->lkb_resource->res_ls;
  183. void (*castfn) (void *astparam);
  184. void (*bastfn) (void *astparam, int mode);
  185. struct dlm_callback callbacks[DLM_CALLBACKS_SIZE];
  186. int i, rv, resid;
  187. memset(&callbacks, 0, sizeof(callbacks));
  188. mutex_lock(&lkb->lkb_cb_mutex);
  189. if (!lkb->lkb_callbacks[0].seq) {
  190. /* no callback work exists, shouldn't happen */
  191. log_error(ls, "dlm_callback_work %x no work", lkb->lkb_id);
  192. dlm_print_lkb(lkb);
  193. dlm_dump_lkb_callbacks(lkb);
  194. }
  195. for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
  196. rv = dlm_rem_lkb_callback(ls, lkb, &callbacks[i], &resid);
  197. if (rv < 0)
  198. break;
  199. }
  200. if (resid) {
  201. /* cbs remain, loop should have removed all, shouldn't happen */
  202. log_error(ls, "dlm_callback_work %x resid %d", lkb->lkb_id,
  203. resid);
  204. dlm_print_lkb(lkb);
  205. dlm_dump_lkb_callbacks(lkb);
  206. }
  207. mutex_unlock(&lkb->lkb_cb_mutex);
  208. castfn = lkb->lkb_astfn;
  209. bastfn = lkb->lkb_bastfn;
  210. for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
  211. if (!callbacks[i].seq)
  212. break;
  213. if (callbacks[i].flags & DLM_CB_SKIP) {
  214. continue;
  215. } else if (callbacks[i].flags & DLM_CB_BAST) {
  216. trace_dlm_bast(ls, lkb, callbacks[i].mode);
  217. bastfn(lkb->lkb_astparam, callbacks[i].mode);
  218. } else if (callbacks[i].flags & DLM_CB_CAST) {
  219. lkb->lkb_lksb->sb_status = callbacks[i].sb_status;
  220. lkb->lkb_lksb->sb_flags = callbacks[i].sb_flags;
  221. trace_dlm_ast(ls, lkb);
  222. castfn(lkb->lkb_astparam);
  223. }
  224. }
  225. /* undo kref_get from dlm_add_callback, may cause lkb to be freed */
  226. dlm_put_lkb(lkb);
  227. }
  228. int dlm_callback_start(struct dlm_ls *ls)
  229. {
  230. ls->ls_callback_wq = alloc_workqueue("dlm_callback",
  231. WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
  232. if (!ls->ls_callback_wq) {
  233. log_print("can't start dlm_callback workqueue");
  234. return -ENOMEM;
  235. }
  236. return 0;
  237. }
  238. void dlm_callback_stop(struct dlm_ls *ls)
  239. {
  240. if (ls->ls_callback_wq)
  241. destroy_workqueue(ls->ls_callback_wq);
  242. }
  243. void dlm_callback_suspend(struct dlm_ls *ls)
  244. {
  245. if (ls->ls_callback_wq) {
  246. mutex_lock(&ls->ls_cb_mutex);
  247. set_bit(LSFL_CB_DELAY, &ls->ls_flags);
  248. mutex_unlock(&ls->ls_cb_mutex);
  249. flush_workqueue(ls->ls_callback_wq);
  250. }
  251. }
  252. #define MAX_CB_QUEUE 25
  253. void dlm_callback_resume(struct dlm_ls *ls)
  254. {
  255. struct dlm_lkb *lkb, *safe;
  256. int count = 0, sum = 0;
  257. bool empty;
  258. if (!ls->ls_callback_wq)
  259. return;
  260. clear_bit(LSFL_CB_DELAY, &ls->ls_flags);
  261. more:
  262. mutex_lock(&ls->ls_cb_mutex);
  263. list_for_each_entry_safe(lkb, safe, &ls->ls_cb_delay, lkb_cb_list) {
  264. list_del_init(&lkb->lkb_cb_list);
  265. queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
  266. count++;
  267. if (count == MAX_CB_QUEUE)
  268. break;
  269. }
  270. empty = list_empty(&ls->ls_cb_delay);
  271. mutex_unlock(&ls->ls_cb_mutex);
  272. sum += count;
  273. if (!empty) {
  274. count = 0;
  275. cond_resched();
  276. goto more;
  277. }
  278. if (sum)
  279. log_rinfo(ls, "%s %d", __func__, sum);
  280. }