^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) * Portions Copyright (C) Tino Reichardt, 2012
^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) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "jfs_incore.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "jfs_superblock.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "jfs_dmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "jfs_imap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "jfs_lock.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "jfs_metapage.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "jfs_debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "jfs_discard.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * SERIALIZATION of the Block Allocation Map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * the working state of the block allocation map is accessed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * two directions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 1) allocation and free requests that start at the dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * level and move up through the dmap control pages (i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * the vast majority of requests).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * 2) allocation requests that start at dmap control page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * level and work down towards the dmaps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * the serialization scheme used here is as follows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * requests which start at the bottom are serialized against each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * other through buffers and each requests holds onto its buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * as it works it way up from a single dmap to the required level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * of dmap control page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * requests that start at the top are serialized against each other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * and request that start from the bottom by the multiple read/single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * write inode lock of the bmap inode. requests starting at the top
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * take this lock in write mode while request starting at the bottom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * take the lock in read mode. a single top-down request may proceed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * exclusively while multiple bottoms-up requests may proceed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * simultaneously (under the protection of busy buffers).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * in addition to information found in dmaps and dmap control pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * the working state of the block allocation map also includes read/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * write information maintained in the bmap descriptor (i.e. total
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * free block count, allocation group level free block counts).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * a single exclusive lock (BMAP_LOCK) is used to guard this information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * in the face of multiple-bottoms up requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * (lock ordering: IREAD_LOCK, BMAP_LOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * accesses to the persistent state of the block allocation map (limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * to the persistent bitmaps in dmaps) is guarded by (busy) buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define BMAP_LOCK_INIT(bmp) mutex_init(&bmp->db_bmaplock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define BMAP_LOCK(bmp) mutex_lock(&bmp->db_bmaplock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define BMAP_UNLOCK(bmp) mutex_unlock(&bmp->db_bmaplock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * forward references
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int dbBackSplit(dmtree_t * tp, int leafno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int dbJoin(dmtree_t * tp, int leafno, int newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static void dbAdjTree(dmtree_t * tp, int leafno, int newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int dbAllocNear(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int nblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int l2nb, s64 * results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int dbAllocDmapLev(struct bmap * bmp, struct dmap * dp, int nblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int l2nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) s64 * results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) s64 * results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) s64 * results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int dbFindBits(u32 word, int l2nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static int dbMaxBud(u8 * cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static int blkstol2(s64 nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int cntlz(u32 value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int cnttz(u32 word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int dbInitDmap(struct dmap * dp, s64 blkno, int nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int dbInitDmapTree(struct dmap * dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int dbInitTree(struct dmaptree * dtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int dbInitDmapCtl(struct dmapctl * dcp, int level, int i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static int dbGetL2AGSize(s64 nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * buddy table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * table used for determining buddy sizes within characters of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * dmap bitmap words. the characters themselves serve as indexes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * into the table, with the table elements yielding the maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * binary buddy of free bits within the character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const s8 budtab[256] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^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) * NAME: dbMount()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * FUNCTION: initializate the block allocation map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * memory is allocated for the in-core bmap descriptor and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * the in-core descriptor is initialized from disk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * ipbmap - pointer to in-core inode for the block map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * -ENOMEM - insufficient memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * -EINVAL - wrong bmap data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int dbMount(struct inode *ipbmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct bmap *bmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct dbmap_disk *dbmp_le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * allocate/initialize the in-memory bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* allocate memory for the in-memory bmap descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bmp = kmalloc(sizeof(struct bmap), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (bmp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* read the on-disk bmap descriptor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) mp = read_metapage(ipbmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) kfree(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* copy the on-disk bmap descriptor to its in-memory version. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) dbmp_le = (struct dbmap_disk *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!bmp->db_numag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) kfree(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (i = 0; i < MAXAG; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) bmp->db_agfree[i] = le64_to_cpu(dbmp_le->dn_agfree[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) bmp->db_agsize = le64_to_cpu(dbmp_le->dn_agsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) bmp->db_maxfreebud = dbmp_le->dn_maxfreebud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* release the buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* bind the bmap inode and the bmap descriptor to each other. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) bmp->db_ipbmap = ipbmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) JFS_SBI(ipbmap->i_sb)->bmap = bmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) memset(bmp->db_active, 0, sizeof(bmp->db_active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * allocate/initialize the bmap lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) BMAP_LOCK_INIT(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * NAME: dbUnmount()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * FUNCTION: terminate the block allocation map in preparation for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * file system unmount.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * the in-core bmap descriptor is written to disk and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * the memory for this descriptor is freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * ipbmap - pointer to in-core inode for the block map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int dbUnmount(struct inode *ipbmap, int mounterror)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!(mounterror || isReadOnly(ipbmap)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) dbSync(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * Invalidate the page cache buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) truncate_inode_pages(ipbmap->i_mapping, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* free the memory for the in-memory bmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) kfree(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return (0);
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * dbSync()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int dbSync(struct inode *ipbmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct dbmap_disk *dbmp_le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * write bmap global control page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* get the buffer for the on-disk bmap descriptor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) mp = read_metapage(ipbmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) jfs_err("dbSync: read_metapage failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* copy the in-memory version of the bmap to the on-disk version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dbmp_le = (struct dbmap_disk *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) dbmp_le->dn_mapsize = cpu_to_le64(bmp->db_mapsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) dbmp_le->dn_nfree = cpu_to_le64(bmp->db_nfree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) dbmp_le->dn_l2nbperpage = cpu_to_le32(bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) dbmp_le->dn_numag = cpu_to_le32(bmp->db_numag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) dbmp_le->dn_maxlevel = cpu_to_le32(bmp->db_maxlevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) dbmp_le->dn_maxag = cpu_to_le32(bmp->db_maxag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) dbmp_le->dn_agpref = cpu_to_le32(bmp->db_agpref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) dbmp_le->dn_aglevel = cpu_to_le32(bmp->db_aglevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dbmp_le->dn_agheight = cpu_to_le32(bmp->db_agheight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) dbmp_le->dn_agwidth = cpu_to_le32(bmp->db_agwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dbmp_le->dn_agstart = cpu_to_le32(bmp->db_agstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dbmp_le->dn_agl2size = cpu_to_le32(bmp->db_agl2size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) for (i = 0; i < MAXAG; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dbmp_le->dn_agfree[i] = cpu_to_le64(bmp->db_agfree[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dbmp_le->dn_agsize = cpu_to_le64(bmp->db_agsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dbmp_le->dn_maxfreebud = bmp->db_maxfreebud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* write the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * write out dirty pages of bmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) filemap_write_and_wait(ipbmap->i_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) diWriteSpecial(ipbmap, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * NAME: dbFree()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * FUNCTION: free the specified block range from the working block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * allocation map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * the blocks will be free from the working map one dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * ip - pointer to in-core inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * blkno - starting block number to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * nblocks - number of blocks to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int nb, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) s64 lblkno, rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct super_block *sb = ipbmap->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* block to be freed better be within the mapsize. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) (unsigned long long) blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) (unsigned long long) nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) jfs_error(ip->i_sb, "block to be freed is outside the map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * TRIM the blocks, when mounted with discard option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (JFS_SBI(sb)->flag & JFS_DISCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (JFS_SBI(sb)->minblks_trim <= nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) jfs_issue_discard(ipbmap, blkno, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * free the blocks a dmap at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) for (rem = nblocks; rem > 0; rem -= nb, blkno += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* release previous dmap if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* get the buffer for the current dmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* determine the number of blocks to be freed from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) nb = min(rem, BPERDMAP - (blkno & (BPERDMAP - 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* free the blocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if ((rc = dbFreeDmap(bmp, dp, blkno, nb))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) jfs_error(ip->i_sb, "error in block map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return (rc);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* write the last buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * NAME: dbUpdatePMap()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * FUNCTION: update the allocation state (free or allocate) of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * specified block range in the persistent block allocation map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * the blocks will be updated in the persistent map one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * dmap at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * ipbmap - pointer to in-core inode for the block map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * free - 'true' if block range is to be freed from the persistent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * map; 'false' if it is to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * blkno - starting block number of the range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * nblocks - number of contiguous blocks in the range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * tblk - transaction block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dbUpdatePMap(struct inode *ipbmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int free, s64 blkno, s64 nblocks, struct tblock * tblk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int nblks, dbitno, wbitno, rbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int word, nbits, nwords;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) s64 lblkno, rem, lastlblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct jfs_log *log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int lsn, difft, diffp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* the blocks better be within the mapsize. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (blkno + nblocks > bmp->db_mapsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) (unsigned long long) blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) (unsigned long long) nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) jfs_error(ipbmap->i_sb, "blocks are outside the map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* compute delta of transaction lsn from log syncpt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) lsn = tblk->lsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) log = (struct jfs_log *) JFS_SBI(tblk->sb)->log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) logdiff(difft, lsn, log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * update the block state a dmap at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) lastlblkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) for (rem = nblocks; rem > 0; rem -= nblks, blkno += nblks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* get the buffer for the current dmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (lblkno != lastlblkno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) metapage_wait_for_io(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* determine the bit number and word within the dmap of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * the starting block. also determine how many blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * are to be updated within this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) dbitno = blkno & (BPERDMAP - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) word = dbitno >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) nblks = min(rem, (s64)BPERDMAP - dbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* update the bits of the dmap words. the first and last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * words may only have a subset of their bits updated. if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * this is the case, we'll work against that word (i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * partial first and/or last) only in a single pass. a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * single pass will also be used to update all words that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * are to have all their bits updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) for (rbits = nblks; rbits > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) rbits -= nbits, dbitno += nbits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* determine the bit number within the word and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * the number of bits within the word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) wbitno = dbitno & (DBWORD - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) nbits = min(rbits, DBWORD - wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* check if only part of the word is to be updated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (nbits < DBWORD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* update (free or allocate) the bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * in this word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) (ONES << (DBWORD - nbits) >> wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dp->pmap[word] &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) cpu_to_le32(~mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) dp->pmap[word] |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) cpu_to_le32(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) word += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* one or more words are to have all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * their bits updated. determine how
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * many words and how many bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) nwords = rbits >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) nbits = nwords << L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /* update (free or allocate) the bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * in these words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) memset(&dp->pmap[word], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) nwords * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) memset(&dp->pmap[word], (int) ONES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) nwords * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) word += nwords;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * update dmap lsn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (lblkno == lastlblkno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) lastlblkno = lblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) LOGSYNC_LOCK(log, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (mp->lsn != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* inherit older/smaller lsn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) logdiff(diffp, mp->lsn, log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (difft < diffp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) mp->lsn = lsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* move bp after tblock in logsync list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) list_move(&mp->synclist, &tblk->synclist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* inherit younger/larger clsn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) logdiff(difft, tblk->clsn, log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) logdiff(diffp, mp->clsn, log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (difft > diffp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mp->clsn = tblk->clsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) mp->log = log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) mp->lsn = lsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* insert bp after tblock in logsync list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) log->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) list_add(&mp->synclist, &tblk->synclist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) mp->clsn = tblk->clsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) LOGSYNC_UNLOCK(log, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* write the last buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * NAME: dbNextAG()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * FUNCTION: find the preferred allocation group for new allocations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * Within the allocation groups, we maintain a preferred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * allocation group which consists of a group with at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * average free space. It is the preferred group that we target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * new inode allocation towards. The tie-in between inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * allocation and block allocation occurs as we allocate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * first (data) block of an inode and specify the inode (block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * as the allocation hint for this block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * We try to avoid having more than one open file growing in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * an allocation group, as this will lead to fragmentation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * This differs from the old OS/2 method of trying to keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * empty ags around for large allocations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * ipbmap - pointer to in-core inode for the block map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * the preferred allocation group number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int dbNextAG(struct inode *ipbmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) s64 avgfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int agpref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) s64 hwm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) int next_best = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) BMAP_LOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* determine the average number of free blocks within the ags. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) avgfree = (u32)bmp->db_nfree / bmp->db_numag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * if the current preferred ag does not have an active allocator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * and has at least average freespace, return it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) agpref = bmp->db_agpref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if ((atomic_read(&bmp->db_active[agpref]) == 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) (bmp->db_agfree[agpref] >= avgfree))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* From the last preferred ag, find the next one with at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * average free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) for (i = 0 ; i < bmp->db_numag; i++, agpref++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (agpref == bmp->db_numag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) agpref = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (atomic_read(&bmp->db_active[agpref]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* open file is currently growing in this ag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (bmp->db_agfree[agpref] >= avgfree) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /* Return this one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) bmp->db_agpref = agpref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) } else if (bmp->db_agfree[agpref] > hwm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* Less than avg. freespace, but best so far */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) hwm = bmp->db_agfree[agpref];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) next_best = agpref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * If no inactive ag was found with average freespace, use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * next best
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (next_best != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) bmp->db_agpref = next_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* else leave db_agpref unchanged */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) BMAP_UNLOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* return the preferred group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return (bmp->db_agpref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * NAME: dbAlloc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * FUNCTION: attempt to allocate a specified number of contiguous free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * blocks from the working allocation block map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * the block allocation policy uses hints and a multi-step
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * approach.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * for allocation requests smaller than the number of blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * per dmap, we first try to allocate the new blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * immediately following the hint. if these blocks are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * available, we try to allocate blocks near the hint. if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * no blocks near the hint are available, we next try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * allocate within the same dmap as contains the hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * if no blocks are available in the dmap or the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * request is larger than the dmap size, we try to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * within the same allocation group as contains the hint. if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * this does not succeed, we finally try to allocate anywhere
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * within the aggregate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * we also try to allocate anywhere within the aggregate for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * for allocation requests larger than the allocation group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * size or requests that specify no hint value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * ip - pointer to in-core inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * hint - allocation hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * nblocks - number of contiguous blocks in the range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * results - on successful return, set to the starting block number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * of the newly allocated contiguous range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) int rc, agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct bmap *bmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) s64 lblkno, blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) int l2nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) s64 mapSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int writers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /* assert that nblocks is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) assert(nblocks > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* get the log2 number of blocks to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * if the number of blocks is not a log2 multiple,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * it will be rounded up to the next log2 multiple.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) l2nb = BLKSTOL2(nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) bmp = JFS_SBI(ip->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) mapSize = bmp->db_mapsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* the hint should be within the map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (hint >= mapSize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) jfs_error(ip->i_sb, "the hint is outside the map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* if the number of blocks to be allocated is greater than the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * allocation group size, try to allocate anywhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (l2nb > bmp->db_agl2size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) rc = dbAllocAny(bmp, nblocks, l2nb, results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) goto write_unlock;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * If no hint, let dbNextAG recommend an allocation group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (hint == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto pref_ag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* we would like to allocate close to the hint. adjust the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * hint to the block following the hint since the allocators
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * will start looking for free space starting at this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) blkno = hint + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (blkno >= bmp->db_mapsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) goto pref_ag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) agno = blkno >> bmp->db_agl2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* check if blkno crosses over into a new allocation group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * if so, check if we should allow allocations within this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * allocation group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if ((blkno & (bmp->db_agsize - 1)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /* check if the AG is currently being written to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * if so, call dbNextAG() to find a non-busy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * AG with sufficient free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (atomic_read(&bmp->db_active[agno]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) goto pref_ag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* check if the allocation request size can be satisfied from a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * single dmap. if so, try to allocate from the dmap containing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * the hint using a tiered strategy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (nblocks <= BPERDMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* get the buffer for the dmap containing the hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* first, try to satisfy the allocation request with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * blocks beginning at the hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if ((rc = dbAllocNext(bmp, dp, blkno, (int) nblocks))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) != -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) *results = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) writers = atomic_read(&bmp->db_active[agno]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if ((writers > 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) ((writers == 1) && (JFS_IP(ip)->active_ag != agno))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * Someone else is writing in this allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * group. To avoid fragmenting, try another ag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) goto pref_ag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /* next, try to satisfy the allocation request with blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * near the hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if ((rc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) dbAllocNear(bmp, dp, blkno, (int) nblocks, l2nb, results))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) != -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) /* try to satisfy the allocation request with blocks within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * the same dmap as the hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if ((rc = dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) != -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) /* try to satisfy the allocation request with blocks within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * the same allocation group as the hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) != -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) goto write_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) IWRITE_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) pref_ag:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * Let dbNextAG recommend a preferred allocation group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) agno = dbNextAG(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) /* Try to allocate within this allocation group. if that fails, try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * allocate anywhere in the map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) == -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) rc = dbAllocAny(bmp, nblocks, l2nb, results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) write_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) IWRITE_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) read_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) #ifdef _NOTYET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) * NAME: dbAllocExact()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * FUNCTION: try to allocate the requested extent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * ip - pointer to in-core inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * blkno - extent address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * nblocks - extent length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) s64 lblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * validate extent request:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * note: defragfs policy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * max 64 blocks will be moved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * allocation request size must be satisfied from a single dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (nblocks <= 0 || nblocks > BPERDMAP || blkno >= bmp->db_mapsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (nblocks > ((s64) 1 << bmp->db_maxfreebud)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) /* the free space is no longer available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) /* read in the dmap covering the extent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) /* try to allocate the requested extent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) rc = dbAllocNext(bmp, dp, blkno, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) #endif /* _NOTYET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * NAME: dbReAlloc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * FUNCTION: attempt to extend a current allocation by a specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * number of blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * this routine attempts to satisfy the allocation request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * by first trying to extend the existing allocation in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * place by allocating the additional blocks as the blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * immediately following the current allocation. if these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * blocks are not available, this routine will attempt to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * allocate a new set of contiguous blocks large enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * to cover the existing allocation plus the additional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * number of blocks required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * ip - pointer to in-core inode requiring allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * blkno - starting block of the current allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) * nblocks - number of contiguous blocks within the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * addnblocks - number of blocks to add to the allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) * results - on successful return, set to the starting block number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * of the existing allocation if the existing allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * was extended in place or to a newly allocated contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * range if the existing allocation could not be extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * in place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) dbReAlloc(struct inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) s64 blkno, s64 nblocks, s64 addnblocks, s64 * results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /* try to extend the allocation in place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if ((rc = dbExtend(ip, blkno, nblocks, addnblocks)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) *results = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (rc != -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /* could not extend the allocation in place, so allocate a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * new set of blocks for the entire request (i.e. try to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * a range of contiguous blocks large enough to cover the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * existing allocation plus the additional blocks.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return (dbAlloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) (ip, blkno + nblocks - 1, addnblocks + nblocks, results));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * NAME: dbExtend()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) * FUNCTION: attempt to extend a current allocation by a specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * number of blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * this routine attempts to satisfy the allocation request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * by first trying to extend the existing allocation in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * place by allocating the additional blocks as the blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * immediately following the current allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * ip - pointer to in-core inode requiring allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * blkno - starting block of the current allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * nblocks - number of contiguous blocks within the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * addnblocks - number of blocks to add to the allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) s64 lblkno, lastblkno, extblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) uint rel_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct inode *ipbmap = sbi->ipbmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct bmap *bmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * We don't want a non-aligned extent to cross a page boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (((rel_block = blkno & (sbi->nbperpage - 1))) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) (rel_block + nblocks + addnblocks > sbi->nbperpage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /* get the last block of the current allocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) lastblkno = blkno + nblocks - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /* determine the block number of the block following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) * the existing allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) extblkno = lastblkno + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /* better be within the file system */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) bmp = sbi->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (lastblkno < 0 || lastblkno >= bmp->db_mapsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) jfs_error(ip->i_sb, "the block is outside the filesystem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return -EIO;
^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) /* we'll attempt to extend the current allocation in place by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * allocating the additional blocks as the blocks immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * following the current allocation. we only try to extend the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * current allocation in place if the number of additional blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * can fit into a dmap, the last block of the current allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * is not the last block of the file system, and the start of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * inplace extension is not on an allocation group boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (addnblocks > BPERDMAP || extblkno >= bmp->db_mapsize ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) (extblkno & (bmp->db_agsize - 1)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /* get the buffer for the dmap containing the first block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * of the extension.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) lblkno = BLKTODMAP(extblkno, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* try to allocate the blocks immediately following the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) * current allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) rc = dbAllocNext(bmp, dp, extblkno, (int) addnblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* were we successful ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) /* we were not successful */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) * NAME: dbAllocNext()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * FUNCTION: attempt to allocate the blocks of the specified block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * range within a dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * dp - pointer to dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) * blkno - starting block number of the range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * nblocks - number of contiguous free blocks of the range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * serialization: IREAD_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) int dbitno, word, rembits, nb, nwords, wbitno, nw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) int l2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) s8 *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (dp->tree.leafidx != cpu_to_le32(LEAFIND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmap page\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /* pick up a pointer to the leaves of the dmap tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) leaf = dp->tree.stree + le32_to_cpu(dp->tree.leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) /* determine the bit number and word within the dmap of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) * starting block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) dbitno = blkno & (BPERDMAP - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) word = dbitno >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /* check if the specified block range is contained within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (dbitno + nblocks > BPERDMAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /* check if the starting leaf indicates that anything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * is free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (leaf[word] == NOFREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /* check the dmaps words corresponding to block range to see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * if the block range is free. not all bits of the first and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * last words may be contained within the block range. if this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * is the case, we'll work against those words (i.e. partial first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) * and/or last) on an individual basis (a single pass) and examine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) * the actual bits to determine if they are free. a single pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * will be used for all dmap words fully contained within the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) * specified range. within this pass, the leaves of the dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * tree will be examined to determine if the blocks are free. a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * single leaf may describe the free space of multiple dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * words, so we may visit only a subset of the actual leaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * corresponding to the dmap words of the block range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /* determine the bit number within the word and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * the number of bits within the word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) wbitno = dbitno & (DBWORD - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) nb = min(rembits, DBWORD - wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* check if only part of the word is to be examined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (nb < DBWORD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* check if the bits are free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) mask = (ONES << (DBWORD - nb) >> wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if ((mask & ~le32_to_cpu(dp->wmap[word])) != mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) word += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) /* one or more dmap words are fully contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * within the block range. determine how many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * words and how many bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) nwords = rembits >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) nb = nwords << L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /* now examine the appropriate leaves to determine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) * if the blocks are free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) while (nwords > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) /* does the leaf describe any free space ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (leaf[word] < BUDMIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) /* determine the l2 number of bits provided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) * by this leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) l2size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) min_t(int, leaf[word], NLSTOL2BSZ(nwords));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) /* determine how many words were handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) nw = BUDSIZE(l2size, BUDMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) nwords -= nw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) word += nw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /* allocate the blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return (dbAllocDmap(bmp, dp, blkno, nblocks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * NAME: dbAllocNear()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * FUNCTION: attempt to allocate a number of contiguous free blocks near
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * a specified block (hint) within a dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) * starting with the dmap leaf that covers the hint, we'll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) * check the next four contiguous leaves for sufficient free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * space. if sufficient free space is found, we'll allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * the desired free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * dp - pointer to dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * blkno - block number to allocate near.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) * nblocks - actual number of contiguous free blocks desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * l2nb - log2 number of contiguous free blocks desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) * results - on successful return, set to the starting block number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * of the newly allocated range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * serialization: IREAD_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) dbAllocNear(struct bmap * bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) struct dmap * dp, s64 blkno, int nblocks, int l2nb, s64 * results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) int word, lword, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) s8 *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (dp->tree.leafidx != cpu_to_le32(LEAFIND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmap page\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) leaf = dp->tree.stree + le32_to_cpu(dp->tree.leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) /* determine the word within the dmap that holds the hint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * (i.e. blkno). also, determine the last word in the dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * that we'll include in our examination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) word = (blkno & (BPERDMAP - 1)) >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) lword = min(word + 4, LPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) /* examine the leaves for sufficient free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) for (; word < lword; word++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /* does the leaf describe sufficient free space ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (leaf[word] < l2nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /* determine the block number within the file system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) * of the first block described by this dmap word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) blkno = le64_to_cpu(dp->start) + (word << L2DBWORD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /* if not all bits of the dmap word are free, get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * starting bit number within the dmap word of the required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * string of free bits and adjust the block number with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (leaf[word] < BUDMIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) blkno +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) dbFindBits(le32_to_cpu(dp->wmap[word]), l2nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) /* allocate the blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if ((rc = dbAllocDmap(bmp, dp, blkno, nblocks)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) *results = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^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) * NAME: dbAllocAG()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) * FUNCTION: attempt to allocate the specified number of contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) * free blocks within the specified allocation group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) * unless the allocation group size is equal to the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) * of blocks per dmap, the dmap control pages will be used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * find the required free space, if available. we start the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) * search at the highest dmap control page level which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) * distinctly describes the allocation group's free space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) * (i.e. the highest level at which the allocation group's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * free space is not mixed in with that of any other group).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * in addition, we start the search within this level at a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) * height of the dmapctl dmtree at which the nodes distinctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * describe the allocation group's free space. at this height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * the allocation group's free space may be represented by 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) * or two sub-trees, depending on the allocation group size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) * we search the top nodes of these subtrees left to right for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * sufficient free space. if sufficient free space is found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * the subtree is searched to find the leftmost leaf that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * has free space. once we have made it to the leaf, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * move the search to the next lower level dmap control page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * corresponding to this leaf. we continue down the dmap control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * pages until we find the dmap that contains or starts the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * sufficient free space and we allocate at this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * if the allocation group size is equal to the dmap size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * we'll start at the dmap corresponding to the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * group and attempt the allocation at this level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * the dmap control page search is also not performed if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * allocation group is completely free and we go to the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * dmap of the allocation group to do the allocation. this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * done because the allocation group may be part (not the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * part) of a larger binary buddy system, causing the dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * control pages to indicate no free space (NOFREE) within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) * the allocation group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) * agno - allocation group number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) * nblocks - actual number of contiguous free blocks desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) * l2nb - log2 number of contiguous free blocks desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) * results - on successful return, set to the starting block number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) * of the newly allocated range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) * note: IWRITE_LOCK(ipmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) struct dmapctl *dcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) int rc, ti, i, k, m, n, agperlev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) s64 blkno, lblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) int budmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) /* allocation request should not be for more than the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * allocation group size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (l2nb > bmp->db_agl2size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) "allocation request is larger than the allocation group size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) /* determine the starting block number of the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) blkno = (s64) agno << bmp->db_agl2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) /* check if the allocation group size is the minimum allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * group size or if the allocation group is completely free. if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * the allocation group size is the minimum size of BPERDMAP (i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) * 1 dmap), there is no need to search the dmap control page (below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) * that fully describes the allocation group since the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * group is already fully described by a dmap. in this case, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * just call dbAllocCtl() to search the dmap tree and allocate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * required space if available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * if the allocation group is completely free, dbAllocCtl() is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * also called to allocate the required space. this is done for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) * two reasons. first, it makes no sense searching the dmap control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * pages for free space when we know that free space exists. second,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) * the dmap control pages may indicate that the allocation group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * has no free space if the allocation group is part (not the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) * part) of a larger binary buddy system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (bmp->db_agsize == BPERDMAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) || bmp->db_agfree[agno] == bmp->db_agsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if ((rc == -ENOSPC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) (bmp->db_agfree[agno] == bmp->db_agsize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) printk(KERN_ERR "blkno = %Lx, blocks = %Lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) (unsigned long long) blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) (unsigned long long) nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) "dbAllocCtl failed in free AG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) /* the buffer for the dmap control page that fully describes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * allocation group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) lblkno = BLKTOCTL(blkno, bmp->db_l2nbperpage, bmp->db_aglevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) dcp = (struct dmapctl *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) budmin = dcp->budmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* search the subtree(s) of the dmap control page that describes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) * the allocation group, looking for sufficient free space. to begin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * determine how many allocation groups are represented in a dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) * control page at the control page level (i.e. L0, L1, L2) that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) * fully describes an allocation group. next, determine the starting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) * tree index of this allocation group within the control page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) agperlev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) (1 << (L2LPERCTL - (bmp->db_agheight << 1))) / bmp->db_agwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) ti = bmp->db_agstart + bmp->db_agwidth * (agno & (agperlev - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) /* dmap control page trees fan-out by 4 and a single allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) * group may be described by 1 or 2 subtrees within the ag level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * dmap control page, depending upon the ag size. examine the ag's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * subtrees for sufficient free space, starting with the leftmost
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) * subtree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) for (i = 0; i < bmp->db_agwidth; i++, ti++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) /* is there sufficient free space ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (l2nb > dcp->stree[ti])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) /* sufficient free space found in a subtree. now search down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) * the subtree to find the leftmost leaf that describes this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) * free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) for (k = bmp->db_agheight; k > 0; k--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) for (n = 0, m = (ti << 2) + 1; n < 4; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (l2nb <= dcp->stree[m + n]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) ti = m + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (n == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) "failed descending stree\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) /* determine the block number within the file system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) * that corresponds to this leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) if (bmp->db_aglevel == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) blkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) else if (bmp->db_aglevel == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) blkno &= ~(MAXL1SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) else /* bmp->db_aglevel == 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) blkno &= ~(MAXL0SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) blkno +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) ((s64) (ti - le32_to_cpu(dcp->leafidx))) << budmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) /* release the buffer in preparation for going down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) * the next level of dmap control pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) /* check if we need to continue to search down the lower
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) * level dmap control pages. we need to if the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) * blocks required is less than maximum number of blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) * described at the next lower level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (l2nb < budmin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) /* search the lower level dmap control pages to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) * the starting block number of the dmap that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) * contains or starts off the free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if ((rc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) dbFindCtl(bmp, l2nb, bmp->db_aglevel - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) &blkno))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (rc == -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) "control page inconsistent\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) /* allocate the blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (rc == -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) "unable to allocate blocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /* no space in the allocation group. release the buffer and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * return -ENOSPC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) * NAME: dbAllocAny()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) * FUNCTION: attempt to allocate the specified number of contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) * free blocks anywhere in the file system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * dbAllocAny() attempts to find the sufficient free space by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * searching down the dmap control pages, starting with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * highest level (i.e. L0, L1, L2) control page. if free space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) * large enough to satisfy the desired free space is found, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) * desired free space is allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) * nblocks - actual number of contiguous free blocks desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) * l2nb - log2 number of contiguous free blocks desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * results - on successful return, set to the starting block number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) * of the newly allocated range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) s64 blkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) /* starting with the top level dmap control page, search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) * down the dmap control levels for sufficient free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) * if free space is found, dbFindCtl() returns the starting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) * block number of the dmap that contains or starts off the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) * range of free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if ((rc = dbFindCtl(bmp, l2nb, bmp->db_maxlevel, &blkno)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) /* allocate the blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) if (rc == -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) jfs_error(bmp->db_ipbmap->i_sb, "unable to allocate blocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^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) * NAME: dbDiscardAG()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) * FUNCTION: attempt to discard (TRIM) all free blocks of specific AG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) * algorithm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) * 1) allocate blocks, as large as possible and save them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) * while holding IWRITE_LOCK on ipbmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) * 2) trim all these saved block/length values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) * 3) mark the blocks free again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) * benefit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) * - we work only on one ag at some time, minimizing how long we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) * need to lock ipbmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * - reading / writing the fs is possible most time, even on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * trimming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) * downside:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) * - we write two times to the dmapctl and dmap pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) * - but for me, this seems the best way, better ideas?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) * /TR 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) * ip - pointer to in-core inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) * agno - ag to trim
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) * minlen - minimum value of contiguous blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) * s64 - actual number of blocks trimmed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) s64 nblocks, blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) u64 trimmed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) int rc, l2nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) struct super_block *sb = ipbmap->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) struct range2trim {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) u64 blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) u64 nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) } *totrim, *tt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) /* max blkno / nblocks pairs to trim */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) int count = 0, range_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) u64 max_ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) /* prevent others from writing new stuff here, while trimming */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) nblocks = bmp->db_agfree[agno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) max_ranges = nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) do_div(max_ranges, minlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) range_cnt = min_t(u64, max_ranges + 1, 32 * 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) totrim = kmalloc_array(range_cnt, sizeof(struct range2trim), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) if (totrim == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) jfs_error(bmp->db_ipbmap->i_sb, "no memory for trim array\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) IWRITE_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) tt = totrim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) while (nblocks >= minlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) l2nb = BLKSTOL2(nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /* 0 = okay, -EIO = fatal, -ENOSPC -> try smaller block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) rc = dbAllocAG(bmp, agno, nblocks, l2nb, &blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) tt->blkno = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) tt->nblocks = nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) tt++; count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) /* the whole ag is free, trim now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) if (bmp->db_agfree[agno] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) /* give a hint for the next while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) nblocks = bmp->db_agfree[agno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) } else if (rc == -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) /* search for next smaller log2 block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) l2nb = BLKSTOL2(nblocks) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) nblocks = 1LL << l2nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) /* Trim any already allocated blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) jfs_error(bmp->db_ipbmap->i_sb, "-EIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) /* check, if our trim array is full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (unlikely(count >= range_cnt - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) IWRITE_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) tt->nblocks = 0; /* mark the current end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) for (tt = totrim; tt->nblocks != 0; tt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) /* when mounted with online discard, dbFree() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) * call jfs_issue_discard() itself */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) if (!(JFS_SBI(sb)->flag & JFS_DISCARD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) jfs_issue_discard(ip, tt->blkno, tt->nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) dbFree(ip, tt->blkno, tt->nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) trimmed += tt->nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) kfree(totrim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) return trimmed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) * NAME: dbFindCtl()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) * FUNCTION: starting at a specified dmap control page level and block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) * number, search down the dmap control levels for a range of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) * contiguous free blocks large enough to satisfy an allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) * request for the specified number of free blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) * if sufficient contiguous free blocks are found, this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * returns the starting block number within a dmap page that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) * contains or starts a range of contiqious free blocks that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) * is sufficient in size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) * level - starting dmap control page level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) * l2nb - log2 number of contiguous free blocks desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) * *blkno - on entry, starting block number for conducting the search.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) * on successful return, the first block within a dmap page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) * that contains or starts a range of contiguous free blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) int rc, leafidx, lev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) s64 b, lblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct dmapctl *dcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) int budmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) /* starting at the specified dmap control page level and block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) * number, search down the dmap control levels for the starting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) * block number of a dmap page that contains or starts off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) * sufficient free blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) for (lev = level, b = *blkno; lev >= 0; lev--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) /* get the buffer of the dmap control page for the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) * number and level (i.e. L0, L1, L2).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) lblkno = BLKTOCTL(b, bmp->db_l2nbperpage, lev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) dcp = (struct dmapctl *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) budmin = dcp->budmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) "Corrupt dmapctl page\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) /* search the tree within the dmap control page for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) * sufficient free space. if sufficient free space is found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) * dbFindLeaf() returns the index of the leaf at which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) * free space was found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) rc = dbFindLeaf((dmtree_t *) dcp, l2nb, &leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) /* release the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) /* space found ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) if (lev != level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) "dmap inconsistent\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) /* adjust the block number to reflect the location within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) * the dmap control page (i.e. the leaf) at which free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) * space was found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) b += (((s64) leafidx) << budmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) /* we stop the search at this dmap control page level if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) * the number of blocks required is greater than or equal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) * to the maximum number of blocks described at the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) * (lower) level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) if (l2nb >= budmin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) *blkno = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) * NAME: dbAllocCtl()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) * FUNCTION: attempt to allocate a specified number of contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) * blocks starting within a specific dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) * this routine is called by higher level routines that search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) * the dmap control pages above the actual dmaps for contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) * free space. the result of successful searches by these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) * routines are the starting block numbers within dmaps, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) * the dmaps themselves containing the desired contiguous free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) * space or starting a contiguous free space of desired size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) * that is made up of the blocks of one or more dmaps. these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) * calls should not fail due to insufficent resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) * this routine is called in some cases where it is not known
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) * whether it will fail due to insufficient resources. more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) * specifically, this occurs when allocating from an allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) * group whose size is equal to the number of blocks per dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) * in this case, the dmap control pages are not examined prior
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) * to calling this routine (to save pathlength) and the call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) * might fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) * for a request size that fits within a dmap, this routine relies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) * upon the dmap's dmtree to find the requested contiguous free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) * space. for request sizes that are larger than a dmap, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) * requested free space will start at the first block of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) * first dmap (i.e. blkno).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) * nblocks - actual number of contiguous free blocks to allocate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) * l2nb - log2 number of contiguous free blocks to allocate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) * blkno - starting block number of the dmap to start the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) * from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) * results - on successful return, set to the starting block number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) * of the newly allocated range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) int rc, nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) s64 b, lblkno, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) /* check if the allocation request is confined to a single dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) if (l2nb <= L2BPERDMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) /* get the buffer for the dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) /* try to allocate the blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) rc = dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) mark_metapage_dirty(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) /* allocation request involving multiple dmaps. it must start on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) * a dmap boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) assert((blkno & (BPERDMAP - 1)) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) /* allocate the blocks dmap by dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) for (n = nblocks, b = blkno; n > 0; n -= nb, b += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) /* get the buffer for the dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) lblkno = BLKTODMAP(b, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) goto backout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) /* the dmap better be all free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) if (dp->tree.stree[ROOT] != L2BPERDMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) "the dmap is not all free\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) goto backout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) /* determine how many blocks to allocate from this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) nb = min_t(s64, n, BPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) /* allocate the blocks from the dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) if ((rc = dbAllocDmap(bmp, dp, b, nb))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) goto backout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) /* write the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) /* set the results (starting block number) and return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) *results = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) /* something failed in handling an allocation request involving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) * multiple dmaps. we'll try to clean up by backing out any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) * allocation that has already happened for this request. if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) * we fail in backing out the allocation, we'll mark the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) * system to indicate that blocks have been leaked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) backout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) /* try to backout the allocations dmap by dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) for (n = nblocks - n, b = blkno; n > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) n -= BPERDMAP, b += BPERDMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) /* get the buffer for this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) lblkno = BLKTODMAP(b, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) /* could not back out. mark the file system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) * to indicate that we have leaked blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) "I/O Error: Block Leakage\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) /* free the blocks is this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) if (dbFreeDmap(bmp, dp, b, BPERDMAP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) /* could not back out. mark the file system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) * to indicate that we have leaked blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) jfs_error(bmp->db_ipbmap->i_sb, "Block Leakage\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) /* write the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) * NAME: dbAllocDmapLev()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) * FUNCTION: attempt to allocate a specified number of contiguous blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) * from a specified dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) * this routine checks if the contiguous blocks are available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) * if so, nblocks of blocks are allocated; otherwise, ENOSPC is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) * mp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) * dp - pointer to dmap to attempt to allocate blocks from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) * l2nb - log2 number of contiguous block desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) * nblocks - actual number of contiguous block desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) * results - on successful return, set to the starting block number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) * of the newly allocated range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) * -ENOSPC - insufficient disk resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) * serialization: IREAD_LOCK(ipbmap), e.g., from dbAlloc(), or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) * IWRITE_LOCK(ipbmap), e.g., dbAllocCtl(), held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) dbAllocDmapLev(struct bmap * bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) struct dmap * dp, int nblocks, int l2nb, s64 * results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) s64 blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) int leafidx, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) /* can't be more than a dmaps worth of blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) assert(l2nb <= L2BPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) /* search the tree within the dmap page for sufficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) * free space. if sufficient free space is found, dbFindLeaf()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) * returns the index of the leaf at which free space was found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) /* determine the block number within the file system corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) * to the leaf at which free space was found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) blkno = le64_to_cpu(dp->start) + (leafidx << L2DBWORD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) /* if not all bits of the dmap word are free, get the starting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) * bit number within the dmap word of the required string of free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) * bits and adjust the block number with this value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) if (dp->tree.stree[leafidx + LEAFIND] < BUDMIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) blkno += dbFindBits(le32_to_cpu(dp->wmap[leafidx]), l2nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) /* allocate the blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) if ((rc = dbAllocDmap(bmp, dp, blkno, nblocks)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) *results = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) * NAME: dbAllocDmap()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) * FUNCTION: adjust the disk allocation map to reflect the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) * of a specified block range within a dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) * this routine allocates the specified blocks from the dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) * through a call to dbAllocBits(). if the allocation of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) * block range causes the maximum string of free blocks within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) * the dmap to change (i.e. the value of the root of the dmap's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) * dmtree), this routine will cause this change to be reflected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) * up through the appropriate levels of the dmap control pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) * by a call to dbAdjCtl() for the L0 dmap control page that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) * covers this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) * dp - pointer to dmap to allocate the block range from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) * blkno - starting block number of the block to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) * nblocks - number of blocks to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) s8 oldroot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) /* save the current value of the root (i.e. maximum free string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) * of the dmap tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) oldroot = dp->tree.stree[ROOT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) /* allocate the specified (blocks) bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) dbAllocBits(bmp, dp, blkno, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) /* if the root has not changed, done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) if (dp->tree.stree[ROOT] == oldroot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) /* root changed. bubble the change up to the dmap control pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) * if the adjustment of the upper level control pages fails,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) * backout the bit allocation (thus making everything consistent).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) if ((rc = dbAdjCtl(bmp, blkno, dp->tree.stree[ROOT], 1, 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) dbFreeBits(bmp, dp, blkno, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) * NAME: dbFreeDmap()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) * FUNCTION: adjust the disk allocation map to reflect the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) * of a specified block range within a dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) * this routine frees the specified blocks from the dmap through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) * a call to dbFreeBits(). if the deallocation of the block range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) * causes the maximum string of free blocks within the dmap to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) * change (i.e. the value of the root of the dmap's dmtree), this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) * routine will cause this change to be reflected up through the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) * appropriate levels of the dmap control pages by a call to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) * dbAdjCtl() for the L0 dmap control page that covers this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) * dp - pointer to dmap to free the block range from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) * blkno - starting block number of the block to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) * nblocks - number of blocks to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) s8 oldroot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) int rc = 0, word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) /* save the current value of the root (i.e. maximum free string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) * of the dmap tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) oldroot = dp->tree.stree[ROOT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) /* free the specified (blocks) bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) rc = dbFreeBits(bmp, dp, blkno, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) /* if error or the root has not changed, done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) if (rc || (dp->tree.stree[ROOT] == oldroot))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) /* root changed. bubble the change up to the dmap control pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) * if the adjustment of the upper level control pages fails,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) * backout the deallocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) if ((rc = dbAdjCtl(bmp, blkno, dp->tree.stree[ROOT], 0, 0))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) word = (blkno & (BPERDMAP - 1)) >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) /* as part of backing out the deallocation, we will have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) * to back split the dmap tree if the deallocation caused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) * the freed blocks to become part of a larger binary buddy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) * system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) if (dp->tree.stree[word] == NOFREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) dbBackSplit((dmtree_t *) & dp->tree, word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) dbAllocBits(bmp, dp, blkno, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) * NAME: dbAllocBits()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) * FUNCTION: allocate a specified block range from a dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) * this routine updates the dmap to reflect the working
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) * state allocation of the specified block range. it directly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) * updates the bits of the working map and causes the adjustment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) * of the binary buddy system described by the dmap's dmtree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) * leaves to reflect the bits allocated. it also causes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) * dmap's dmtree, as a whole, to reflect the allocated range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) * dp - pointer to dmap to allocate bits from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) * blkno - starting block number of the bits to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) * nblocks - number of bits to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) * RETURN VALUES: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) int dbitno, word, rembits, nb, nwords, wbitno, nw, agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) dmtree_t *tp = (dmtree_t *) & dp->tree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) s8 *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) /* pick up a pointer to the leaves of the dmap tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) leaf = dp->tree.stree + LEAFIND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) /* determine the bit number and word within the dmap of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) * starting block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) dbitno = blkno & (BPERDMAP - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) word = dbitno >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) /* block range better be within the dmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) assert(dbitno + nblocks <= BPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) /* allocate the bits of the dmap's words corresponding to the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) * range. not all bits of the first and last words may be contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) * within the block range. if this is the case, we'll work against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) * those words (i.e. partial first and/or last) on an individual basis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) * (a single pass), allocating the bits of interest by hand and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) * updating the leaf corresponding to the dmap word. a single pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) * will be used for all dmap words fully contained within the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) * specified range. within this pass, the bits of all fully contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) * dmap words will be marked as free in a single shot and the leaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) * will be updated. a single leaf may describe the free space of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) * multiple dmap words, so we may update only a subset of the actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) * leaves corresponding to the dmap words of the block range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) /* determine the bit number within the word and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) * the number of bits within the word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) wbitno = dbitno & (DBWORD - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) nb = min(rembits, DBWORD - wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) /* check if only part of a word is to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) if (nb < DBWORD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) /* allocate (set to 1) the appropriate bits within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) * this dmap word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) dp->wmap[word] |= cpu_to_le32(ONES << (DBWORD - nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) >> wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) /* update the leaf for this dmap word. in addition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) * to setting the leaf value to the binary buddy max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) * of the updated dmap word, dbSplit() will split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) * the binary system of the leaves if need be.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) dbSplit(tp, word, BUDMIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) dbMaxBud((u8 *) & dp->wmap[word]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) word += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) /* one or more dmap words are fully contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) * within the block range. determine how many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) * words and allocate (set to 1) the bits of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) * words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) nwords = rembits >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) memset(&dp->wmap[word], (int) ONES, nwords * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) /* determine how many bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) nb = nwords << L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) /* now update the appropriate leaves to reflect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) * the allocated words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) for (; nwords > 0; nwords -= nw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) if (leaf[word] < BUDMIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) "leaf page corrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) /* determine what the leaf value should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) * updated to as the minimum of the l2 number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) * of bits being allocated and the l2 number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) * of bits currently described by this leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) size = min_t(int, leaf[word],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) NLSTOL2BSZ(nwords));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) /* update the leaf to reflect the allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) * in addition to setting the leaf value to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) * NOFREE, dbSplit() will split the binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) * system of the leaves to reflect the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) * allocation (size).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) dbSplit(tp, word, size, NOFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) /* get the number of dmap words handled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) nw = BUDSIZE(size, BUDMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) word += nw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) /* update the free count for this dmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) le32_add_cpu(&dp->nfree, -nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) BMAP_LOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) /* if this allocation group is completely free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) * update the maximum allocation group number if this allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) * group is the new max.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) agno = blkno >> bmp->db_agl2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) if (agno > bmp->db_maxag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) bmp->db_maxag = agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) /* update the free count for the allocation group and map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) bmp->db_agfree[agno] -= nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) bmp->db_nfree -= nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) BMAP_UNLOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) * NAME: dbFreeBits()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) * FUNCTION: free a specified block range from a dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) * this routine updates the dmap to reflect the working
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) * state allocation of the specified block range. it directly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) * updates the bits of the working map and causes the adjustment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) * of the binary buddy system described by the dmap's dmtree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) * leaves to reflect the bits freed. it also causes the dmap's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) * dmtree, as a whole, to reflect the deallocated range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) * dp - pointer to dmap to free bits from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) * blkno - starting block number of the bits to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) * nblocks - number of bits to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) * RETURN VALUES: 0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) int dbitno, word, rembits, nb, nwords, wbitno, nw, agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) dmtree_t *tp = (dmtree_t *) & dp->tree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) /* determine the bit number and word within the dmap of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) * starting block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) dbitno = blkno & (BPERDMAP - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) word = dbitno >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) /* block range better be within the dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) assert(dbitno + nblocks <= BPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) /* free the bits of the dmaps words corresponding to the block range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) * not all bits of the first and last words may be contained within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) * the block range. if this is the case, we'll work against those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) * words (i.e. partial first and/or last) on an individual basis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) * (a single pass), freeing the bits of interest by hand and updating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) * the leaf corresponding to the dmap word. a single pass will be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) * for all dmap words fully contained within the specified range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) * within this pass, the bits of all fully contained dmap words will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) * be marked as free in a single shot and the leaves will be updated. a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) * single leaf may describe the free space of multiple dmap words,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) * so we may update only a subset of the actual leaves corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) * to the dmap words of the block range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) * dbJoin() is used to update leaf values and will join the binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) * buddy system of the leaves if the new leaf values indicate this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) * should be done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) /* determine the bit number within the word and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) * the number of bits within the word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) wbitno = dbitno & (DBWORD - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) nb = min(rembits, DBWORD - wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) /* check if only part of a word is to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) if (nb < DBWORD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) /* free (zero) the appropriate bits within this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) * dmap word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) dp->wmap[word] &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) cpu_to_le32(~(ONES << (DBWORD - nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) >> wbitno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) /* update the leaf for this dmap word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) rc = dbJoin(tp, word,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) dbMaxBud((u8 *) & dp->wmap[word]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) word += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) /* one or more dmap words are fully contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) * within the block range. determine how many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) * words and free (zero) the bits of these words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) nwords = rembits >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) memset(&dp->wmap[word], 0, nwords * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) /* determine how many bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) nb = nwords << L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) /* now update the appropriate leaves to reflect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) * the freed words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) for (; nwords > 0; nwords -= nw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) /* determine what the leaf value should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) * updated to as the minimum of the l2 number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) * of bits being freed and the l2 (max) number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) * of bits that can be described by this leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) min(LITOL2BSZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) (word, L2LPERDMAP, BUDMIN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) NLSTOL2BSZ(nwords));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) /* update the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) rc = dbJoin(tp, word, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) /* get the number of dmap words handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) nw = BUDSIZE(size, BUDMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) word += nw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) /* update the free count for this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) le32_add_cpu(&dp->nfree, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) BMAP_LOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) /* update the free count for the allocation group and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) * map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) agno = blkno >> bmp->db_agl2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) bmp->db_nfree += nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) bmp->db_agfree[agno] += nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) /* check if this allocation group is not completely free and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) * if it is currently the maximum (rightmost) allocation group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) * if so, establish the new maximum allocation group number by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) * searching left for the first allocation group with allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) if ((bmp->db_agfree[agno] == bmp->db_agsize && agno == bmp->db_maxag) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) (agno == bmp->db_numag - 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) bmp->db_agfree[agno] == (bmp-> db_mapsize & (BPERDMAP - 1)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) while (bmp->db_maxag > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) bmp->db_maxag -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) if (bmp->db_agfree[bmp->db_maxag] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) bmp->db_agsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) /* re-establish the allocation group preference if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) * current preference is right of the maximum allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) * group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) if (bmp->db_agpref > bmp->db_maxag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) bmp->db_agpref = bmp->db_maxag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) BMAP_UNLOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) return 0;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) * NAME: dbAdjCtl()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) * FUNCTION: adjust a dmap control page at a specified level to reflect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) * the change in a lower level dmap or dmap control page's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) * maximum string of free blocks (i.e. a change in the root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) * of the lower level object's dmtree) due to the allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) * or deallocation of a range of blocks with a single dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) * on entry, this routine is provided with the new value of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) * the lower level dmap or dmap control page root and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) * starting block number of the block range whose allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) * or deallocation resulted in the root change. this range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) * is respresented by a single leaf of the current dmapctl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) * and the leaf will be updated with this value, possibly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) * causing a binary buddy system within the leaves to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) * split or joined. the update may also cause the dmapctl's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) * dmtree to be updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) * if the adjustment of the dmap control page, itself, causes its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) * root to change, this change will be bubbled up to the next dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) * control level by a recursive call to this routine, specifying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) * the new root value and the next dmap control page level to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) * be adjusted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) * bmp - pointer to bmap descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) * blkno - the first block of a block range within a dmap. it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) * the allocation or deallocation of this block range that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) * requires the dmap control page to be adjusted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) * newval - the new value of the lower level dmap or dmap control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) * page root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) * alloc - 'true' if adjustment is due to an allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) * level - current level of dmap control page (i.e. L0, L1, L2) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) * be adjusted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) s8 oldroot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) int oldval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) s64 lblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) struct dmapctl *dcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) int rc, leafno, ti;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) /* get the buffer for the dmap control page for the specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) * block number and control page level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) lblkno = BLKTOCTL(blkno, bmp->db_l2nbperpage, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) dcp = (struct dmapctl *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) /* determine the leaf number corresponding to the block and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) * the index within the dmap control tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) leafno = BLKTOCTLLEAF(blkno, dcp->budmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) ti = leafno + le32_to_cpu(dcp->leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) /* save the current leaf value and the current root level (i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) * maximum l2 free string described by this dmapctl).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) oldval = dcp->stree[ti];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) oldroot = dcp->stree[ROOT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) /* check if this is a control page update for an allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) * if so, update the leaf to reflect the new leaf value using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) * dbSplit(); otherwise (deallocation), use dbJoin() to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) * the leaf with the new value. in addition to updating the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) * leaf, dbSplit() will also split the binary buddy system of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) * the leaves, if required, and bubble new values within the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) * dmapctl tree, if required. similarly, dbJoin() will join
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) * the binary buddy system of leaves and bubble new values up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) * the dmapctl tree as required by the new leaf value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) if (alloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) /* check if we are in the middle of a binary buddy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) * system. this happens when we are performing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) * first allocation out of an allocation group that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) * is part (not the first part) of a larger binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) * buddy system. if we are in the middle, back split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) * the system prior to calling dbSplit() which assumes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) * that it is at the front of a binary buddy system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) if (oldval == NOFREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) rc = dbBackSplit((dmtree_t *) dcp, leafno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) oldval = dcp->stree[ti];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) rc = dbJoin((dmtree_t *) dcp, leafno, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) /* check if the root of the current dmap control page changed due
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) * to the update and if the current dmap control page is not at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) * the current top level (i.e. L0, L1, L2) of the map. if so (i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) * root changed and this is not the top level), call this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) * again (recursion) for the next higher level of the mapping to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) * reflect the change in root for the current dmap control page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) if (dcp->stree[ROOT] != oldroot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) /* are we below the top level of the map. if so,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) * bubble the root up to the next higher level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) if (level < bmp->db_maxlevel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) /* bubble up the new root of this dmap control page to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) * the next level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) if ((rc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) dbAdjCtl(bmp, blkno, dcp->stree[ROOT], alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) level + 1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) /* something went wrong in bubbling up the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) * root value, so backout the changes to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) * current dmap control page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) if (alloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) dbJoin((dmtree_t *) dcp, leafno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) oldval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) /* the dbJoin() above might have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) * caused a larger binary buddy system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) * to form and we may now be in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) * middle of it. if this is the case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) * back split the buddies.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) if (dcp->stree[ti] == NOFREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) dbBackSplit((dmtree_t *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) dcp, leafno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) dbSplit((dmtree_t *) dcp, leafno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) dcp->budmin, oldval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) /* release the buffer and return the error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) /* we're at the top level of the map. update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) * the bmap control page to reflect the size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) * of the maximum free buddy system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) assert(level == bmp->db_maxlevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) if (bmp->db_maxfreebud != oldroot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) jfs_error(bmp->db_ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) "the maximum free buddy is not the old root\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) bmp->db_maxfreebud = dcp->stree[ROOT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) /* write the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) * NAME: dbSplit()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) * FUNCTION: update the leaf of a dmtree with a new value, splitting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) * the leaf from the binary buddy system of the dmtree's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) * leaves, as required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) * tp - pointer to the tree containing the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) * leafno - the number of the leaf to be updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) * splitsz - the size the binary buddy system starting at the leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) * must be split to, specified as the log2 number of blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) * newval - the new value for the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) * RETURN VALUES: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) int budsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) int cursz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) s8 *leaf = tp->dmt_stree + le32_to_cpu(tp->dmt_leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) /* check if the leaf needs to be split.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) if (leaf[leafno] > tp->dmt_budmin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) /* the split occurs by cutting the buddy system in half
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) * at the specified leaf until we reach the specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) * size. pick up the starting split size (current size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) * - 1 in l2) and the corresponding buddy size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) cursz = leaf[leafno] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) budsz = BUDSIZE(cursz, tp->dmt_budmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) /* split until we reach the specified size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) while (cursz >= splitsz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) /* update the buddy's leaf with its new value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) dbAdjTree(tp, leafno ^ budsz, cursz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) /* on to the next size and buddy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) cursz -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) budsz >>= 1;
^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) /* adjust the dmap tree to reflect the specified leaf's new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) * value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) dbAdjTree(tp, leafno, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) * NAME: dbBackSplit()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) * FUNCTION: back split the binary buddy system of dmtree leaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) * that hold a specified leaf until the specified leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) * starts its own binary buddy system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) * the allocators typically perform allocations at the start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) * of binary buddy systems and dbSplit() is used to accomplish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) * any required splits. in some cases, however, allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) * may occur in the middle of a binary system and requires a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) * back split, with the split proceeding out from the middle of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) * the system (less efficient) rather than the start of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) * system (more efficient). the cases in which a back split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) * is required are rare and are limited to the first allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) * within an allocation group which is a part (not first part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) * of a larger binary buddy system and a few exception cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) * in which a previous join operation must be backed out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) * tp - pointer to the tree containing the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) * leafno - the number of the leaf to be updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) * RETURN VALUES: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) static int dbBackSplit(dmtree_t * tp, int leafno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) int budsz, bud, w, bsz, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) int cursz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) s8 *leaf = tp->dmt_stree + le32_to_cpu(tp->dmt_leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) /* leaf should be part (not first part) of a binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) * buddy system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) assert(leaf[leafno] == NOFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) /* the back split is accomplished by iteratively finding the leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) * that starts the buddy system that contains the specified leaf and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) * splitting that system in two. this iteration continues until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) * the specified leaf becomes the start of a buddy system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) * determine maximum possible l2 size for the specified leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) LITOL2BSZ(leafno, le32_to_cpu(tp->dmt_l2nleafs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) tp->dmt_budmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) /* determine the number of leaves covered by this size. this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) * is the buddy size that we will start with as we search for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) * the buddy system that contains the specified leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) budsz = BUDSIZE(size, tp->dmt_budmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) /* back split.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) while (leaf[leafno] == NOFREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) /* find the leftmost buddy leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) for (w = leafno, bsz = budsz;; bsz <<= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) w = (w < bud) ? w : bud) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) if (bsz >= le32_to_cpu(tp->dmt_nleafs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) jfs_err("JFS: block map error in dbBackSplit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) /* determine the buddy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) bud = w ^ bsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) /* check if this buddy is the start of the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) if (leaf[bud] != NOFREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) /* split the leaf at the start of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) * system in two.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) cursz = leaf[bud] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) dbSplit(tp, bud, cursz, cursz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) }
^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) if (leaf[leafno] != size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) jfs_err("JFS: wrong leaf value in dbBackSplit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) * NAME: dbJoin()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) * FUNCTION: update the leaf of a dmtree with a new value, joining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) * the leaf with other leaves of the dmtree into a multi-leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) * binary buddy system, as required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) * tp - pointer to the tree containing the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) * leafno - the number of the leaf to be updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) * newval - the new value for the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) * RETURN VALUES: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) static int dbJoin(dmtree_t * tp, int leafno, int newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) int budsz, buddy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) s8 *leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) /* can the new leaf value require a join with other leaves ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) if (newval >= tp->dmt_budmin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) /* pickup a pointer to the leaves of the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) leaf = tp->dmt_stree + le32_to_cpu(tp->dmt_leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) /* try to join the specified leaf into a large binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) * buddy system. the join proceeds by attempting to join
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) * the specified leafno with its buddy (leaf) at new value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) * if the join occurs, we attempt to join the left leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) * of the joined buddies with its buddy at new value + 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) * we continue to join until we find a buddy that cannot be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) * joined (does not have a value equal to the size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) * last join) or until all leaves have been joined into a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) * single system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) * get the buddy size (number of words covered) of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) * the new value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) budsz = BUDSIZE(newval, tp->dmt_budmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) /* try to join.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) while (budsz < le32_to_cpu(tp->dmt_nleafs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) /* get the buddy leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) buddy = leafno ^ budsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) /* if the leaf's new value is greater than its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) * buddy's value, we join no more.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) if (newval > leaf[buddy])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) /* It shouldn't be less */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) if (newval < leaf[buddy])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) /* check which (leafno or buddy) is the left buddy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) * the left buddy gets to claim the blocks resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) * from the join while the right gets to claim none.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) * the left buddy is also eligible to participate in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) * a join at the next higher level while the right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) * is not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) if (leafno < buddy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) /* leafno is the left buddy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) dbAdjTree(tp, buddy, NOFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) /* buddy is the left buddy and becomes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) * leafno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) dbAdjTree(tp, leafno, NOFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) leafno = buddy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) /* on to try the next join.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) newval += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) budsz <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) /* update the leaf value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) dbAdjTree(tp, leafno, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) * NAME: dbAdjTree()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) * FUNCTION: update a leaf of a dmtree with a new value, adjusting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) * the dmtree, as required, to reflect the new leaf value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) * the combination of any buddies must already be done before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) * this is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) * tp - pointer to the tree to be adjusted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) * leafno - the number of the leaf to be updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) * newval - the new value for the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) * RETURN VALUES: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) int lp, pp, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) int max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) /* pick up the index of the leaf for this leafno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) lp = leafno + le32_to_cpu(tp->dmt_leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) /* is the current value the same as the old value ? if so,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) * there is nothing to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) if (tp->dmt_stree[lp] == newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) /* set the new value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) tp->dmt_stree[lp] = newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) /* bubble the new value up the tree as required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) for (k = 0; k < le32_to_cpu(tp->dmt_height); k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) /* get the index of the first leaf of the 4 leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) * group containing the specified leaf (leafno).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) lp = ((lp - 1) & ~0x03) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) /* get the index of the parent of this 4 leaf group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) pp = (lp - 1) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) /* determine the maximum of the 4 leaves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) max = TREEMAX(&tp->dmt_stree[lp]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) /* if the maximum of the 4 is the same as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) * parent's value, we're done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) if (tp->dmt_stree[pp] == max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) /* parent gets new value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) tp->dmt_stree[pp] = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) /* parent becomes leaf for next go-round.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) lp = pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) * NAME: dbFindLeaf()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) * FUNCTION: search a dmtree_t for sufficient free blocks, returning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) * the index of a leaf describing the free blocks if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) * sufficient free blocks are found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) * the search starts at the top of the dmtree_t tree and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) * proceeds down the tree to the leftmost leaf with sufficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) * free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) * tp - pointer to the tree to be searched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) * l2nb - log2 number of free blocks to search for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) * leafidx - return pointer to be set to the index of the leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) * describing at least l2nb free blocks if sufficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) * free blocks are found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) * -ENOSPC - insufficient free blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) int ti, n = 0, k, x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) /* first check the root of the tree to see if there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) * sufficient free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) if (l2nb > tp->dmt_stree[ROOT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) /* sufficient free space available. now search down the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) * starting at the next level for the leftmost leaf that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) * describes sufficient free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) for (k = le32_to_cpu(tp->dmt_height), ti = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) k > 0; k--, ti = ((ti + n) << 2) + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) /* search the four nodes at this level, starting from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) * the left.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) for (x = ti, n = 0; n < 4; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) /* sufficient free space found. move to the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) * level (or quit if this is the last level).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) if (l2nb <= tp->dmt_stree[x + n])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) /* better have found something since the higher
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) * levels of the tree said it was here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) assert(n < 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) /* set the return to the leftmost leaf describing sufficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) * free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) *leafidx = x + n - le32_to_cpu(tp->dmt_leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) * NAME: dbFindBits()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) * FUNCTION: find a specified number of binary buddy free bits within a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) * dmap bitmap word value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) * this routine searches the bitmap value for (1 << l2nb) free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) * bits at (1 << l2nb) alignments within the value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) * word - dmap bitmap word value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) * l2nb - number of free bits specified as a log2 number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) * starting bit number of free bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) static int dbFindBits(u32 word, int l2nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) int bitno, nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) /* get the number of bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) nb = 1 << l2nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) assert(nb <= DBWORD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) /* complement the word so we can use a mask (i.e. 0s represent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) * free bits) and compute the mask.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) word = ~word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) mask = ONES << (DBWORD - nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) /* scan the word for nb free bits at nb alignments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) for (bitno = 0; mask != 0; bitno += nb, mask >>= nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) if ((mask & word) == mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) ASSERT(bitno < 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) /* return the bit number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) return (bitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) * NAME: dbMaxBud(u8 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) * FUNCTION: determine the largest binary buddy string of free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) * bits within 32-bits of the map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) * cp - pointer to the 32-bit value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) * largest binary buddy of free bits within a dmap word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) static int dbMaxBud(u8 * cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) signed char tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) /* check if the wmap word is all free. if so, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) * free buddy size is BUDMIN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) if (*((uint *) cp) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) return (BUDMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) /* check if the wmap word is half free. if so, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) * free buddy size is BUDMIN-1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) if (*((u16 *) cp) == 0 || *((u16 *) cp + 1) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) return (BUDMIN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) /* not all free or half free. determine the free buddy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) * size thru table lookup using quarters of the wmap word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) tmp1 = max(budtab[cp[2]], budtab[cp[3]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) tmp2 = max(budtab[cp[0]], budtab[cp[1]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) return (max(tmp1, tmp2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) * NAME: cnttz(uint word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) * FUNCTION: determine the number of trailing zeros within a 32-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) * value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) * value - 32-bit value to be examined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) * count of trailing zeros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) static int cnttz(u32 word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) for (n = 0; n < 32; n++, word >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) if (word & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) return (n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) * NAME: cntlz(u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) * FUNCTION: determine the number of leading zeros within a 32-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) * value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) * value - 32-bit value to be examined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) * count of leading zeros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) static int cntlz(u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) for (n = 0; n < 32; n++, value <<= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) if (value & HIGHORDER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) return (n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) * NAME: blkstol2(s64 nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) * FUNCTION: convert a block count to its log2 value. if the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) * count is not a l2 multiple, it is rounded up to the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) * larger l2 multiple.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) * nb - number of blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) * log2 number of blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) static int blkstol2(s64 nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) int l2nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) s64 mask; /* meant to be signed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) mask = (s64) 1 << (64 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) /* count the leading bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) for (l2nb = 0; l2nb < 64; l2nb++, mask >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) /* leading bit found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) if (nb & mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) /* determine the l2 value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) l2nb = (64 - 1) - l2nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) /* check if we need to round up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) if (~mask & nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) l2nb++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) return (l2nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) assert(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) return 0; /* fix compiler warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) * NAME: dbAllocBottomUp()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) * FUNCTION: alloc the specified block range from the working block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) * allocation map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) * the blocks will be alloc from the working map one dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) * at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) * ip - pointer to in-core inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) * blkno - starting block number to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) * nblocks - number of blocks to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) * RETURN VALUES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) * -EIO - i/o error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) struct metapage *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) int nb, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) s64 lblkno, rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) /* block to be allocated better be within the mapsize. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) ASSERT(nblocks <= bmp->db_mapsize - blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) * allocate the blocks a dmap at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) for (rem = nblocks; rem > 0; rem -= nb, blkno += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) /* release previous dmap if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) if (mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) /* get the buffer for the current dmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) if (mp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) /* determine the number of blocks to be allocated from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) * this dmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) nb = min(rem, BPERDMAP - (blkno & (BPERDMAP - 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) /* allocate the blocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) if ((rc = dbAllocDmapBU(bmp, dp, blkno, nb))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) release_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) /* write the last buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) IREAD_UNLOCK(ipbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) int dbitno, word, rembits, nb, nwords, wbitno, agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) s8 oldroot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) struct dmaptree *tp = (struct dmaptree *) & dp->tree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) /* save the current value of the root (i.e. maximum free string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) * of the dmap tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) oldroot = tp->stree[ROOT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) /* determine the bit number and word within the dmap of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) * starting block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) dbitno = blkno & (BPERDMAP - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) word = dbitno >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) /* block range better be within the dmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) assert(dbitno + nblocks <= BPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) /* allocate the bits of the dmap's words corresponding to the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) * range. not all bits of the first and last words may be contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) * within the block range. if this is the case, we'll work against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) * those words (i.e. partial first and/or last) on an individual basis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) * (a single pass), allocating the bits of interest by hand and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) * updating the leaf corresponding to the dmap word. a single pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) * will be used for all dmap words fully contained within the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) * specified range. within this pass, the bits of all fully contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) * dmap words will be marked as free in a single shot and the leaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) * will be updated. a single leaf may describe the free space of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) * multiple dmap words, so we may update only a subset of the actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) * leaves corresponding to the dmap words of the block range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) /* determine the bit number within the word and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) * the number of bits within the word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) wbitno = dbitno & (DBWORD - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) nb = min(rembits, DBWORD - wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) /* check if only part of a word is to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) if (nb < DBWORD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) /* allocate (set to 1) the appropriate bits within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) * this dmap word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) dp->wmap[word] |= cpu_to_le32(ONES << (DBWORD - nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) >> wbitno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) word++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) /* one or more dmap words are fully contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) * within the block range. determine how many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) * words and allocate (set to 1) the bits of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) * words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) nwords = rembits >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) memset(&dp->wmap[word], (int) ONES, nwords * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) /* determine how many bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) nb = nwords << L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) word += nwords;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) }
^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) /* update the free count for this dmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) le32_add_cpu(&dp->nfree, -nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) /* reconstruct summary tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) dbInitDmapTree(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) BMAP_LOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) /* if this allocation group is completely free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) * update the highest active allocation group number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) * if this allocation group is the new max.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) agno = blkno >> bmp->db_agl2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) if (agno > bmp->db_maxag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) bmp->db_maxag = agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) /* update the free count for the allocation group and map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) bmp->db_agfree[agno] -= nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) bmp->db_nfree -= nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) BMAP_UNLOCK(bmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) /* if the root has not changed, done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) if (tp->stree[ROOT] == oldroot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) /* root changed. bubble the change up to the dmap control pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) * if the adjustment of the upper level control pages fails,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) * backout the bit allocation (thus making everything consistent).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) if ((rc = dbAdjCtl(bmp, blkno, tp->stree[ROOT], 1, 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) dbFreeBits(bmp, dp, blkno, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) * NAME: dbExtendFS()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) * FUNCTION: extend bmap from blkno for nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) * dbExtendFS() updates bmap ready for dbAllocBottomUp();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) * L2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) * L1---------------------------------L1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) * | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) * L0---------L0---------L0 L0---------L0---------L0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) * | | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) * d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,.,dm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) * L2L1L0d0,...,dnL0d0,...,dnL0d0,...,dnL1L0d0,...,dnL0d0,...,dnL0d0,..dm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) * <---old---><----------------------------extend----------------------->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) struct jfs_sb_info *sbi = JFS_SBI(ipbmap->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) int nbperpage = sbi->nbperpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) int i, i0 = true, j, j0 = true, k, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) s64 newsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) s64 p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) struct metapage *mp, *l2mp, *l1mp = NULL, *l0mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) struct dmapctl *l2dcp, *l1dcp, *l0dcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) struct dmap *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) s8 *l0leaf, *l1leaf, *l2leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) struct bmap *bmp = sbi->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) int agno, l2agsize, oldl2agsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) s64 ag_rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) newsize = blkno + nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) jfs_info("dbExtendFS: blkno:%Ld nblocks:%Ld newsize:%Ld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) (long long) blkno, (long long) nblocks, (long long) newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) * initialize bmap control page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) * all the data in bmap control page should exclude
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) * the mkfs hidden dmap page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) /* update mapsize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) bmp->db_mapsize = newsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) bmp->db_maxlevel = BMAPSZTOLEV(bmp->db_mapsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) /* compute new AG size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) l2agsize = dbGetL2AGSize(newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) oldl2agsize = bmp->db_agl2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) bmp->db_agl2size = l2agsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) bmp->db_agsize = 1 << l2agsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) /* compute new number of AG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) agno = bmp->db_numag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) bmp->db_numag = newsize >> l2agsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) bmp->db_numag += ((u32) newsize % (u32) bmp->db_agsize) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) * reconfigure db_agfree[]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) * from old AG configuration to new AG configuration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) * coalesce contiguous k (newAGSize/oldAGSize) AGs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) * i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) * note: new AG size = old AG size * (2**x).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) if (l2agsize == oldl2agsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) goto extend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) k = 1 << (l2agsize - oldl2agsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) ag_rem = bmp->db_agfree[0]; /* save agfree[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) for (i = 0, n = 0; i < agno; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) bmp->db_agfree[n] = 0; /* init collection point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) /* coalesce contiguous k AGs; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) for (j = 0; j < k && i < agno; j++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) /* merge AGi to AGn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) bmp->db_agfree[n] += bmp->db_agfree[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) bmp->db_agfree[0] += ag_rem; /* restore agfree[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) for (; n < MAXAG; n++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) bmp->db_agfree[n] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) * update highest active ag number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) bmp->db_maxag = bmp->db_maxag / k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) * extend bmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) * update bit maps and corresponding level control pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) * global control page db_nfree, db_agfree[agno], db_maxfreebud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) extend:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) /* get L2 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) p = BMAPBLKNO + nbperpage; /* L2 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) l2mp = read_metapage(ipbmap, p, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) if (!l2mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) jfs_error(ipbmap->i_sb, "L2 page could not be read\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) l2dcp = (struct dmapctl *) l2mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) /* compute start L1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) k = blkno >> L2MAXL1SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) l2leaf = l2dcp->stree + CTLLEAFIND + k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) p = BLKTOL1(blkno, sbi->l2nbperpage); /* L1 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) * extend each L1 in L2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) for (; k < LPERCTL; k++, p += nbperpage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) /* get L1 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) if (j0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) /* read in L1 page: (blkno & (MAXL1SIZE - 1)) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) l1mp = read_metapage(ipbmap, p, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) if (l1mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) l1dcp = (struct dmapctl *) l1mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) /* compute start L0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) j = (blkno & (MAXL1SIZE - 1)) >> L2MAXL0SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) l1leaf = l1dcp->stree + CTLLEAFIND + j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) p = BLKTOL0(blkno, sbi->l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) j0 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) /* assign/init L1 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) l1mp = get_metapage(ipbmap, p, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) if (l1mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) l1dcp = (struct dmapctl *) l1mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) /* compute start L0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) l1leaf = l1dcp->stree + CTLLEAFIND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) p += nbperpage; /* 1st L0 of L1.k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) }
^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) * extend each L0 in L1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) for (; j < LPERCTL; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) /* get L0 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) if (i0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) /* read in L0 page: (blkno & (MAXL0SIZE - 1)) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) l0mp = read_metapage(ipbmap, p, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) if (l0mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) l0dcp = (struct dmapctl *) l0mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) /* compute start dmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) i = (blkno & (MAXL0SIZE - 1)) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) L2BPERDMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) l0leaf = l0dcp->stree + CTLLEAFIND + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) p = BLKTODMAP(blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) sbi->l2nbperpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) i0 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) /* assign/init L0 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) l0mp = get_metapage(ipbmap, p, PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) if (l0mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) l0dcp = (struct dmapctl *) l0mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) /* compute start dmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) l0leaf = l0dcp->stree + CTLLEAFIND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) p += nbperpage; /* 1st dmap of L0.j */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) * extend each dmap in L0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) for (; i < LPERCTL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) * reconstruct the dmap page, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) * initialize corresponding parent L0 leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) if ((n = blkno & (BPERDMAP - 1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) /* read in dmap page: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) mp = read_metapage(ipbmap, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) n = min(nblocks, (s64)BPERDMAP - n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) /* assign/init dmap page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) mp = read_metapage(ipbmap, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) PSIZE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) if (mp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) n = min_t(s64, nblocks, BPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) dp = (struct dmap *) mp->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) *l0leaf = dbInitDmap(dp, blkno, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) bmp->db_nfree += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) agno = le64_to_cpu(dp->start) >> l2agsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) bmp->db_agfree[agno] += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) write_metapage(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) l0leaf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) p += nbperpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) blkno += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) nblocks -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) if (nblocks == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) } /* for each dmap in a L0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) * build current L0 page from its leaves, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) * initialize corresponding parent L1 leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) *l1leaf = dbInitDmapCtl(l0dcp, 0, ++i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) write_metapage(l0mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) l0mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) if (nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) l1leaf++; /* continue for next L0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) /* more than 1 L0 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) if (j > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) break; /* build L1 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) /* summarize in global bmap page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) bmp->db_maxfreebud = *l1leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) release_metapage(l1mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) release_metapage(l2mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) goto finalize;
^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) } /* for each L0 in a L1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) * build current L1 page from its leaves, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) * initialize corresponding parent L2 leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) *l2leaf = dbInitDmapCtl(l1dcp, 1, ++j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) write_metapage(l1mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) l1mp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) if (nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) l2leaf++; /* continue for next L1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) /* more than 1 L1 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) if (k > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) break; /* build L2 page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) /* summarize in global bmap page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) bmp->db_maxfreebud = *l2leaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) release_metapage(l2mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) goto finalize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) } /* for each L1 in a L2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) jfs_error(ipbmap->i_sb, "function has not returned as expected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) errout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) if (l0mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) release_metapage(l0mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) if (l1mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) release_metapage(l1mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) release_metapage(l2mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) * finalize bmap control page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) finalize:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) * dbFinalizeBmap()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) void dbFinalizeBmap(struct inode *ipbmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) int actags, inactags, l2nl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) s64 ag_rem, actfree, inactfree, avgfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) int i, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) * finalize bmap control page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) //finalize:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) * compute db_agpref: preferred ag to allocate from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) * (the leftmost ag with average free space in it);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) //agpref:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) /* get the number of active ags and inacitve ags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) actags = bmp->db_maxag + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) inactags = bmp->db_numag - actags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) ag_rem = bmp->db_mapsize & (bmp->db_agsize - 1); /* ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) /* determine how many blocks are in the inactive allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) * groups. in doing this, we must account for the fact that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) * the rightmost group might be a partial group (i.e. file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) * system size is not a multiple of the group size).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) inactfree = (inactags && ag_rem) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) ((inactags - 1) << bmp->db_agl2size) + ag_rem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) : inactags << bmp->db_agl2size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) /* determine how many free blocks are in the active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) * allocation groups plus the average number of free blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) * within the active ags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) actfree = bmp->db_nfree - inactfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) avgfree = (u32) actfree / (u32) actags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) /* if the preferred allocation group has not average free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) * re-establish the preferred group as the leftmost
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) * group with average free space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) if (bmp->db_agfree[bmp->db_agpref] < avgfree) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) for (bmp->db_agpref = 0; bmp->db_agpref < actags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) bmp->db_agpref++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) if (bmp->db_agfree[bmp->db_agpref] >= avgfree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) if (bmp->db_agpref >= bmp->db_numag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) jfs_error(ipbmap->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) "cannot find ag with average freespace\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) * compute db_aglevel, db_agheight, db_width, db_agstart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) * an ag is covered in aglevel dmapctl summary tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) * at agheight level height (from leaf) with agwidth number of nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) * each, which starts at agstart index node of the smmary tree node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) * array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) bmp->db_aglevel = BMAPSZTOLEV(bmp->db_agsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) l2nl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) bmp->db_agl2size - (L2BPERDMAP + bmp->db_aglevel * L2LPERCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) bmp->db_agheight = l2nl >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) bmp->db_agwidth = 1 << (l2nl - (bmp->db_agheight << 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) for (i = 5 - bmp->db_agheight, bmp->db_agstart = 0, n = 1; i > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) bmp->db_agstart += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) n <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) }
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) * NAME: dbInitDmap()/ujfs_idmap_page()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) * FUNCTION: initialize working/persistent bitmap of the dmap page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) * for the specified number of blocks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) * at entry, the bitmaps had been initialized as free (ZEROS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) * The number of blocks will only account for the actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) * existing blocks. Blocks which don't actually exist in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) * the aggregate will be marked as allocated (ONES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) * dp - pointer to page of map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) * nblocks - number of blocks this page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) * RETURNS: NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) static int dbInitDmap(struct dmap * dp, s64 Blkno, int nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) int blkno, w, b, r, nw, nb, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) /* starting block number within the dmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) blkno = Blkno & (BPERDMAP - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) if (blkno == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) dp->nblocks = dp->nfree = cpu_to_le32(nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) dp->start = cpu_to_le64(Blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) if (nblocks == BPERDMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) memset(&dp->wmap[0], 0, LPERDMAP * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) memset(&dp->pmap[0], 0, LPERDMAP * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) goto initTree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) le32_add_cpu(&dp->nblocks, nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) le32_add_cpu(&dp->nfree, nblocks);
^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) /* word number containing start block number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) w = blkno >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) * free the bits corresponding to the block range (ZEROS):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) * note: not all bits of the first and last words may be contained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) * within the block range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) for (r = nblocks; r > 0; r -= nb, blkno += nb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) /* number of bits preceding range to be freed in the word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) b = blkno & (DBWORD - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) /* number of bits to free in the word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) nb = min(r, DBWORD - b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) /* is partial word to be freed ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) if (nb < DBWORD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) /* free (set to 0) from the bitmap word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) dp->wmap[w] &= cpu_to_le32(~(ONES << (DBWORD - nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) >> b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) dp->pmap[w] &= cpu_to_le32(~(ONES << (DBWORD - nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) >> b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) /* skip the word freed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) w++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) /* free (set to 0) contiguous bitmap words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) nw = r >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) memset(&dp->wmap[w], 0, nw * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) memset(&dp->pmap[w], 0, nw * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) /* skip the words freed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) nb = nw << L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) w += nw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) * mark bits following the range to be freed (non-existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) * blocks) as allocated (ONES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) if (blkno == BPERDMAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) goto initTree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) /* the first word beyond the end of existing blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) w = blkno >> L2DBWORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) /* does nblocks fall on a 32-bit boundary ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) b = blkno & (DBWORD - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) if (b) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) /* mark a partial word allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) dp->wmap[w] = dp->pmap[w] = cpu_to_le32(ONES >> b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) w++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) /* set the rest of the words in the page to allocated (ONES) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) for (i = w; i < LPERDMAP; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) dp->pmap[i] = dp->wmap[i] = cpu_to_le32(ONES);
^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) * init tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) initTree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) return (dbInitDmapTree(dp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) * NAME: dbInitDmapTree()/ujfs_complete_dmap()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) * FUNCTION: initialize summary tree of the specified dmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) * at entry, bitmap of the dmap has been initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) * dp - dmap to complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) * blkno - starting block number for this dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) * treemax - will be filled in with max free for this dmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) * RETURNS: max free string at the root of the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) static int dbInitDmapTree(struct dmap * dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) struct dmaptree *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) s8 *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) /* init fixed info of tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) tp = &dp->tree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) tp->nleafs = cpu_to_le32(LPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) tp->l2nleafs = cpu_to_le32(L2LPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) tp->leafidx = cpu_to_le32(LEAFIND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) tp->height = cpu_to_le32(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) tp->budmin = BUDMIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) /* init each leaf from corresponding wmap word:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) * note: leaf is set to NOFREE(-1) if all blocks of corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) * bitmap word are allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) cp = tp->stree + le32_to_cpu(tp->leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) for (i = 0; i < LPERDMAP; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) *cp++ = dbMaxBud((u8 *) & dp->wmap[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) /* build the dmap's binary buddy summary tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) return (dbInitTree(tp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) * NAME: dbInitTree()/ujfs_adjtree()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) * FUNCTION: initialize binary buddy summary tree of a dmap or dmapctl.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) * at entry, the leaves of the tree has been initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) * from corresponding bitmap word or root of summary tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) * of the child control page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) * configure binary buddy system at the leaf level, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) * bubble up the values of the leaf nodes up the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) * cp - Pointer to the root of the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) * l2leaves- Number of leaf nodes as a power of 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) * l2min - Number of blocks that can be covered by a leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) * as a power of 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) * RETURNS: max free string at the root of the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) static int dbInitTree(struct dmaptree * dtp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) int l2max, l2free, bsize, nextb, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) int child, parent, nparent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) s8 *tp, *cp, *cp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) tp = dtp->stree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) /* Determine the maximum free string possible for the leaves */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) l2max = le32_to_cpu(dtp->l2nleafs) + dtp->budmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) * configure the leaf levevl into binary buddy system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) * Try to combine buddies starting with a buddy size of 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) * (i.e. two leaves). At a buddy size of 1 two buddy leaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) * can be combined if both buddies have a maximum free of l2min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) * the combination will result in the left-most buddy leaf having
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) * a maximum free of l2min+1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) * After processing all buddies for a given size, process buddies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) * at the next higher buddy size (i.e. current size * 2) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) * the next maximum free (current free + 1).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) * This continues until the maximum possible buddy combination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) * yields maximum free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) for (l2free = dtp->budmin, bsize = 1; l2free < l2max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) l2free++, bsize = nextb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) /* get next buddy size == current buddy pair size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) nextb = bsize << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) /* scan each adjacent buddy pair at current buddy size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) for (i = 0, cp = tp + le32_to_cpu(dtp->leafidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) i < le32_to_cpu(dtp->nleafs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) i += nextb, cp += nextb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) /* coalesce if both adjacent buddies are max free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) if (*cp == l2free && *(cp + bsize) == l2free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) *cp = l2free + 1; /* left take right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) *(cp + bsize) = -1; /* right give left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) * bubble summary information of leaves up the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) * Starting at the leaf node level, the four nodes described by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) * the higher level parent node are compared for a maximum free and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) * this maximum becomes the value of the parent node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) * when all lower level nodes are processed in this fashion then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) * move up to the next level (parent becomes a lower level node) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) * continue the process for that level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) for (child = le32_to_cpu(dtp->leafidx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) nparent = le32_to_cpu(dtp->nleafs) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) nparent > 0; nparent >>= 2, child = parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) /* get index of 1st node of parent level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) parent = (child - 1) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) /* set the value of the parent node as the maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) * of the four nodes of the current level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) for (i = 0, cp = tp + child, cp1 = tp + parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) i < nparent; i++, cp += 4, cp1++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) *cp1 = TREEMAX(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) return (*tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) * dbInitDmapCtl()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) * function: initialize dmapctl page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) static int dbInitDmapCtl(struct dmapctl * dcp, int level, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) { /* start leaf index not covered by range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) s8 *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) dcp->nleafs = cpu_to_le32(LPERCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) dcp->l2nleafs = cpu_to_le32(L2LPERCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) dcp->leafidx = cpu_to_le32(CTLLEAFIND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) dcp->height = cpu_to_le32(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) dcp->budmin = L2BPERDMAP + L2LPERCTL * level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) * initialize the leaves of current level that were not covered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) * by the specified input block range (i.e. the leaves have no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) * low level dmapctl or dmap).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) cp = &dcp->stree[CTLLEAFIND + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) for (; i < LPERCTL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) *cp++ = NOFREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) /* build the dmap's binary buddy summary tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) return (dbInitTree((struct dmaptree *) dcp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) * NAME: dbGetL2AGSize()/ujfs_getagl2size()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) * FUNCTION: Determine log2(allocation group size) from aggregate size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) * PARAMETERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) * nblocks - Number of blocks in aggregate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) * RETURNS: log2(allocation group size) in aggregate blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) static int dbGetL2AGSize(s64 nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) s64 sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) s64 m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) int l2sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) if (nblocks < BPERDMAP * MAXAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) return (L2BPERDMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) /* round up aggregate size to power of 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) m = ((u64) 1 << (64 - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) for (l2sz = 64; l2sz >= 0; l2sz--, m >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) if (m & nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) sz = (s64) 1 << l2sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) if (sz < nblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) l2sz += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) /* agsize = roundupSize/max_number_of_ag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) return (l2sz - L2MAXAG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) * NAME: dbMapFileSizeToMapSize()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) * FUNCTION: compute number of blocks the block allocation map file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) * can cover from the map file size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) * RETURNS: Number of blocks which can be covered by this block map file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) * maximum number of map pages at each level including control pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) #define MAXL0PAGES (1 + LPERCTL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) #define MAXL1PAGES (1 + LPERCTL * MAXL0PAGES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) * convert number of map pages to the zero origin top dmapctl level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) #define BMAPPGTOLEV(npages) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) (((npages) <= 3 + MAXL0PAGES) ? 0 : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) struct super_block *sb = ipbmap->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) s64 nblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) s64 npages, ndmaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) int level, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) int complete, factor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) nblocks = ipbmap->i_size >> JFS_SBI(sb)->l2bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) npages = nblocks >> JFS_SBI(sb)->l2nbperpage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) level = BMAPPGTOLEV(npages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) /* At each level, accumulate the number of dmap pages covered by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) * the number of full child levels below it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) * repeat for the last incomplete child level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) ndmaps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) npages--; /* skip the first global control page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) /* skip higher level control pages above top level covered by map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) npages -= (2 - level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) npages--; /* skip top level's control page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) for (i = level; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) factor =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) (i == 2) ? MAXL1PAGES : ((i == 1) ? MAXL0PAGES : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) complete = (u32) npages / factor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) ((i == 1) ? LPERCTL : 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) /* pages in last/incomplete child */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) npages = (u32) npages % factor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) /* skip incomplete child's level control page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) npages--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) /* convert the number of dmaps into the number of blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) * which can be covered by the dmaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) nblocks = ndmaps << L2BPERDMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) return (nblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) }