root/fs/erofs/zdata.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. erofs_page_is_managed
  2. z_erofs_onlinepage_index
  3. z_erofs_onlinepage_init
  4. z_erofs_onlinepage_fixup
  5. z_erofs_onlinepage_endio

   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * Copyright (C) 2018 HUAWEI, Inc.
   4  *             http://www.huawei.com/
   5  * Created by Gao Xiang <gaoxiang25@huawei.com>
   6  */
   7 #ifndef __EROFS_FS_ZDATA_H
   8 #define __EROFS_FS_ZDATA_H
   9 
  10 #include "internal.h"
  11 #include "zpvec.h"
  12 
  13 #define Z_EROFS_NR_INLINE_PAGEVECS      3
  14 
  15 /*
  16  * Structure fields follow one of the following exclusion rules.
  17  *
  18  * I: Modifiable by initialization/destruction paths and read-only
  19  *    for everyone else;
  20  *
  21  * L: Field should be protected by pageset lock;
  22  *
  23  * A: Field should be accessed / updated in atomic for parallelized code.
  24  */
  25 struct z_erofs_collection {
  26         struct mutex lock;
  27 
  28         /* I: page offset of start position of decompression */
  29         unsigned short pageofs;
  30 
  31         /* L: maximum relative page index in pagevec[] */
  32         unsigned short nr_pages;
  33 
  34         /* L: total number of pages in pagevec[] */
  35         unsigned int vcnt;
  36 
  37         union {
  38                 /* L: inline a certain number of pagevecs for bootstrap */
  39                 erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS];
  40 
  41                 /* I: can be used to free the pcluster by RCU. */
  42                 struct rcu_head rcu;
  43         };
  44 };
  45 
  46 #define Z_EROFS_PCLUSTER_FULL_LENGTH    0x00000001
  47 #define Z_EROFS_PCLUSTER_LENGTH_BIT     1
  48 
  49 /*
  50  * let's leave a type here in case of introducing
  51  * another tagged pointer later.
  52  */
  53 typedef void *z_erofs_next_pcluster_t;
  54 
  55 struct z_erofs_pcluster {
  56         struct erofs_workgroup obj;
  57         struct z_erofs_collection primary_collection;
  58 
  59         /* A: point to next chained pcluster or TAILs */
  60         z_erofs_next_pcluster_t next;
  61 
  62         /* A: compressed pages (including multi-usage pages) */
  63         struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES];
  64 
  65         /* A: lower limit of decompressed length and if full length or not */
  66         unsigned int length;
  67 
  68         /* I: compression algorithm format */
  69         unsigned char algorithmformat;
  70         /* I: bit shift of physical cluster size */
  71         unsigned char clusterbits;
  72 };
  73 
  74 #define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection)
  75 
  76 /* let's avoid the valid 32-bit kernel addresses */
  77 
  78 /* the chained workgroup has't submitted io (still open) */
  79 #define Z_EROFS_PCLUSTER_TAIL           ((void *)0x5F0ECAFE)
  80 /* the chained workgroup has already submitted io */
  81 #define Z_EROFS_PCLUSTER_TAIL_CLOSED    ((void *)0x5F0EDEAD)
  82 
  83 #define Z_EROFS_PCLUSTER_NIL            (NULL)
  84 
  85 #define Z_EROFS_WORKGROUP_SIZE  sizeof(struct z_erofs_pcluster)
  86 
  87 struct z_erofs_unzip_io {
  88         atomic_t pending_bios;
  89         z_erofs_next_pcluster_t head;
  90 
  91         union {
  92                 wait_queue_head_t wait;
  93                 struct work_struct work;
  94         } u;
  95 };
  96 
  97 struct z_erofs_unzip_io_sb {
  98         struct z_erofs_unzip_io io;
  99         struct super_block *sb;
 100 };
 101 
 102 #define MNGD_MAPPING(sbi)       ((sbi)->managed_cache->i_mapping)
 103 static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi,
 104                                          struct page *page)
 105 {
 106         return page->mapping == MNGD_MAPPING(sbi);
 107 }
 108 
 109 #define Z_EROFS_ONLINEPAGE_COUNT_BITS   2
 110 #define Z_EROFS_ONLINEPAGE_COUNT_MASK   ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1)
 111 #define Z_EROFS_ONLINEPAGE_INDEX_SHIFT  (Z_EROFS_ONLINEPAGE_COUNT_BITS)
 112 
 113 /*
 114  * waiters (aka. ongoing_packs): # to unlock the page
 115  * sub-index: 0 - for partial page, >= 1 full page sub-index
 116  */
 117 typedef atomic_t z_erofs_onlinepage_t;
 118 
 119 /* type punning */
 120 union z_erofs_onlinepage_converter {
 121         z_erofs_onlinepage_t *o;
 122         unsigned long *v;
 123 };
 124 
 125 static inline unsigned int z_erofs_onlinepage_index(struct page *page)
 126 {
 127         union z_erofs_onlinepage_converter u;
 128 
 129         DBG_BUGON(!PagePrivate(page));
 130         u.v = &page_private(page);
 131 
 132         return atomic_read(u.o) >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
 133 }
 134 
 135 static inline void z_erofs_onlinepage_init(struct page *page)
 136 {
 137         union {
 138                 z_erofs_onlinepage_t o;
 139                 unsigned long v;
 140         /* keep from being unlocked in advance */
 141         } u = { .o = ATOMIC_INIT(1) };
 142 
 143         set_page_private(page, u.v);
 144         smp_wmb();
 145         SetPagePrivate(page);
 146 }
 147 
 148 static inline void z_erofs_onlinepage_fixup(struct page *page,
 149         uintptr_t index, bool down)
 150 {
 151         unsigned long *p, o, v, id;
 152 repeat:
 153         p = &page_private(page);
 154         o = READ_ONCE(*p);
 155 
 156         id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
 157         if (id) {
 158                 if (!index)
 159                         return;
 160 
 161                 DBG_BUGON(id != index);
 162         }
 163 
 164         v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
 165                 ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
 166         if (cmpxchg(p, o, v) != o)
 167                 goto repeat;
 168 }
 169 
 170 static inline void z_erofs_onlinepage_endio(struct page *page)
 171 {
 172         union z_erofs_onlinepage_converter u;
 173         unsigned int v;
 174 
 175         DBG_BUGON(!PagePrivate(page));
 176         u.v = &page_private(page);
 177 
 178         v = atomic_dec_return(u.o);
 179         if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) {
 180                 ClearPagePrivate(page);
 181                 if (!PageError(page))
 182                         SetPageUptodate(page);
 183                 unlock_page(page);
 184         }
 185         erofs_dbg("%s, page %p value %x", __func__, page, atomic_read(u.o));
 186 }
 187 
 188 #define Z_EROFS_VMAP_ONSTACK_PAGES      \
 189         min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
 190 #define Z_EROFS_VMAP_GLOBAL_PAGES       2048
 191 
 192 #endif
 193 

/* [<][>][^][v][top][bottom][index][help] */