1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2018 HUAWEI, Inc.
4 * https://www.huawei.com/
6 #ifndef __EROFS_FS_ZDATA_H
7 #define __EROFS_FS_ZDATA_H
12 #define Z_EROFS_PCLUSTER_MAX_PAGES (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE)
13 #define Z_EROFS_INLINE_BVECS 2
16 * let's leave a type here in case of introducing
17 * another tagged pointer later.
19 typedef void *z_erofs_next_pcluster_t;
27 #define __Z_EROFS_BVSET(name, total) \
29 /* point to the next page which contains the following bvecs */ \
30 struct page *nextpage; \
31 struct z_erofs_bvec bvec[total]; \
33 __Z_EROFS_BVSET(z_erofs_bvset,);
34 __Z_EROFS_BVSET(z_erofs_bvset_inline, Z_EROFS_INLINE_BVECS);
37 * Structure fields follow one of the following exclusion rules.
39 * I: Modifiable by initialization/destruction paths and read-only
42 * L: Field should be protected by the pcluster lock;
44 * A: Field should be accessed / updated in atomic for parallelized code.
46 struct z_erofs_pcluster {
47 struct erofs_workgroup obj;
50 /* A: point to next chained pcluster or TAILs */
51 z_erofs_next_pcluster_t next;
53 /* L: the maximum decompression size of this round */
56 /* L: total number of bvecs */
59 /* I: page offset of start position of decompression */
60 unsigned short pageofs_out;
62 /* I: page offset of inline compressed data */
63 unsigned short pageofs_in;
66 /* L: inline a certain number of bvec for bootstrap */
67 struct z_erofs_bvset_inline bvset;
69 /* I: can be used to free the pcluster by RCU. */
74 /* I: physical cluster size in pages */
75 unsigned short pclusterpages;
77 /* I: tailpacking inline compressed size */
78 unsigned short tailpacking_size;
81 /* I: compression algorithm format */
82 unsigned char algorithmformat;
84 /* L: whether partial decompression or not */
87 /* L: indicate several pageofs_outs or not */
90 /* A: compressed bvecs (can be cached or inplaced pages) */
91 struct z_erofs_bvec compressed_bvecs[];
94 /* let's avoid the valid 32-bit kernel addresses */
96 /* the chained workgroup has't submitted io (still open) */
97 #define Z_EROFS_PCLUSTER_TAIL ((void *)0x5F0ECAFE)
98 /* the chained workgroup has already submitted io */
99 #define Z_EROFS_PCLUSTER_TAIL_CLOSED ((void *)0x5F0EDEAD)
101 #define Z_EROFS_PCLUSTER_NIL (NULL)
103 struct z_erofs_decompressqueue {
104 struct super_block *sb;
105 atomic_t pending_bios;
106 z_erofs_next_pcluster_t head;
109 struct completion done;
110 struct work_struct work;
116 static inline bool z_erofs_is_inline_pcluster(struct z_erofs_pcluster *pcl)
118 return !pcl->obj.index;
121 static inline unsigned int z_erofs_pclusterpages(struct z_erofs_pcluster *pcl)
123 if (z_erofs_is_inline_pcluster(pcl))
125 return pcl->pclusterpages;
129 * bit 31: I/O error occurred on this page
130 * bit 0 - 30: remaining parts to complete this page
132 #define Z_EROFS_PAGE_EIO (1 << 31)
134 static inline void z_erofs_onlinepage_init(struct page *page)
139 } u = { .o = ATOMIC_INIT(1) };
141 set_page_private(page, u.v);
143 SetPagePrivate(page);
146 static inline void z_erofs_onlinepage_split(struct page *page)
148 atomic_inc((atomic_t *)&page->private);
151 static inline void z_erofs_page_mark_eio(struct page *page)
156 orig = atomic_read((atomic_t *)&page->private);
157 } while (atomic_cmpxchg((atomic_t *)&page->private, orig,
158 orig | Z_EROFS_PAGE_EIO) != orig);
161 static inline void z_erofs_onlinepage_endio(struct page *page)
165 DBG_BUGON(!PagePrivate(page));
166 v = atomic_dec_return((atomic_t *)&page->private);
167 if (!(v & ~Z_EROFS_PAGE_EIO)) {
168 set_page_private(page, 0);
169 ClearPagePrivate(page);
170 if (!(v & Z_EROFS_PAGE_EIO))
171 SetPageUptodate(page);
176 #define Z_EROFS_ONSTACK_PAGES 32