fscache_volume.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* Volume-level cache cookie handling.
  3. *
  4. * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #define FSCACHE_DEBUG_LEVEL COOKIE
  8. #include <linux/export.h>
  9. #include <linux/slab.h>
  10. #include "internal.h"
  11. #define fscache_volume_hash_shift 10
  12. static struct hlist_bl_head fscache_volume_hash[1 << fscache_volume_hash_shift];
  13. static atomic_t fscache_volume_debug_id;
  14. static LIST_HEAD(fscache_volumes);
  15. static void fscache_create_volume_work(struct work_struct *work);
  16. struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
  17. enum fscache_volume_trace where)
  18. {
  19. int ref;
  20. __refcount_inc(&volume->ref, &ref);
  21. trace_fscache_volume(volume->debug_id, ref + 1, where);
  22. return volume;
  23. }
  24. struct fscache_volume *fscache_try_get_volume(struct fscache_volume *volume,
  25. enum fscache_volume_trace where)
  26. {
  27. int ref;
  28. if (!__refcount_inc_not_zero(&volume->ref, &ref))
  29. return NULL;
  30. trace_fscache_volume(volume->debug_id, ref + 1, where);
  31. return volume;
  32. }
  33. EXPORT_SYMBOL(fscache_try_get_volume);
  34. static void fscache_see_volume(struct fscache_volume *volume,
  35. enum fscache_volume_trace where)
  36. {
  37. int ref = refcount_read(&volume->ref);
  38. trace_fscache_volume(volume->debug_id, ref, where);
  39. }
  40. /*
  41. * Pin the cache behind a volume so that we can access it.
  42. */
  43. static void __fscache_begin_volume_access(struct fscache_volume *volume,
  44. struct fscache_cookie *cookie,
  45. enum fscache_access_trace why)
  46. {
  47. int n_accesses;
  48. n_accesses = atomic_inc_return(&volume->n_accesses);
  49. smp_mb__after_atomic();
  50. trace_fscache_access_volume(volume->debug_id, cookie ? cookie->debug_id : 0,
  51. refcount_read(&volume->ref),
  52. n_accesses, why);
  53. }
  54. /**
  55. * fscache_begin_volume_access - Pin a cache so a volume can be accessed
  56. * @volume: The volume cookie
  57. * @cookie: A datafile cookie for a tracing reference (or NULL)
  58. * @why: An indication of the circumstances of the access for tracing
  59. *
  60. * Attempt to pin the cache to prevent it from going away whilst we're
  61. * accessing a volume and returns true if successful. This works as follows:
  62. *
  63. * (1) If the cache tests as not live (state is not FSCACHE_CACHE_IS_ACTIVE),
  64. * then we return false to indicate access was not permitted.
  65. *
  66. * (2) If the cache tests as live, then we increment the volume's n_accesses
  67. * count and then recheck the cache liveness, ending the access if it
  68. * ceased to be live.
  69. *
  70. * (3) When we end the access, we decrement the volume's n_accesses and wake
  71. * up the any waiters if it reaches 0.
  72. *
  73. * (4) Whilst the cache is caching, the volume's n_accesses is kept
  74. * artificially incremented to prevent wakeups from happening.
  75. *
  76. * (5) When the cache is taken offline, the state is changed to prevent new
  77. * accesses, the volume's n_accesses is decremented and we wait for it to
  78. * become 0.
  79. *
  80. * The datafile @cookie and the @why indicator are merely provided for tracing
  81. * purposes.
  82. */
  83. bool fscache_begin_volume_access(struct fscache_volume *volume,
  84. struct fscache_cookie *cookie,
  85. enum fscache_access_trace why)
  86. {
  87. if (!fscache_cache_is_live(volume->cache))
  88. return false;
  89. __fscache_begin_volume_access(volume, cookie, why);
  90. if (!fscache_cache_is_live(volume->cache)) {
  91. fscache_end_volume_access(volume, cookie, fscache_access_unlive);
  92. return false;
  93. }
  94. return true;
  95. }
  96. /**
  97. * fscache_end_volume_access - Unpin a cache at the end of an access.
  98. * @volume: The volume cookie
  99. * @cookie: A datafile cookie for a tracing reference (or NULL)
  100. * @why: An indication of the circumstances of the access for tracing
  101. *
  102. * Unpin a cache volume after we've accessed it. The datafile @cookie and the
  103. * @why indicator are merely provided for tracing purposes.
  104. */
  105. void fscache_end_volume_access(struct fscache_volume *volume,
  106. struct fscache_cookie *cookie,
  107. enum fscache_access_trace why)
  108. {
  109. int n_accesses;
  110. smp_mb__before_atomic();
  111. n_accesses = atomic_dec_return(&volume->n_accesses);
  112. trace_fscache_access_volume(volume->debug_id, cookie ? cookie->debug_id : 0,
  113. refcount_read(&volume->ref),
  114. n_accesses, why);
  115. if (n_accesses == 0)
  116. wake_up_var(&volume->n_accesses);
  117. }
  118. EXPORT_SYMBOL(fscache_end_volume_access);
  119. static bool fscache_volume_same(const struct fscache_volume *a,
  120. const struct fscache_volume *b)
  121. {
  122. size_t klen;
  123. if (a->key_hash != b->key_hash ||
  124. a->cache != b->cache ||
  125. a->key[0] != b->key[0])
  126. return false;
  127. klen = round_up(a->key[0] + 1, sizeof(__le32));
  128. return memcmp(a->key, b->key, klen) == 0;
  129. }
  130. static bool fscache_is_acquire_pending(struct fscache_volume *volume)
  131. {
  132. return test_bit(FSCACHE_VOLUME_ACQUIRE_PENDING, &volume->flags);
  133. }
  134. static void fscache_wait_on_volume_collision(struct fscache_volume *candidate,
  135. unsigned int collidee_debug_id)
  136. {
  137. wait_on_bit_timeout(&candidate->flags, FSCACHE_VOLUME_ACQUIRE_PENDING,
  138. TASK_UNINTERRUPTIBLE, 20 * HZ);
  139. if (fscache_is_acquire_pending(candidate)) {
  140. pr_notice("Potential volume collision new=%08x old=%08x",
  141. candidate->debug_id, collidee_debug_id);
  142. fscache_stat(&fscache_n_volumes_collision);
  143. wait_on_bit(&candidate->flags, FSCACHE_VOLUME_ACQUIRE_PENDING,
  144. TASK_UNINTERRUPTIBLE);
  145. }
  146. }
  147. /*
  148. * Attempt to insert the new volume into the hash. If there's a collision, we
  149. * wait for the old volume to complete if it's being relinquished and an error
  150. * otherwise.
  151. */
  152. static bool fscache_hash_volume(struct fscache_volume *candidate)
  153. {
  154. struct fscache_volume *cursor;
  155. struct hlist_bl_head *h;
  156. struct hlist_bl_node *p;
  157. unsigned int bucket, collidee_debug_id = 0;
  158. bucket = candidate->key_hash & (ARRAY_SIZE(fscache_volume_hash) - 1);
  159. h = &fscache_volume_hash[bucket];
  160. hlist_bl_lock(h);
  161. hlist_bl_for_each_entry(cursor, p, h, hash_link) {
  162. if (fscache_volume_same(candidate, cursor)) {
  163. if (!test_bit(FSCACHE_VOLUME_RELINQUISHED, &cursor->flags))
  164. goto collision;
  165. fscache_see_volume(cursor, fscache_volume_get_hash_collision);
  166. set_bit(FSCACHE_VOLUME_COLLIDED_WITH, &cursor->flags);
  167. set_bit(FSCACHE_VOLUME_ACQUIRE_PENDING, &candidate->flags);
  168. collidee_debug_id = cursor->debug_id;
  169. break;
  170. }
  171. }
  172. hlist_bl_add_head(&candidate->hash_link, h);
  173. hlist_bl_unlock(h);
  174. if (fscache_is_acquire_pending(candidate))
  175. fscache_wait_on_volume_collision(candidate, collidee_debug_id);
  176. return true;
  177. collision:
  178. fscache_see_volume(cursor, fscache_volume_collision);
  179. hlist_bl_unlock(h);
  180. return false;
  181. }
  182. /*
  183. * Allocate and initialise a volume representation cookie.
  184. */
  185. static struct fscache_volume *fscache_alloc_volume(const char *volume_key,
  186. const char *cache_name,
  187. const void *coherency_data,
  188. size_t coherency_len)
  189. {
  190. struct fscache_volume *volume;
  191. struct fscache_cache *cache;
  192. size_t klen, hlen;
  193. u8 *key;
  194. klen = strlen(volume_key);
  195. if (klen > NAME_MAX)
  196. return NULL;
  197. if (!coherency_data)
  198. coherency_len = 0;
  199. cache = fscache_lookup_cache(cache_name, false);
  200. if (IS_ERR(cache))
  201. return NULL;
  202. volume = kzalloc_flex(*volume, coherency, coherency_len);
  203. if (!volume)
  204. goto err_cache;
  205. volume->cache = cache;
  206. volume->coherency_len = coherency_len;
  207. if (coherency_data)
  208. memcpy(volume->coherency, coherency_data, coherency_len);
  209. INIT_LIST_HEAD(&volume->proc_link);
  210. INIT_WORK(&volume->work, fscache_create_volume_work);
  211. refcount_set(&volume->ref, 1);
  212. spin_lock_init(&volume->lock);
  213. /* Stick the length on the front of the key and pad it out to make
  214. * hashing easier.
  215. */
  216. hlen = round_up(1 + klen + 1, sizeof(__le32));
  217. key = kzalloc(hlen, GFP_KERNEL);
  218. if (!key)
  219. goto err_vol;
  220. key[0] = klen;
  221. memcpy(key + 1, volume_key, klen);
  222. volume->key = key;
  223. volume->key_hash = fscache_hash(0, key, hlen);
  224. volume->debug_id = atomic_inc_return(&fscache_volume_debug_id);
  225. down_write(&fscache_addremove_sem);
  226. atomic_inc(&cache->n_volumes);
  227. list_add_tail(&volume->proc_link, &fscache_volumes);
  228. fscache_see_volume(volume, fscache_volume_new_acquire);
  229. fscache_stat(&fscache_n_volumes);
  230. up_write(&fscache_addremove_sem);
  231. _leave(" = v=%x", volume->debug_id);
  232. return volume;
  233. err_vol:
  234. kfree(volume);
  235. err_cache:
  236. fscache_put_cache(cache, fscache_cache_put_alloc_volume);
  237. fscache_stat(&fscache_n_volumes_nomem);
  238. return NULL;
  239. }
  240. /*
  241. * Create a volume's representation on disk. Have a volume ref and a cache
  242. * access we have to release.
  243. */
  244. static void fscache_create_volume_work(struct work_struct *work)
  245. {
  246. const struct fscache_cache_ops *ops;
  247. struct fscache_volume *volume =
  248. container_of(work, struct fscache_volume, work);
  249. fscache_see_volume(volume, fscache_volume_see_create_work);
  250. ops = volume->cache->ops;
  251. if (ops->acquire_volume)
  252. ops->acquire_volume(volume);
  253. fscache_end_cache_access(volume->cache,
  254. fscache_access_acquire_volume_end);
  255. clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags);
  256. fscache_put_volume(volume, fscache_volume_put_create_work);
  257. }
  258. /*
  259. * Dispatch a worker thread to create a volume's representation on disk.
  260. */
  261. void fscache_create_volume(struct fscache_volume *volume, bool wait)
  262. {
  263. if (test_and_set_bit(FSCACHE_VOLUME_CREATING, &volume->flags))
  264. goto maybe_wait;
  265. if (volume->cache_priv)
  266. goto no_wait; /* We raced */
  267. if (!fscache_begin_cache_access(volume->cache,
  268. fscache_access_acquire_volume))
  269. goto no_wait;
  270. fscache_get_volume(volume, fscache_volume_get_create_work);
  271. if (!schedule_work(&volume->work))
  272. fscache_put_volume(volume, fscache_volume_put_create_work);
  273. maybe_wait:
  274. if (wait) {
  275. fscache_see_volume(volume, fscache_volume_wait_create_work);
  276. wait_on_bit(&volume->flags, FSCACHE_VOLUME_CREATING,
  277. TASK_UNINTERRUPTIBLE);
  278. }
  279. return;
  280. no_wait:
  281. clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags);
  282. }
  283. /*
  284. * Acquire a volume representation cookie and link it to a (proposed) cache.
  285. */
  286. struct fscache_volume *__fscache_acquire_volume(const char *volume_key,
  287. const char *cache_name,
  288. const void *coherency_data,
  289. size_t coherency_len)
  290. {
  291. struct fscache_volume *volume;
  292. volume = fscache_alloc_volume(volume_key, cache_name,
  293. coherency_data, coherency_len);
  294. if (!volume)
  295. return ERR_PTR(-ENOMEM);
  296. if (!fscache_hash_volume(volume)) {
  297. fscache_put_volume(volume, fscache_volume_put_hash_collision);
  298. return ERR_PTR(-EBUSY);
  299. }
  300. fscache_create_volume(volume, false);
  301. return volume;
  302. }
  303. EXPORT_SYMBOL(__fscache_acquire_volume);
  304. static void fscache_wake_pending_volume(struct fscache_volume *volume,
  305. struct hlist_bl_head *h)
  306. {
  307. struct fscache_volume *cursor;
  308. struct hlist_bl_node *p;
  309. hlist_bl_for_each_entry(cursor, p, h, hash_link) {
  310. if (fscache_volume_same(cursor, volume)) {
  311. fscache_see_volume(cursor, fscache_volume_see_hash_wake);
  312. clear_and_wake_up_bit(FSCACHE_VOLUME_ACQUIRE_PENDING,
  313. &cursor->flags);
  314. return;
  315. }
  316. }
  317. }
  318. /*
  319. * Remove a volume cookie from the hash table.
  320. */
  321. static void fscache_unhash_volume(struct fscache_volume *volume)
  322. {
  323. struct hlist_bl_head *h;
  324. unsigned int bucket;
  325. bucket = volume->key_hash & (ARRAY_SIZE(fscache_volume_hash) - 1);
  326. h = &fscache_volume_hash[bucket];
  327. hlist_bl_lock(h);
  328. hlist_bl_del(&volume->hash_link);
  329. if (test_bit(FSCACHE_VOLUME_COLLIDED_WITH, &volume->flags))
  330. fscache_wake_pending_volume(volume, h);
  331. hlist_bl_unlock(h);
  332. }
  333. /*
  334. * Drop a cache's volume attachments.
  335. */
  336. static void fscache_free_volume(struct fscache_volume *volume)
  337. {
  338. struct fscache_cache *cache = volume->cache;
  339. if (volume->cache_priv) {
  340. __fscache_begin_volume_access(volume, NULL,
  341. fscache_access_relinquish_volume);
  342. if (volume->cache_priv)
  343. cache->ops->free_volume(volume);
  344. fscache_end_volume_access(volume, NULL,
  345. fscache_access_relinquish_volume_end);
  346. }
  347. down_write(&fscache_addremove_sem);
  348. list_del_init(&volume->proc_link);
  349. atomic_dec(&volume->cache->n_volumes);
  350. up_write(&fscache_addremove_sem);
  351. if (!hlist_bl_unhashed(&volume->hash_link))
  352. fscache_unhash_volume(volume);
  353. trace_fscache_volume(volume->debug_id, 0, fscache_volume_free);
  354. kfree(volume->key);
  355. kfree(volume);
  356. fscache_stat_d(&fscache_n_volumes);
  357. fscache_put_cache(cache, fscache_cache_put_volume);
  358. }
  359. /*
  360. * Drop a reference to a volume cookie.
  361. */
  362. void fscache_put_volume(struct fscache_volume *volume,
  363. enum fscache_volume_trace where)
  364. {
  365. if (volume) {
  366. unsigned int debug_id = volume->debug_id;
  367. bool zero;
  368. int ref;
  369. zero = __refcount_dec_and_test(&volume->ref, &ref);
  370. trace_fscache_volume(debug_id, ref - 1, where);
  371. if (zero)
  372. fscache_free_volume(volume);
  373. }
  374. }
  375. EXPORT_SYMBOL(fscache_put_volume);
  376. /*
  377. * Relinquish a volume representation cookie.
  378. */
  379. void __fscache_relinquish_volume(struct fscache_volume *volume,
  380. const void *coherency_data,
  381. bool invalidate)
  382. {
  383. if (WARN_ON(test_and_set_bit(FSCACHE_VOLUME_RELINQUISHED, &volume->flags)))
  384. return;
  385. if (invalidate) {
  386. set_bit(FSCACHE_VOLUME_INVALIDATE, &volume->flags);
  387. } else if (coherency_data) {
  388. memcpy(volume->coherency, coherency_data, volume->coherency_len);
  389. }
  390. fscache_put_volume(volume, fscache_volume_put_relinquish);
  391. }
  392. EXPORT_SYMBOL(__fscache_relinquish_volume);
  393. /**
  394. * fscache_withdraw_volume - Withdraw a volume from being cached
  395. * @volume: Volume cookie
  396. *
  397. * Withdraw a cache volume from service, waiting for all accesses to complete
  398. * before returning.
  399. */
  400. void fscache_withdraw_volume(struct fscache_volume *volume)
  401. {
  402. int n_accesses;
  403. _debug("withdraw V=%x", volume->debug_id);
  404. /* Allow wakeups on dec-to-0 */
  405. n_accesses = atomic_dec_return(&volume->n_accesses);
  406. trace_fscache_access_volume(volume->debug_id, 0,
  407. refcount_read(&volume->ref),
  408. n_accesses, fscache_access_cache_unpin);
  409. wait_var_event(&volume->n_accesses,
  410. atomic_read(&volume->n_accesses) == 0);
  411. }
  412. EXPORT_SYMBOL(fscache_withdraw_volume);
  413. #ifdef CONFIG_PROC_FS
  414. /*
  415. * Generate a list of volumes in /proc/fs/fscache/volumes
  416. */
  417. static int fscache_volumes_seq_show(struct seq_file *m, void *v)
  418. {
  419. struct fscache_volume *volume;
  420. if (v == &fscache_volumes) {
  421. seq_puts(m,
  422. "VOLUME REF nCOOK ACC FL CACHE KEY\n"
  423. "======== ===== ===== === == =============== ================\n");
  424. return 0;
  425. }
  426. volume = list_entry(v, struct fscache_volume, proc_link);
  427. seq_printf(m,
  428. "%08x %5d %5d %3d %02lx %-15.15s %s\n",
  429. volume->debug_id,
  430. refcount_read(&volume->ref),
  431. atomic_read(&volume->n_cookies),
  432. atomic_read(&volume->n_accesses),
  433. volume->flags,
  434. volume->cache->name ?: "-",
  435. volume->key + 1);
  436. return 0;
  437. }
  438. static void *fscache_volumes_seq_start(struct seq_file *m, loff_t *_pos)
  439. __acquires(&fscache_addremove_sem)
  440. {
  441. down_read(&fscache_addremove_sem);
  442. return seq_list_start_head(&fscache_volumes, *_pos);
  443. }
  444. static void *fscache_volumes_seq_next(struct seq_file *m, void *v, loff_t *_pos)
  445. {
  446. return seq_list_next(v, &fscache_volumes, _pos);
  447. }
  448. static void fscache_volumes_seq_stop(struct seq_file *m, void *v)
  449. __releases(&fscache_addremove_sem)
  450. {
  451. up_read(&fscache_addremove_sem);
  452. }
  453. const struct seq_operations fscache_volumes_seq_ops = {
  454. .start = fscache_volumes_seq_start,
  455. .next = fscache_volumes_seq_next,
  456. .stop = fscache_volumes_seq_stop,
  457. .show = fscache_volumes_seq_show,
  458. };
  459. #endif /* CONFIG_PROC_FS */