xfs
[Top] [All Lists]

Re: [PATCH 03/15] xfs: Introduce a new ioctl(2) to set AG state

To: xfs@xxxxxxxxxxx
Subject: Re: [PATCH 03/15] xfs: Introduce a new ioctl(2) to set AG state
From: Jeff Liu <jeff.liu@xxxxxxxxxx>
Date: Fri, 16 Nov 2012 17:06:35 +0800
Cc: jeff.liu@xxxxxxxxxx
In-reply-to: <50A5E0FB.5060201@xxxxxxxxxx>
References: <50A5E0FB.5060201@xxxxxxxxxx>
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121028 Thunderbird/16.0.2
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@xxxxxxxxxx>
> ---
>  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.
> 

<Prev in Thread] Current Thread [Next in Thread>