1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*/
#ifndef __LIBFROG_FSGEOM_H__
#define __LIBFROG_FSGEOM_H__
struct xfs_rtgroup_geometry;
void xfs_report_geom(struct xfs_fsop_geom *geo, const char *mntpoint,
const char *logname, const char *rtname);
int xfrog_geometry(int fd, struct xfs_fsop_geom *fsgeo);
int xfrog_ag_geometry(int fd, unsigned int agno, struct xfs_ag_geometry *ageo);
int xfrog_rtgroup_geometry(int fd, unsigned int rgno,
struct xfs_rtgroup_geometry *rgeo);
/*
* Structure for recording whatever observations we want about the level of
* xfs runtime support for this fd. Right now we only store the fd and fs
* geometry.
*/
struct xfs_fd {
/* ioctl file descriptor */
int fd;
/* filesystem geometry */
struct xfs_fsop_geom fsgeom;
/* log2 of sb_agblocks (rounded up) */
unsigned int agblklog;
/* log2 of sb_blocksize */
unsigned int blocklog;
/* log2 of sb_inodesize */
unsigned int inodelog;
/* log2 of sb_inopblock */
unsigned int inopblog;
/* bits for agino in inum */
unsigned int aginolog;
/* log2 of sb_blocksize / sb_sectsize */
unsigned int blkbb_log;
/* XFROG_FLAG_* state flags */
unsigned int flags;
};
/* Only use v1 bulkstat/inumbers ioctls. */
#define XFROG_FLAG_BULKSTAT_FORCE_V1 (1 << 0)
/* Only use v5 bulkstat/inumbers ioctls. */
#define XFROG_FLAG_BULKSTAT_FORCE_V5 (1 << 1)
/* Only use the older one-at-a-time scrub ioctl. */
#define XFROG_FLAG_SCRUB_FORCE_SINGLE (1 << 2)
/* Only use the vectored scrub ioctl. */
#define XFROG_FLAG_SCRUB_FORCE_VECTOR (1 << 3)
/* Static initializers */
#define XFS_FD_INIT(_fd) { .fd = (_fd), }
#define XFS_FD_INIT_EMPTY XFS_FD_INIT(-1)
int xfd_prepare_geometry(struct xfs_fd *xfd);
void xfd_install_geometry(struct xfs_fd *xfd, struct xfs_fsop_geom *fsgeom);
int xfd_open(struct xfs_fd *xfd, const char *pathname, int flags);
int xfd_close(struct xfs_fd *xfd);
/* Convert AG number and AG inode number into fs inode number. */
static inline uint64_t
cvt_agino_to_ino(
const struct xfs_fd *xfd,
uint32_t agno,
uint32_t agino)
{
return ((uint64_t)agno << xfd->aginolog) + agino;
}
/* Convert fs inode number into AG number. */
static inline uint32_t
cvt_ino_to_agno(
const struct xfs_fd *xfd,
uint64_t ino)
{
return ino >> xfd->aginolog;
}
/* Convert fs inode number into AG inode number. */
static inline uint32_t
cvt_ino_to_agino(
const struct xfs_fd *xfd,
uint64_t ino)
{
return ino & ((1ULL << xfd->aginolog) - 1);
}
/*
* Convert a linear fs block offset number into bytes. This is the runtime
* equivalent of XFS_FSB_TO_B, which means that it is /not/ for segmented fsbno
* format (= agno | agbno) that we use internally for the data device.
*/
static inline uint64_t
cvt_off_fsb_to_b(
const struct xfs_fd *xfd,
uint64_t fsb)
{
return fsb << xfd->blocklog;
}
/*
* Convert bytes into a (rounded down) linear fs block offset number. This is
* the runtime equivalent of XFS_B_TO_FSBT. It does not produce segmented
* fsbno numbers (= agno | agbno).
*/
static inline uint64_t
cvt_b_to_off_fsbt(
const struct xfs_fd *xfd,
uint64_t bytes)
{
return bytes >> xfd->blocklog;
}
/* Convert sector number to bytes. */
static inline uint64_t
cvt_bbtob(
uint64_t daddr)
{
return daddr << BBSHIFT;
}
/* Convert bytes to sector number, rounding down. */
static inline uint64_t
cvt_btobbt(
uint64_t bytes)
{
return bytes >> BBSHIFT;
}
/* Convert fs block number to sector number. */
static inline uint64_t
cvt_off_fsb_to_bb(
struct xfs_fd *xfd,
uint64_t fsbno)
{
return fsbno << xfd->blkbb_log;
}
/* Convert sector number to fs block number, rounded down. */
static inline uint64_t
cvt_bb_to_off_fsbt(
struct xfs_fd *xfd,
uint64_t daddr)
{
return daddr >> xfd->blkbb_log;
}
/* Convert AG number and AG block to fs block number */
static inline uint64_t
cvt_agb_to_daddr(
struct xfs_fd *xfd,
uint32_t agno,
uint32_t agbno)
{
return cvt_off_fsb_to_bb(xfd,
(uint64_t)agno * xfd->fsgeom.agblocks + agbno);
}
/* Convert sector number to AG number. */
static inline uint32_t
cvt_daddr_to_agno(
struct xfs_fd *xfd,
uint64_t daddr)
{
return cvt_bb_to_off_fsbt(xfd, daddr) / xfd->fsgeom.agblocks;
}
/* Convert sector number to AG block number. */
static inline uint32_t
cvt_daddr_to_agbno(
struct xfs_fd *xfd,
uint64_t daddr)
{
return cvt_bb_to_off_fsbt(xfd, daddr) % xfd->fsgeom.agblocks;
}
/* Convert AG number and AG block to a byte location on disk. */
static inline uint64_t
cvt_agbno_to_b(
struct xfs_fd *xfd,
xfs_agnumber_t agno,
xfs_agblock_t agbno)
{
return cvt_bbtob(cvt_agb_to_daddr(xfd, agno, agbno));
}
/* Convert byte location on disk to AG block. */
static inline xfs_agblock_t
cvt_b_to_agbno(
struct xfs_fd *xfd,
uint64_t byteno)
{
return cvt_daddr_to_agbno(xfd, cvt_btobbt(byteno));
}
/* Return the number of bytes in an rtgroup. */
static inline uint64_t
bytes_per_rtgroup(
const struct xfs_fsop_geom *fsgeo)
{
if (!fsgeo->rgcount)
return 0;
return (uint64_t)fsgeo->rgextents * fsgeo->rtextsize *
fsgeo->blocksize;
}
#endif /* __LIBFROG_FSGEOM_H__ */
|