* [PATCH 03/15] xfs: Introduce a new ioctl(2) to set AG state
@ 2012-11-16 6:45 Jeff Liu
2012-11-16 9:06 ` Jeff Liu
0 siblings, 1 reply; 2+ messages in thread
From: Jeff Liu @ 2012-11-16 6:45 UTC (permalink / raw)
To: xfs
Introduce a new ioctl(2) for setting a.g. state.
- Add a new structure xfs_ioc_agstate.
- Add a macro to indicate an a.g. is offline.
- Add XFS_IOC_SET_AGSTATE for ioctl(2).
- Teach xfs_alloc_log_agf() aware of agf_state.
Signed-off-by: Jie Liu <jeff.liu@oracle.com>
---
fs/xfs/xfs_ag.h | 17 ++++++++++++
fs/xfs/xfs_alloc.c | 1 +
fs/xfs/xfs_fs.h | 1 +
fs/xfs/xfs_fsops.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-
fs/xfs/xfs_ioctl.c | 13 +++++++++
fs/xfs/xfs_trans.h | 2 +-
6 files changed, 104 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index fd578e6..e2588d9 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -235,6 +235,23 @@ typedef struct xfs_perag {
} xfs_perag_t;
/*
+ * Structure for ioctl per a.g. state get/set.
+ */
+typedef struct xfs_ioc_agstate {
+ xfs_agnumber_t agno;
+ __uint32_t state;
+} xfs_ioc_agstate_t;
+
+/*
+ * Skip an AG with below state for inodes/blocks allocation.
+ */
+#define XFS_AG_STATE_ALLOC_DENY (1 << 0)
+#define XFS_AG_ALL_STATE (XFS_AG_STATE_ALLOC_DENY)
+
+extern int xfs_set_agstate(struct xfs_mount *mp,
+ struct xfs_ioc_agstate *agstate);
+
+/*
* tags for inode radix tree
*/
#define XFS_ICI_NO_TAG (-1) /* special flag for an untagged lookup
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 4f33c32..bd9cc41 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2005,6 +2005,7 @@ xfs_alloc_log_agf(
offsetof(xfs_agf_t, agf_freeblks),
offsetof(xfs_agf_t, agf_longest),
offsetof(xfs_agf_t, agf_btreeblks),
+ offsetof(xfs_agf_t, agf_state),
sizeof(xfs_agf_t)
};
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index c13fed8..991c09e 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -486,6 +486,7 @@ typedef struct xfs_handle {
#define XFS_IOC_ATTRMULTI_BY_HANDLE _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
#define XFS_IOC_FSGEOMETRY _IOR ('X', 124, struct xfs_fsop_geom)
#define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t)
+#define XFS_IOC_SET_AGSTATE _IOW('X', 126, struct xfs_ioc_agstate)
/* XFS_IOC_GETFSUUID ---------- deprecated 140 */
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index c25b094..3742511 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -112,10 +112,79 @@ xfs_fs_geometry(
return 0;
}
+/*
+ * Setting a.g. persistent state as well as perag incore state.
+ */
+static void
+xfs_set_agstate_private(
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_buf_t *agbp, /* buffer for a.g. freelist header */
+ xfs_perag_t *pag, /* incore perag structure */
+ __uint32_t state) /* a.g. state to be set */
+{
+ xfs_agf_t *agf; /* a.g. free space */
+
+ agf = XFS_BUF_TO_AGF(agbp);
+ agf->agf_state |= cpu_to_be32(state);
+ pag->pag_state |= state;
+
+ xfs_alloc_log_agf(tp, agbp, XFS_AGF_STATE);
+}
+
+/*
+ * Setting the state of the given AG.
+ *
+ * For now, we can set a given AG to be offline or online, and
+ * allocaters will skip an AG being offline to allocate inodes
+ * or free space.
+ */
+int
+xfs_set_agstate(
+ xfs_mount_t *mp,
+ xfs_ioc_agstate_t *agstate)
+{
+ xfs_agnumber_t agno;
+ xfs_perag_t *pag;
+ xfs_trans_t *tp;
+ xfs_buf_t *bp;
+ int error;
+
+ agno = agstate->agno;
+ if (agno >= mp->m_sb.sb_agcount)
+ return XFS_ERROR(EINVAL);
+
+ if ((agstate->state & XFS_AG_ALL_STATE) != agstate->state)
+ return XFS_ERROR(EINVAL);
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_SET_AGSTATE);
+ error = xfs_trans_reserve(tp, 0, XFS_SETAGSTATE_LOG_RES(mp), 0, 0,
+ XFS_DEFAULT_LOG_COUNT);
+ if (error) {
+ xfs_trans_cancel(tp, 0);
+ return error;
+ }
+
+ error = xfs_alloc_read_agf(mp, tp, agno, 0, &bp);
+ if (error)
+ goto error0;
+
+ pag = xfs_perag_get(mp, agno);
+ xfs_set_agstate_private(tp, bp, pag, agstate->state);
+ xfs_perag_put(pag);
+
+ xfs_trans_set_sync(tp);
+ xfs_trans_commit(tp, 0);
+ return error;
+
+error0:
+ xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+ return error;
+}
+
static int
xfs_growfs_data_private(
- xfs_mount_t *mp, /* mount point for filesystem */
- xfs_growfs_data_t *in) /* growfs data input struct */
+ xfs_mount_t *mp, /* mount point for filesystem */
+ xfs_growfs_data_t *in) /* growfs data input struct */
{
xfs_agf_t *agf;
xfs_agi_t *agi;
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 8305f2a..efe39ef 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1602,6 +1602,19 @@ xfs_file_ioctl(
error = xfs_errortag_clearall(mp, 1);
return -error;
+ case XFS_IOC_SET_AGSTATE: {
+ xfs_ioc_agstate_t in;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&in, arg, sizeof(in)))
+ return -XFS_ERROR(EFAULT);
+
+ error = xfs_set_agstate(mp, &in);
+ return -error;
+ }
+
default:
return -ENOTTY;
}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index a4f4092..14f897d 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -264,7 +264,7 @@ struct xfs_log_item_desc {
(128 * (ext + (ext * XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))))
#define XFS_ATTRRM_LOG_RES(mp) ((mp)->m_reservations.tr_attrrm)
#define XFS_CLEAR_AGI_BUCKET_LOG_RES(mp) ((mp)->m_reservations.tr_clearagi)
-#define XFS_SETAGSTATE_LOG_RES ((mp)->m_reservations.tr_setagstate)
+#define XFS_SETAGSTATE_LOG_RES(mp) ((mp)->m_reservations.tr_setagstate)
/*
* Various log count values.
--
1.7.4.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH 03/15] xfs: Introduce a new ioctl(2) to set AG state
2012-11-16 6:45 [PATCH 03/15] xfs: Introduce a new ioctl(2) to set AG state Jeff Liu
@ 2012-11-16 9:06 ` Jeff Liu
0 siblings, 0 replies; 2+ messages in thread
From: Jeff Liu @ 2012-11-16 9:06 UTC (permalink / raw)
To: xfs; +Cc: jeff.liu
On 11/16/2012 02:45 PM, Jeff Liu wrote:
> Introduce a new ioctl(2) for setting a.g. state.
>
> - Add a new structure xfs_ioc_agstate.
> - Add a macro to indicate an a.g. is offline.
> - Add XFS_IOC_SET_AGSTATE for ioctl(2).
> - Teach xfs_alloc_log_agf() aware of agf_state.
>
>
> Signed-off-by: Jie Liu <jeff.liu@oracle.com>
> ---
> fs/xfs/xfs_ag.h | 17 ++++++++++++
> fs/xfs/xfs_alloc.c | 1 +
> fs/xfs/xfs_fs.h | 1 +
> fs/xfs/xfs_fsops.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> fs/xfs/xfs_ioctl.c | 13 +++++++++
> fs/xfs/xfs_trans.h | 2 +-
> 6 files changed, 104 insertions(+), 3 deletions(-)
>
> diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
> index fd578e6..e2588d9 100644
> --- a/fs/xfs/xfs_ag.h
> +++ b/fs/xfs/xfs_ag.h
> @@ -235,6 +235,23 @@ typedef struct xfs_perag {
> } xfs_perag_t;
>
> /*
> + * Structure for ioctl per a.g. state get/set.
> + */
> +typedef struct xfs_ioc_agstate {
> + xfs_agnumber_t agno;
> + __uint32_t state;
> +} xfs_ioc_agstate_t;
> +
> +/*
> + * Skip an AG with below state for inodes/blocks allocation.
> + */
> +#define XFS_AG_STATE_ALLOC_DENY (1 << 0)
> +#define XFS_AG_ALL_STATE (XFS_AG_STATE_ALLOC_DENY)
> +
> +extern int xfs_set_agstate(struct xfs_mount *mp,
> + struct xfs_ioc_agstate *agstate);
> +
> +/*
> * tags for inode radix tree
> */
> #define XFS_ICI_NO_TAG (-1) /* special flag for an untagged lookup
> diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
> index 4f33c32..bd9cc41 100644
> --- a/fs/xfs/xfs_alloc.c
> +++ b/fs/xfs/xfs_alloc.c
> @@ -2005,6 +2005,7 @@ xfs_alloc_log_agf(
> offsetof(xfs_agf_t, agf_freeblks),
> offsetof(xfs_agf_t, agf_longest),
> offsetof(xfs_agf_t, agf_btreeblks),
> + offsetof(xfs_agf_t, agf_state),
> sizeof(xfs_agf_t)
> };
>
> diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
> index c13fed8..991c09e 100644
> --- a/fs/xfs/xfs_fs.h
> +++ b/fs/xfs/xfs_fs.h
> @@ -486,6 +486,7 @@ typedef struct xfs_handle {
> #define XFS_IOC_ATTRMULTI_BY_HANDLE _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
> #define XFS_IOC_FSGEOMETRY _IOR ('X', 124, struct xfs_fsop_geom)
> #define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t)
> +#define XFS_IOC_SET_AGSTATE _IOW('X', 126, struct xfs_ioc_agstate)
> /* XFS_IOC_GETFSUUID ---------- deprecated 140 */
>
>
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index c25b094..3742511 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -112,10 +112,79 @@ xfs_fs_geometry(
> return 0;
> }
>
> +/*
> + * Setting a.g. persistent state as well as perag incore state.
> + */
> +static void
> +xfs_set_agstate_private(
> + xfs_trans_t *tp, /* transaction pointer */
> + xfs_buf_t *agbp, /* buffer for a.g. freelist header */
> + xfs_perag_t *pag, /* incore perag structure */
> + __uint32_t state) /* a.g. state to be set */
> +{
> + xfs_agf_t *agf; /* a.g. free space */
> +
> + agf = XFS_BUF_TO_AGF(agbp);
> + agf->agf_state |= cpu_to_be32(state);
> + pag->pag_state |= state;
> +
> + xfs_alloc_log_agf(tp, agbp, XFS_AGF_STATE);
> +}
> +
> +/*
> + * Setting the state of the given AG.
> + *
> + * For now, we can set a given AG to be offline or online, and
> + * allocaters will skip an AG being offline to allocate inodes
> + * or free space.
> + */
> +int
> +xfs_set_agstate(
> + xfs_mount_t *mp,
> + xfs_ioc_agstate_t *agstate)
> +{
> + xfs_agnumber_t agno;
> + xfs_perag_t *pag;
> + xfs_trans_t *tp;
> + xfs_buf_t *bp;
> + int error;
> +
> + agno = agstate->agno;
> + if (agno >= mp->m_sb.sb_agcount)
> + return XFS_ERROR(EINVAL);
> +
> + if ((agstate->state & XFS_AG_ALL_STATE) != agstate->state)
> + return XFS_ERROR(EINVAL);
Maybe it's better to rename XFS_AG_ALL_STATE to XFS_AG_STATS_VALID, and
do this check as below:
if (agstate->state &~ XFS_AG_STATES_VALID)
return XFS_ERROR(EINVAL);
> +
> + tp = xfs_trans_alloc(mp, XFS_TRANS_SET_AGSTATE);
> + error = xfs_trans_reserve(tp, 0, XFS_SETAGSTATE_LOG_RES(mp), 0, 0,
> + XFS_DEFAULT_LOG_COUNT);
> + if (error) {
> + xfs_trans_cancel(tp, 0);
> + return error;
> + }
> +
> + error = xfs_alloc_read_agf(mp, tp, agno, 0, &bp);
> + if (error)
> + goto error0;
> +
> + pag = xfs_perag_get(mp, agno);
> + xfs_set_agstate_private(tp, bp, pag, agstate->state);
> + xfs_perag_put(pag);
> +
> + xfs_trans_set_sync(tp);
> + xfs_trans_commit(tp, 0);
> + return error;
> +
> +error0:
> + xfs_trans_cancel(tp, XFS_TRANS_ABORT);
> + return error;
> +}
> +
> static int
> xfs_growfs_data_private(
> - xfs_mount_t *mp, /* mount point for filesystem */
> - xfs_growfs_data_t *in) /* growfs data input struct */
> + xfs_mount_t *mp, /* mount point for filesystem */
> + xfs_growfs_data_t *in) /* growfs data input struct */
> {
> xfs_agf_t *agf;
> xfs_agi_t *agi;
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 8305f2a..efe39ef 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -1602,6 +1602,19 @@ xfs_file_ioctl(
> error = xfs_errortag_clearall(mp, 1);
> return -error;
>
> + case XFS_IOC_SET_AGSTATE: {
> + xfs_ioc_agstate_t in;
> +
> + if (!capable(CAP_SYS_ADMIN))
> + return -EPERM;
> +
> + if (copy_from_user(&in, arg, sizeof(in)))
> + return -XFS_ERROR(EFAULT);
> +
> + error = xfs_set_agstate(mp, &in);
> + return -error;
> + }
> +
> default:
> return -ENOTTY;
> }
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index a4f4092..14f897d 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -264,7 +264,7 @@ struct xfs_log_item_desc {
> (128 * (ext + (ext * XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))))
> #define XFS_ATTRRM_LOG_RES(mp) ((mp)->m_reservations.tr_attrrm)
> #define XFS_CLEAR_AGI_BUCKET_LOG_RES(mp) ((mp)->m_reservations.tr_clearagi)
> -#define XFS_SETAGSTATE_LOG_RES ((mp)->m_reservations.tr_setagstate)
> +#define XFS_SETAGSTATE_LOG_RES(mp) ((mp)->m_reservations.tr_setagstate)
>
> /*
> * Various log count values.
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-11-16 9:04 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-16 6:45 [PATCH 03/15] xfs: Introduce a new ioctl(2) to set AG state Jeff Liu
2012-11-16 9:06 ` Jeff Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox