^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) International Business Machines Corp., 2000-2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * jfs_dtree.c: directory B+-tree manager
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * B+-tree with variable length key directory:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * each directory page is structured as an array of 32-byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * directory entry slots initialized as a freelist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * to avoid search/compaction of free space at insertion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * when an entry is inserted, a number of slots are allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * from the freelist as required to store variable length data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * of the entry; when the entry is deleted, slots of the entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * are returned to freelist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * leaf entry stores full name as key and file serial number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * (aka inode number) as data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * internal/router entry stores sufffix compressed name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * as key and simple extent descriptor as data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * each directory page maintains a sorted entry index table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * which stores the start slot index of sorted entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * to allow binary search on the table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * directory starts as a root/leaf page in on-disk inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * inline data area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * when it becomes full, it starts a leaf of a external extent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * of length of 1 block. each time the first leaf becomes full,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * it is extended rather than split (its size is doubled),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * until its length becoms 4 KBytes, from then the extent is split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * with new 4 Kbyte extent when it becomes full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * to reduce external fragmentation of small directories.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * blah, blah, blah, for linear scan of directory in pieces by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * readdir().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * case-insensitive directory file system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * names are stored in case-sensitive way in leaf entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * but stored, searched and compared in case-insensitive (uppercase) order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * (i.e., both search key and entry key are folded for search/compare):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * (note that case-sensitive order is BROKEN in storage, e.g.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * sensitive: Ad, aB, aC, aD -> insensitive: aB, aC, aD, Ad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * entries which folds to the same key makes up a equivalent class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * whose members are stored as contiguous cluster (may cross page boundary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * but whose order is arbitrary and acts as duplicate, e.g.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * abc, Abc, aBc, abC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * once match is found at leaf, requires scan forward/backward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * either for, in case-insensitive search, duplicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * or for, in case-sensitive search, for exact match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * router entry must be created/stored in case-insensitive way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * in internal entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * (right most key of left page and left most key of right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * are folded, and its suffix compression is propagated as router
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * key in parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * (e.g., if split occurs <abc> and <aBd>, <ABD> trather than <aB>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * should be made the router key for the split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * case-insensitive search:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * fold search key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * case-insensitive search of B-tree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * for internal entry, router key is already folded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * for leaf entry, fold the entry key before comparison.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * if (leaf entry case-insensitive match found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * if (next entry satisfies case-insensitive match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * return EDUPLICATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * if (prev entry satisfies case-insensitive match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * return EDUPLICATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * return match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * return no match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * serialization:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * target directory inode lock is being held on entry/exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * of all main directory service routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * log based recovery:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #include <linux/quotaops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #include "jfs_incore.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #include "jfs_superblock.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #include "jfs_filsys.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #include "jfs_metapage.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #include "jfs_dmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #include "jfs_unicode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #include "jfs_debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* dtree split parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct dtsplit {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) s16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) s16 nslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct component_name *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ddata_t *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct pxdlist *pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define DT_PAGE(IP, MP) BT_PAGE(IP, MP, dtpage_t, i_dtroot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* get page buffer for specified block address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define DT_GETPAGE(IP, BN, MP, SIZE, P, RC) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!(RC)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (((P)->header.nextindex > \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) (((BN) == 0) ? DTROOTMAXSLOT : (P)->header.maxslot)) || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT))) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) BT_PUTPAGE(MP); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) jfs_error((IP)->i_sb, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) "DT_GETPAGE: dtree page corrupt\n"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) MP = NULL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) RC = -EIO; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* for consistency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define DT_PUTPAGE(MP) BT_PUTPAGE(MP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define DT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) BT_GETSEARCH(IP, LEAF, BN, MP, dtpage_t, P, INDEX, i_dtroot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * forward references
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int dtSplitUp(tid_t tid, struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct dtsplit * split, struct btstack * btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct metapage ** rmpp, dtpage_t ** rpp, pxd_t * rxdp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int dtExtendPage(tid_t tid, struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct dtsplit * split, struct btstack * btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int dtSplitRoot(tid_t tid, struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct dtsplit * split, struct metapage ** rmpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int dtDeleteUp(tid_t tid, struct inode *ip, struct metapage * fmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dtpage_t * fp, struct btstack * btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int dtRelink(tid_t tid, struct inode *ip, dtpage_t * p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int dtReadFirst(struct inode *ip, struct btstack * btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int dtReadNext(struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) loff_t * offset, struct btstack * btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int dtCompare(struct component_name * key, dtpage_t * p, int si);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int ciCompare(struct component_name * key, dtpage_t * p, int si,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static void dtGetKey(dtpage_t * p, int i, struct component_name * key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int ri, struct component_name * key, int flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ddata_t * data, struct dt_lock **);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void dtMoveEntry(dtpage_t * sp, int si, dtpage_t * dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct dt_lock ** sdtlock, struct dt_lock ** ddtlock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int do_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void dtDeleteEntry(dtpage_t * p, int fi, struct dt_lock ** dtlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void dtTruncateEntry(dtpage_t * p, int ti, struct dt_lock ** dtlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void dtLinelockFreelist(dtpage_t * p, int m, struct dt_lock ** dtlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define ciToUpper(c) UniStrupr((c)->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * read_index_page()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Reads a page of a directory's index table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * Having metadata mapped into the directory inode's address space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * presents a multitude of problems. We avoid this by mapping to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * the absolute address space outside of the *_metapage routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static struct metapage *read_index_page(struct inode *inode, s64 blkno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) s64 xaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int xflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) s32 xlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (rc || (xaddr == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return read_metapage(inode, xaddr, PSIZE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * get_index_page()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Same as get_index_page(), but get's a new page without reading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static struct metapage *get_index_page(struct inode *inode, s64 blkno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) s64 xaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int xflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) s32 xlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (rc || (xaddr == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return get_metapage(inode, xaddr, PSIZE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * find_index()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * Returns dtree page containing directory table entry for specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * index and pointer to its entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * mp must be released by caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static struct dir_table_slot *find_index(struct inode *ip, u32 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct metapage ** mp, s64 *lblock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct jfs_inode_info *jfs_ip = JFS_IP(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) s64 blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) s64 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int page_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct dir_table_slot *slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int maxWarnings = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (index < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (maxWarnings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) jfs_warn("find_entry called with index = %d", index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) maxWarnings--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (index >= jfs_ip->next_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) jfs_warn("find_entry called with index >= next_index");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (jfs_dirtable_inline(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Inline directory table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) slot = &jfs_ip->i_dirtable[index - 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) offset = (index - 2) * sizeof(struct dir_table_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) page_offset = offset & (PSIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) blkno = ((offset + 1) >> L2PSIZE) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) JFS_SBI(ip->i_sb)->l2nbperpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (*mp && (*lblock != blkno)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) release_metapage(*mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) *mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (!(*mp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *lblock = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *mp = read_index_page(ip, blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!(*mp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) jfs_err("free_index: error reading directory table");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) slot =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) (struct dir_table_slot *) ((char *) (*mp)->data +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) page_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static inline void lock_index(tid_t tid, struct inode *ip, struct metapage * mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct linelock *llck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) tlck = txLock(tid, ip, mp, tlckDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) llck = (struct linelock *) tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (llck->index >= llck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) llck = txLinelock(llck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) lv = &llck->lv[llck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * Linelock slot size is twice the size of directory table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * slot size. 512 entries per page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) lv->offset = ((index - 2) & 511) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) llck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * add_index()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * Adds an entry to the directory index table. This is used to provide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * each directory entry with a persistent index in which to resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * directory traversals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct super_block *sb = ip->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct jfs_sb_info *sbi = JFS_SBI(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct jfs_inode_info *jfs_ip = JFS_IP(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u64 blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct dir_table_slot *dirtab_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct linelock *llck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) s64 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) uint page_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) s64 xaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ASSERT(DO_INDEX(ip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (jfs_ip->next_index < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) jfs_warn("add_index: next_index = %d. Resetting!",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) jfs_ip->next_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) jfs_ip->next_index = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) index = jfs_ip->next_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (index <= MAX_INLINE_DIRTABLE_ENTRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * i_size reflects size of index table, or 8 bytes per entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ip->i_size = (loff_t) (index - 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * dir table fits inline within inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dirtab_slot = &jfs_ip->i_dirtable[index-2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) dirtab_slot->flag = DIR_INDEX_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) dirtab_slot->slot = slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) DTSaddress(dirtab_slot, bn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) set_cflag(COMMIT_Dirtable, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (index == (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct dir_table_slot temp_table[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * It's time to move the inline table to an external
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * page and begin to build the xtree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (dquot_alloc_block(ip, sbi->nbperpage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto clean_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) dquot_free_block(ip, sbi->nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) goto clean_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Save the table, we're going to overwrite it with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * xtree root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) memcpy(temp_table, &jfs_ip->i_dirtable, sizeof(temp_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * Initialize empty x-tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) xtInitRoot(tid, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * Add the first block to the xtree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (xtInsert(tid, ip, 0, 0, sbi->nbperpage, &xaddr, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* This really shouldn't fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) jfs_warn("add_index: xtInsert failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) memcpy(&jfs_ip->i_dirtable, temp_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) sizeof (temp_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) dbFree(ip, xaddr, sbi->nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) dquot_free_block(ip, sbi->nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto clean_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) ip->i_size = PSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) mp = get_index_page(ip, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) jfs_err("add_index: get_metapage failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) xtTruncate(tid, ip, 0, COMMIT_PWMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) memcpy(&jfs_ip->i_dirtable, temp_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) sizeof (temp_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) goto clean_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) tlck = txLock(tid, ip, mp, tlckDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) llck = (struct linelock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ASSERT(llck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) lv = &llck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) lv->length = 6; /* tlckDATA slot size is 16 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) llck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) memcpy(mp->data, temp_table, sizeof(temp_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * Logging is now directed by xtree tlocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) clear_cflag(COMMIT_Dirtable, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) offset = (index - 2) * sizeof(struct dir_table_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) page_offset = offset & (PSIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) blkno = ((offset + 1) >> L2PSIZE) << sbi->l2nbperpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (page_offset == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * This will be the beginning of a new page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) xaddr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (xtInsert(tid, ip, 0, blkno, sbi->nbperpage, &xaddr, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) jfs_warn("add_index: xtInsert failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) goto clean_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ip->i_size += PSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if ((mp = get_index_page(ip, blkno)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) memset(mp->data, 0, PSIZE); /* Just looks better */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) xtTruncate(tid, ip, offset, COMMIT_PWMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) mp = read_index_page(ip, blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (!mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) jfs_err("add_index: get/read_metapage failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) goto clean_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) lock_index(tid, ip, mp, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dirtab_slot =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) (struct dir_table_slot *) ((char *) mp->data + page_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) dirtab_slot->flag = DIR_INDEX_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) dirtab_slot->slot = slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) DTSaddress(dirtab_slot, bn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) clean_up:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) jfs_ip->next_index--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * free_index()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * Marks an entry to the directory index table as free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static void free_index(tid_t tid, struct inode *ip, u32 index, u32 next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct dir_table_slot *dirtab_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) s64 lblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct metapage *mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) dirtab_slot = find_index(ip, index, &mp, &lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (!dirtab_slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dirtab_slot->flag = DIR_INDEX_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) dirtab_slot->slot = dirtab_slot->addr1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) dirtab_slot->addr2 = cpu_to_le32(next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) lock_index(tid, ip, mp, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) set_cflag(COMMIT_Dirtable, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * modify_index()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * Changes an entry in the directory index table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static void modify_index(tid_t tid, struct inode *ip, u32 index, s64 bn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int slot, struct metapage ** mp, s64 *lblock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct dir_table_slot *dirtab_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) dirtab_slot = find_index(ip, index, mp, lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (!dirtab_slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) DTSaddress(dirtab_slot, bn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) dirtab_slot->slot = slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (*mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) lock_index(tid, ip, *mp, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) mark_metapage_dirty(*mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) set_cflag(COMMIT_Dirtable, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * read_index()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * reads a directory table slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static int read_index(struct inode *ip, u32 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct dir_table_slot * dirtab_slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) s64 lblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct metapage *mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct dir_table_slot *slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) slot = find_index(ip, index, &mp, &lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (!slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) memcpy(dirtab_slot, slot, sizeof(struct dir_table_slot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * dtSearch()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * Search for the entry with specified key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * return: 0 - search result on stack, leaf page pinned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * errno - I/O error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct btstack * btstack, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int cmp = 1; /* init for empty page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) int base, index, lim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct btframe *btsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) pxd_t *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) int psize = 288; /* initial in-line directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ino_t inumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct component_name ciKey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct super_block *sb = ip->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ciKey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!ciKey.name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) goto dtSearch_Exit2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /* uppercase search key for c-i directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) UniStrcpy(ciKey.name, key->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ciKey.namlen = key->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* only uppercase if case-insensitive support is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if ((JFS_SBI(sb)->mntflag & JFS_OS2) == JFS_OS2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ciToUpper(&ciKey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) BT_CLR(btstack); /* reset stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* init level count for max pages to split */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) btstack->nsplit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * search down tree from root:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * internal page, child page Pi contains entry with k, Ki <= K < Kj.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * if entry with search key K is not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * internal page search find the entry with largest key Ki
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * less than K which point to the child page to search;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * leaf page search find the entry with smallest key Kj
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * greater than K so that the returned index is the position of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * the entry to be shifted right for insertion of new entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * for empty tree, search key is greater than any key of the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * by convention, root bn = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) for (bn = 0;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* get/pin the page to search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) DT_GETPAGE(ip, bn, mp, psize, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) goto dtSearch_Exit1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /* get sorted entry table of the page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * binary search with search key K on the current page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) for (base = 0, lim = p->header.nextindex; lim; lim >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) index = base + (lim >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* uppercase leaf name to compare */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) cmp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ciCompare(&ciKey, p, stbl[index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) JFS_SBI(sb)->mntflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* router key is in uppercase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) cmp = dtCompare(&ciKey, p, stbl[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (cmp == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * search hit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /* search hit - leaf page:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * return the entry found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) inumber = le32_to_cpu(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ((struct ldtentry *) & p->slot[stbl[index]])->inumber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * search for JFS_LOOKUP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (flag == JFS_LOOKUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) *data = inumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * search for JFS_CREATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (flag == JFS_CREATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) *data = inumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) rc = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * search for JFS_REMOVE or JFS_RENAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if ((flag == JFS_REMOVE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) flag == JFS_RENAME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) *data != inumber) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) rc = -ESTALE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * JFS_REMOVE|JFS_FINDDIR|JFS_RENAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /* save search result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) *data = inumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) btsp = btstack->top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) btsp->bn = bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) btsp->index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) btsp->mp = mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) goto dtSearch_Exit1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* search hit - internal page:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * descend/search its child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) goto getChild;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (cmp > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) base = index + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) --lim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * search miss
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * base is the smallest index with key (Kj) greater than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * search key (K) and may be zero or (maxindex + 1) index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * search miss - leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * return location of entry (base) where new entry with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * search key K is to be inserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * search for JFS_LOOKUP, JFS_REMOVE, or JFS_RENAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (flag == JFS_LOOKUP || flag == JFS_REMOVE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) flag == JFS_RENAME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) rc = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) * search for JFS_CREATE|JFS_FINDDIR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * save search result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) *data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) btsp = btstack->top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) btsp->bn = bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) btsp->index = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) btsp->mp = mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) goto dtSearch_Exit1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * search miss - internal page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * if base is non-zero, decrement base by one to get the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * entry of the child page to search.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) index = base ? base - 1 : base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * go down to child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) getChild:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /* update max. number of pages to split */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (BT_STACK_FULL(btstack)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* Something's corrupted, mark filesystem dirty so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * chkdsk will fix it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) jfs_error(sb, "stack overrun!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) BT_STACK_DUMP(btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) btstack->nsplit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* push (bn, index) of the parent page/entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) BT_PUSH(btstack, bn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) /* get the child page block number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) pxd = (pxd_t *) & p->slot[stbl[index]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) bn = addressPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) psize = lengthPXD(pxd) << JFS_SBI(ip->i_sb)->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* unpin the parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) dtSearch_Exit1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) kfree(ciKey.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dtSearch_Exit2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * dtInsert()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * function: insert an entry to directory tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * return: 0 - success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * errno - failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) int dtInsert(tid_t tid, struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) struct component_name * name, ino_t * fsn, struct btstack * btstack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct metapage *mp; /* meta-page buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) dtpage_t *p; /* base B+-tree index page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) struct dtsplit split; /* split information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) ddata_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * retrieve search result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * dtSearch() returns (leaf page pinned, index at which to insert).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * n.b. dtSearch() may return index of (maxindex + 1) of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * the full page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * insert entry for new key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (DO_INDEX(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (JFS_IP(ip)->next_index == DIREND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return -EMLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) n = NDTLEAF(name->namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) data.leaf.tid = tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) data.leaf.ip = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) n = NDTLEAF_LEGACY(name->namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) data.leaf.ip = NULL; /* signifies legacy directory format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) data.leaf.ino = *fsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * leaf page does not have enough room for new entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * extend/split the leaf page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * dtSplitUp() will insert the entry and unpin the leaf page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (n > p->header.freecnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) split.mp = mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) split.index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) split.nslot = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) split.key = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) split.data = &data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) rc = dtSplitUp(tid, ip, &split, btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * leaf page does have enough room for new entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * insert the new data entry into the leaf page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) BT_MARK_DIRTY(mp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * acquire a transaction lock on the leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) dtInsertEntry(p, index, name, &data, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* linelock stbl of non-root leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (!(p->header.flag & BT_ROOT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) n = index >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) lv->offset = p->header.stblindex + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) lv->length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ((p->header.nextindex - 1) >> L2DTSLOTSIZE) - n + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /* unpin the leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * dtSplitUp()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * function: propagate insertion bottom up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * return: 0 - success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * errno - failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * leaf page unpinned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) static int dtSplitUp(tid_t tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct inode *ip, struct dtsplit * split, struct btstack * btstack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct metapage *smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) dtpage_t *sp; /* split page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) struct metapage *rmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) dtpage_t *rp; /* new right page split from sp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) pxd_t rpxd; /* new right page extent descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) struct metapage *lmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) dtpage_t *lp; /* left child page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) int skip; /* index of entry of insertion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct btframe *parent; /* parent page entry on traverse stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) s64 xaddr, nxaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) int xlen, xsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct pxdlist pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) pxd_t *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct component_name key = { 0, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ddata_t *data = split->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) int quota_allocation = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* get split page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) smp = split->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) sp = DT_PAGE(ip, smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) key.name = kmalloc_array(JFS_NAME_MAX + 2, sizeof(wchar_t), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (!key.name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) goto dtSplitUp_Exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * split leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * The split routines insert the new entry, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * acquire txLock as appropriate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * split root leaf page:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (sp->header.flag & BT_ROOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * allocate a single extent child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) xlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) n = sbi->bsize >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) n -= (n + 31) >> L2DTSLOTSIZE; /* stbl size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) n -= DTROOTMAXSLOT - sp->header.freecnt; /* header + entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (n <= split->nslot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) xlen++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) goto freeKeyName;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) pxdlist.maxnpxd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) pxdlist.npxd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) pxd = &pxdlist.pxd[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) PXDaddress(pxd, xaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) PXDlength(pxd, xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) split->pxdlist = &pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) rc = dtSplitRoot(tid, ip, split, &rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) dbFree(ip, xaddr, xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) DT_PUTPAGE(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (!DO_INDEX(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) ip->i_size = xlen << sbi->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) goto freeKeyName;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * extend first leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * extend the 1st extent if less than buffer page size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * (dtExtendPage() reurns leaf page unpinned)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) pxd = &sp->header.self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) xlen = lengthPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) xsize = xlen << sbi->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (xsize < PSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) xaddr = addressPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) n = xsize >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) n -= (n + 31) >> L2DTSLOTSIZE; /* stbl size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if ((n + sp->header.freecnt) <= split->nslot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) n = xlen + (xlen << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) n = xlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /* Allocate blocks to quota. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) rc = dquot_alloc_block(ip, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) goto extendOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) quota_allocation += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) (s64) n, &nxaddr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) goto extendOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) pxdlist.maxnpxd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) pxdlist.npxd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) pxd = &pxdlist.pxd[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) PXDaddress(pxd, nxaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) PXDlength(pxd, xlen + n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) split->pxdlist = &pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if ((rc = dtExtendPage(tid, ip, split, btstack))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) nxaddr = addressPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (xaddr != nxaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /* free relocated extent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) xlen = lengthPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) dbFree(ip, nxaddr, (s64) xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /* free extended delta */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) xlen = lengthPXD(pxd) - n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) xaddr = addressPXD(pxd) + xlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) dbFree(ip, xaddr, (s64) n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) } else if (!DO_INDEX(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ip->i_size = lengthPXD(pxd) << sbi->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) extendOut:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) goto freeKeyName;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * split leaf page <sp> into <sp> and a new right page <rp>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * return <rp> pinned and its extent descriptor <rpxd>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * allocate new directory page extent and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * new index page(s) to cover page split(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * allocation hint: ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) n = btstack->nsplit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) pxdlist.maxnpxd = pxdlist.npxd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) xlen = sbi->nbperpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) for (pxd = pxdlist.pxd; n > 0; n--, pxd++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) PXDaddress(pxd, xaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) PXDlength(pxd, xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) pxdlist.maxnpxd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* undo allocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) goto splitOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) split->pxdlist = &pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if ((rc = dtSplitPage(tid, ip, split, &rmp, &rp, &rpxd))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /* undo allocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) goto splitOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (!DO_INDEX(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) ip->i_size += PSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) * propagate up the router entry for the leaf page just split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * insert a router entry for the new page into the parent page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * propagate the insert/split up the tree by walking back the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * of (bn of parent page, index of child page entry in parent page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) * that were traversed during the search for the page that split.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * the propagation of insert/split up the tree stops if the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * splits or the page inserted into doesn't have to split to hold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * the new entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * the parent entry for the split page remains the same, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * a new entry is inserted at its right with the first key and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * block number of the new right page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * There are a maximum of 4 pages pinned at any time:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * two children, left parent and right parent (when the parent splits).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * keep the child pages pinned while working on the parent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * make sure that all pins are released at exit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) while ((parent = BT_POP(btstack)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /* parent page specified by stack frame <parent> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /* keep current child pages (<lp>, <rp>) pinned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) lmp = smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) lp = sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * insert router entry in parent for new right child page <rp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /* get the parent page <sp> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) DT_GETPAGE(ip, parent->bn, smp, PSIZE, sp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) DT_PUTPAGE(lmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) DT_PUTPAGE(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) goto splitOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) * The new key entry goes ONE AFTER the index of parent entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) * because the split was to the right.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) skip = parent->index + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) * compute the key for the router entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * key suffix compression:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * for internal pages that have leaf pages as children,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * retain only what's needed to distinguish between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * the new entry and the entry on the page to its left.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) * If the keys compare equal, retain the entire key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * note that compression is performed only at computing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * router key at the lowest internal level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * further compression of the key between pairs of higher
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * level internal pages loses too much information and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * the search may fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) * (e.g., two adjacent leaf pages of {a, ..., x} {xx, ...,}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) * results in two adjacent parent entries (a)(xx).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * if split occurs between these two entries, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * if compression is applied, the router key of parent entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * of right page (x) will divert search for x into right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) * subtree and miss x in the left subtree.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * the entire key must be retained for the next-to-leftmost
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) * internal key at any level of the tree, or search may fail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * (e.g., ?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) switch (rp->header.flag & BT_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) case BT_LEAF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * compute the length of prefix for suffix compression
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * between last entry of left page and first entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * of right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if ((sp->header.flag & BT_ROOT && skip > 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) sp->header.prev != 0 || skip > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) /* compute uppercase router prefix key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) rc = ciGetLeafPrefixKey(lp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) lp->header.nextindex-1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) rp, 0, &key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) sbi->mntflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) DT_PUTPAGE(lmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) DT_PUTPAGE(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) goto splitOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) /* next to leftmost entry of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) lowest internal level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) /* compute uppercase router key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) dtGetKey(rp, 0, &key, sbi->mntflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) key.name[key.namlen] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if ((sbi->mntflag & JFS_OS2) == JFS_OS2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) ciToUpper(&key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) n = NDTINTERNAL(key.namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) case BT_INTERNAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dtGetKey(rp, 0, &key, sbi->mntflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) n = NDTINTERNAL(key.namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) jfs_err("dtSplitUp(): UFO!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /* unpin left child page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) DT_PUTPAGE(lmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) * compute the data for the router entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) data->xd = rpxd; /* child page xd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) * parent page is full - split the parent page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (n > sp->header.freecnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) /* init for parent page split */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) split->mp = smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) split->index = skip; /* index at insert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) split->nslot = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) split->key = &key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /* split->data = data; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /* unpin right child page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) DT_PUTPAGE(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* The split routines insert the new entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * acquire txLock as appropriate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * return <rp> pinned and its block number <rbn>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) rc = (sp->header.flag & BT_ROOT) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) dtSplitRoot(tid, ip, split, &rmp) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) dtSplitPage(tid, ip, split, &rmp, &rp, &rpxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) goto splitOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) /* smp and rmp are pinned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * parent page is not full - insert router entry in parent page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) BT_MARK_DIRTY(smp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) * acquire a transaction lock on the parent page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) tlck = txLock(tid, ip, smp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) /* linelock stbl of non-root parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (!(sp->header.flag & BT_ROOT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) lv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) n = skip >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) lv->offset = sp->header.stblindex + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) lv->length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) ((sp->header.nextindex -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 1) >> L2DTSLOTSIZE) - n + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) dtInsertEntry(sp, skip, &key, data, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) /* exit propagate up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) /* unpin current split and its right page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) DT_PUTPAGE(smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) DT_PUTPAGE(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * free remaining extents allocated for split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) splitOut:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) n = pxdlist.npxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) pxd = &pxdlist.pxd[n];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) for (; n < pxdlist.maxnpxd; n++, pxd++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) dbFree(ip, addressPXD(pxd), (s64) lengthPXD(pxd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) freeKeyName:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) kfree(key.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) /* Rollback quota allocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (rc && quota_allocation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) dquot_free_block(ip, quota_allocation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) dtSplitUp_Exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) * dtSplitPage()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) * function: Split a non-root page of a btree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) * return: 0 - success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) * errno - failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) * return split and new page pinned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) struct metapage ** rmpp, dtpage_t ** rpp, pxd_t * rpxdp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) struct metapage *smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) dtpage_t *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) struct metapage *rmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) dtpage_t *rp; /* new right page allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) s64 rbn; /* new right page block number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) s64 nextbn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) struct pxdlist *pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) pxd_t *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) int skip, nextindex, half, left, nxt, off, si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) struct ldtentry *ldtentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) struct idtentry *idtentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) u8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) struct dtslot *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) int fsi, stblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct dt_lock *sdtlck, *rdtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) struct lv *slv, *rlv, *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) /* get split page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) smp = split->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) sp = DT_PAGE(ip, smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) * allocate the new right page for the split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) pxdlist = split->pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) pxd = &pxdlist->pxd[pxdlist->npxd];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) pxdlist->npxd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) rbn = addressPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) rmp = get_metapage(ip, rbn, PSIZE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (rmp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) /* Allocate blocks to quota. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) rc = dquot_alloc_block(ip, lengthPXD(pxd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) release_metapage(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) BT_MARK_DIRTY(rmp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * acquire a transaction lock on the new right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) tlck = txLock(tid, ip, rmp, tlckDTREE | tlckNEW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) rdtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) rp = (dtpage_t *) rmp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) *rpp = rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) rp->header.self = *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) BT_MARK_DIRTY(smp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * acquire a transaction lock on the split page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * action:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) tlck = txLock(tid, ip, smp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) sdtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) /* linelock header of split page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) ASSERT(sdtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) slv = & sdtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) slv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) slv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) sdtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * initialize/update sibling pointers between sp and rp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) nextbn = le64_to_cpu(sp->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) rp->header.next = cpu_to_le64(nextbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) rp->header.prev = cpu_to_le64(addressPXD(&sp->header.self));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) sp->header.next = cpu_to_le64(rbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) * initialize new right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) rp->header.flag = sp->header.flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) /* compute sorted entry table at start of extent data area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) rp->header.nextindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) rp->header.stblindex = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) n = PSIZE >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) rp->header.maxslot = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) stblsize = (n + 31) >> L2DTSLOTSIZE; /* in unit of slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) /* init freelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) fsi = rp->header.stblindex + stblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) rp->header.freelist = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) rp->header.freecnt = rp->header.maxslot - fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * sequential append at tail: append without split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) * If splitting the last page on a level because of appending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * a entry to it (skip is maxentry), it's likely that the access is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * sequential. Adding an empty page on the side of the level is less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * work and can push the fill factor much higher than normal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * If we're wrong it's no big deal, we'll just do the split the right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) * way next time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) * (It may look like it's equally easy to do a similar hack for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * reverse sorted data, that is, split the tree left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) * but it's not. Be my guest.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) if (nextbn == 0 && split->index == sp->header.nextindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) /* linelock header + stbl (first slot) of new page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) rlv = & rdtlck->lv[rdtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) rlv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) rlv->length = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) rdtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * initialize freelist of new right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) f = &rp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) for (fsi++; fsi < rp->header.maxslot; f++, fsi++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) f->next = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) f->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) /* insert entry at the first entry of the new right page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) dtInsertEntry(rp, 0, split->key, split->data, &rdtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) * non-sequential insert (at possibly middle page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) * update prev pointer of previous right sibling page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (nextbn != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) DT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) discard_metapage(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) BT_MARK_DIRTY(mp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) * acquire a transaction lock on the next page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) tlck = txLock(tid, ip, mp, tlckDTREE | tlckRELINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) jfs_info("dtSplitPage: tlck = 0x%p, ip = 0x%p, mp=0x%p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) tlck, ip, mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) /* linelock header of previous right sibling page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) p->header.prev = cpu_to_le64(rbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) * split the data between the split and right pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) skip = split->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) half = (PSIZE >> L2DTSLOTSIZE) >> 1; /* swag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) * compute fill factor for split pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) * <nxt> traces the next entry to move to rp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) * <off> traces the next entry to stay in sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) stbl = (u8 *) & sp->slot[sp->header.stblindex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) nextindex = sp->header.nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) for (nxt = off = 0; nxt < nextindex; ++off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (off == skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) /* check for fill factor with new entry size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) n = split->nslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) si = stbl[nxt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) switch (sp->header.flag & BT_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) case BT_LEAF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) ldtentry = (struct ldtentry *) & sp->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (DO_INDEX(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) n = NDTLEAF(ldtentry->namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) n = NDTLEAF_LEGACY(ldtentry->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) case BT_INTERNAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) idtentry = (struct idtentry *) & sp->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) n = NDTINTERNAL(idtentry->namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) ++nxt; /* advance to next entry to move in sp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) left += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) if (left >= half)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) /* <nxt> poins to the 1st entry to move */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * move entries to right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) * dtMoveEntry() initializes rp and reserves entry for insertion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) * split page moved out entries are linelocked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * new/right page moved in entries are linelocked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) /* linelock header + stbl of new right page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) rlv = & rdtlck->lv[rdtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) rlv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) rlv->length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) rdtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) dtMoveEntry(sp, nxt, rp, &sdtlck, &rdtlck, DO_INDEX(ip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) sp->header.nextindex = nxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) * finalize freelist of new right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) fsi = rp->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) f = &rp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) for (fsi++; fsi < rp->header.maxslot; f++, fsi++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) f->next = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) f->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) * Update directory index table for entries now in right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) s64 lblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) stbl = DT_GETSTBL(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) for (n = 0; n < rp->header.nextindex; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) ldtentry = (struct ldtentry *) & rp->slot[stbl[n]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) modify_index(tid, ip, le32_to_cpu(ldtentry->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) rbn, n, &mp, &lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) if (mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) * the skipped index was on the left page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) if (skip <= off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) /* insert the new entry in the split page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) dtInsertEntry(sp, skip, split->key, split->data, &sdtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) /* linelock stbl of split page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (sdtlck->index >= sdtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) sdtlck = (struct dt_lock *) txLinelock(sdtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) slv = & sdtlck->lv[sdtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) n = skip >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) slv->offset = sp->header.stblindex + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) slv->length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) ((sp->header.nextindex - 1) >> L2DTSLOTSIZE) - n + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) sdtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) * the skipped index was on the right page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) /* adjust the skip index to reflect the new position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) skip -= nxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) /* insert the new entry in the right page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) dtInsertEntry(rp, skip, split->key, split->data, &rdtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) *rmpp = rmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) *rpxdp = *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) * dtExtendPage()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) * function: extend 1st/only directory leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) * return: 0 - success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) * errno - failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) * return extended page pinned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) static int dtExtendPage(tid_t tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) struct inode *ip, struct dtsplit * split, struct btstack * btstack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) struct super_block *sb = ip->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) struct metapage *smp, *pmp, *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) dtpage_t *sp, *pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) struct pxdlist *pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) pxd_t *pxd, *tpxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) int xlen, xsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) int newstblindex, newstblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) int oldstblindex, oldstblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) int fsi, last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) struct dtslot *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) struct btframe *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) s64 xaddr, txaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) struct pxd_lock *pxdlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) uint type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) struct ldtentry *ldtentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) u8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) /* get page to extend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) smp = split->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) sp = DT_PAGE(ip, smp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* get parent/root page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) parent = BT_POP(btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) DT_GETPAGE(ip, parent->bn, pmp, PSIZE, pp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) * extend the extent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) pxdlist = split->pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) pxd = &pxdlist->pxd[pxdlist->npxd];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) pxdlist->npxd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) xaddr = addressPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) tpxd = &sp->header.self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) txaddr = addressPXD(tpxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) /* in-place extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (xaddr == txaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) type = tlckEXTEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) /* relocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) type = tlckNEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) /* save moved extent descriptor for later free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) tlck = txMaplock(tid, ip, tlckDTREE | tlckRELOCATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) pxdlock = (struct pxd_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) pxdlock->flag = mlckFREEPXD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) pxdlock->pxd = sp->header.self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) pxdlock->index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) * Update directory index table to reflect new page address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (DO_INDEX(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) s64 lblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) stbl = DT_GETSTBL(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) for (n = 0; n < sp->header.nextindex; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) ldtentry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) (struct ldtentry *) & sp->slot[stbl[n]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) modify_index(tid, ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) le32_to_cpu(ldtentry->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) xaddr, n, &mp, &lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) if (mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) * extend the page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) sp->header.self = *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) jfs_info("dtExtendPage: ip:0x%p smp:0x%p sp:0x%p", ip, smp, sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) BT_MARK_DIRTY(smp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) * acquire a transaction lock on the extended/leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) tlck = txLock(tid, ip, smp, tlckDTREE | type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) /* update buffer extent descriptor of extended page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) xlen = lengthPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) xsize = xlen << JFS_SBI(sb)->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) * copy old stbl to new stbl at start of extended area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) oldstblindex = sp->header.stblindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) oldstblsize = (sp->header.maxslot + 31) >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) newstblindex = sp->header.maxslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) n = xsize >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) newstblsize = (n + 31) >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) memcpy(&sp->slot[newstblindex], &sp->slot[oldstblindex],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) sp->header.nextindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) * in-line extension: linelock old area of extended page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) if (type == tlckEXTEND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) lv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) /* linelock new stbl of extended page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) lv->offset = newstblindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) lv->length = newstblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) * relocation: linelock whole relocated area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) lv->length = sp->header.maxslot + newstblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) sp->header.maxslot = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) sp->header.stblindex = newstblindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) /* sp->header.nextindex remains the same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) * add old stbl region at head of freelist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) fsi = oldstblindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) f = &sp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) last = sp->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) for (n = 0; n < oldstblsize; n++, fsi++, f++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) f->next = last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) last = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) sp->header.freelist = last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) sp->header.freecnt += oldstblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) * append free region of newly extended area at tail of freelist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) /* init free region of newly extended area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) fsi = n = newstblindex + newstblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) f = &sp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) for (fsi++; fsi < sp->header.maxslot; f++, fsi++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) f->next = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) f->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) /* append new free region at tail of old freelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) fsi = sp->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) if (fsi == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) sp->header.freelist = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) f = &sp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) fsi = f->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) } while (fsi != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) f->next = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) sp->header.freecnt += sp->header.maxslot - n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) * insert the new entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) dtInsertEntry(sp, split->index, split->key, split->data, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) BT_MARK_DIRTY(pmp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) * linelock any freeslots residing in old extent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if (type == tlckEXTEND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) n = sp->header.maxslot >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) if (sp->header.freelist < n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) dtLinelockFreelist(sp, n, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) * update parent entry on the parent/root page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) * acquire a transaction lock on the parent/root page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) /* linelock parent entry - 1st slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) lv->offset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) /* update the parent pxd for page extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) tpxd = (pxd_t *) & pp->slot[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) *tpxd = *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) DT_PUTPAGE(pmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) * dtSplitRoot()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) * function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) * split the full root page into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) * original/root/split page and new right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) * i.e., root remains fixed in tree anchor (inode) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) * the root is copied to a single new right child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) * since root page << non-root page, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) * the split root page contains a single entry for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) * new right child page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) * return: 0 - success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) * errno - failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) * return new page pinned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) static int dtSplitRoot(tid_t tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) struct inode *ip, struct dtsplit * split, struct metapage ** rmpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) struct super_block *sb = ip->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) struct metapage *smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) dtroot_t *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) struct metapage *rmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) dtpage_t *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) s64 rbn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) int xlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) int xsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) struct dtslot *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) int fsi, stblsize, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) struct idtentry *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) pxd_t *ppxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) struct pxdlist *pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) pxd_t *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) /* get split root page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) smp = split->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) sp = &JFS_IP(ip)->i_dtroot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) * allocate/initialize a single (right) child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) * N.B. at first split, a one (or two) block to fit new entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) * is allocated; at subsequent split, a full page is allocated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) pxdlist = split->pxdlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) pxd = &pxdlist->pxd[pxdlist->npxd];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) pxdlist->npxd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) rbn = addressPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) xlen = lengthPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) xsize = xlen << JFS_SBI(sb)->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) rmp = get_metapage(ip, rbn, xsize, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) if (!rmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) rp = rmp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) /* Allocate blocks to quota. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) rc = dquot_alloc_block(ip, lengthPXD(pxd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) release_metapage(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) BT_MARK_DIRTY(rmp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) * acquire a transaction lock on the new right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) tlck = txLock(tid, ip, rmp, tlckDTREE | tlckNEW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) rp->header.flag =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) (sp->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) rp->header.self = *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) /* initialize sibling pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) rp->header.next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) rp->header.prev = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) * move in-line root page into new right page extent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) /* linelock header + copied entries + new stbl (1st slot) in new page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) lv->length = 10; /* 1 + 8 + 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) n = xsize >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) rp->header.maxslot = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) stblsize = (n + 31) >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) /* copy old stbl to new stbl at start of extended area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) rp->header.stblindex = DTROOTMAXSLOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) stbl = (s8 *) & rp->slot[DTROOTMAXSLOT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) memcpy(stbl, sp->header.stbl, sp->header.nextindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) rp->header.nextindex = sp->header.nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) /* copy old data area to start of new data area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) memcpy(&rp->slot[1], &sp->slot[1], IDATASIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) * append free region of newly extended area at tail of freelist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) /* init free region of newly extended area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) fsi = n = DTROOTMAXSLOT + stblsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) f = &rp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) for (fsi++; fsi < rp->header.maxslot; f++, fsi++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) f->next = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) f->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) /* append new free region at tail of old freelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) fsi = sp->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) if (fsi == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) rp->header.freelist = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) rp->header.freelist = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) f = &rp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) fsi = f->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) } while (fsi != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) f->next = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) rp->header.freecnt = sp->header.freecnt + rp->header.maxslot - n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) * Update directory index table for entries now in right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) s64 lblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) struct metapage *mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) struct ldtentry *ldtentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) stbl = DT_GETSTBL(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) for (n = 0; n < rp->header.nextindex; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) ldtentry = (struct ldtentry *) & rp->slot[stbl[n]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) modify_index(tid, ip, le32_to_cpu(ldtentry->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) rbn, n, &mp, &lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) if (mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) * insert the new entry into the new right/child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) * (skip index in the new right page will not change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) * reset parent/root page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) * set the 1st entry offset to 0, which force the left-most key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) * at any level of the tree to be less than any search key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) * The btree comparison code guarantees that the left-most key on any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) * level of the tree is never used, so it doesn't need to be filled in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) BT_MARK_DIRTY(smp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) * acquire a transaction lock on the root page (in-memory inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) tlck = txLock(tid, ip, smp, tlckDTREE | tlckNEW | tlckBTROOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) /* linelock root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) lv->length = DTROOTMAXSLOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) /* update page header of root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) if (sp->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) sp->header.flag &= ~BT_LEAF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) sp->header.flag |= BT_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) /* init the first entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) s = (struct idtentry *) & sp->slot[DTENTRYSTART];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) ppxd = (pxd_t *) s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) *ppxd = *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) s->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) s->namlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) stbl = sp->header.stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) stbl[0] = DTENTRYSTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) sp->header.nextindex = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) /* init freelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) fsi = DTENTRYSTART + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) f = &sp->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) /* init free region of remaining area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) for (fsi++; fsi < DTROOTMAXSLOT; f++, fsi++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) f->next = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) f->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) sp->header.freelist = DTENTRYSTART + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) sp->header.freecnt = DTROOTMAXSLOT - (DTENTRYSTART + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) *rmpp = rmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) * dtDelete()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) * function: delete the entry(s) referenced by a key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) * return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) int dtDelete(tid_t tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) struct inode *ip, struct component_name * key, ino_t * ino, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) struct metapage *mp, *imp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) struct btstack btstack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) struct ldtentry *ldtentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) u8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) u32 table_index, next_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) struct metapage *nmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) dtpage_t *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) * search for the entry to delete:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) * dtSearch() returns (leaf page pinned, index at which to delete).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) if ((rc = dtSearch(ip, key, ino, &btstack, flag)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) /* retrieve search result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) * We need to find put the index of the next entry into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) * directory index table in order to resume a readdir from this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) * entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) if (DO_INDEX(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) ldtentry = (struct ldtentry *) & p->slot[stbl[index]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) table_index = le32_to_cpu(ldtentry->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) if (index == (p->header.nextindex - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) * Last entry in this leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) if ((p->header.flag & BT_ROOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) || (p->header.next == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) next_index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) /* Read next leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) DT_GETPAGE(ip, le64_to_cpu(p->header.next),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) nmp, PSIZE, np, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) next_index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) stbl = DT_GETSTBL(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) ldtentry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) (struct ldtentry *) & np->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) slot[stbl[0]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) next_index =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) le32_to_cpu(ldtentry->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) DT_PUTPAGE(nmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) ldtentry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) (struct ldtentry *) & p->slot[stbl[index + 1]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) next_index = le32_to_cpu(ldtentry->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) free_index(tid, ip, table_index, next_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) * the leaf page becomes empty, delete the page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) if (p->header.nextindex == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) /* delete empty page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) rc = dtDeleteUp(tid, ip, mp, p, &btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) * the leaf page has other entries remaining:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) * delete the entry from the leaf page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) BT_MARK_DIRTY(mp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) * acquire a transaction lock on the leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) * Do not assume that dtlck->index will be zero. During a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) * rename within a directory, this transaction may have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) * modified this page already when adding the new entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) /* linelock stbl of non-root leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) if (!(p->header.flag & BT_ROOT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) i = index >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) lv->offset = p->header.stblindex + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) lv->length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) ((p->header.nextindex - 1) >> L2DTSLOTSIZE) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) /* free the leaf entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) dtDeleteEntry(p, index, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) * Update directory index table for entries moved in stbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) if (DO_INDEX(ip) && index < p->header.nextindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) s64 lblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) imp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) for (i = index; i < p->header.nextindex; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) ldtentry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) (struct ldtentry *) & p->slot[stbl[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) modify_index(tid, ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) le32_to_cpu(ldtentry->index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) bn, i, &imp, &lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) if (imp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) release_metapage(imp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) * dtDeleteUp()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) * function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) * free empty pages as propagating deletion up the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) * return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) static int dtDeleteUp(tid_t tid, struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) struct metapage * fmp, dtpage_t * fp, struct btstack * btstack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) int index, nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) int xlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) struct btframe *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) struct pxd_lock *pxdlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) * keep the root leaf page which has become empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) if (BT_IS_ROOT(fmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) * reset the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) * dtInitRoot() acquires txlock on the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) dtInitRoot(tid, ip, PARENT(ip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) DT_PUTPAGE(fmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) * free the non-root leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) * acquire a transaction lock on the page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) * write FREEXTENT|NOREDOPAGE log record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) * N.B. linelock is overlaid as freed extent descriptor, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) * the buffer page is freed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) tlck = txMaplock(tid, ip, tlckDTREE | tlckFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) pxdlock = (struct pxd_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) pxdlock->flag = mlckFREEPXD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) pxdlock->pxd = fp->header.self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) pxdlock->index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) /* update sibling pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) if ((rc = dtRelink(tid, ip, fp))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) BT_PUTPAGE(fmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) xlen = lengthPXD(&fp->header.self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) /* Free quota allocation. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) dquot_free_block(ip, xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) /* free/invalidate its buffer page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) discard_metapage(fmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) * propagate page deletion up the directory tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) * If the delete from the parent page makes it empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) * continue all the way up the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) * stop if the root page is reached (which is never deleted) or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) * if the entry deletion does not empty the page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) while ((parent = BT_POP(btstack)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) /* pin the parent page <sp> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) DT_GETPAGE(ip, parent->bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) * free the extent of the child page deleted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) index = parent->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) * delete the entry for the child page from parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) nextindex = p->header.nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) * the parent has the single entry being deleted:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) * free the parent page which has become empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) if (nextindex == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) * keep the root internal page which has become empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) if (p->header.flag & BT_ROOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) * reset the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) * dtInitRoot() acquires txlock on the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) dtInitRoot(tid, ip, PARENT(ip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) * free the parent page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) * acquire a transaction lock on the page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) * write FREEXTENT|NOREDOPAGE log record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) tlck =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) txMaplock(tid, ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) tlckDTREE | tlckFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) pxdlock = (struct pxd_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) pxdlock->flag = mlckFREEPXD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) pxdlock->pxd = p->header.self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) pxdlock->index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) /* update sibling pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) if ((rc = dtRelink(tid, ip, p))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) xlen = lengthPXD(&p->header.self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) /* Free quota allocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) dquot_free_block(ip, xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) /* free/invalidate its buffer page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) discard_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) /* propagate up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) * the parent has other entries remaining:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) * delete the router entry from the parent page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) BT_MARK_DIRTY(mp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) * acquire a transaction lock on the page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) * action: router entry deletion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) /* linelock stbl of non-root leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) if (!(p->header.flag & BT_ROOT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) if (dtlck->index < dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) lv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) i = index >> L2DTSLOTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) lv->offset = p->header.stblindex + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) lv->length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) ((p->header.nextindex - 1) >> L2DTSLOTSIZE) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) /* free the router entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) dtDeleteEntry(p, index, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) /* reset key of new leftmost entry of level (for consistency) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) if (index == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) ((p->header.flag & BT_ROOT) || p->header.prev == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) dtTruncateEntry(p, 0, &dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) /* unpin the parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) /* exit propagation up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) if (!DO_INDEX(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) ip->i_size -= PSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) #ifdef _NOTYET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) * NAME: dtRelocate()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) * FUNCTION: relocate dtpage (internal or leaf) of directory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) * This function is mainly used by defragfs utility.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) s64 nxaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) struct metapage *mp, *pmp, *lmp, *rmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) dtpage_t *p, *pp, *rp = 0, *lp= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) struct btstack btstack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) pxd_t *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) s64 oxaddr, nextbn, prevbn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) int xlen, xsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) struct pxd_lock *pxdlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) oxaddr = addressPXD(opxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) xlen = lengthPXD(opxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) jfs_info("dtRelocate: lmxaddr:%Ld xaddr:%Ld:%Ld xlen:%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) (long long)lmxaddr, (long long)oxaddr, (long long)nxaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) * 1. get the internal parent dtpage covering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) * router entry for the tartget page to be relocated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) /* retrieve search result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) DT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) jfs_info("dtRelocate: parent router entry validated.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) * 2. relocate the target dtpage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) /* read in the target page from src extent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) /* release the pinned parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) DT_PUTPAGE(pmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) * read in sibling pages if any to update sibling pointers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) rmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) if (p->header.next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) nextbn = le64_to_cpu(p->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) DT_GETPAGE(ip, nextbn, rmp, PSIZE, rp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) DT_PUTPAGE(pmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) lmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) if (p->header.prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) prevbn = le64_to_cpu(p->header.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) DT_GETPAGE(ip, prevbn, lmp, PSIZE, lp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) DT_PUTPAGE(pmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) if (rmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) DT_PUTPAGE(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) /* at this point, all xtpages to be updated are in memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) * update sibling pointers of sibling dtpages if any;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) if (lmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) tlck = txLock(tid, ip, lmp, tlckDTREE | tlckRELINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) lp->header.next = cpu_to_le64(nxaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) DT_PUTPAGE(lmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) if (rmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) tlck = txLock(tid, ip, rmp, tlckDTREE | tlckRELINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) rp->header.prev = cpu_to_le64(nxaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) DT_PUTPAGE(rmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) * update the target dtpage to be relocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) * write LOG_REDOPAGE of LOG_NEW type for dst page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) * for the whole target page (logredo() will apply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) * after image and update bmap for allocation of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) * dst extent), and update bmap for allocation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) * the dst extent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) tlck = txLock(tid, ip, mp, tlckDTREE | tlckNEW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) /* update the self address in the dtpage header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) pxd = &p->header.self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) PXDaddress(pxd, nxaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) /* the dst page is the same as the src page, i.e.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) * linelock for afterimage of the whole page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) lv->length = p->header.maxslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) /* update the buffer extent descriptor of the dtpage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) /* unpin the relocated page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) jfs_info("dtRelocate: target dtpage relocated.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) /* the moved extent is dtpage, then a LOG_NOREDOPAGE log rec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) * needs to be written (in logredo(), the LOG_NOREDOPAGE log rec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) * will also force a bmap update ).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) * 3. acquire maplock for the source extent to be freed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) /* for dtpage relocation, write a LOG_NOREDOPAGE record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) * for the source dtpage (logredo() will init NoRedoPage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) * filter and will also update bmap for free of the source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) * dtpage), and upadte bmap for free of the source dtpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) tlck = txMaplock(tid, ip, tlckDTREE | tlckFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) pxdlock = (struct pxd_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) pxdlock->flag = mlckFREEPXD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) PXDaddress(&pxdlock->pxd, oxaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) PXDlength(&pxdlock->pxd, xlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) pxdlock->index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) * 4. update the parent router entry for relocation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) * acquire tlck for the parent entry covering the target dtpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) * write LOG_REDOPAGE to apply after image only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) jfs_info("dtRelocate: update parent router entry.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) /* update the PXD with the new address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) stbl = DT_GETSTBL(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) pxd = (pxd_t *) & pp->slot[stbl[index]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) PXDaddress(pxd, nxaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) lv->offset = stbl[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) /* unpin the parent dtpage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) DT_PUTPAGE(pmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) * NAME: dtSearchNode()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) * FUNCTION: Search for an dtpage containing a specified address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) * This function is mainly used by defragfs utility.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) * NOTE: Search result on stack, the found page is pinned at exit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) * The result page must be an internal dtpage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) * lmxaddr give the address of the left most page of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) * dtree level, in which the required dtpage resides.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) struct btstack * btstack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) int psize = 288; /* initial in-line directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) pxd_t *pxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) struct btframe *btsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) BT_CLR(btstack); /* reset stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) * descend tree to the level with specified leftmost page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) * by convention, root bn = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) for (bn = 0;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) /* get/pin the page to search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) DT_GETPAGE(ip, bn, mp, psize, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) /* does the xaddr of leftmost page of the levevl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) * matches levevl search key ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) if (p->header.flag & BT_ROOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) if (lmxaddr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) } else if (addressPXD(&p->header.self) == lmxaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) * descend down to leftmost child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) return -ESTALE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) /* get the leftmost entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) pxd = (pxd_t *) & p->slot[stbl[0]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) /* get the child page block address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) bn = addressPXD(pxd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) psize = lengthPXD(pxd) << JFS_SBI(ip->i_sb)->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) /* unpin the parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) * search each page at the current levevl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) for (i = 0; i < p->header.nextindex; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) pxd = (pxd_t *) & p->slot[stbl[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) /* found the specified router entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) if (addressPXD(pxd) == addressPXD(kpxd) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) lengthPXD(pxd) == lengthPXD(kpxd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) btsp = btstack->top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) btsp->bn = bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) btsp->index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) btsp->mp = mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) /* get the right sibling page if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) if (p->header.next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) bn = le64_to_cpu(p->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) return -ESTALE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) /* unpin current page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) /* get the right sibling page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) goto loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) #endif /* _NOTYET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) * dtRelink()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) * function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) * link around a freed page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) * fp: page to be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) * return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) static int dtRelink(tid_t tid, struct inode *ip, dtpage_t * p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) s64 nextbn, prevbn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) nextbn = le64_to_cpu(p->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) prevbn = le64_to_cpu(p->header.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) /* update prev pointer of the next page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) if (nextbn != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) DT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) BT_MARK_DIRTY(mp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) * acquire a transaction lock on the next page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) * action: update prev pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) tlck = txLock(tid, ip, mp, tlckDTREE | tlckRELINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) jfs_info("dtRelink nextbn: tlck = 0x%p, ip = 0x%p, mp=0x%p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) tlck, ip, mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) p->header.prev = cpu_to_le64(prevbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) /* update next pointer of the previous page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) if (prevbn != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) DT_GETPAGE(ip, prevbn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) BT_MARK_DIRTY(mp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) * acquire a transaction lock on the prev page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) * action: update next pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) tlck = txLock(tid, ip, mp, tlckDTREE | tlckRELINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) jfs_info("dtRelink prevbn: tlck = 0x%p, ip = 0x%p, mp=0x%p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) tlck, ip, mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) /* linelock header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) p->header.next = cpu_to_le64(nextbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) * dtInitRoot()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) * initialize directory root (inline in inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) void dtInitRoot(tid_t tid, struct inode *ip, u32 idotdot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) struct jfs_inode_info *jfs_ip = JFS_IP(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) dtroot_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) int fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) struct dtslot *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) u16 xflag_save;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) * If this was previously an non-empty directory, we need to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) * the old directory table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) if (DO_INDEX(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) if (!jfs_dirtable_inline(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) struct tblock *tblk = tid_to_tblock(tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) * We're playing games with the tid's xflag. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) * we're removing a regular file, the file's xtree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) * is committed with COMMIT_PMAP, but we always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) * commit the directories xtree with COMMIT_PWMAP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) xflag_save = tblk->xflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) tblk->xflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) * xtTruncate isn't guaranteed to fully truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) * the xtree. The caller needs to check i_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) * after committing the transaction to see if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) * additional truncation is needed. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) * COMMIT_Stale flag tells caller that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) * initiated the truncation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) xtTruncate(tid, ip, 0, COMMIT_PWMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) set_cflag(COMMIT_Stale, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) tblk->xflag = xflag_save;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) ip->i_size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) jfs_ip->next_index = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) ip->i_size = IDATASIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) * acquire a transaction lock on the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) * action: directory initialization;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) tlck = txLock(tid, ip, (struct metapage *) & jfs_ip->bxflag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) tlckDTREE | tlckENTRY | tlckBTROOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) /* linelock root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) lv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) lv->length = DTROOTMAXSLOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) p = &jfs_ip->i_dtroot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) p->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) p->header.nextindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) /* init freelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) fsi = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) f = &p->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) /* init data area of root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) for (fsi++; fsi < DTROOTMAXSLOT; f++, fsi++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) f->next = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) f->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) p->header.freelist = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) p->header.freecnt = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) /* init '..' entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) p->header.idotdot = cpu_to_le32(idotdot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) * add_missing_indices()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) * function: Fix dtree page in which one or more entries has an invalid index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) * fsck.jfs should really fix this, but it currently does not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) * Called from jfs_readdir when bad index is detected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) static void add_missing_indices(struct inode *inode, s64 bn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) struct ldtentry *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) uint index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) tid_t tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) tid = txBegin(inode->i_sb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) DT_GETPAGE(inode, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) printk(KERN_ERR "DT_GETPAGE failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) BT_MARK_DIRTY(mp, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) ASSERT(p->header.flag & BT_LEAF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) if (BT_IS_ROOT(mp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) tlck->type |= tlckBTROOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) dtlck = (struct dt_lock *) &tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) for (i = 0; i < p->header.nextindex; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) d = (struct ldtentry *) &p->slot[stbl[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) index = le32_to_cpu(d->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) if ((index < 2) || (index >= JFS_IP(inode)->next_index)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) d->index = cpu_to_le32(add_index(tid, inode, bn, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) lv = &dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) lv->offset = stbl[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) (void) txCommit(tid, 1, &inode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) txEnd(tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) * Buffer to hold directory entry info while traversing a dtree page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) * before being fed to the filldir function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) struct jfs_dirent {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) loff_t position;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) int ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) u16 name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) char name[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) * function to determine next variable-sized jfs_dirent in buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) return (struct jfs_dirent *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) ((char *)dirent +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) ((sizeof (struct jfs_dirent) + dirent->name_len + 1 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) sizeof (loff_t) - 1) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) ~(sizeof (loff_t) - 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) * jfs_readdir()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) * function: read directory entries sequentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) * from the specified entry offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) * parameter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) * return: offset = (pn, index) of start entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) * of next jfs_readdir()/dtRead()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) int jfs_readdir(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) struct inode *ip = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) loff_t dtpos; /* legacy OS/2 style position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) struct dtoffset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) s16 pn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) s16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) s32 unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) } *dtoffset = (struct dtoffset *) &dtpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) struct btstack btstack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) int i, next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) struct ldtentry *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) struct dtslot *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) int d_namleft, len, outlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) unsigned long dirent_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) char *name_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) u32 dir_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) int do_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) uint loop_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) struct jfs_dirent *jfs_dirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) int jfs_dirents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) int overflow, fix_page, page_fixed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) static int unique_pos = 2; /* If we can't fix broken index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) if (ctx->pos == DIREND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) if (DO_INDEX(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) * persistent index is stored in directory entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) * Special cases: 0 = .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) * 1 = ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) * -1 = End of directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) do_index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) dir_index = (u32) ctx->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) * NFSv4 reserves cookies 1 and 2 for . and .. so the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) * we return to the vfs is one greater than the one we use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) * internally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) if (dir_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) dir_index--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) if (dir_index > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) struct dir_table_slot dirtab_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) if (dtEmpty(ip) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) (dir_index >= JFS_IP(ip)->next_index)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) /* Stale position. Directory has shrunk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) repeat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) rc = read_index(ip, dir_index, &dirtab_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) if (dirtab_slot.flag == DIR_INDEX_FREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) if (loop_count++ > JFS_IP(ip)->next_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) jfs_err("jfs_readdir detected infinite loop!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) dir_index = le32_to_cpu(dirtab_slot.addr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) if (dir_index == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) goto repeat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) bn = addressDTS(&dirtab_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) index = dirtab_slot.slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) if (p->header.flag & BT_INTERNAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) jfs_err("jfs_readdir: bad index table");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) if (dir_index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) * self "."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) ctx->pos = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) * parent ".."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) ctx->pos = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) * Find first entry of left-most leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) if (dtEmpty(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) if ((rc = dtReadFirst(ip, &btstack)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) * pn = 0; index = 1: First entry "."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) * pn = 0; index = 2: Second entry ".."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) * pn > 0: Real entries, pn=1 -> leftmost page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) * pn = index = -1: No more entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) dtpos = ctx->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) if (dtpos < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) /* build "." entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) ctx->pos = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) dtoffset->index = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) ctx->pos = dtpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) if (dtoffset->pn == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) if (dtoffset->index == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) /* build ".." entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) jfs_err("jfs_readdir called with invalid offset!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) dtoffset->pn = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) dtoffset->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) ctx->pos = dtpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) if (dtEmpty(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) if ((rc = dtReadNext(ip, &ctx->pos, &btstack))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) jfs_err("jfs_readdir: unexpected rc = %d from dtReadNext",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) /* get start leaf page and index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) /* offset beyond directory eof ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) if (bn < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) dirent_buf = __get_free_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) if (dirent_buf == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) jfs_warn("jfs_readdir: __get_free_page failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) jfs_dirent = (struct jfs_dirent *) dirent_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) jfs_dirents = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) overflow = fix_page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) for (i = index; i < p->header.nextindex; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) d = (struct ldtentry *) & p->slot[stbl[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) if (((long) jfs_dirent + d->namlen + 1) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) (dirent_buf + PAGE_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) /* DBCS codepages could overrun dirent_buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) overflow = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) d_namleft = d->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) name_ptr = jfs_dirent->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) jfs_dirent->ino = le32_to_cpu(d->inumber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) if (do_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) len = min(d_namleft, DTLHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) jfs_dirent->position = le32_to_cpu(d->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) * d->index should always be valid, but it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) * isn't. fsck.jfs doesn't create the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) * directory index for the lost+found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) * directory. Rather than let it go,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) * we can try to fix it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) if ((jfs_dirent->position < 2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) (jfs_dirent->position >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) JFS_IP(ip)->next_index)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) if (!page_fixed && !isReadOnly(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) fix_page = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) * setting overflow and setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) * index to i will cause the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) * same page to be processed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) * again starting here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) overflow = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) jfs_dirent->position = unique_pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) * We add 1 to the index because we may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) * use a value of 2 internally, and NFSv4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) * doesn't like that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) jfs_dirent->position++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) jfs_dirent->position = dtpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) len = min(d_namleft, DTLHDRDATALEN_LEGACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) /* copy the name of head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) outlen = jfs_strfromUCS_le(name_ptr, d->name, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) codepage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) jfs_dirent->name_len = outlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) /* copy name in the additional segment(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) next = d->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) while (next >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) t = (struct dtslot *) & p->slot[next];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) name_ptr += outlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) d_namleft -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) /* Sanity Check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) if (d_namleft == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) jfs_error(ip->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) "JFS:Dtree error: ino = %ld, bn=%lld, index = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) (long)ip->i_ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) (long long)bn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) goto skip_one;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) len = min(d_namleft, DTSLOTDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) outlen = jfs_strfromUCS_le(name_ptr, t->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) len, codepage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) jfs_dirent->name_len += outlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) next = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) jfs_dirents++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) jfs_dirent = next_jfs_dirent(jfs_dirent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) skip_one:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) if (!do_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) dtoffset->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) if (!overflow) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) /* Point to next leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) if (p->header.flag & BT_ROOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) bn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) bn = le64_to_cpu(p->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) /* update offset (pn:index) for new page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) if (!do_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) dtoffset->pn++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) dtoffset->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) page_fixed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) /* unpin previous leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) jfs_dirent = (struct jfs_dirent *) dirent_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) while (jfs_dirents--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) ctx->pos = jfs_dirent->position;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) if (!dir_emit(ctx, jfs_dirent->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) jfs_dirent->name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) jfs_dirent->ino, DT_UNKNOWN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) jfs_dirent = next_jfs_dirent(jfs_dirent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) if (fix_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) add_missing_indices(ip, bn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) page_fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) if (!overflow && (bn == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) ctx->pos = DIREND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) free_page(dirent_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) free_page(dirent_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) * dtReadFirst()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) * function: get the leftmost page of the directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) static int dtReadFirst(struct inode *ip, struct btstack * btstack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) int psize = 288; /* initial in-line directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) struct btframe *btsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) pxd_t *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) BT_CLR(btstack); /* reset stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) * descend leftmost path of the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) * by convention, root bn = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) for (bn = 0;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) DT_GETPAGE(ip, bn, mp, psize, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) * leftmost leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) /* return leftmost entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) btsp = btstack->top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) btsp->bn = bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) btsp->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) btsp->mp = mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) * descend down to leftmost child page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) if (BT_STACK_FULL(btstack)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) jfs_error(ip->i_sb, "btstack overrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) BT_STACK_DUMP(btstack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) /* push (bn, index) of the parent page/entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) BT_PUSH(btstack, bn, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) /* get the leftmost entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) xd = (pxd_t *) & p->slot[stbl[0]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) /* get the child page block address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) bn = addressPXD(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) psize = lengthPXD(xd) << JFS_SBI(ip->i_sb)->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) /* unpin the parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) * dtReadNext()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) * function: get the page of the specified offset (pn:index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) * return: if (offset > eof), bn = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) * note: if index > nextindex of the target leaf page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) * start with 1st entry of next leaf page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) static int dtReadNext(struct inode *ip, loff_t * offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) struct btstack * btstack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) struct dtoffset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) s16 pn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) s16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) s32 unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) } *dtoffset = (struct dtoffset *) offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) int pn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) struct btframe *btsp, *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) pxd_t *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) * get leftmost leaf page pinned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) if ((rc = dtReadFirst(ip, btstack)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) /* get leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) /* get the start offset (pn:index) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) pn = dtoffset->pn - 1; /* Now pn = 0 represents leftmost leaf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) index = dtoffset->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) /* start at leftmost page ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) if (pn == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) /* offset beyond eof ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) if (index < p->header.nextindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) if (p->header.flag & BT_ROOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) bn = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) /* start with 1st entry of next leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) dtoffset->pn++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) dtoffset->index = index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) goto a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) /* start at non-leftmost page: scan parent pages for large pn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) if (p->header.flag & BT_ROOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) bn = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) /* start after next leaf page ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) if (pn > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) goto b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) /* get leaf page pn = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) bn = le64_to_cpu(p->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) /* unpin leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) /* offset beyond eof ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) if (bn == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) bn = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) goto c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) * scan last internal page level to get target leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) /* unpin leftmost leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) /* get left most parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) btsp = btstack->top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) parent = btsp - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) bn = parent->bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) /* scan parent pages at last internal page level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) while (pn >= p->header.nextindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) pn -= p->header.nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) /* get next parent page address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) bn = le64_to_cpu(p->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) /* unpin current parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) /* offset beyond eof ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) if (bn == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) bn = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) /* get next parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) /* update parent page stack frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) parent->bn = bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) /* get leaf page address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) xd = (pxd_t *) & p->slot[stbl[pn]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) bn = addressPXD(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) /* unpin parent page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) * get target leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) * leaf page has been completed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) * start with 1st entry of next leaf page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) if (index >= p->header.nextindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) bn = le64_to_cpu(p->header.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) /* unpin leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) /* offset beyond eof ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) if (bn == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) bn = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) /* get next leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) /* start with 1st entry of next leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) dtoffset->pn++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) dtoffset->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) /* return target leaf page pinned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) btsp = btstack->top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) btsp->bn = bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) btsp->index = dtoffset->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) btsp->mp = mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) * dtCompare()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) * function: compare search key with an internal entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) * return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) * < 0 if k is < record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) * = 0 if k is = record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) * > 0 if k is > record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) static int dtCompare(struct component_name * key, /* search key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) dtpage_t * p, /* directory page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) int si)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) { /* entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) wchar_t *kname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) __le16 *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) int klen, namlen, len, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) struct idtentry *ih;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) struct dtslot *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) * force the left-most key on internal pages, at any level of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) * the tree, to be less than any search key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) * this obviates having to update the leftmost key on an internal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) * page when the user inserts a new key in the tree smaller than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) * anything that has been stored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) * (? if/when dtSearch() narrows down to 1st entry (index = 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) * at any internal page at any level of the tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) * it descends to child of the entry anyway -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) * ? make the entry as min size dummy entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) * if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & BT_LEAF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) * return (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) kname = key->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) klen = key->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) ih = (struct idtentry *) & p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) si = ih->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) name = ih->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) namlen = ih->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) len = min(namlen, DTIHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) /* compare with head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) len = min(klen, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) if ((rc = UniStrncmp_le(kname, name, len)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) klen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) namlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) /* compare with additional segment(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) kname += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) while (klen > 0 && namlen > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) /* compare with next name segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) t = (struct dtslot *) & p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) len = min(namlen, DTSLOTDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) len = min(klen, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) name = t->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) if ((rc = UniStrncmp_le(kname, name, len)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) klen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) namlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) kname += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) si = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) return (klen - namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) * ciCompare()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) * function: compare search key with an (leaf/internal) entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) * return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) * < 0 if k is < record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) * = 0 if k is = record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) * > 0 if k is > record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) static int ciCompare(struct component_name * key, /* search key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) dtpage_t * p, /* directory page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) int si, /* entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) wchar_t *kname, x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) __le16 *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) int klen, namlen, len, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) struct ldtentry *lh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) struct idtentry *ih;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) struct dtslot *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) * force the left-most key on internal pages, at any level of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) * the tree, to be less than any search key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) * this obviates having to update the leftmost key on an internal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) * page when the user inserts a new key in the tree smaller than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) * anything that has been stored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) * (? if/when dtSearch() narrows down to 1st entry (index = 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) * at any internal page at any level of the tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) * it descends to child of the entry anyway -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) * ? make the entry as min size dummy entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) * if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & BT_LEAF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) * return (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) kname = key->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) klen = key->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) * leaf page entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) lh = (struct ldtentry *) & p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) si = lh->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) name = lh->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) namlen = lh->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) if (flag & JFS_DIR_INDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) len = min(namlen, DTLHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) len = min(namlen, DTLHDRDATALEN_LEGACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) * internal page entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) ih = (struct idtentry *) & p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) si = ih->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) name = ih->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) namlen = ih->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) len = min(namlen, DTIHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) /* compare with head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) len = min(klen, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) for (i = 0; i < len; i++, kname++, name++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) /* only uppercase if case-insensitive support is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) if ((flag & JFS_OS2) == JFS_OS2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) x = UniToupper(le16_to_cpu(*name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) x = le16_to_cpu(*name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) if ((rc = *kname - x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) klen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) namlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) /* compare with additional segment(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) while (klen > 0 && namlen > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) /* compare with next name segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) t = (struct dtslot *) & p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) len = min(namlen, DTSLOTDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) len = min(klen, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) name = t->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) for (i = 0; i < len; i++, kname++, name++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) /* only uppercase if case-insensitive support is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) if ((flag & JFS_OS2) == JFS_OS2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) x = UniToupper(le16_to_cpu(*name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) x = le16_to_cpu(*name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) if ((rc = *kname - x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) klen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) namlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) si = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) return (klen - namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) * ciGetLeafPrefixKey()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) * function: compute prefix of suffix compression
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) * from two adjacent leaf entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) * across page boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) * return: non-zero on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) int ri, struct component_name * key, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) int klen, namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) wchar_t *pl, *pr, *kname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) struct component_name lkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) struct component_name rkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) lkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) if (lkey.name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) rkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) if (rkey.name == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) kfree(lkey.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) /* get left and right key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) dtGetKey(lp, li, &lkey, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) lkey.name[lkey.namlen] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) if ((flag & JFS_OS2) == JFS_OS2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) ciToUpper(&lkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) dtGetKey(rp, ri, &rkey, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) rkey.name[rkey.namlen] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) if ((flag & JFS_OS2) == JFS_OS2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) ciToUpper(&rkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) /* compute prefix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) klen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) kname = key->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) namlen = min(lkey.namlen, rkey.namlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) for (pl = lkey.name, pr = rkey.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) namlen; pl++, pr++, namlen--, klen++, kname++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) *kname = *pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) if (*pl != *pr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) key->namlen = klen + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) goto free_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) /* l->namlen <= r->namlen since l <= r */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) if (lkey.namlen < rkey.namlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) *kname = *pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) key->namlen = klen + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) } else /* l->namelen == r->namelen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) key->namlen = klen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) free_names:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) kfree(lkey.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) kfree(rkey.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) * dtGetKey()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) * function: get key of the entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) static void dtGetKey(dtpage_t * p, int i, /* entry index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) struct component_name * key, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) int si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) struct ldtentry *lh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) struct idtentry *ih;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) struct dtslot *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) int namlen, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) wchar_t *kname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) __le16 *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) /* get entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) si = stbl[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) lh = (struct ldtentry *) & p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) si = lh->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) namlen = lh->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) name = lh->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) if (flag & JFS_DIR_INDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) len = min(namlen, DTLHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) len = min(namlen, DTLHDRDATALEN_LEGACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) ih = (struct idtentry *) & p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) si = ih->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) namlen = ih->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) name = ih->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) len = min(namlen, DTIHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) key->namlen = namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) kname = key->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) * move head/only segment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) UniStrncpy_from_le(kname, name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) * move additional segment(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) while (si >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) /* get next segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) t = &p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) kname += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) namlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) len = min(namlen, DTSLOTDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) UniStrncpy_from_le(kname, t->name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) si = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) * dtInsertEntry()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) * function: allocate free slot(s) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) * write a leaf/internal entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) * return: entry slot index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) ddata_t * data, struct dt_lock ** dtlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) struct dtslot *h, *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) struct ldtentry *lh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) struct idtentry *ih = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) int hsi, fsi, klen, len, nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) wchar_t *kname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) __le16 *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) pxd_t *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) struct dt_lock *dtlck = *dtlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) int xsi, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) s64 bn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) struct metapage *mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) klen = key->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) kname = key->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) /* allocate a free slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) hsi = fsi = p->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) h = &p->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) p->header.freelist = h->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) --p->header.freecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) lv->offset = hsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) /* write head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) if (p->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) lh = (struct ldtentry *) h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) lh->next = h->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) lh->inumber = cpu_to_le32(data->leaf.ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) lh->namlen = klen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) name = lh->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) if (data->leaf.ip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) len = min(klen, DTLHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) if (!(p->header.flag & BT_ROOT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) bn = addressPXD(&p->header.self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) lh->index = cpu_to_le32(add_index(data->leaf.tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) data->leaf.ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) bn, index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) len = min(klen, DTLHDRDATALEN_LEGACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) ih = (struct idtentry *) h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) ih->next = h->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) xd = (pxd_t *) ih;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) *xd = data->xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) ih->namlen = klen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) name = ih->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) len = min(klen, DTIHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) UniStrncpy_to_le(name, kname, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) n = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) xsi = hsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) /* write additional segment(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) t = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) klen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) while (klen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) /* get free slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) fsi = p->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) t = &p->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) p->header.freelist = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) --p->header.freecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) /* is next slot contiguous ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) if (fsi != xsi + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) if (dtlck->index < dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) lv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) lv->offset = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) kname += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) len = min(klen, DTSLOTDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) UniStrncpy_to_le(t->name, kname, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) xsi = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) klen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) *dtlock = dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) /* terminate last/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) if (h == t) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) /* single segment entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) if (p->header.flag & BT_LEAF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) lh->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) ih->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) /* multi-segment entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) t->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) /* if insert into middle, shift right succeeding entries in stbl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) nextindex = p->header.nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) if (index < nextindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) memmove(stbl + index + 1, stbl + index, nextindex - index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) if ((p->header.flag & BT_LEAF) && data->leaf.ip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) s64 lblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) * Need to update slot number for entries that moved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) * in the stbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) for (n = index + 1; n <= nextindex; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) lh = (struct ldtentry *) & (p->slot[stbl[n]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) modify_index(data->leaf.tid, data->leaf.ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) le32_to_cpu(lh->index), bn, n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) &mp, &lblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) if (mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) stbl[index] = hsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) /* advance next available entry index of stbl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) ++p->header.nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) * dtMoveEntry()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) * function: move entries from split/left page to new/right page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) * nextindex of dst page and freelist/freecnt of both pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) * are updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) static void dtMoveEntry(dtpage_t * sp, int si, dtpage_t * dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) struct dt_lock ** sdtlock, struct dt_lock ** ddtlock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) int do_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) int ssi, next; /* src slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) int di; /* dst entry index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) int dsi; /* dst slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) s8 *sstbl, *dstbl; /* sorted entry table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) int snamlen, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) struct ldtentry *slh, *dlh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) struct idtentry *sih, *dih = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) struct dtslot *h, *s, *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) struct dt_lock *sdtlck = *sdtlock, *ddtlck = *ddtlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) struct lv *slv, *dlv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) int xssi, ns, nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) int sfsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) sstbl = (s8 *) & sp->slot[sp->header.stblindex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) dstbl = (s8 *) & dp->slot[dp->header.stblindex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) dsi = dp->header.freelist; /* first (whole page) free slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) sfsi = sp->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) /* linelock destination entry slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) dlv = & ddtlck->lv[ddtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) dlv->offset = dsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) /* linelock source entry slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) slv = & sdtlck->lv[sdtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) slv->offset = sstbl[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) xssi = slv->offset - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) * move entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) ns = nd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) for (di = 0; si < sp->header.nextindex; si++, di++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) ssi = sstbl[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) dstbl[di] = dsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) /* is next slot contiguous ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) if (ssi != xssi + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) slv->length = ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) sdtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) if (sdtlck->index < sdtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) slv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) sdtlck = (struct dt_lock *) txLinelock(sdtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) slv = & sdtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) slv->offset = ssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) ns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) * move head/only segment of an entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) /* get dst slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) h = d = &dp->slot[dsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) /* get src slot and move */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) s = &sp->slot[ssi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) if (sp->header.flag & BT_LEAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) /* get source entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) slh = (struct ldtentry *) s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) dlh = (struct ldtentry *) h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) snamlen = slh->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) if (do_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) len = min(snamlen, DTLHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) dlh->index = slh->index; /* little-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) len = min(snamlen, DTLHDRDATALEN_LEGACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) memcpy(dlh, slh, 6 + len * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) next = slh->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) /* update dst head/only segment next field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) dsi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) dlh->next = dsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) sih = (struct idtentry *) s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) snamlen = sih->namlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) len = min(snamlen, DTIHDRDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) dih = (struct idtentry *) h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) memcpy(dih, sih, 10 + len * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) next = sih->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) dsi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) dih->next = dsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) /* free src head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) s->next = sfsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) s->cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) sfsi = ssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) ns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) nd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) xssi = ssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) * move additional segment(s) of the entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) snamlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) while ((ssi = next) >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) /* is next slot contiguous ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) if (ssi != xssi + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) slv->length = ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) sdtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) if (sdtlck->index < sdtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) slv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) sdtlck =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) (struct dt_lock *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) txLinelock(sdtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) slv = & sdtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) slv->offset = ssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) ns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) /* get next source segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) s = &sp->slot[ssi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) /* get next destination free slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) d++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) len = min(snamlen, DTSLOTDATALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) UniStrncpy_le(d->name, s->name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) ns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) nd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) xssi = ssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) dsi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) d->next = dsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) /* free source segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) next = s->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) s->next = sfsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) s->cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) sfsi = ssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) snamlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) } /* end while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) /* terminate dst last/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) if (h == d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) /* single segment entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) if (dp->header.flag & BT_LEAF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) dlh->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) dih->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) /* multi-segment entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) d->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) } /* end for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) slv->length = ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) sdtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) *sdtlock = sdtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) dlv->length = nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) ddtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) *ddtlock = ddtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) /* update source header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) sp->header.freelist = sfsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) sp->header.freecnt += nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) /* update destination header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) dp->header.nextindex = di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) dp->header.freelist = dsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) dp->header.freecnt -= nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) * dtDeleteEntry()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) * function: free a (leaf/internal) entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) * log freelist header, stbl, and each segment slot of entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) * (even though last/only segment next field is modified,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) * physical image logging requires all segment slots of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) * the entry logged to avoid applying previous updates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) * to the same slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) static void dtDeleteEntry(dtpage_t * p, int fi, struct dt_lock ** dtlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) int fsi; /* free entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) struct dtslot *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) int si, freecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) struct dt_lock *dtlck = *dtlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) int xsi, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) /* get free entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) fsi = stbl[fi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) lv->offset = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) /* get the head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) t = &p->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) if (p->header.flag & BT_LEAF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) si = ((struct ldtentry *) t)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) si = ((struct idtentry *) t)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) t->next = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) t->cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) n = freecnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) xsi = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) /* find the last/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) while (si >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) /* is next slot contiguous ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) if (si != xsi + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) if (dtlck->index < dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) lv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) lv->offset = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) xsi = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) freecnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) t = &p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) t->cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) si = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) *dtlock = dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) /* update freelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) t->next = p->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) p->header.freelist = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323) p->header.freecnt += freecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) /* if delete from middle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) * shift left the succedding entries in the stbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) si = p->header.nextindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) if (fi < si - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) memmove(&stbl[fi], &stbl[fi + 1], si - fi - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) p->header.nextindex--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) * dtTruncateEntry()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339) * function: truncate a (leaf/internal) entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) * log freelist header, stbl, and each segment slot of entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) * (even though last/only segment next field is modified,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343) * physical image logging requires all segment slots of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) * the entry logged to avoid applying previous updates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) * to the same slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) static void dtTruncateEntry(dtpage_t * p, int ti, struct dt_lock ** dtlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349) int tsi; /* truncate entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351) struct dtslot *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) int si, freecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353) struct dt_lock *dtlck = *dtlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) int fsi, xsi, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357) /* get free entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359) tsi = stbl[ti];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) lv->offset = tsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) /* get the head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) t = &p->slot[tsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) ASSERT(p->header.flag & BT_INTERNAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371) ((struct idtentry *) t)->namlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) si = ((struct idtentry *) t)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) ((struct idtentry *) t)->next = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) n = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376) freecnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) fsi = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) xsi = tsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380) /* find the last/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381) while (si >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382) /* is next slot contiguous ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383) if (si != xsi + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389) if (dtlck->index < dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) lv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396) lv->offset = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) xsi = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402) freecnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404) t = &p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) t->cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406) si = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413) *dtlock = dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) /* update freelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) if (freecnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) t->next = p->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419) p->header.freelist = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) p->header.freecnt += freecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) * dtLinelockFreelist()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) static void dtLinelockFreelist(dtpage_t * p, /* directory page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428) int m, /* max slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) struct dt_lock ** dtlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) int fsi; /* free entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432) struct dtslot *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) int si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434) struct dt_lock *dtlck = *dtlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) int xsi, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438) /* get free entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) fsi = p->header.freelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442) if (dtlck->index >= dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444) lv = & dtlck->lv[dtlck->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446) lv->offset = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) n = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) xsi = fsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) t = &p->slot[fsi];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) si = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) /* find the last/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) while (si < m && si >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456) /* is next slot contiguous ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) if (si != xsi + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462) /* open new linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) if (dtlck->index < dtlck->maxcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) lv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) dtlck = (struct dt_lock *) txLinelock(dtlck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470) lv->offset = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) xsi = si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) t = &p->slot[si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) si = t->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481) /* close current linelock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) lv->length = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) *dtlock = dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) * NAME: dtModify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) * FUNCTION: Modify the inode number part of a directory entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495) * tid - Transaction id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) * ip - Inode of parent directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) * key - Name of entry to be modified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) * orig_ino - Original inode number expected in entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) * new_ino - New inode number to put into entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) * flag - JFS_RENAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) * RETURNS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) * -ESTALE - If entry found does not match orig_ino passed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) * -ENOENT - If no entry can be found to match key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) * 0 - If successfully modified entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) int dtModify(tid_t tid, struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508) struct component_name * key, ino_t * orig_ino, ino_t new_ino, int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511) s64 bn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) dtpage_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) struct btstack btstack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) struct tlock *tlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) struct dt_lock *dtlck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518) struct lv *lv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) s8 *stbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) int entry_si; /* entry slot index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521) struct ldtentry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) * search for the entry to modify:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) * dtSearch() returns (leaf page pinned, index at which to modify).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528) if ((rc = dtSearch(ip, key, orig_ino, &btstack, flag)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531) /* retrieve search result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) BT_MARK_DIRTY(mp, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536) * acquire a transaction lock on the leaf page of named entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538) tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539) dtlck = (struct dt_lock *) & tlck->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) /* get slot index of the entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542) stbl = DT_GETSTBL(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543) entry_si = stbl[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) /* linelock entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) ASSERT(dtlck->index == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547) lv = & dtlck->lv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) lv->offset = entry_si;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549) lv->length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550) dtlck->index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) /* get the head/only segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553) entry = (struct ldtentry *) & p->slot[entry_si];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555) /* substitute the inode number of the entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556) entry->inumber = cpu_to_le32(new_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) /* unpin the leaf page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559) DT_PUTPAGE(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562) }