]> git.ipfire.org Git - people/ms/linux.git/blobdiff - fs/erofs/zdata.h
Merge branch 'for-6.0/dax' into libnvdimm-fixes
[people/ms/linux.git] / fs / erofs / zdata.h
index 58053bb5066f6095478014a92c9496700a7a1d10..e7f04c4fbb81c5742915f5120d5e198efce62218 100644 (file)
@@ -7,13 +7,10 @@
 #define __EROFS_FS_ZDATA_H
 
 #include "internal.h"
-#include "zpvec.h"
+#include "tagptr.h"
 
 #define Z_EROFS_PCLUSTER_MAX_PAGES     (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE)
-#define Z_EROFS_NR_INLINE_PAGEVECS      3
-
-#define Z_EROFS_PCLUSTER_FULL_LENGTH    0x00000001
-#define Z_EROFS_PCLUSTER_LENGTH_BIT     1
+#define Z_EROFS_INLINE_BVECS           2
 
 /*
  * let's leave a type here in case of introducing
  */
 typedef void *z_erofs_next_pcluster_t;
 
+struct z_erofs_bvec {
+       struct page *page;
+       int offset;
+       unsigned int end;
+};
+
+#define __Z_EROFS_BVSET(name, total) \
+struct name { \
+       /* point to the next page which contains the following bvecs */ \
+       struct page *nextpage; \
+       struct z_erofs_bvec bvec[total]; \
+}
+__Z_EROFS_BVSET(z_erofs_bvset,);
+__Z_EROFS_BVSET(z_erofs_bvset_inline, Z_EROFS_INLINE_BVECS);
+
 /*
  * Structure fields follow one of the following exclusion rules.
  *
@@ -38,24 +50,21 @@ struct z_erofs_pcluster {
        /* A: point to next chained pcluster or TAILs */
        z_erofs_next_pcluster_t next;
 
-       /* A: lower limit of decompressed length and if full length or not */
+       /* L: the maximum decompression size of this round */
        unsigned int length;
 
+       /* L: total number of bvecs */
+       unsigned int vcnt;
+
        /* I: page offset of start position of decompression */
        unsigned short pageofs_out;
 
        /* I: page offset of inline compressed data */
        unsigned short pageofs_in;
 
-       /* L: maximum relative page index in pagevec[] */
-       unsigned short nr_pages;
-
-       /* L: total number of pages in pagevec[] */
-       unsigned int vcnt;
-
        union {
-               /* L: inline a certain number of pagevecs for bootstrap */
-               erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS];
+               /* L: inline a certain number of bvec for bootstrap */
+               struct z_erofs_bvset_inline bvset;
 
                /* I: can be used to free the pcluster by RCU. */
                struct rcu_head rcu;
@@ -72,8 +81,14 @@ struct z_erofs_pcluster {
        /* I: compression algorithm format */
        unsigned char algorithmformat;
 
-       /* A: compressed pages (can be cached or inplaced pages) */
-       struct page *compressed_pages[];
+       /* L: whether partial decompression or not */
+       bool partial;
+
+       /* L: indicate several pageofs_outs or not */
+       bool multibases;
+
+       /* A: compressed bvecs (can be cached or inplaced pages) */
+       struct z_erofs_bvec compressed_bvecs[];
 };
 
 /* let's avoid the valid 32-bit kernel addresses */
@@ -94,6 +109,8 @@ struct z_erofs_decompressqueue {
                struct completion done;
                struct work_struct work;
        } u;
+
+       bool eio;
 };
 
 static inline bool z_erofs_is_inline_pcluster(struct z_erofs_pcluster *pcl)
@@ -108,38 +125,17 @@ static inline unsigned int z_erofs_pclusterpages(struct z_erofs_pcluster *pcl)
        return pcl->pclusterpages;
 }
 
-#define Z_EROFS_ONLINEPAGE_COUNT_BITS   2
-#define Z_EROFS_ONLINEPAGE_COUNT_MASK   ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1)
-#define Z_EROFS_ONLINEPAGE_INDEX_SHIFT  (Z_EROFS_ONLINEPAGE_COUNT_BITS)
-
 /*
- * waiters (aka. ongoing_packs): # to unlock the page
- * sub-index: 0 - for partial page, >= 1 full page sub-index
+ * bit 31: I/O error occurred on this page
+ * bit 0 - 30: remaining parts to complete this page
  */
-typedef atomic_t z_erofs_onlinepage_t;
-
-/* type punning */
-union z_erofs_onlinepage_converter {
-       z_erofs_onlinepage_t *o;
-       unsigned long *v;
-};
-
-static inline unsigned int z_erofs_onlinepage_index(struct page *page)
-{
-       union z_erofs_onlinepage_converter u;
-
-       DBG_BUGON(!PagePrivate(page));
-       u.v = &page_private(page);
-
-       return atomic_read(u.o) >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
-}
+#define Z_EROFS_PAGE_EIO                       (1 << 31)
 
 static inline void z_erofs_onlinepage_init(struct page *page)
 {
        union {
-               z_erofs_onlinepage_t o;
+               atomic_t o;
                unsigned long v;
-       /* keep from being unlocked in advance */
        } u = { .o = ATOMIC_INIT(1) };
 
        set_page_private(page, u.v);
@@ -147,49 +143,36 @@ static inline void z_erofs_onlinepage_init(struct page *page)
        SetPagePrivate(page);
 }
 
-static inline void z_erofs_onlinepage_fixup(struct page *page,
-       uintptr_t index, bool down)
+static inline void z_erofs_onlinepage_split(struct page *page)
 {
-       union z_erofs_onlinepage_converter u = { .v = &page_private(page) };
-       int orig, orig_index, val;
-
-repeat:
-       orig = atomic_read(u.o);
-       orig_index = orig >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
-       if (orig_index) {
-               if (!index)
-                       return;
+       atomic_inc((atomic_t *)&page->private);
+}
 
-               DBG_BUGON(orig_index != index);
-       }
+static inline void z_erofs_page_mark_eio(struct page *page)
+{
+       int orig;
 
-       val = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
-               ((orig & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
-       if (atomic_cmpxchg(u.o, orig, val) != orig)
-               goto repeat;
+       do {
+               orig = atomic_read((atomic_t *)&page->private);
+       } while (atomic_cmpxchg((atomic_t *)&page->private, orig,
+                               orig | Z_EROFS_PAGE_EIO) != orig);
 }
 
 static inline void z_erofs_onlinepage_endio(struct page *page)
 {
-       union z_erofs_onlinepage_converter u;
        unsigned int v;
 
        DBG_BUGON(!PagePrivate(page));
-       u.v = &page_private(page);
-
-       v = atomic_dec_return(u.o);
-       if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) {
+       v = atomic_dec_return((atomic_t *)&page->private);
+       if (!(v & ~Z_EROFS_PAGE_EIO)) {
                set_page_private(page, 0);
                ClearPagePrivate(page);
-               if (!PageError(page))
+               if (!(v & Z_EROFS_PAGE_EIO))
                        SetPageUptodate(page);
                unlock_page(page);
        }
-       erofs_dbg("%s, page %p value %x", __func__, page, atomic_read(u.o));
 }
 
-#define Z_EROFS_VMAP_ONSTACK_PAGES     \
-       min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
-#define Z_EROFS_VMAP_GLOBAL_PAGES      2048
+#define Z_EROFS_ONSTACK_PAGES          32
 
 #endif