fscache_volume.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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(struct_size(volume, coherency, coherency_len),
  203. GFP_KERNEL);
  204. if (!volume)
  205. goto err_cache;
  206. volume->cache = cache;
  207. volume->coherency_len = coherency_len;
  208. if (coherency_data)
  209. memcpy(volume->coherency, coherency_data, coherency_len);
  210. INIT_LIST_HEAD(&volume->proc_link);
  211. INIT_WORK(&volume->work, fscache_create_volume_work);
  212. refcount_set(&volume->ref, 1);
  213. spin_lock_init(&volume->lock);
  214. /* Stick the length on the front of the key and pad it out to make
  215. * hashing easier.
  216. */
  217. hlen = round_up(1 + klen + 1, sizeof(__le32));
  218. key = kzalloc(hlen, GFP_KERNEL);
  219. if (!key)
  220. goto err_vol;
  221. key[0] = klen;
  222. memcpy(key + 1, volume_key, klen);
  223. volume->key = key;
  224. volume->key_hash = fscache_hash(0, key, hlen);
  225. volume->debug_id = atomic_inc_return(&fscache_volume_debug_id);
  226. down_write(&fscache_addremove_sem);
  227. atomic_inc(&cache->n_volumes);
  228. list_add_tail(&volume->proc_link, &fscache_volumes);
  229. fscache_see_volume(volume, fscache_volume_new_acquire);
  230. fscache_stat(&fscache_n_volumes);
  231. up_write(&fscache_addremove_sem);
  232. _leave(" = v=%x", volume->debug_id);
  233. return volume;
  234. err_vol:
  235. kfree(volume);
  236. err_cache:
  237. fscache_put_cache(cache, fscache_cache_put_alloc_volume);
  238. fscache_stat(&fscache_n_volumes_nomem);
  239. return NULL;
  240. }
  241. /*
  242. * Create a volume's representation on disk. Have a volume ref and a cache
  243. * access we have to release.
  244. */
  245. static void fscache_create_volume_work(struct work_struct *work)
  246. {
  247. const struct fscache_cache_ops *ops;
  248. struct fscache_volume *volume =
  249. container_of(work, struct fscache_volume, work);
  250. fscache_see_volume(volume, fscache_volume_see_create_work);
  251. ops = volume->cache->ops;
  252. if (ops->acquire_volume)
  253. ops->acquire_volume(volume);
  254. fscache_end_cache_access(volume->cache,
  255. fscache_access_acquire_volume_end);
  256. clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags);
  257. fscache_put_volume(volume, fscache_volume_put_create_work);
  258. }
  259. /*
  260. * Dispatch a worker thread to create a volume's representation on disk.
  261. */
  262. void fscache_create_volume(struct fscache_volume *volume, bool wait)
  263. {
  264. if (test_and_set_bit(FSCACHE_VOLUME_CREATING, &volume->flags))
  265. goto maybe_wait;
  266. if (volume->cache_priv)
  267. goto no_wait; /* We raced */
  268. if (!fscache_begin_cache_access(volume->cache,
  269. fscache_access_acquire_volume))
  270. goto no_wait;
  271. fscache_get_volume(volume, fscache_volume_get_create_work);
  272. if (!schedule_work(&volume->work))
  273. fscache_put_volume(volume, fscache_volume_put_create_work);
  274. maybe_wait:
  275. if (wait) {
  276. fscache_see_volume(volume, fscache_volume_wait_create_work);
  277. wait_on_bit(&volume->flags, FSCACHE_VOLUME_CREATING,
  278. TASK_UNINTERRUPTIBLE);
  279. }
  280. return;
  281. no_wait:
  282. clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags);
  283. }
  284. /*
  285. * Acquire a volume representation cookie and link it to a (proposed) cache.
  286. */
  287. struct fscache_volume *__fscache_acquire_volume(const char *volume_key,
  288. const char *cache_name,
  289. const void *coherency_data,
  290. size_t coherency_len)
  291. {
  292. struct fscache_volume *volume;
  293. volume = fscache_alloc_volume(volume_key, cache_name,
  294. coherency_data, coherency_len);
  295. if (!volume)
  296. return ERR_PTR(-ENOMEM);
  297. if (!fscache_hash_volume(volume)) {
  298. fscache_put_volume(volume, fscache_volume_put_hash_collision);
  299. return ERR_PTR(-EBUSY);
  300. }
  301. fscache_create_volume(volume, false);
  302. return volume;
  303. }
  304. EXPORT_SYMBOL(__fscache_acquire_volume);
  305. static void fscache_wake_pending_volume(struct fscache_volume *volume,
  306. struct hlist_bl_head *h)
  307. {
  308. struct fscache_volume *cursor;
  309. struct hlist_bl_node *p;
  310. hlist_bl_for_each_entry(cursor, p, h, hash_link) {
  311. if (fscache_volume_same(cursor, volume)) {
  312. fscache_see_volume(cursor, fscache_volume_see_hash_wake);
  313. clear_and_wake_up_bit(FSCACHE_VOLUME_ACQUIRE_PENDING,
  314. &cursor->flags);
  315. return;
  316. }
  317. }
  318. }
  319. /*
  320. * Remove a volume cookie from the hash table.
  321. */
  322. static void fscache_unhash_volume(struct fscache_volume *volume)
  323. {
  324. struct hlist_bl_head *h;
  325. unsigned int bucket;
  326. bucket = volume->key_hash & (ARRAY_SIZE(fscache_volume_hash) - 1);
  327. h = &fscache_volume_hash[bucket];
  328. hlist_bl_lock(h);
  329. hlist_bl_del(&volume->hash_link);
  330. if (test_bit(FSCACHE_VOLUME_COLLIDED_WITH, &volume->flags))
  331. fscache_wake_pending_volume(volume, h);
  332. hlist_bl_unlock(h);
  333. }
  334. /*
  335. * Drop a cache's volume attachments.
  336. */
  337. static void fscache_free_volume(struct fscache_volume *volume)
  338. {
  339. struct fscache_cache *cache = volume->cache;
  340. if (volume->cache_priv) {
  341. __fscache_begin_volume_access(volume, NULL,
  342. fscache_access_relinquish_volume);
  343. if (volume->cache_priv)
  344. cache->ops->free_volume(volume);
  345. fscache_end_volume_access(volume, NULL,
  346. fscache_access_relinquish_volume_end);
  347. }
  348. down_write(&fscache_addremove_sem);
  349. list_del_init(&volume->proc_link);
  350. atomic_dec(&volume->cache->n_volumes);
  351. up_write(&fscache_addremove_sem);
  352. if (!hlist_bl_unhashed(&volume->hash_link))
  353. fscache_unhash_volume(volume);
  354. trace_fscache_volume(volume->debug_id, 0, fscache_volume_free);
  355. kfree(volume->key);
  356. kfree(volume);
  357. fscache_stat_d(&fscache_n_volumes);
  358. fscache_put_cache(cache, fscache_cache_put_volume);
  359. }
  360. /*
  361. * Drop a reference to a volume cookie.
  362. */
  363. void fscache_put_volume(struct fscache_volume *volume,
  364. enum fscache_volume_trace where)
  365. {
  366. if (volume) {
  367. unsigned int debug_id = volume->debug_id;
  368. bool zero;
  369. int ref;
  370. zero = __refcount_dec_and_test(&volume->ref, &ref);
  371. trace_fscache_volume(debug_id, ref - 1, where);
  372. if (zero)
  373. fscache_free_volume(volume);
  374. }
  375. }
  376. EXPORT_SYMBOL(fscache_put_volume);
  377. /*
  378. * Relinquish a volume representation cookie.
  379. */
  380. void __fscache_relinquish_volume(struct fscache_volume *volume,
  381. const void *coherency_data,
  382. bool invalidate)
  383. {
  384. if (WARN_ON(test_and_set_bit(FSCACHE_VOLUME_RELINQUISHED, &volume->flags)))
  385. return;
  386. if (invalidate) {
  387. set_bit(FSCACHE_VOLUME_INVALIDATE, &volume->flags);
  388. } else if (coherency_data) {
  389. memcpy(volume->coherency, coherency_data, volume->coherency_len);
  390. }
  391. fscache_put_volume(volume, fscache_volume_put_relinquish);
  392. }
  393. EXPORT_SYMBOL(__fscache_relinquish_volume);
  394. /**
  395. * fscache_withdraw_volume - Withdraw a volume from being cached
  396. * @volume: Volume cookie
  397. *
  398. * Withdraw a cache volume from service, waiting for all accesses to complete
  399. * before returning.
  400. */
  401. void fscache_withdraw_volume(struct fscache_volume *volume)
  402. {
  403. int n_accesses;
  404. _debug("withdraw V=%x", volume->debug_id);
  405. /* Allow wakeups on dec-to-0 */
  406. n_accesses = atomic_dec_return(&volume->n_accesses);
  407. trace_fscache_access_volume(volume->debug_id, 0,
  408. refcount_read(&volume->ref),
  409. n_accesses, fscache_access_cache_unpin);
  410. wait_var_event(&volume->n_accesses,
  411. atomic_read(&volume->n_accesses) == 0);
  412. }
  413. EXPORT_SYMBOL(fscache_withdraw_volume);
  414. #ifdef CONFIG_PROC_FS
  415. /*
  416. * Generate a list of volumes in /proc/fs/fscache/volumes
  417. */
  418. static int fscache_volumes_seq_show(struct seq_file *m, void *v)
  419. {
  420. struct fscache_volume *volume;
  421. if (v == &fscache_volumes) {
  422. seq_puts(m,
  423. "VOLUME REF nCOOK ACC FL CACHE KEY\n"
  424. "======== ===== ===== === == =============== ================\n");
  425. return 0;
  426. }
  427. volume = list_entry(v, struct fscache_volume, proc_link);
  428. seq_printf(m,
  429. "%08x %5d %5d %3d %02lx %-15.15s %s\n",
  430. volume->debug_id,
  431. refcount_read(&volume->ref),
  432. atomic_read(&volume->n_cookies),
  433. atomic_read(&volume->n_accesses),
  434. volume->flags,
  435. volume->cache->name ?: "-",
  436. volume->key + 1);
  437. return 0;
  438. }
  439. static void *fscache_volumes_seq_start(struct seq_file *m, loff_t *_pos)
  440. __acquires(&fscache_addremove_sem)
  441. {
  442. down_read(&fscache_addremove_sem);
  443. return seq_list_start_head(&fscache_volumes, *_pos);
  444. }
  445. static void *fscache_volumes_seq_next(struct seq_file *m, void *v, loff_t *_pos)
  446. {
  447. return seq_list_next(v, &fscache_volumes, _pos);
  448. }
  449. static void fscache_volumes_seq_stop(struct seq_file *m, void *v)
  450. __releases(&fscache_addremove_sem)
  451. {
  452. up_read(&fscache_addremove_sem);
  453. }
  454. const struct seq_operations fscache_volumes_seq_ops = {
  455. .start = fscache_volumes_seq_start,
  456. .next = fscache_volumes_seq_next,
  457. .stop = fscache_volumes_seq_stop,
  458. .show = fscache_volumes_seq_show,
  459. };
  460. #endif /* CONFIG_PROC_FS */