Commit 7cd5006b authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: add a new ioctl to describe allocation group geometry

Add a new ioctl to describe an allocation group's geometry.
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent 1b6d968d
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "xfs_ialloc.h" #include "xfs_ialloc.h"
#include "xfs_rmap.h" #include "xfs_rmap.h"
#include "xfs_ag.h" #include "xfs_ag.h"
#include "xfs_ag_resv.h"
static struct xfs_buf * static struct xfs_buf *
xfs_get_aghdr_buf( xfs_get_aghdr_buf(
...@@ -461,3 +462,54 @@ xfs_ag_extend_space( ...@@ -461,3 +462,54 @@ xfs_ag_extend_space(
len, &XFS_RMAP_OINFO_SKIP_UPDATE, len, &XFS_RMAP_OINFO_SKIP_UPDATE,
XFS_AG_RESV_NONE); XFS_AG_RESV_NONE);
} }
/* Retrieve AG geometry. */
int
xfs_ag_get_geometry(
struct xfs_mount *mp,
xfs_agnumber_t agno,
struct xfs_ag_geometry *ageo)
{
struct xfs_buf *agi_bp;
struct xfs_buf *agf_bp;
struct xfs_agi *agi;
struct xfs_agf *agf;
struct xfs_perag *pag;
unsigned int freeblks;
int error;
if (agno >= mp->m_sb.sb_agcount)
return -EINVAL;
/* Lock the AG headers. */
error = xfs_ialloc_read_agi(mp, NULL, agno, &agi_bp);
if (error)
return error;
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agf_bp);
if (error)
goto out_agi;
pag = xfs_perag_get(mp, agno);
/* Fill out form. */
memset(ageo, 0, sizeof(*ageo));
ageo->ag_number = agno;
agi = XFS_BUF_TO_AGI(agi_bp);
ageo->ag_icount = be32_to_cpu(agi->agi_count);
ageo->ag_ifree = be32_to_cpu(agi->agi_freecount);
agf = XFS_BUF_TO_AGF(agf_bp);
ageo->ag_length = be32_to_cpu(agf->agf_length);
freeblks = pag->pagf_freeblks +
pag->pagf_flcount +
pag->pagf_btreeblks -
xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE);
ageo->ag_freeblks = freeblks;
/* Release resources. */
xfs_perag_put(pag);
xfs_buf_relse(agf_bp);
out_agi:
xfs_buf_relse(agi_bp);
return error;
}
...@@ -26,5 +26,7 @@ struct aghdr_init_data { ...@@ -26,5 +26,7 @@ struct aghdr_init_data {
int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id); int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
int xfs_ag_extend_space(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_ag_extend_space(struct xfs_mount *mp, struct xfs_trans *tp,
struct aghdr_init_data *id, xfs_extlen_t len); struct aghdr_init_data *id, xfs_extlen_t len);
int xfs_ag_get_geometry(struct xfs_mount *mp, xfs_agnumber_t agno,
struct xfs_ag_geometry *ageo);
#endif /* __LIBXFS_AG_H */ #endif /* __LIBXFS_AG_H */
...@@ -267,6 +267,19 @@ typedef struct xfs_fsop_resblks { ...@@ -267,6 +267,19 @@ typedef struct xfs_fsop_resblks {
#define XFS_MIN_DBLOCKS(s) ((xfs_rfsblock_t)((s)->sb_agcount - 1) * \ #define XFS_MIN_DBLOCKS(s) ((xfs_rfsblock_t)((s)->sb_agcount - 1) * \
(s)->sb_agblocks + XFS_MIN_AG_BLOCKS) (s)->sb_agblocks + XFS_MIN_AG_BLOCKS)
/*
* Output for XFS_IOC_AG_GEOMETRY
*/
struct xfs_ag_geometry {
uint32_t ag_number; /* i/o: AG number */
uint32_t ag_length; /* o: length in blocks */
uint32_t ag_freeblks; /* o: free space */
uint32_t ag_icount; /* o: inodes allocated */
uint32_t ag_ifree; /* o: inodes free */
uint32_t ag_reserved32; /* o: zero */
uint64_t ag_reserved[13];/* o: zero */
};
/* /*
* Structures for XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG & XFS_IOC_FSGROWFSRT * Structures for XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG & XFS_IOC_FSGROWFSRT
*/ */
...@@ -620,6 +633,7 @@ struct xfs_scrub_metadata { ...@@ -620,6 +633,7 @@ struct xfs_scrub_metadata {
#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks) #define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
/* XFS_IOC_GETFSMAP ------ hoisted 59 */ /* XFS_IOC_GETFSMAP ------ hoisted 59 */
#define XFS_IOC_SCRUB_METADATA _IOWR('X', 60, struct xfs_scrub_metadata) #define XFS_IOC_SCRUB_METADATA _IOWR('X', 60, struct xfs_scrub_metadata)
#define XFS_IOC_AG_GEOMETRY _IOWR('X', 61, struct xfs_ag_geometry)
/* /*
* ioctl commands that replace IRIX syssgi()'s * ioctl commands that replace IRIX syssgi()'s
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "xfs_fsmap.h" #include "xfs_fsmap.h"
#include "scrub/xfs_scrub.h" #include "scrub/xfs_scrub.h"
#include "xfs_sb.h" #include "xfs_sb.h"
#include "xfs_ag.h"
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/cred.h> #include <linux/cred.h>
...@@ -804,6 +805,26 @@ xfs_ioc_fsgeometry( ...@@ -804,6 +805,26 @@ xfs_ioc_fsgeometry(
return 0; return 0;
} }
STATIC int
xfs_ioc_ag_geometry(
struct xfs_mount *mp,
void __user *arg)
{
struct xfs_ag_geometry ageo;
int error;
if (copy_from_user(&ageo, arg, sizeof(ageo)))
return -EFAULT;
error = xfs_ag_get_geometry(mp, ageo.ag_number, &ageo);
if (error)
return error;
if (copy_to_user(arg, &ageo, sizeof(ageo)))
return -EFAULT;
return 0;
}
/* /*
* Linux extended inode flags interface. * Linux extended inode flags interface.
*/ */
...@@ -1930,6 +1951,9 @@ xfs_file_ioctl( ...@@ -1930,6 +1951,9 @@ xfs_file_ioctl(
case XFS_IOC_FSGEOMETRY: case XFS_IOC_FSGEOMETRY:
return xfs_ioc_fsgeometry(mp, arg, 5); return xfs_ioc_fsgeometry(mp, arg, 5);
case XFS_IOC_AG_GEOMETRY:
return xfs_ioc_ag_geometry(mp, arg);
case XFS_IOC_GETVERSION: case XFS_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *)arg); return put_user(inode->i_generation, (int __user *)arg);
......
...@@ -563,6 +563,7 @@ xfs_file_compat_ioctl( ...@@ -563,6 +563,7 @@ xfs_file_compat_ioctl(
case XFS_IOC_DIOINFO: case XFS_IOC_DIOINFO:
case XFS_IOC_FSGEOMETRY_V4: case XFS_IOC_FSGEOMETRY_V4:
case XFS_IOC_FSGEOMETRY: case XFS_IOC_FSGEOMETRY:
case XFS_IOC_AG_GEOMETRY:
case XFS_IOC_FSGETXATTR: case XFS_IOC_FSGETXATTR:
case XFS_IOC_FSSETXATTR: case XFS_IOC_FSSETXATTR:
case XFS_IOC_FSGETXATTRA: case XFS_IOC_FSGETXATTRA:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment