z3fold.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * z3fold.c
  4. *
  5. * Author: Vitaly Wool <vitaly.wool@konsulko.com>
  6. * Copyright (C) 2016, Sony Mobile Communications Inc.
  7. *
  8. * This implementation is based on zbud written by Seth Jennings.
  9. *
  10. * z3fold is an special purpose allocator for storing compressed pages. It
  11. * can store up to three compressed pages per page which improves the
  12. * compression ratio of zbud while retaining its main concepts (e. g. always
  13. * storing an integral number of objects per page) and simplicity.
  14. * It still has simple and deterministic reclaim properties that make it
  15. * preferable to a higher density approach (with no requirement on integral
  16. * number of object per page) when reclaim is used.
  17. *
  18. * As in zbud, pages are divided into "chunks". The size of the chunks is
  19. * fixed at compile time and is determined by NCHUNKS_ORDER below.
  20. *
  21. * z3fold doesn't export any API and is meant to be used via zpool API.
  22. */
  23. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  24. #include <linux/atomic.h>
  25. #include <linux/sched.h>
  26. #include <linux/cpumask.h>
  27. #include <linux/list.h>
  28. #include <linux/mm.h>
  29. #include <linux/module.h>
  30. #include <linux/page-flags.h>
  31. #include <linux/migrate.h>
  32. #include <linux/node.h>
  33. #include <linux/compaction.h>
  34. #include <linux/percpu.h>
  35. #include <linux/preempt.h>
  36. #include <linux/workqueue.h>
  37. #include <linux/slab.h>
  38. #include <linux/spinlock.h>
  39. #include <linux/zpool.h>
  40. #include <linux/kmemleak.h>
  41. /*
  42. * NCHUNKS_ORDER determines the internal allocation granularity, effectively
  43. * adjusting internal fragmentation. It also determines the number of
  44. * freelists maintained in each pool. NCHUNKS_ORDER of 6 means that the
  45. * allocation granularity will be in chunks of size PAGE_SIZE/64. Some chunks
  46. * in the beginning of an allocated page are occupied by z3fold header, so
  47. * NCHUNKS will be calculated to 63 (or 62 in case CONFIG_DEBUG_SPINLOCK=y),
  48. * which shows the max number of free chunks in z3fold page, also there will
  49. * be 63, or 62, respectively, freelists per pool.
  50. */
  51. #define NCHUNKS_ORDER 6
  52. #define CHUNK_SHIFT (PAGE_SHIFT - NCHUNKS_ORDER)
  53. #define CHUNK_SIZE (1 << CHUNK_SHIFT)
  54. #define ZHDR_SIZE_ALIGNED round_up(sizeof(struct z3fold_header), CHUNK_SIZE)
  55. #define ZHDR_CHUNKS (ZHDR_SIZE_ALIGNED >> CHUNK_SHIFT)
  56. #define TOTAL_CHUNKS (PAGE_SIZE >> CHUNK_SHIFT)
  57. #define NCHUNKS (TOTAL_CHUNKS - ZHDR_CHUNKS)
  58. #define BUDDY_MASK (0x3)
  59. #define BUDDY_SHIFT 2
  60. #define SLOTS_ALIGN (0x40)
  61. /*****************
  62. * Structures
  63. *****************/
  64. struct z3fold_pool;
  65. enum buddy {
  66. HEADLESS = 0,
  67. FIRST,
  68. MIDDLE,
  69. LAST,
  70. BUDDIES_MAX = LAST
  71. };
  72. struct z3fold_buddy_slots {
  73. /*
  74. * we are using BUDDY_MASK in handle_to_buddy etc. so there should
  75. * be enough slots to hold all possible variants
  76. */
  77. unsigned long slot[BUDDY_MASK + 1];
  78. unsigned long pool; /* back link */
  79. rwlock_t lock;
  80. };
  81. #define HANDLE_FLAG_MASK (0x03)
  82. /*
  83. * struct z3fold_header - z3fold page metadata occupying first chunks of each
  84. * z3fold page, except for HEADLESS pages
  85. * @buddy: links the z3fold page into the relevant list in the
  86. * pool
  87. * @page_lock: per-page lock
  88. * @refcount: reference count for the z3fold page
  89. * @work: work_struct for page layout optimization
  90. * @slots: pointer to the structure holding buddy slots
  91. * @pool: pointer to the containing pool
  92. * @cpu: CPU which this page "belongs" to
  93. * @first_chunks: the size of the first buddy in chunks, 0 if free
  94. * @middle_chunks: the size of the middle buddy in chunks, 0 if free
  95. * @last_chunks: the size of the last buddy in chunks, 0 if free
  96. * @first_num: the starting number (for the first handle)
  97. * @mapped_count: the number of objects currently mapped
  98. */
  99. struct z3fold_header {
  100. struct list_head buddy;
  101. spinlock_t page_lock;
  102. struct kref refcount;
  103. struct work_struct work;
  104. struct z3fold_buddy_slots *slots;
  105. struct z3fold_pool *pool;
  106. short cpu;
  107. unsigned short first_chunks;
  108. unsigned short middle_chunks;
  109. unsigned short last_chunks;
  110. unsigned short start_middle;
  111. unsigned short first_num:2;
  112. unsigned short mapped_count:2;
  113. unsigned short foreign_handles:2;
  114. };
  115. /**
  116. * struct z3fold_pool - stores metadata for each z3fold pool
  117. * @name: pool name
  118. * @lock: protects pool unbuddied lists
  119. * @stale_lock: protects pool stale page list
  120. * @unbuddied: per-cpu array of lists tracking z3fold pages that contain 2-
  121. * buddies; the list each z3fold page is added to depends on
  122. * the size of its free region.
  123. * @stale: list of pages marked for freeing
  124. * @pages_nr: number of z3fold pages in the pool.
  125. * @c_handle: cache for z3fold_buddy_slots allocation
  126. * @compact_wq: workqueue for page layout background optimization
  127. * @release_wq: workqueue for safe page release
  128. * @work: work_struct for safe page release
  129. *
  130. * This structure is allocated at pool creation time and maintains metadata
  131. * pertaining to a particular z3fold pool.
  132. */
  133. struct z3fold_pool {
  134. const char *name;
  135. spinlock_t lock;
  136. spinlock_t stale_lock;
  137. struct list_head __percpu *unbuddied;
  138. struct list_head stale;
  139. atomic64_t pages_nr;
  140. struct kmem_cache *c_handle;
  141. struct workqueue_struct *compact_wq;
  142. struct workqueue_struct *release_wq;
  143. struct work_struct work;
  144. };
  145. /*
  146. * Internal z3fold page flags
  147. */
  148. enum z3fold_page_flags {
  149. PAGE_HEADLESS = 0,
  150. MIDDLE_CHUNK_MAPPED,
  151. NEEDS_COMPACTING,
  152. PAGE_STALE,
  153. PAGE_CLAIMED, /* by either reclaim or free */
  154. PAGE_MIGRATED, /* page is migrated and soon to be released */
  155. };
  156. /*
  157. * handle flags, go under HANDLE_FLAG_MASK
  158. */
  159. enum z3fold_handle_flags {
  160. HANDLES_NOFREE = 0,
  161. };
  162. /*
  163. * Forward declarations
  164. */
  165. static struct z3fold_header *__z3fold_alloc(struct z3fold_pool *, size_t, bool);
  166. static void compact_page_work(struct work_struct *w);
  167. /*****************
  168. * Helpers
  169. *****************/
  170. /* Converts an allocation size in bytes to size in z3fold chunks */
  171. static int size_to_chunks(size_t size)
  172. {
  173. return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT;
  174. }
  175. #define for_each_unbuddied_list(_iter, _begin) \
  176. for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++)
  177. static inline struct z3fold_buddy_slots *alloc_slots(struct z3fold_pool *pool,
  178. gfp_t gfp)
  179. {
  180. struct z3fold_buddy_slots *slots = kmem_cache_zalloc(pool->c_handle,
  181. gfp);
  182. if (slots) {
  183. /* It will be freed separately in free_handle(). */
  184. kmemleak_not_leak(slots);
  185. slots->pool = (unsigned long)pool;
  186. rwlock_init(&slots->lock);
  187. }
  188. return slots;
  189. }
  190. static inline struct z3fold_pool *slots_to_pool(struct z3fold_buddy_slots *s)
  191. {
  192. return (struct z3fold_pool *)(s->pool & ~HANDLE_FLAG_MASK);
  193. }
  194. static inline struct z3fold_buddy_slots *handle_to_slots(unsigned long handle)
  195. {
  196. return (struct z3fold_buddy_slots *)(handle & ~(SLOTS_ALIGN - 1));
  197. }
  198. /* Lock a z3fold page */
  199. static inline void z3fold_page_lock(struct z3fold_header *zhdr)
  200. {
  201. spin_lock(&zhdr->page_lock);
  202. }
  203. /* Try to lock a z3fold page */
  204. static inline int z3fold_page_trylock(struct z3fold_header *zhdr)
  205. {
  206. return spin_trylock(&zhdr->page_lock);
  207. }
  208. /* Unlock a z3fold page */
  209. static inline void z3fold_page_unlock(struct z3fold_header *zhdr)
  210. {
  211. spin_unlock(&zhdr->page_lock);
  212. }
  213. /* return locked z3fold page if it's not headless */
  214. static inline struct z3fold_header *get_z3fold_header(unsigned long handle)
  215. {
  216. struct z3fold_buddy_slots *slots;
  217. struct z3fold_header *zhdr;
  218. int locked = 0;
  219. if (!(handle & (1 << PAGE_HEADLESS))) {
  220. slots = handle_to_slots(handle);
  221. do {
  222. unsigned long addr;
  223. read_lock(&slots->lock);
  224. addr = *(unsigned long *)handle;
  225. zhdr = (struct z3fold_header *)(addr & PAGE_MASK);
  226. locked = z3fold_page_trylock(zhdr);
  227. read_unlock(&slots->lock);
  228. if (locked) {
  229. struct page *page = virt_to_page(zhdr);
  230. if (!test_bit(PAGE_MIGRATED, &page->private))
  231. break;
  232. z3fold_page_unlock(zhdr);
  233. }
  234. cpu_relax();
  235. } while (true);
  236. } else {
  237. zhdr = (struct z3fold_header *)(handle & PAGE_MASK);
  238. }
  239. return zhdr;
  240. }
  241. static inline void put_z3fold_header(struct z3fold_header *zhdr)
  242. {
  243. struct page *page = virt_to_page(zhdr);
  244. if (!test_bit(PAGE_HEADLESS, &page->private))
  245. z3fold_page_unlock(zhdr);
  246. }
  247. static inline void free_handle(unsigned long handle, struct z3fold_header *zhdr)
  248. {
  249. struct z3fold_buddy_slots *slots;
  250. int i;
  251. bool is_free;
  252. if (WARN_ON(*(unsigned long *)handle == 0))
  253. return;
  254. slots = handle_to_slots(handle);
  255. write_lock(&slots->lock);
  256. *(unsigned long *)handle = 0;
  257. if (test_bit(HANDLES_NOFREE, &slots->pool)) {
  258. write_unlock(&slots->lock);
  259. return; /* simple case, nothing else to do */
  260. }
  261. if (zhdr->slots != slots)
  262. zhdr->foreign_handles--;
  263. is_free = true;
  264. for (i = 0; i <= BUDDY_MASK; i++) {
  265. if (slots->slot[i]) {
  266. is_free = false;
  267. break;
  268. }
  269. }
  270. write_unlock(&slots->lock);
  271. if (is_free) {
  272. struct z3fold_pool *pool = slots_to_pool(slots);
  273. if (zhdr->slots == slots)
  274. zhdr->slots = NULL;
  275. kmem_cache_free(pool->c_handle, slots);
  276. }
  277. }
  278. /* Initializes the z3fold header of a newly allocated z3fold page */
  279. static struct z3fold_header *init_z3fold_page(struct page *page, bool headless,
  280. struct z3fold_pool *pool, gfp_t gfp)
  281. {
  282. struct z3fold_header *zhdr = page_address(page);
  283. struct z3fold_buddy_slots *slots;
  284. clear_bit(PAGE_HEADLESS, &page->private);
  285. clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
  286. clear_bit(NEEDS_COMPACTING, &page->private);
  287. clear_bit(PAGE_STALE, &page->private);
  288. clear_bit(PAGE_CLAIMED, &page->private);
  289. clear_bit(PAGE_MIGRATED, &page->private);
  290. if (headless)
  291. return zhdr;
  292. slots = alloc_slots(pool, gfp);
  293. if (!slots)
  294. return NULL;
  295. memset(zhdr, 0, sizeof(*zhdr));
  296. spin_lock_init(&zhdr->page_lock);
  297. kref_init(&zhdr->refcount);
  298. zhdr->cpu = -1;
  299. zhdr->slots = slots;
  300. zhdr->pool = pool;
  301. INIT_LIST_HEAD(&zhdr->buddy);
  302. INIT_WORK(&zhdr->work, compact_page_work);
  303. return zhdr;
  304. }
  305. /* Resets the struct page fields and frees the page */
  306. static void free_z3fold_page(struct page *page, bool headless)
  307. {
  308. if (!headless) {
  309. lock_page(page);
  310. __ClearPageMovable(page);
  311. unlock_page(page);
  312. }
  313. __free_page(page);
  314. }
  315. /* Helper function to build the index */
  316. static inline int __idx(struct z3fold_header *zhdr, enum buddy bud)
  317. {
  318. return (bud + zhdr->first_num) & BUDDY_MASK;
  319. }
  320. /*
  321. * Encodes the handle of a particular buddy within a z3fold page.
  322. * Zhdr->page_lock should be held as this function accesses first_num
  323. * if bud != HEADLESS.
  324. */
  325. static unsigned long __encode_handle(struct z3fold_header *zhdr,
  326. struct z3fold_buddy_slots *slots,
  327. enum buddy bud)
  328. {
  329. unsigned long h = (unsigned long)zhdr;
  330. int idx = 0;
  331. /*
  332. * For a headless page, its handle is its pointer with the extra
  333. * PAGE_HEADLESS bit set
  334. */
  335. if (bud == HEADLESS)
  336. return h | (1 << PAGE_HEADLESS);
  337. /* otherwise, return pointer to encoded handle */
  338. idx = __idx(zhdr, bud);
  339. h += idx;
  340. if (bud == LAST)
  341. h |= (zhdr->last_chunks << BUDDY_SHIFT);
  342. write_lock(&slots->lock);
  343. slots->slot[idx] = h;
  344. write_unlock(&slots->lock);
  345. return (unsigned long)&slots->slot[idx];
  346. }
  347. static unsigned long encode_handle(struct z3fold_header *zhdr, enum buddy bud)
  348. {
  349. return __encode_handle(zhdr, zhdr->slots, bud);
  350. }
  351. /* only for LAST bud, returns zero otherwise */
  352. static unsigned short handle_to_chunks(unsigned long handle)
  353. {
  354. struct z3fold_buddy_slots *slots = handle_to_slots(handle);
  355. unsigned long addr;
  356. read_lock(&slots->lock);
  357. addr = *(unsigned long *)handle;
  358. read_unlock(&slots->lock);
  359. return (addr & ~PAGE_MASK) >> BUDDY_SHIFT;
  360. }
  361. /*
  362. * (handle & BUDDY_MASK) < zhdr->first_num is possible in encode_handle
  363. * but that doesn't matter. because the masking will result in the
  364. * correct buddy number.
  365. */
  366. static enum buddy handle_to_buddy(unsigned long handle)
  367. {
  368. struct z3fold_header *zhdr;
  369. struct z3fold_buddy_slots *slots = handle_to_slots(handle);
  370. unsigned long addr;
  371. read_lock(&slots->lock);
  372. WARN_ON(handle & (1 << PAGE_HEADLESS));
  373. addr = *(unsigned long *)handle;
  374. read_unlock(&slots->lock);
  375. zhdr = (struct z3fold_header *)(addr & PAGE_MASK);
  376. return (addr - zhdr->first_num) & BUDDY_MASK;
  377. }
  378. static inline struct z3fold_pool *zhdr_to_pool(struct z3fold_header *zhdr)
  379. {
  380. return zhdr->pool;
  381. }
  382. static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked)
  383. {
  384. struct page *page = virt_to_page(zhdr);
  385. struct z3fold_pool *pool = zhdr_to_pool(zhdr);
  386. WARN_ON(!list_empty(&zhdr->buddy));
  387. set_bit(PAGE_STALE, &page->private);
  388. clear_bit(NEEDS_COMPACTING, &page->private);
  389. spin_lock(&pool->lock);
  390. spin_unlock(&pool->lock);
  391. if (locked)
  392. z3fold_page_unlock(zhdr);
  393. spin_lock(&pool->stale_lock);
  394. list_add(&zhdr->buddy, &pool->stale);
  395. queue_work(pool->release_wq, &pool->work);
  396. spin_unlock(&pool->stale_lock);
  397. atomic64_dec(&pool->pages_nr);
  398. }
  399. static void release_z3fold_page_locked(struct kref *ref)
  400. {
  401. struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
  402. refcount);
  403. WARN_ON(z3fold_page_trylock(zhdr));
  404. __release_z3fold_page(zhdr, true);
  405. }
  406. static void release_z3fold_page_locked_list(struct kref *ref)
  407. {
  408. struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
  409. refcount);
  410. struct z3fold_pool *pool = zhdr_to_pool(zhdr);
  411. spin_lock(&pool->lock);
  412. list_del_init(&zhdr->buddy);
  413. spin_unlock(&pool->lock);
  414. WARN_ON(z3fold_page_trylock(zhdr));
  415. __release_z3fold_page(zhdr, true);
  416. }
  417. static inline int put_z3fold_locked(struct z3fold_header *zhdr)
  418. {
  419. return kref_put(&zhdr->refcount, release_z3fold_page_locked);
  420. }
  421. static inline int put_z3fold_locked_list(struct z3fold_header *zhdr)
  422. {
  423. return kref_put(&zhdr->refcount, release_z3fold_page_locked_list);
  424. }
  425. static void free_pages_work(struct work_struct *w)
  426. {
  427. struct z3fold_pool *pool = container_of(w, struct z3fold_pool, work);
  428. spin_lock(&pool->stale_lock);
  429. while (!list_empty(&pool->stale)) {
  430. struct z3fold_header *zhdr = list_first_entry(&pool->stale,
  431. struct z3fold_header, buddy);
  432. struct page *page = virt_to_page(zhdr);
  433. list_del(&zhdr->buddy);
  434. if (WARN_ON(!test_bit(PAGE_STALE, &page->private)))
  435. continue;
  436. spin_unlock(&pool->stale_lock);
  437. cancel_work_sync(&zhdr->work);
  438. free_z3fold_page(page, false);
  439. cond_resched();
  440. spin_lock(&pool->stale_lock);
  441. }
  442. spin_unlock(&pool->stale_lock);
  443. }
  444. /*
  445. * Returns the number of free chunks in a z3fold page.
  446. * NB: can't be used with HEADLESS pages.
  447. */
  448. static int num_free_chunks(struct z3fold_header *zhdr)
  449. {
  450. int nfree;
  451. /*
  452. * If there is a middle object, pick up the bigger free space
  453. * either before or after it. Otherwise just subtract the number
  454. * of chunks occupied by the first and the last objects.
  455. */
  456. if (zhdr->middle_chunks != 0) {
  457. int nfree_before = zhdr->first_chunks ?
  458. 0 : zhdr->start_middle - ZHDR_CHUNKS;
  459. int nfree_after = zhdr->last_chunks ?
  460. 0 : TOTAL_CHUNKS -
  461. (zhdr->start_middle + zhdr->middle_chunks);
  462. nfree = max(nfree_before, nfree_after);
  463. } else
  464. nfree = NCHUNKS - zhdr->first_chunks - zhdr->last_chunks;
  465. return nfree;
  466. }
  467. /* Add to the appropriate unbuddied list */
  468. static inline void add_to_unbuddied(struct z3fold_pool *pool,
  469. struct z3fold_header *zhdr)
  470. {
  471. if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0 ||
  472. zhdr->middle_chunks == 0) {
  473. struct list_head *unbuddied;
  474. int freechunks = num_free_chunks(zhdr);
  475. migrate_disable();
  476. unbuddied = this_cpu_ptr(pool->unbuddied);
  477. spin_lock(&pool->lock);
  478. list_add(&zhdr->buddy, &unbuddied[freechunks]);
  479. spin_unlock(&pool->lock);
  480. zhdr->cpu = smp_processor_id();
  481. migrate_enable();
  482. }
  483. }
  484. static inline enum buddy get_free_buddy(struct z3fold_header *zhdr, int chunks)
  485. {
  486. enum buddy bud = HEADLESS;
  487. if (zhdr->middle_chunks) {
  488. if (!zhdr->first_chunks &&
  489. chunks <= zhdr->start_middle - ZHDR_CHUNKS)
  490. bud = FIRST;
  491. else if (!zhdr->last_chunks)
  492. bud = LAST;
  493. } else {
  494. if (!zhdr->first_chunks)
  495. bud = FIRST;
  496. else if (!zhdr->last_chunks)
  497. bud = LAST;
  498. else
  499. bud = MIDDLE;
  500. }
  501. return bud;
  502. }
  503. static inline void *mchunk_memmove(struct z3fold_header *zhdr,
  504. unsigned short dst_chunk)
  505. {
  506. void *beg = zhdr;
  507. return memmove(beg + (dst_chunk << CHUNK_SHIFT),
  508. beg + (zhdr->start_middle << CHUNK_SHIFT),
  509. zhdr->middle_chunks << CHUNK_SHIFT);
  510. }
  511. static inline bool buddy_single(struct z3fold_header *zhdr)
  512. {
  513. return !((zhdr->first_chunks && zhdr->middle_chunks) ||
  514. (zhdr->first_chunks && zhdr->last_chunks) ||
  515. (zhdr->middle_chunks && zhdr->last_chunks));
  516. }
  517. static struct z3fold_header *compact_single_buddy(struct z3fold_header *zhdr)
  518. {
  519. struct z3fold_pool *pool = zhdr_to_pool(zhdr);
  520. void *p = zhdr;
  521. unsigned long old_handle = 0;
  522. size_t sz = 0;
  523. struct z3fold_header *new_zhdr = NULL;
  524. int first_idx = __idx(zhdr, FIRST);
  525. int middle_idx = __idx(zhdr, MIDDLE);
  526. int last_idx = __idx(zhdr, LAST);
  527. unsigned short *moved_chunks = NULL;
  528. /*
  529. * No need to protect slots here -- all the slots are "local" and
  530. * the page lock is already taken
  531. */
  532. if (zhdr->first_chunks && zhdr->slots->slot[first_idx]) {
  533. p += ZHDR_SIZE_ALIGNED;
  534. sz = zhdr->first_chunks << CHUNK_SHIFT;
  535. old_handle = (unsigned long)&zhdr->slots->slot[first_idx];
  536. moved_chunks = &zhdr->first_chunks;
  537. } else if (zhdr->middle_chunks && zhdr->slots->slot[middle_idx]) {
  538. p += zhdr->start_middle << CHUNK_SHIFT;
  539. sz = zhdr->middle_chunks << CHUNK_SHIFT;
  540. old_handle = (unsigned long)&zhdr->slots->slot[middle_idx];
  541. moved_chunks = &zhdr->middle_chunks;
  542. } else if (zhdr->last_chunks && zhdr->slots->slot[last_idx]) {
  543. p += PAGE_SIZE - (zhdr->last_chunks << CHUNK_SHIFT);
  544. sz = zhdr->last_chunks << CHUNK_SHIFT;
  545. old_handle = (unsigned long)&zhdr->slots->slot[last_idx];
  546. moved_chunks = &zhdr->last_chunks;
  547. }
  548. if (sz > 0) {
  549. enum buddy new_bud = HEADLESS;
  550. short chunks = size_to_chunks(sz);
  551. void *q;
  552. new_zhdr = __z3fold_alloc(pool, sz, false);
  553. if (!new_zhdr)
  554. return NULL;
  555. if (WARN_ON(new_zhdr == zhdr))
  556. goto out_fail;
  557. new_bud = get_free_buddy(new_zhdr, chunks);
  558. q = new_zhdr;
  559. switch (new_bud) {
  560. case FIRST:
  561. new_zhdr->first_chunks = chunks;
  562. q += ZHDR_SIZE_ALIGNED;
  563. break;
  564. case MIDDLE:
  565. new_zhdr->middle_chunks = chunks;
  566. new_zhdr->start_middle =
  567. new_zhdr->first_chunks + ZHDR_CHUNKS;
  568. q += new_zhdr->start_middle << CHUNK_SHIFT;
  569. break;
  570. case LAST:
  571. new_zhdr->last_chunks = chunks;
  572. q += PAGE_SIZE - (new_zhdr->last_chunks << CHUNK_SHIFT);
  573. break;
  574. default:
  575. goto out_fail;
  576. }
  577. new_zhdr->foreign_handles++;
  578. memcpy(q, p, sz);
  579. write_lock(&zhdr->slots->lock);
  580. *(unsigned long *)old_handle = (unsigned long)new_zhdr +
  581. __idx(new_zhdr, new_bud);
  582. if (new_bud == LAST)
  583. *(unsigned long *)old_handle |=
  584. (new_zhdr->last_chunks << BUDDY_SHIFT);
  585. write_unlock(&zhdr->slots->lock);
  586. add_to_unbuddied(pool, new_zhdr);
  587. z3fold_page_unlock(new_zhdr);
  588. *moved_chunks = 0;
  589. }
  590. return new_zhdr;
  591. out_fail:
  592. if (new_zhdr && !put_z3fold_locked(new_zhdr)) {
  593. add_to_unbuddied(pool, new_zhdr);
  594. z3fold_page_unlock(new_zhdr);
  595. }
  596. return NULL;
  597. }
  598. #define BIG_CHUNK_GAP 3
  599. /* Has to be called with lock held */
  600. static int z3fold_compact_page(struct z3fold_header *zhdr)
  601. {
  602. struct page *page = virt_to_page(zhdr);
  603. if (test_bit(MIDDLE_CHUNK_MAPPED, &page->private))
  604. return 0; /* can't move middle chunk, it's used */
  605. if (unlikely(PageIsolated(page)))
  606. return 0;
  607. if (zhdr->middle_chunks == 0)
  608. return 0; /* nothing to compact */
  609. if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) {
  610. /* move to the beginning */
  611. mchunk_memmove(zhdr, ZHDR_CHUNKS);
  612. zhdr->first_chunks = zhdr->middle_chunks;
  613. zhdr->middle_chunks = 0;
  614. zhdr->start_middle = 0;
  615. zhdr->first_num++;
  616. return 1;
  617. }
  618. /*
  619. * moving data is expensive, so let's only do that if
  620. * there's substantial gain (at least BIG_CHUNK_GAP chunks)
  621. */
  622. if (zhdr->first_chunks != 0 && zhdr->last_chunks == 0 &&
  623. zhdr->start_middle - (zhdr->first_chunks + ZHDR_CHUNKS) >=
  624. BIG_CHUNK_GAP) {
  625. mchunk_memmove(zhdr, zhdr->first_chunks + ZHDR_CHUNKS);
  626. zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS;
  627. return 1;
  628. } else if (zhdr->last_chunks != 0 && zhdr->first_chunks == 0 &&
  629. TOTAL_CHUNKS - (zhdr->last_chunks + zhdr->start_middle
  630. + zhdr->middle_chunks) >=
  631. BIG_CHUNK_GAP) {
  632. unsigned short new_start = TOTAL_CHUNKS - zhdr->last_chunks -
  633. zhdr->middle_chunks;
  634. mchunk_memmove(zhdr, new_start);
  635. zhdr->start_middle = new_start;
  636. return 1;
  637. }
  638. return 0;
  639. }
  640. static void do_compact_page(struct z3fold_header *zhdr, bool locked)
  641. {
  642. struct z3fold_pool *pool = zhdr_to_pool(zhdr);
  643. struct page *page;
  644. page = virt_to_page(zhdr);
  645. if (locked)
  646. WARN_ON(z3fold_page_trylock(zhdr));
  647. else
  648. z3fold_page_lock(zhdr);
  649. if (WARN_ON(!test_and_clear_bit(NEEDS_COMPACTING, &page->private))) {
  650. z3fold_page_unlock(zhdr);
  651. return;
  652. }
  653. spin_lock(&pool->lock);
  654. list_del_init(&zhdr->buddy);
  655. spin_unlock(&pool->lock);
  656. if (put_z3fold_locked(zhdr))
  657. return;
  658. if (test_bit(PAGE_STALE, &page->private) ||
  659. test_and_set_bit(PAGE_CLAIMED, &page->private)) {
  660. z3fold_page_unlock(zhdr);
  661. return;
  662. }
  663. if (!zhdr->foreign_handles && buddy_single(zhdr) &&
  664. zhdr->mapped_count == 0 && compact_single_buddy(zhdr)) {
  665. if (!put_z3fold_locked(zhdr)) {
  666. clear_bit(PAGE_CLAIMED, &page->private);
  667. z3fold_page_unlock(zhdr);
  668. }
  669. return;
  670. }
  671. z3fold_compact_page(zhdr);
  672. add_to_unbuddied(pool, zhdr);
  673. clear_bit(PAGE_CLAIMED, &page->private);
  674. z3fold_page_unlock(zhdr);
  675. }
  676. static void compact_page_work(struct work_struct *w)
  677. {
  678. struct z3fold_header *zhdr = container_of(w, struct z3fold_header,
  679. work);
  680. do_compact_page(zhdr, false);
  681. }
  682. /* returns _locked_ z3fold page header or NULL */
  683. static inline struct z3fold_header *__z3fold_alloc(struct z3fold_pool *pool,
  684. size_t size, bool can_sleep)
  685. {
  686. struct z3fold_header *zhdr = NULL;
  687. struct page *page;
  688. struct list_head *unbuddied;
  689. int chunks = size_to_chunks(size), i;
  690. lookup:
  691. migrate_disable();
  692. /* First, try to find an unbuddied z3fold page. */
  693. unbuddied = this_cpu_ptr(pool->unbuddied);
  694. for_each_unbuddied_list(i, chunks) {
  695. struct list_head *l = &unbuddied[i];
  696. zhdr = list_first_entry_or_null(READ_ONCE(l),
  697. struct z3fold_header, buddy);
  698. if (!zhdr)
  699. continue;
  700. /* Re-check under lock. */
  701. spin_lock(&pool->lock);
  702. if (unlikely(zhdr != list_first_entry(READ_ONCE(l),
  703. struct z3fold_header, buddy)) ||
  704. !z3fold_page_trylock(zhdr)) {
  705. spin_unlock(&pool->lock);
  706. zhdr = NULL;
  707. migrate_enable();
  708. if (can_sleep)
  709. cond_resched();
  710. goto lookup;
  711. }
  712. list_del_init(&zhdr->buddy);
  713. zhdr->cpu = -1;
  714. spin_unlock(&pool->lock);
  715. page = virt_to_page(zhdr);
  716. if (test_bit(NEEDS_COMPACTING, &page->private) ||
  717. test_bit(PAGE_CLAIMED, &page->private)) {
  718. z3fold_page_unlock(zhdr);
  719. zhdr = NULL;
  720. migrate_enable();
  721. if (can_sleep)
  722. cond_resched();
  723. goto lookup;
  724. }
  725. /*
  726. * this page could not be removed from its unbuddied
  727. * list while pool lock was held, and then we've taken
  728. * page lock so kref_put could not be called before
  729. * we got here, so it's safe to just call kref_get()
  730. */
  731. kref_get(&zhdr->refcount);
  732. break;
  733. }
  734. migrate_enable();
  735. if (!zhdr) {
  736. int cpu;
  737. /* look for _exact_ match on other cpus' lists */
  738. for_each_online_cpu(cpu) {
  739. struct list_head *l;
  740. unbuddied = per_cpu_ptr(pool->unbuddied, cpu);
  741. spin_lock(&pool->lock);
  742. l = &unbuddied[chunks];
  743. zhdr = list_first_entry_or_null(READ_ONCE(l),
  744. struct z3fold_header, buddy);
  745. if (!zhdr || !z3fold_page_trylock(zhdr)) {
  746. spin_unlock(&pool->lock);
  747. zhdr = NULL;
  748. continue;
  749. }
  750. list_del_init(&zhdr->buddy);
  751. zhdr->cpu = -1;
  752. spin_unlock(&pool->lock);
  753. page = virt_to_page(zhdr);
  754. if (test_bit(NEEDS_COMPACTING, &page->private) ||
  755. test_bit(PAGE_CLAIMED, &page->private)) {
  756. z3fold_page_unlock(zhdr);
  757. zhdr = NULL;
  758. if (can_sleep)
  759. cond_resched();
  760. continue;
  761. }
  762. kref_get(&zhdr->refcount);
  763. break;
  764. }
  765. }
  766. if (zhdr && !zhdr->slots) {
  767. zhdr->slots = alloc_slots(pool, GFP_ATOMIC);
  768. if (!zhdr->slots)
  769. goto out_fail;
  770. }
  771. return zhdr;
  772. out_fail:
  773. if (!put_z3fold_locked(zhdr)) {
  774. add_to_unbuddied(pool, zhdr);
  775. z3fold_page_unlock(zhdr);
  776. }
  777. return NULL;
  778. }
  779. /*
  780. * API Functions
  781. */
  782. /**
  783. * z3fold_create_pool() - create a new z3fold pool
  784. * @name: pool name
  785. * @gfp: gfp flags when allocating the z3fold pool structure
  786. *
  787. * Return: pointer to the new z3fold pool or NULL if the metadata allocation
  788. * failed.
  789. */
  790. static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp)
  791. {
  792. struct z3fold_pool *pool = NULL;
  793. int i, cpu;
  794. pool = kzalloc(sizeof(struct z3fold_pool), gfp);
  795. if (!pool)
  796. goto out;
  797. pool->c_handle = kmem_cache_create("z3fold_handle",
  798. sizeof(struct z3fold_buddy_slots),
  799. SLOTS_ALIGN, 0, NULL);
  800. if (!pool->c_handle)
  801. goto out_c;
  802. spin_lock_init(&pool->lock);
  803. spin_lock_init(&pool->stale_lock);
  804. pool->unbuddied = __alloc_percpu(sizeof(struct list_head) * NCHUNKS,
  805. __alignof__(struct list_head));
  806. if (!pool->unbuddied)
  807. goto out_pool;
  808. for_each_possible_cpu(cpu) {
  809. struct list_head *unbuddied =
  810. per_cpu_ptr(pool->unbuddied, cpu);
  811. for_each_unbuddied_list(i, 0)
  812. INIT_LIST_HEAD(&unbuddied[i]);
  813. }
  814. INIT_LIST_HEAD(&pool->stale);
  815. atomic64_set(&pool->pages_nr, 0);
  816. pool->name = name;
  817. pool->compact_wq = create_singlethread_workqueue(pool->name);
  818. if (!pool->compact_wq)
  819. goto out_unbuddied;
  820. pool->release_wq = create_singlethread_workqueue(pool->name);
  821. if (!pool->release_wq)
  822. goto out_wq;
  823. INIT_WORK(&pool->work, free_pages_work);
  824. return pool;
  825. out_wq:
  826. destroy_workqueue(pool->compact_wq);
  827. out_unbuddied:
  828. free_percpu(pool->unbuddied);
  829. out_pool:
  830. kmem_cache_destroy(pool->c_handle);
  831. out_c:
  832. kfree(pool);
  833. out:
  834. return NULL;
  835. }
  836. /**
  837. * z3fold_destroy_pool() - destroys an existing z3fold pool
  838. * @pool: the z3fold pool to be destroyed
  839. *
  840. * The pool should be emptied before this function is called.
  841. */
  842. static void z3fold_destroy_pool(struct z3fold_pool *pool)
  843. {
  844. kmem_cache_destroy(pool->c_handle);
  845. /*
  846. * We need to destroy pool->compact_wq before pool->release_wq,
  847. * as any pending work on pool->compact_wq will call
  848. * queue_work(pool->release_wq, &pool->work).
  849. *
  850. * There are still outstanding pages until both workqueues are drained,
  851. * so we cannot unregister migration until then.
  852. */
  853. destroy_workqueue(pool->compact_wq);
  854. destroy_workqueue(pool->release_wq);
  855. free_percpu(pool->unbuddied);
  856. kfree(pool);
  857. }
  858. static const struct movable_operations z3fold_mops;
  859. /**
  860. * z3fold_alloc() - allocates a region of a given size
  861. * @pool: z3fold pool from which to allocate
  862. * @size: size in bytes of the desired allocation
  863. * @gfp: gfp flags used if the pool needs to grow
  864. * @handle: handle of the new allocation
  865. *
  866. * This function will attempt to find a free region in the pool large enough to
  867. * satisfy the allocation request. A search of the unbuddied lists is
  868. * performed first. If no suitable free region is found, then a new page is
  869. * allocated and added to the pool to satisfy the request.
  870. *
  871. * Return: 0 if success and handle is set, otherwise -EINVAL if the size or
  872. * gfp arguments are invalid or -ENOMEM if the pool was unable to allocate
  873. * a new page.
  874. */
  875. static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp,
  876. unsigned long *handle)
  877. {
  878. int chunks = size_to_chunks(size);
  879. struct z3fold_header *zhdr = NULL;
  880. struct page *page = NULL;
  881. enum buddy bud;
  882. bool can_sleep = gfpflags_allow_blocking(gfp);
  883. if (!size || (gfp & __GFP_HIGHMEM))
  884. return -EINVAL;
  885. if (size > PAGE_SIZE)
  886. return -ENOSPC;
  887. if (size > PAGE_SIZE - ZHDR_SIZE_ALIGNED - CHUNK_SIZE)
  888. bud = HEADLESS;
  889. else {
  890. retry:
  891. zhdr = __z3fold_alloc(pool, size, can_sleep);
  892. if (zhdr) {
  893. bud = get_free_buddy(zhdr, chunks);
  894. if (bud == HEADLESS) {
  895. if (!put_z3fold_locked(zhdr))
  896. z3fold_page_unlock(zhdr);
  897. pr_err("No free chunks in unbuddied\n");
  898. WARN_ON(1);
  899. goto retry;
  900. }
  901. page = virt_to_page(zhdr);
  902. goto found;
  903. }
  904. bud = FIRST;
  905. }
  906. page = alloc_page(gfp);
  907. if (!page)
  908. return -ENOMEM;
  909. zhdr = init_z3fold_page(page, bud == HEADLESS, pool, gfp);
  910. if (!zhdr) {
  911. __free_page(page);
  912. return -ENOMEM;
  913. }
  914. atomic64_inc(&pool->pages_nr);
  915. if (bud == HEADLESS) {
  916. set_bit(PAGE_HEADLESS, &page->private);
  917. goto headless;
  918. }
  919. if (can_sleep) {
  920. lock_page(page);
  921. __SetPageMovable(page, &z3fold_mops);
  922. unlock_page(page);
  923. } else {
  924. WARN_ON(!trylock_page(page));
  925. __SetPageMovable(page, &z3fold_mops);
  926. unlock_page(page);
  927. }
  928. z3fold_page_lock(zhdr);
  929. found:
  930. if (bud == FIRST)
  931. zhdr->first_chunks = chunks;
  932. else if (bud == LAST)
  933. zhdr->last_chunks = chunks;
  934. else {
  935. zhdr->middle_chunks = chunks;
  936. zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS;
  937. }
  938. add_to_unbuddied(pool, zhdr);
  939. headless:
  940. spin_lock(&pool->lock);
  941. *handle = encode_handle(zhdr, bud);
  942. spin_unlock(&pool->lock);
  943. if (bud != HEADLESS)
  944. z3fold_page_unlock(zhdr);
  945. return 0;
  946. }
  947. /**
  948. * z3fold_free() - frees the allocation associated with the given handle
  949. * @pool: pool in which the allocation resided
  950. * @handle: handle associated with the allocation returned by z3fold_alloc()
  951. *
  952. * In the case that the z3fold page in which the allocation resides is under
  953. * reclaim, as indicated by the PAGE_CLAIMED flag being set, this function
  954. * only sets the first|middle|last_chunks to 0. The page is actually freed
  955. * once all buddies are evicted (see z3fold_reclaim_page() below).
  956. */
  957. static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
  958. {
  959. struct z3fold_header *zhdr;
  960. struct page *page;
  961. enum buddy bud;
  962. bool page_claimed;
  963. zhdr = get_z3fold_header(handle);
  964. page = virt_to_page(zhdr);
  965. page_claimed = test_and_set_bit(PAGE_CLAIMED, &page->private);
  966. if (test_bit(PAGE_HEADLESS, &page->private)) {
  967. /* if a headless page is under reclaim, just leave.
  968. * NB: we use test_and_set_bit for a reason: if the bit
  969. * has not been set before, we release this page
  970. * immediately so we don't care about its value any more.
  971. */
  972. if (!page_claimed) {
  973. put_z3fold_header(zhdr);
  974. free_z3fold_page(page, true);
  975. atomic64_dec(&pool->pages_nr);
  976. }
  977. return;
  978. }
  979. /* Non-headless case */
  980. bud = handle_to_buddy(handle);
  981. switch (bud) {
  982. case FIRST:
  983. zhdr->first_chunks = 0;
  984. break;
  985. case MIDDLE:
  986. zhdr->middle_chunks = 0;
  987. break;
  988. case LAST:
  989. zhdr->last_chunks = 0;
  990. break;
  991. default:
  992. pr_err("%s: unknown bud %d\n", __func__, bud);
  993. WARN_ON(1);
  994. put_z3fold_header(zhdr);
  995. return;
  996. }
  997. if (!page_claimed)
  998. free_handle(handle, zhdr);
  999. if (put_z3fold_locked_list(zhdr))
  1000. return;
  1001. if (page_claimed) {
  1002. /* the page has not been claimed by us */
  1003. put_z3fold_header(zhdr);
  1004. return;
  1005. }
  1006. if (test_and_set_bit(NEEDS_COMPACTING, &page->private)) {
  1007. clear_bit(PAGE_CLAIMED, &page->private);
  1008. put_z3fold_header(zhdr);
  1009. return;
  1010. }
  1011. if (zhdr->cpu < 0 || !cpu_online(zhdr->cpu)) {
  1012. zhdr->cpu = -1;
  1013. kref_get(&zhdr->refcount);
  1014. clear_bit(PAGE_CLAIMED, &page->private);
  1015. do_compact_page(zhdr, true);
  1016. return;
  1017. }
  1018. kref_get(&zhdr->refcount);
  1019. clear_bit(PAGE_CLAIMED, &page->private);
  1020. queue_work_on(zhdr->cpu, pool->compact_wq, &zhdr->work);
  1021. put_z3fold_header(zhdr);
  1022. }
  1023. /**
  1024. * z3fold_map() - maps the allocation associated with the given handle
  1025. * @pool: pool in which the allocation resides
  1026. * @handle: handle associated with the allocation to be mapped
  1027. *
  1028. * Extracts the buddy number from handle and constructs the pointer to the
  1029. * correct starting chunk within the page.
  1030. *
  1031. * Returns: a pointer to the mapped allocation
  1032. */
  1033. static void *z3fold_map(struct z3fold_pool *pool, unsigned long handle)
  1034. {
  1035. struct z3fold_header *zhdr;
  1036. struct page *page;
  1037. void *addr;
  1038. enum buddy buddy;
  1039. zhdr = get_z3fold_header(handle);
  1040. addr = zhdr;
  1041. page = virt_to_page(zhdr);
  1042. if (test_bit(PAGE_HEADLESS, &page->private))
  1043. goto out;
  1044. buddy = handle_to_buddy(handle);
  1045. switch (buddy) {
  1046. case FIRST:
  1047. addr += ZHDR_SIZE_ALIGNED;
  1048. break;
  1049. case MIDDLE:
  1050. addr += zhdr->start_middle << CHUNK_SHIFT;
  1051. set_bit(MIDDLE_CHUNK_MAPPED, &page->private);
  1052. break;
  1053. case LAST:
  1054. addr += PAGE_SIZE - (handle_to_chunks(handle) << CHUNK_SHIFT);
  1055. break;
  1056. default:
  1057. pr_err("unknown buddy id %d\n", buddy);
  1058. WARN_ON(1);
  1059. addr = NULL;
  1060. break;
  1061. }
  1062. if (addr)
  1063. zhdr->mapped_count++;
  1064. out:
  1065. put_z3fold_header(zhdr);
  1066. return addr;
  1067. }
  1068. /**
  1069. * z3fold_unmap() - unmaps the allocation associated with the given handle
  1070. * @pool: pool in which the allocation resides
  1071. * @handle: handle associated with the allocation to be unmapped
  1072. */
  1073. static void z3fold_unmap(struct z3fold_pool *pool, unsigned long handle)
  1074. {
  1075. struct z3fold_header *zhdr;
  1076. struct page *page;
  1077. enum buddy buddy;
  1078. zhdr = get_z3fold_header(handle);
  1079. page = virt_to_page(zhdr);
  1080. if (test_bit(PAGE_HEADLESS, &page->private))
  1081. return;
  1082. buddy = handle_to_buddy(handle);
  1083. if (buddy == MIDDLE)
  1084. clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
  1085. zhdr->mapped_count--;
  1086. put_z3fold_header(zhdr);
  1087. }
  1088. /**
  1089. * z3fold_get_pool_pages() - gets the z3fold pool size in pages
  1090. * @pool: pool whose size is being queried
  1091. *
  1092. * Returns: size in pages of the given pool.
  1093. */
  1094. static u64 z3fold_get_pool_pages(struct z3fold_pool *pool)
  1095. {
  1096. return atomic64_read(&pool->pages_nr);
  1097. }
  1098. static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
  1099. {
  1100. struct z3fold_header *zhdr;
  1101. struct z3fold_pool *pool;
  1102. VM_BUG_ON_PAGE(PageIsolated(page), page);
  1103. if (test_bit(PAGE_HEADLESS, &page->private))
  1104. return false;
  1105. zhdr = page_address(page);
  1106. z3fold_page_lock(zhdr);
  1107. if (test_bit(NEEDS_COMPACTING, &page->private) ||
  1108. test_bit(PAGE_STALE, &page->private))
  1109. goto out;
  1110. if (zhdr->mapped_count != 0 || zhdr->foreign_handles != 0)
  1111. goto out;
  1112. if (test_and_set_bit(PAGE_CLAIMED, &page->private))
  1113. goto out;
  1114. pool = zhdr_to_pool(zhdr);
  1115. spin_lock(&pool->lock);
  1116. if (!list_empty(&zhdr->buddy))
  1117. list_del_init(&zhdr->buddy);
  1118. spin_unlock(&pool->lock);
  1119. kref_get(&zhdr->refcount);
  1120. z3fold_page_unlock(zhdr);
  1121. return true;
  1122. out:
  1123. z3fold_page_unlock(zhdr);
  1124. return false;
  1125. }
  1126. static int z3fold_page_migrate(struct page *newpage, struct page *page,
  1127. enum migrate_mode mode)
  1128. {
  1129. struct z3fold_header *zhdr, *new_zhdr;
  1130. struct z3fold_pool *pool;
  1131. VM_BUG_ON_PAGE(!PageIsolated(page), page);
  1132. VM_BUG_ON_PAGE(!test_bit(PAGE_CLAIMED, &page->private), page);
  1133. VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
  1134. zhdr = page_address(page);
  1135. pool = zhdr_to_pool(zhdr);
  1136. if (!z3fold_page_trylock(zhdr))
  1137. return -EAGAIN;
  1138. if (zhdr->mapped_count != 0 || zhdr->foreign_handles != 0) {
  1139. clear_bit(PAGE_CLAIMED, &page->private);
  1140. z3fold_page_unlock(zhdr);
  1141. return -EBUSY;
  1142. }
  1143. if (work_pending(&zhdr->work)) {
  1144. z3fold_page_unlock(zhdr);
  1145. return -EAGAIN;
  1146. }
  1147. new_zhdr = page_address(newpage);
  1148. memcpy(new_zhdr, zhdr, PAGE_SIZE);
  1149. newpage->private = page->private;
  1150. set_bit(PAGE_MIGRATED, &page->private);
  1151. z3fold_page_unlock(zhdr);
  1152. spin_lock_init(&new_zhdr->page_lock);
  1153. INIT_WORK(&new_zhdr->work, compact_page_work);
  1154. /*
  1155. * z3fold_page_isolate() ensures that new_zhdr->buddy is empty,
  1156. * so we only have to reinitialize it.
  1157. */
  1158. INIT_LIST_HEAD(&new_zhdr->buddy);
  1159. __ClearPageMovable(page);
  1160. get_page(newpage);
  1161. z3fold_page_lock(new_zhdr);
  1162. if (new_zhdr->first_chunks)
  1163. encode_handle(new_zhdr, FIRST);
  1164. if (new_zhdr->last_chunks)
  1165. encode_handle(new_zhdr, LAST);
  1166. if (new_zhdr->middle_chunks)
  1167. encode_handle(new_zhdr, MIDDLE);
  1168. set_bit(NEEDS_COMPACTING, &newpage->private);
  1169. new_zhdr->cpu = smp_processor_id();
  1170. __SetPageMovable(newpage, &z3fold_mops);
  1171. z3fold_page_unlock(new_zhdr);
  1172. queue_work_on(new_zhdr->cpu, pool->compact_wq, &new_zhdr->work);
  1173. /* PAGE_CLAIMED and PAGE_MIGRATED are cleared now. */
  1174. page->private = 0;
  1175. put_page(page);
  1176. return 0;
  1177. }
  1178. static void z3fold_page_putback(struct page *page)
  1179. {
  1180. struct z3fold_header *zhdr;
  1181. struct z3fold_pool *pool;
  1182. zhdr = page_address(page);
  1183. pool = zhdr_to_pool(zhdr);
  1184. z3fold_page_lock(zhdr);
  1185. if (!list_empty(&zhdr->buddy))
  1186. list_del_init(&zhdr->buddy);
  1187. INIT_LIST_HEAD(&page->lru);
  1188. if (put_z3fold_locked(zhdr))
  1189. return;
  1190. if (list_empty(&zhdr->buddy))
  1191. add_to_unbuddied(pool, zhdr);
  1192. clear_bit(PAGE_CLAIMED, &page->private);
  1193. z3fold_page_unlock(zhdr);
  1194. }
  1195. static const struct movable_operations z3fold_mops = {
  1196. .isolate_page = z3fold_page_isolate,
  1197. .migrate_page = z3fold_page_migrate,
  1198. .putback_page = z3fold_page_putback,
  1199. };
  1200. /*****************
  1201. * zpool
  1202. ****************/
  1203. static void *z3fold_zpool_create(const char *name, gfp_t gfp)
  1204. {
  1205. return z3fold_create_pool(name, gfp);
  1206. }
  1207. static void z3fold_zpool_destroy(void *pool)
  1208. {
  1209. z3fold_destroy_pool(pool);
  1210. }
  1211. static int z3fold_zpool_malloc(void *pool, size_t size, gfp_t gfp,
  1212. unsigned long *handle)
  1213. {
  1214. return z3fold_alloc(pool, size, gfp, handle);
  1215. }
  1216. static void z3fold_zpool_free(void *pool, unsigned long handle)
  1217. {
  1218. z3fold_free(pool, handle);
  1219. }
  1220. static void *z3fold_zpool_map(void *pool, unsigned long handle,
  1221. enum zpool_mapmode mm)
  1222. {
  1223. return z3fold_map(pool, handle);
  1224. }
  1225. static void z3fold_zpool_unmap(void *pool, unsigned long handle)
  1226. {
  1227. z3fold_unmap(pool, handle);
  1228. }
  1229. static u64 z3fold_zpool_total_pages(void *pool)
  1230. {
  1231. return z3fold_get_pool_pages(pool);
  1232. }
  1233. static struct zpool_driver z3fold_zpool_driver = {
  1234. .type = "z3fold",
  1235. .sleep_mapped = true,
  1236. .owner = THIS_MODULE,
  1237. .create = z3fold_zpool_create,
  1238. .destroy = z3fold_zpool_destroy,
  1239. .malloc = z3fold_zpool_malloc,
  1240. .free = z3fold_zpool_free,
  1241. .map = z3fold_zpool_map,
  1242. .unmap = z3fold_zpool_unmap,
  1243. .total_pages = z3fold_zpool_total_pages,
  1244. };
  1245. MODULE_ALIAS("zpool-z3fold");
  1246. static int __init init_z3fold(void)
  1247. {
  1248. /*
  1249. * Make sure the z3fold header is not larger than the page size and
  1250. * there has remaining spaces for its buddy.
  1251. */
  1252. BUILD_BUG_ON(ZHDR_SIZE_ALIGNED > PAGE_SIZE - CHUNK_SIZE);
  1253. zpool_register_driver(&z3fold_zpool_driver);
  1254. return 0;
  1255. }
  1256. static void __exit exit_z3fold(void)
  1257. {
  1258. zpool_unregister_driver(&z3fold_zpool_driver);
  1259. }
  1260. module_init(init_z3fold);
  1261. module_exit(exit_z3fold);
  1262. MODULE_LICENSE("GPL");
  1263. MODULE_AUTHOR("Vitaly Wool <vitalywool@gmail.com>");
  1264. MODULE_DESCRIPTION("3-Fold Allocator for Compressed Pages");