blob: df2ca2a408e78a99e1d50112648eb074b4d277e0 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*/
#ifndef __LIBFROG_FSGEOM_H__
#define __LIBFROG_FSGEOM_H__
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);
/*
* 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));
}
#endif /* __LIBFROG_FSGEOM_H__ */