at v6.0 178 lines 4.1 kB view raw
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (C) 2018 HUAWEI, Inc. 4 * https://www.huawei.com/ 5 */ 6#ifndef __EROFS_FS_ZDATA_H 7#define __EROFS_FS_ZDATA_H 8 9#include "internal.h" 10#include "tagptr.h" 11 12#define Z_EROFS_PCLUSTER_MAX_PAGES (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE) 13#define Z_EROFS_INLINE_BVECS 2 14 15/* 16 * let's leave a type here in case of introducing 17 * another tagged pointer later. 18 */ 19typedef void *z_erofs_next_pcluster_t; 20 21struct z_erofs_bvec { 22 struct page *page; 23 int offset; 24 unsigned int end; 25}; 26 27#define __Z_EROFS_BVSET(name, total) \ 28struct name { \ 29 /* point to the next page which contains the following bvecs */ \ 30 struct page *nextpage; \ 31 struct z_erofs_bvec bvec[total]; \ 32} 33__Z_EROFS_BVSET(z_erofs_bvset,); 34__Z_EROFS_BVSET(z_erofs_bvset_inline, Z_EROFS_INLINE_BVECS); 35 36/* 37 * Structure fields follow one of the following exclusion rules. 38 * 39 * I: Modifiable by initialization/destruction paths and read-only 40 * for everyone else; 41 * 42 * L: Field should be protected by the pcluster lock; 43 * 44 * A: Field should be accessed / updated in atomic for parallelized code. 45 */ 46struct z_erofs_pcluster { 47 struct erofs_workgroup obj; 48 struct mutex lock; 49 50 /* A: point to next chained pcluster or TAILs */ 51 z_erofs_next_pcluster_t next; 52 53 /* L: the maximum decompression size of this round */ 54 unsigned int length; 55 56 /* L: total number of bvecs */ 57 unsigned int vcnt; 58 59 /* I: page offset of start position of decompression */ 60 unsigned short pageofs_out; 61 62 /* I: page offset of inline compressed data */ 63 unsigned short pageofs_in; 64 65 union { 66 /* L: inline a certain number of bvec for bootstrap */ 67 struct z_erofs_bvset_inline bvset; 68 69 /* I: can be used to free the pcluster by RCU. */ 70 struct rcu_head rcu; 71 }; 72 73 union { 74 /* I: physical cluster size in pages */ 75 unsigned short pclusterpages; 76 77 /* I: tailpacking inline compressed size */ 78 unsigned short tailpacking_size; 79 }; 80 81 /* I: compression algorithm format */ 82 unsigned char algorithmformat; 83 84 /* L: whether partial decompression or not */ 85 bool partial; 86 87 /* L: indicate several pageofs_outs or not */ 88 bool multibases; 89 90 /* A: compressed bvecs (can be cached or inplaced pages) */ 91 struct z_erofs_bvec compressed_bvecs[]; 92}; 93 94/* let's avoid the valid 32-bit kernel addresses */ 95 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) 100 101#define Z_EROFS_PCLUSTER_NIL (NULL) 102 103struct z_erofs_decompressqueue { 104 struct super_block *sb; 105 atomic_t pending_bios; 106 z_erofs_next_pcluster_t head; 107 108 union { 109 struct completion done; 110 struct work_struct work; 111 } u; 112 113 bool eio; 114}; 115 116static inline bool z_erofs_is_inline_pcluster(struct z_erofs_pcluster *pcl) 117{ 118 return !pcl->obj.index; 119} 120 121static inline unsigned int z_erofs_pclusterpages(struct z_erofs_pcluster *pcl) 122{ 123 if (z_erofs_is_inline_pcluster(pcl)) 124 return 1; 125 return pcl->pclusterpages; 126} 127 128/* 129 * bit 31: I/O error occurred on this page 130 * bit 0 - 30: remaining parts to complete this page 131 */ 132#define Z_EROFS_PAGE_EIO (1 << 31) 133 134static inline void z_erofs_onlinepage_init(struct page *page) 135{ 136 union { 137 atomic_t o; 138 unsigned long v; 139 } u = { .o = ATOMIC_INIT(1) }; 140 141 set_page_private(page, u.v); 142 smp_wmb(); 143 SetPagePrivate(page); 144} 145 146static inline void z_erofs_onlinepage_split(struct page *page) 147{ 148 atomic_inc((atomic_t *)&page->private); 149} 150 151static inline void z_erofs_page_mark_eio(struct page *page) 152{ 153 int orig; 154 155 do { 156 orig = atomic_read((atomic_t *)&page->private); 157 } while (atomic_cmpxchg((atomic_t *)&page->private, orig, 158 orig | Z_EROFS_PAGE_EIO) != orig); 159} 160 161static inline void z_erofs_onlinepage_endio(struct page *page) 162{ 163 unsigned int v; 164 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); 172 unlock_page(page); 173 } 174} 175 176#define Z_EROFS_ONSTACK_PAGES 32 177 178#endif