PageRenderTime 37ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/fs/ocfs2/reservations.c

https://gitlab.com/LiquidSmooth-Devices/android_kernel_htc_msm8974
C | 715 lines | 526 code | 164 blank | 25 comment | 95 complexity | 7263f327550913f87a3c43bfafcb1dfa MD5 | raw file
Possible License(s): GPL-2.0
  1. /* -*- mode: c; c-basic-offset: 8; -*-
  2. * vim: noexpandtab sw=8 ts=8 sts=0:
  3. *
  4. * reservations.c
  5. *
  6. * Allocation reservations implementation
  7. *
  8. * Some code borrowed from fs/ext3/balloc.c and is:
  9. *
  10. * Copyright (C) 1992, 1993, 1994, 1995
  11. * Remy Card (card@masi.ibp.fr)
  12. * Laboratoire MASI - Institut Blaise Pascal
  13. * Universite Pierre et Marie Curie (Paris VI)
  14. *
  15. * The rest is copyright (C) 2010 Novell. All rights reserved.
  16. *
  17. * This program is free software; you can redistribute it and/or
  18. * modify it under the terms of the GNU General Public
  19. * License version 2 as published by the Free Software Foundation.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  24. * General Public License for more details.
  25. */
  26. #include <linux/fs.h>
  27. #include <linux/types.h>
  28. #include <linux/highmem.h>
  29. #include <linux/bitops.h>
  30. #include <linux/list.h>
  31. #include <cluster/masklog.h>
  32. #include "ocfs2.h"
  33. #include "ocfs2_trace.h"
  34. #ifdef CONFIG_OCFS2_DEBUG_FS
  35. #define OCFS2_CHECK_RESERVATIONS
  36. #endif
  37. DEFINE_SPINLOCK(resv_lock);
  38. #define OCFS2_MIN_RESV_WINDOW_BITS 8
  39. #define OCFS2_MAX_RESV_WINDOW_BITS 1024
  40. int ocfs2_dir_resv_allowed(struct ocfs2_super *osb)
  41. {
  42. return (osb->osb_resv_level && osb->osb_dir_resv_level);
  43. }
  44. static unsigned int ocfs2_resv_window_bits(struct ocfs2_reservation_map *resmap,
  45. struct ocfs2_alloc_reservation *resv)
  46. {
  47. struct ocfs2_super *osb = resmap->m_osb;
  48. unsigned int bits;
  49. if (!(resv->r_flags & OCFS2_RESV_FLAG_DIR)) {
  50. bits = 4 << osb->osb_resv_level;
  51. } else {
  52. bits = 4 << osb->osb_dir_resv_level;
  53. }
  54. return bits;
  55. }
  56. static inline unsigned int ocfs2_resv_end(struct ocfs2_alloc_reservation *resv)
  57. {
  58. if (resv->r_len)
  59. return resv->r_start + resv->r_len - 1;
  60. return resv->r_start;
  61. }
  62. static inline int ocfs2_resv_empty(struct ocfs2_alloc_reservation *resv)
  63. {
  64. return !!(resv->r_len == 0);
  65. }
  66. static inline int ocfs2_resmap_disabled(struct ocfs2_reservation_map *resmap)
  67. {
  68. if (resmap->m_osb->osb_resv_level == 0)
  69. return 1;
  70. return 0;
  71. }
  72. static void ocfs2_dump_resv(struct ocfs2_reservation_map *resmap)
  73. {
  74. struct ocfs2_super *osb = resmap->m_osb;
  75. struct rb_node *node;
  76. struct ocfs2_alloc_reservation *resv;
  77. int i = 0;
  78. mlog(ML_NOTICE, "Dumping resmap for device %s. Bitmap length: %u\n",
  79. osb->dev_str, resmap->m_bitmap_len);
  80. node = rb_first(&resmap->m_reservations);
  81. while (node) {
  82. resv = rb_entry(node, struct ocfs2_alloc_reservation, r_node);
  83. mlog(ML_NOTICE, "start: %u\tend: %u\tlen: %u\tlast_start: %u"
  84. "\tlast_len: %u\n", resv->r_start,
  85. ocfs2_resv_end(resv), resv->r_len, resv->r_last_start,
  86. resv->r_last_len);
  87. node = rb_next(node);
  88. i++;
  89. }
  90. mlog(ML_NOTICE, "%d reservations found. LRU follows\n", i);
  91. i = 0;
  92. list_for_each_entry(resv, &resmap->m_lru, r_lru) {
  93. mlog(ML_NOTICE, "LRU(%d) start: %u\tend: %u\tlen: %u\t"
  94. "last_start: %u\tlast_len: %u\n", i, resv->r_start,
  95. ocfs2_resv_end(resv), resv->r_len, resv->r_last_start,
  96. resv->r_last_len);
  97. i++;
  98. }
  99. }
  100. #ifdef OCFS2_CHECK_RESERVATIONS
  101. static int ocfs2_validate_resmap_bits(struct ocfs2_reservation_map *resmap,
  102. int i,
  103. struct ocfs2_alloc_reservation *resv)
  104. {
  105. char *disk_bitmap = resmap->m_disk_bitmap;
  106. unsigned int start = resv->r_start;
  107. unsigned int end = ocfs2_resv_end(resv);
  108. while (start <= end) {
  109. if (ocfs2_test_bit(start, disk_bitmap)) {
  110. mlog(ML_ERROR,
  111. "reservation %d covers an allocated area "
  112. "starting at bit %u!\n", i, start);
  113. return 1;
  114. }
  115. start++;
  116. }
  117. return 0;
  118. }
  119. static void ocfs2_check_resmap(struct ocfs2_reservation_map *resmap)
  120. {
  121. unsigned int off = 0;
  122. int i = 0;
  123. struct rb_node *node;
  124. struct ocfs2_alloc_reservation *resv;
  125. node = rb_first(&resmap->m_reservations);
  126. while (node) {
  127. resv = rb_entry(node, struct ocfs2_alloc_reservation, r_node);
  128. if (i > 0 && resv->r_start <= off) {
  129. mlog(ML_ERROR, "reservation %d has bad start off!\n",
  130. i);
  131. goto bad;
  132. }
  133. if (resv->r_len == 0) {
  134. mlog(ML_ERROR, "reservation %d has no length!\n",
  135. i);
  136. goto bad;
  137. }
  138. if (resv->r_start > ocfs2_resv_end(resv)) {
  139. mlog(ML_ERROR, "reservation %d has invalid range!\n",
  140. i);
  141. goto bad;
  142. }
  143. if (ocfs2_resv_end(resv) >= resmap->m_bitmap_len) {
  144. mlog(ML_ERROR, "reservation %d extends past bitmap!\n",
  145. i);
  146. goto bad;
  147. }
  148. if (ocfs2_validate_resmap_bits(resmap, i, resv))
  149. goto bad;
  150. off = ocfs2_resv_end(resv);
  151. node = rb_next(node);
  152. i++;
  153. }
  154. return;
  155. bad:
  156. ocfs2_dump_resv(resmap);
  157. BUG();
  158. }
  159. #else
  160. static inline void ocfs2_check_resmap(struct ocfs2_reservation_map *resmap)
  161. {
  162. }
  163. #endif
  164. void ocfs2_resv_init_once(struct ocfs2_alloc_reservation *resv)
  165. {
  166. memset(resv, 0, sizeof(*resv));
  167. INIT_LIST_HEAD(&resv->r_lru);
  168. }
  169. void ocfs2_resv_set_type(struct ocfs2_alloc_reservation *resv,
  170. unsigned int flags)
  171. {
  172. BUG_ON(flags & ~OCFS2_RESV_TYPES);
  173. resv->r_flags |= flags;
  174. }
  175. int ocfs2_resmap_init(struct ocfs2_super *osb,
  176. struct ocfs2_reservation_map *resmap)
  177. {
  178. memset(resmap, 0, sizeof(*resmap));
  179. resmap->m_osb = osb;
  180. resmap->m_reservations = RB_ROOT;
  181. INIT_LIST_HEAD(&resmap->m_lru);
  182. return 0;
  183. }
  184. static void ocfs2_resv_mark_lru(struct ocfs2_reservation_map *resmap,
  185. struct ocfs2_alloc_reservation *resv)
  186. {
  187. assert_spin_locked(&resv_lock);
  188. if (!list_empty(&resv->r_lru))
  189. list_del_init(&resv->r_lru);
  190. list_add_tail(&resv->r_lru, &resmap->m_lru);
  191. }
  192. static void __ocfs2_resv_trunc(struct ocfs2_alloc_reservation *resv)
  193. {
  194. resv->r_len = 0;
  195. resv->r_start = 0;
  196. }
  197. static void ocfs2_resv_remove(struct ocfs2_reservation_map *resmap,
  198. struct ocfs2_alloc_reservation *resv)
  199. {
  200. if (resv->r_flags & OCFS2_RESV_FLAG_INUSE) {
  201. list_del_init(&resv->r_lru);
  202. rb_erase(&resv->r_node, &resmap->m_reservations);
  203. resv->r_flags &= ~OCFS2_RESV_FLAG_INUSE;
  204. }
  205. }
  206. static void __ocfs2_resv_discard(struct ocfs2_reservation_map *resmap,
  207. struct ocfs2_alloc_reservation *resv)
  208. {
  209. assert_spin_locked(&resv_lock);
  210. __ocfs2_resv_trunc(resv);
  211. resv->r_last_len = resv->r_last_start = 0;
  212. ocfs2_resv_remove(resmap, resv);
  213. }
  214. void ocfs2_resv_discard(struct ocfs2_reservation_map *resmap,
  215. struct ocfs2_alloc_reservation *resv)
  216. {
  217. if (resv) {
  218. spin_lock(&resv_lock);
  219. __ocfs2_resv_discard(resmap, resv);
  220. spin_unlock(&resv_lock);
  221. }
  222. }
  223. static void ocfs2_resmap_clear_all_resv(struct ocfs2_reservation_map *resmap)
  224. {
  225. struct rb_node *node;
  226. struct ocfs2_alloc_reservation *resv;
  227. assert_spin_locked(&resv_lock);
  228. while ((node = rb_last(&resmap->m_reservations)) != NULL) {
  229. resv = rb_entry(node, struct ocfs2_alloc_reservation, r_node);
  230. __ocfs2_resv_discard(resmap, resv);
  231. }
  232. }
  233. void ocfs2_resmap_restart(struct ocfs2_reservation_map *resmap,
  234. unsigned int clen, char *disk_bitmap)
  235. {
  236. if (ocfs2_resmap_disabled(resmap))
  237. return;
  238. spin_lock(&resv_lock);
  239. ocfs2_resmap_clear_all_resv(resmap);
  240. resmap->m_bitmap_len = clen;
  241. resmap->m_disk_bitmap = disk_bitmap;
  242. spin_unlock(&resv_lock);
  243. }
  244. void ocfs2_resmap_uninit(struct ocfs2_reservation_map *resmap)
  245. {
  246. }
  247. static void ocfs2_resv_insert(struct ocfs2_reservation_map *resmap,
  248. struct ocfs2_alloc_reservation *new)
  249. {
  250. struct rb_root *root = &resmap->m_reservations;
  251. struct rb_node *parent = NULL;
  252. struct rb_node **p = &root->rb_node;
  253. struct ocfs2_alloc_reservation *tmp;
  254. assert_spin_locked(&resv_lock);
  255. trace_ocfs2_resv_insert(new->r_start, new->r_len);
  256. while (*p) {
  257. parent = *p;
  258. tmp = rb_entry(parent, struct ocfs2_alloc_reservation, r_node);
  259. if (new->r_start < tmp->r_start) {
  260. p = &(*p)->rb_left;
  261. BUG_ON(ocfs2_resv_end(new) >= tmp->r_start);
  262. } else if (new->r_start > ocfs2_resv_end(tmp)) {
  263. p = &(*p)->rb_right;
  264. } else {
  265. mlog(ML_ERROR, "Duplicate reservation window!\n");
  266. BUG();
  267. }
  268. }
  269. rb_link_node(&new->r_node, parent, p);
  270. rb_insert_color(&new->r_node, root);
  271. new->r_flags |= OCFS2_RESV_FLAG_INUSE;
  272. ocfs2_resv_mark_lru(resmap, new);
  273. ocfs2_check_resmap(resmap);
  274. }
  275. static struct ocfs2_alloc_reservation *
  276. ocfs2_find_resv_lhs(struct ocfs2_reservation_map *resmap, unsigned int goal)
  277. {
  278. struct ocfs2_alloc_reservation *resv = NULL;
  279. struct ocfs2_alloc_reservation *prev_resv = NULL;
  280. struct rb_node *node = resmap->m_reservations.rb_node;
  281. assert_spin_locked(&resv_lock);
  282. if (!node)
  283. return NULL;
  284. node = rb_first(&resmap->m_reservations);
  285. while (node) {
  286. resv = rb_entry(node, struct ocfs2_alloc_reservation, r_node);
  287. if (resv->r_start <= goal && ocfs2_resv_end(resv) >= goal)
  288. break;
  289. if (resv->r_start > goal) {
  290. resv = prev_resv;
  291. break;
  292. }
  293. prev_resv = resv;
  294. node = rb_next(node);
  295. }
  296. return resv;
  297. }
  298. static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap,
  299. unsigned int wanted,
  300. unsigned int search_start,
  301. unsigned int search_len,
  302. unsigned int *rstart,
  303. unsigned int *rlen)
  304. {
  305. void *bitmap = resmap->m_disk_bitmap;
  306. unsigned int best_start, best_len = 0;
  307. int offset, start, found;
  308. trace_ocfs2_resmap_find_free_bits_begin(search_start, search_len,
  309. wanted, resmap->m_bitmap_len);
  310. found = best_start = best_len = 0;
  311. start = search_start;
  312. while ((offset = ocfs2_find_next_zero_bit(bitmap, resmap->m_bitmap_len,
  313. start)) != -1) {
  314. if (offset >= (search_start + search_len))
  315. break;
  316. if (offset == start) {
  317. found++;
  318. start++;
  319. } else {
  320. found = 1;
  321. start = offset + 1;
  322. }
  323. if (found > best_len) {
  324. best_len = found;
  325. best_start = start - found;
  326. }
  327. if (found >= wanted)
  328. break;
  329. }
  330. if (best_len == 0)
  331. return 0;
  332. if (best_len >= wanted)
  333. best_len = wanted;
  334. *rlen = best_len;
  335. *rstart = best_start;
  336. trace_ocfs2_resmap_find_free_bits_end(best_start, best_len);
  337. return *rlen;
  338. }
  339. static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
  340. struct ocfs2_alloc_reservation *resv,
  341. unsigned int goal, unsigned int wanted)
  342. {
  343. struct rb_root *root = &resmap->m_reservations;
  344. unsigned int gap_start, gap_end, gap_len;
  345. struct ocfs2_alloc_reservation *prev_resv, *next_resv;
  346. struct rb_node *prev, *next;
  347. unsigned int cstart, clen;
  348. unsigned int best_start = 0, best_len = 0;
  349. trace_ocfs2_resv_find_window_begin(resv->r_start, ocfs2_resv_end(resv),
  350. goal, wanted, RB_EMPTY_ROOT(root));
  351. assert_spin_locked(&resv_lock);
  352. if (RB_EMPTY_ROOT(root)) {
  353. clen = ocfs2_resmap_find_free_bits(resmap, wanted, goal,
  354. resmap->m_bitmap_len - goal,
  355. &cstart, &clen);
  356. BUG_ON(goal == 0 && clen == 0);
  357. if (clen == 0)
  358. return;
  359. resv->r_start = cstart;
  360. resv->r_len = clen;
  361. ocfs2_resv_insert(resmap, resv);
  362. return;
  363. }
  364. prev_resv = ocfs2_find_resv_lhs(resmap, goal);
  365. if (prev_resv == NULL) {
  366. next = rb_first(root);
  367. next_resv = rb_entry(next, struct ocfs2_alloc_reservation,
  368. r_node);
  369. if (next_resv->r_start <= goal) {
  370. mlog(ML_ERROR, "goal: %u next_resv: start %u len %u\n",
  371. goal, next_resv->r_start, next_resv->r_len);
  372. ocfs2_dump_resv(resmap);
  373. BUG();
  374. }
  375. clen = ocfs2_resmap_find_free_bits(resmap, wanted, goal,
  376. next_resv->r_start - goal,
  377. &cstart, &clen);
  378. if (clen) {
  379. best_len = clen;
  380. best_start = cstart;
  381. if (best_len == wanted)
  382. goto out_insert;
  383. }
  384. prev_resv = next_resv;
  385. next_resv = NULL;
  386. }
  387. trace_ocfs2_resv_find_window_prev(prev_resv->r_start,
  388. ocfs2_resv_end(prev_resv));
  389. prev = &prev_resv->r_node;
  390. while (1) {
  391. next = rb_next(prev);
  392. if (next) {
  393. next_resv = rb_entry(next,
  394. struct ocfs2_alloc_reservation,
  395. r_node);
  396. gap_start = ocfs2_resv_end(prev_resv) + 1;
  397. gap_end = next_resv->r_start - 1;
  398. gap_len = gap_end - gap_start + 1;
  399. } else {
  400. gap_start = ocfs2_resv_end(prev_resv) + 1;
  401. gap_len = resmap->m_bitmap_len - gap_start;
  402. gap_end = resmap->m_bitmap_len - 1;
  403. }
  404. trace_ocfs2_resv_find_window_next(next ? next_resv->r_start: -1,
  405. next ? ocfs2_resv_end(next_resv) : -1);
  406. if (gap_len <= best_len)
  407. goto next_resv;
  408. clen = ocfs2_resmap_find_free_bits(resmap, wanted, gap_start,
  409. gap_len, &cstart, &clen);
  410. if (clen == wanted) {
  411. best_len = clen;
  412. best_start = cstart;
  413. goto out_insert;
  414. } else if (clen > best_len) {
  415. best_len = clen;
  416. best_start = cstart;
  417. }
  418. next_resv:
  419. if (!next)
  420. break;
  421. prev = next;
  422. prev_resv = rb_entry(prev, struct ocfs2_alloc_reservation,
  423. r_node);
  424. }
  425. out_insert:
  426. if (best_len) {
  427. resv->r_start = best_start;
  428. resv->r_len = best_len;
  429. ocfs2_resv_insert(resmap, resv);
  430. }
  431. }
  432. static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap,
  433. struct ocfs2_alloc_reservation *resv,
  434. unsigned int wanted)
  435. {
  436. struct ocfs2_alloc_reservation *lru_resv;
  437. int tmpwindow = !!(resv->r_flags & OCFS2_RESV_FLAG_TMP);
  438. unsigned int min_bits;
  439. if (!tmpwindow)
  440. min_bits = ocfs2_resv_window_bits(resmap, resv) >> 1;
  441. else
  442. min_bits = wanted;
  443. lru_resv = list_first_entry(&resmap->m_lru,
  444. struct ocfs2_alloc_reservation, r_lru);
  445. trace_ocfs2_cannibalize_resv_begin(lru_resv->r_start,
  446. lru_resv->r_len,
  447. ocfs2_resv_end(lru_resv));
  448. if (lru_resv->r_len <= min_bits) {
  449. resv->r_start = lru_resv->r_start;
  450. resv->r_len = lru_resv->r_len;
  451. __ocfs2_resv_discard(resmap, lru_resv);
  452. } else {
  453. unsigned int shrink;
  454. if (tmpwindow)
  455. shrink = min_bits;
  456. else
  457. shrink = lru_resv->r_len / 2;
  458. lru_resv->r_len -= shrink;
  459. resv->r_start = ocfs2_resv_end(lru_resv) + 1;
  460. resv->r_len = shrink;
  461. }
  462. trace_ocfs2_cannibalize_resv_end(resv->r_start, ocfs2_resv_end(resv),
  463. resv->r_len, resv->r_last_start,
  464. resv->r_last_len);
  465. ocfs2_resv_insert(resmap, resv);
  466. }
  467. static void ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
  468. struct ocfs2_alloc_reservation *resv,
  469. unsigned int wanted)
  470. {
  471. unsigned int goal = 0;
  472. BUG_ON(!ocfs2_resv_empty(resv));
  473. if (resv->r_last_len) {
  474. goal = resv->r_last_start + resv->r_last_len;
  475. if (goal >= resmap->m_bitmap_len)
  476. goal = 0;
  477. }
  478. __ocfs2_resv_find_window(resmap, resv, goal, wanted);
  479. if (ocfs2_resv_empty(resv) && goal != 0)
  480. __ocfs2_resv_find_window(resmap, resv, 0, wanted);
  481. if (ocfs2_resv_empty(resv)) {
  482. ocfs2_cannibalize_resv(resmap, resv, wanted);
  483. }
  484. BUG_ON(ocfs2_resv_empty(resv));
  485. }
  486. int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap,
  487. struct ocfs2_alloc_reservation *resv,
  488. int *cstart, int *clen)
  489. {
  490. if (resv == NULL || ocfs2_resmap_disabled(resmap))
  491. return -ENOSPC;
  492. spin_lock(&resv_lock);
  493. if (ocfs2_resv_empty(resv)) {
  494. unsigned int wanted = ocfs2_resv_window_bits(resmap, resv);
  495. if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen)
  496. wanted = *clen;
  497. ocfs2_resv_find_window(resmap, resv, wanted);
  498. trace_ocfs2_resmap_resv_bits(resv->r_start, resv->r_len);
  499. }
  500. BUG_ON(ocfs2_resv_empty(resv));
  501. *cstart = resv->r_start;
  502. *clen = resv->r_len;
  503. spin_unlock(&resv_lock);
  504. return 0;
  505. }
  506. static void
  507. ocfs2_adjust_resv_from_alloc(struct ocfs2_reservation_map *resmap,
  508. struct ocfs2_alloc_reservation *resv,
  509. unsigned int start, unsigned int end)
  510. {
  511. unsigned int rhs = 0;
  512. unsigned int old_end = ocfs2_resv_end(resv);
  513. BUG_ON(start != resv->r_start || old_end < end);
  514. if (old_end == end) {
  515. __ocfs2_resv_discard(resmap, resv);
  516. return;
  517. }
  518. rhs = old_end - end;
  519. BUG_ON(rhs == 0);
  520. resv->r_start = end + 1;
  521. resv->r_len = old_end - resv->r_start + 1;
  522. }
  523. void ocfs2_resmap_claimed_bits(struct ocfs2_reservation_map *resmap,
  524. struct ocfs2_alloc_reservation *resv,
  525. u32 cstart, u32 clen)
  526. {
  527. unsigned int cend = cstart + clen - 1;
  528. if (resmap == NULL || ocfs2_resmap_disabled(resmap))
  529. return;
  530. if (resv == NULL)
  531. return;
  532. BUG_ON(cstart != resv->r_start);
  533. spin_lock(&resv_lock);
  534. trace_ocfs2_resmap_claimed_bits_begin(cstart, cend, clen, resv->r_start,
  535. ocfs2_resv_end(resv), resv->r_len,
  536. resv->r_last_start,
  537. resv->r_last_len);
  538. BUG_ON(cstart < resv->r_start);
  539. BUG_ON(cstart > ocfs2_resv_end(resv));
  540. BUG_ON(cend > ocfs2_resv_end(resv));
  541. ocfs2_adjust_resv_from_alloc(resmap, resv, cstart, cend);
  542. resv->r_last_start = cstart;
  543. resv->r_last_len = clen;
  544. if (!ocfs2_resv_empty(resv))
  545. ocfs2_resv_mark_lru(resmap, resv);
  546. trace_ocfs2_resmap_claimed_bits_end(resv->r_start, ocfs2_resv_end(resv),
  547. resv->r_len, resv->r_last_start,
  548. resv->r_last_len);
  549. ocfs2_check_resmap(resmap);
  550. spin_unlock(&resv_lock);
  551. }