Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (C) 2018 HUAWEI, Inc.
0004  *             https://www.huawei.com/
0005  */
0006 #ifndef __EROFS_FS_ZDATA_H
0007 #define __EROFS_FS_ZDATA_H
0008 
0009 #include "internal.h"
0010 #include "tagptr.h"
0011 
0012 #define Z_EROFS_PCLUSTER_MAX_PAGES  (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE)
0013 #define Z_EROFS_INLINE_BVECS        2
0014 
0015 /*
0016  * let's leave a type here in case of introducing
0017  * another tagged pointer later.
0018  */
0019 typedef void *z_erofs_next_pcluster_t;
0020 
0021 struct z_erofs_bvec {
0022     struct page *page;
0023     int offset;
0024     unsigned int end;
0025 };
0026 
0027 #define __Z_EROFS_BVSET(name, total) \
0028 struct name { \
0029     /* point to the next page which contains the following bvecs */ \
0030     struct page *nextpage; \
0031     struct z_erofs_bvec bvec[total]; \
0032 }
0033 __Z_EROFS_BVSET(z_erofs_bvset,);
0034 __Z_EROFS_BVSET(z_erofs_bvset_inline, Z_EROFS_INLINE_BVECS);
0035 
0036 /*
0037  * Structure fields follow one of the following exclusion rules.
0038  *
0039  * I: Modifiable by initialization/destruction paths and read-only
0040  *    for everyone else;
0041  *
0042  * L: Field should be protected by the pcluster lock;
0043  *
0044  * A: Field should be accessed / updated in atomic for parallelized code.
0045  */
0046 struct z_erofs_pcluster {
0047     struct erofs_workgroup obj;
0048     struct mutex lock;
0049 
0050     /* A: point to next chained pcluster or TAILs */
0051     z_erofs_next_pcluster_t next;
0052 
0053     /* L: the maximum decompression size of this round */
0054     unsigned int length;
0055 
0056     /* L: total number of bvecs */
0057     unsigned int vcnt;
0058 
0059     /* I: page offset of start position of decompression */
0060     unsigned short pageofs_out;
0061 
0062     /* I: page offset of inline compressed data */
0063     unsigned short pageofs_in;
0064 
0065     union {
0066         /* L: inline a certain number of bvec for bootstrap */
0067         struct z_erofs_bvset_inline bvset;
0068 
0069         /* I: can be used to free the pcluster by RCU. */
0070         struct rcu_head rcu;
0071     };
0072 
0073     union {
0074         /* I: physical cluster size in pages */
0075         unsigned short pclusterpages;
0076 
0077         /* I: tailpacking inline compressed size */
0078         unsigned short tailpacking_size;
0079     };
0080 
0081     /* I: compression algorithm format */
0082     unsigned char algorithmformat;
0083 
0084     /* L: whether partial decompression or not */
0085     bool partial;
0086 
0087     /* L: indicate several pageofs_outs or not */
0088     bool multibases;
0089 
0090     /* A: compressed bvecs (can be cached or inplaced pages) */
0091     struct z_erofs_bvec compressed_bvecs[];
0092 };
0093 
0094 /* let's avoid the valid 32-bit kernel addresses */
0095 
0096 /* the chained workgroup has't submitted io (still open) */
0097 #define Z_EROFS_PCLUSTER_TAIL           ((void *)0x5F0ECAFE)
0098 /* the chained workgroup has already submitted io */
0099 #define Z_EROFS_PCLUSTER_TAIL_CLOSED    ((void *)0x5F0EDEAD)
0100 
0101 #define Z_EROFS_PCLUSTER_NIL            (NULL)
0102 
0103 struct z_erofs_decompressqueue {
0104     struct super_block *sb;
0105     atomic_t pending_bios;
0106     z_erofs_next_pcluster_t head;
0107 
0108     union {
0109         struct completion done;
0110         struct work_struct work;
0111     } u;
0112 
0113     bool eio;
0114 };
0115 
0116 static inline bool z_erofs_is_inline_pcluster(struct z_erofs_pcluster *pcl)
0117 {
0118     return !pcl->obj.index;
0119 }
0120 
0121 static inline unsigned int z_erofs_pclusterpages(struct z_erofs_pcluster *pcl)
0122 {
0123     if (z_erofs_is_inline_pcluster(pcl))
0124         return 1;
0125     return pcl->pclusterpages;
0126 }
0127 
0128 /*
0129  * bit 31: I/O error occurred on this page
0130  * bit 0 - 30: remaining parts to complete this page
0131  */
0132 #define Z_EROFS_PAGE_EIO            (1 << 31)
0133 
0134 static inline void z_erofs_onlinepage_init(struct page *page)
0135 {
0136     union {
0137         atomic_t o;
0138         unsigned long v;
0139     } u = { .o = ATOMIC_INIT(1) };
0140 
0141     set_page_private(page, u.v);
0142     smp_wmb();
0143     SetPagePrivate(page);
0144 }
0145 
0146 static inline void z_erofs_onlinepage_split(struct page *page)
0147 {
0148     atomic_inc((atomic_t *)&page->private);
0149 }
0150 
0151 static inline void z_erofs_page_mark_eio(struct page *page)
0152 {
0153     int orig;
0154 
0155     do {
0156         orig = atomic_read((atomic_t *)&page->private);
0157     } while (atomic_cmpxchg((atomic_t *)&page->private, orig,
0158                 orig | Z_EROFS_PAGE_EIO) != orig);
0159 }
0160 
0161 static inline void z_erofs_onlinepage_endio(struct page *page)
0162 {
0163     unsigned int v;
0164 
0165     DBG_BUGON(!PagePrivate(page));
0166     v = atomic_dec_return((atomic_t *)&page->private);
0167     if (!(v & ~Z_EROFS_PAGE_EIO)) {
0168         set_page_private(page, 0);
0169         ClearPagePrivate(page);
0170         if (!(v & Z_EROFS_PAGE_EIO))
0171             SetPageUptodate(page);
0172         unlock_page(page);
0173     }
0174 }
0175 
0176 #define Z_EROFS_ONSTACK_PAGES       32
0177 
0178 #endif