xfs
[Top] [All Lists]

Re: XFS shrink functionality

To: Ruben Porras <nahoo82@xxxxxxxxx>
Subject: Re: XFS shrink functionality
From: David Chinner <dgc@xxxxxxx>
Date: Thu, 14 Jun 2007 19:14:26 +1000
Cc: David Chinner <dgc@xxxxxxx>, xfs@xxxxxxxxxxx, cw@xxxxxxxx, iusty@xxxxxxxxx
In-reply-to: <1181810127.6539.13.camel@localhost>
References: <1180715974.10796.46.camel@localhost> <20070604001632.GA86004887@sgi.com> <20070604084154.GA8273@teal.hq.k1024.org> <1181291033.7510.40.camel@localhost> <20070608101532.GA18788@teal.hq.k1024.org> <20070608151223.GF86004887@sgi.com> <1181810127.6539.13.camel@localhost>
Sender: xfs-bounce@xxxxxxxxxxx
User-agent: Mutt/1.4.2.1i
On Thu, Jun 14, 2007 at 10:35:27AM +0200, Ruben Porras wrote:
> > > I took a look at both items since this discussion started. And honestly,
> > > I think 1) is harder that 4), so you're welcome to work on it :) The
> > > points that make it harder is that, per David's suggestion, there needs
> > > to be:
> > >  - define two new transaction types
> > 
> > one new transaction type:
> > 
> > XFS_TRANS_AGF_FLAGS
> 
> done
> 
> > and and extension to xfs_alloc_log_agf(). Is about all that is
> > needed there.
> 
> still to do. Will come after the ioctls.
> 
> > See the patch here:
> > 
> > http://oss.sgi.com/archives/xfs/2007-04/msg00103.html
> > 
> > For an example of a very simlar transaction to what is needed
> > (look at xfs_log_sbcount()) and very similar addition to
> > the AGF (xfs_btreeblks).
> > 
> > >  - define two new ioctls
> > 
> > XFS_IOC_ALLOC_ALLOW_AG, parameter xfsagnumber_t.
> > XFS_IOC_ALLOC_DENY_AG, parameter xfsagnumber_t.
> 
> almost done.

FWIW, I've had second thoughts on this ioctl interface. It's
horribly specific, considering all we are doing are setting
or clearing a flag in an AG.

Perhaps a better interface is:

XFS_IOC_GET_AGF_FLAGS
XFS_IOC_SET_AGF_FLAGS

with:

struct xfs_ioc_agflags {
        xfs_agnumber_t  ag;
        __u32           flags;
}

As the parameter structure and:

#define XFS_AGF_FLAGS_ALLOC_DENY        (1<<0)


> How I'm should I obtain a pointer to an xfs_agf_t from
> inside the ioctls?
> 
> I guess that the first step is to get a *bp with xfs_getsb and then an *sbp,
> but, which function/macro gives me the xfs_agf_t pointer? Sorry, I can't
> find the way greeping through the code.

I've attached the quick hack I did when thinking this through
initially. It'll give you an idea of how to do this and a bit more.
FWIW, it was this hack that made me think the above interface
is a better way to go....

Cheers,

Dave.
-- 
Dave Chinner
Principal Engineer
SGI Australian Software Group

---
 fs/xfs/linux-2.6/xfs_ioctl.c |   27 +++++++++++
 fs/xfs/xfs_ag.h              |    7 ++
 fs/xfs/xfs_alloc.c           |  103 +++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_fs.h              |    2 
 fs/xfs/xfs_trans.h           |    3 -
 5 files changed, 140 insertions(+), 2 deletions(-)

Index: 2.6.x-xfs-new/fs/xfs/linux-2.6/xfs_ioctl.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/linux-2.6/xfs_ioctl.c     2007-06-08 
21:34:37.000000000 +1000
+++ 2.6.x-xfs-new/fs/xfs/linux-2.6/xfs_ioctl.c  2007-06-08 22:22:59.305412098 
+1000
@@ -899,6 +899,33 @@ xfs_ioctl(
                return -error;
        }
 
+       case XFS_IOC_ALLOC_DENY_AG: {
+               xfs_agnumber_t in;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               if (copy_from_user(&in, arg, sizeof(in)))
+                       return -XFS_ERROR(EFAULT);
+
+               error = xfs_alloc_deny_ag(mp, &in);
+               return -error;
+
+       }
+       case XFS_IOC_ALLOC_ALLOW_AG: {
+               xfs_agnumber_t in;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               if (copy_from_user(&in, arg, sizeof(in)))
+                       return -XFS_ERROR(EFAULT);
+
+               error = xfs_alloc_allow_ag(mp, &in);
+               return -error;
+
+       }
+
        case XFS_IOC_FREEZE:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
Index: 2.6.x-xfs-new/fs/xfs/xfs_ag.h
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_ag.h  2007-06-08 21:46:28.000000000 +1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_ag.h       2007-06-08 22:09:18.323606142 +1000
@@ -69,6 +69,7 @@ typedef struct xfs_agf {
        __be32          agf_freeblks;   /* total free blocks */
        __be32          agf_longest;    /* longest free space */
        __be32          agf_btreeblks;  /* # of blocks held in AGF btrees */
+       __be32          agf_flags;      /* status flags */
 } xfs_agf_t;
 
 #define        XFS_AGF_MAGICNUM        0x00000001
@@ -83,9 +84,12 @@ typedef struct xfs_agf {
 #define        XFS_AGF_FREEBLKS        0x00000200
 #define        XFS_AGF_LONGEST         0x00000400
 #define        XFS_AGF_BTREEBLKS       0x00000800
-#define        XFS_AGF_NUM_BITS        12
+#define        XFS_AGF_FLAGS           0x00001000
+#define        XFS_AGF_NUM_BITS        13
 #define        XFS_AGF_ALL_BITS        ((1 << XFS_AGF_NUM_BITS) - 1)
 
+
+
 /* disk block (xfs_daddr_t) in the AG */
 #define XFS_AGF_DADDR(mp)      ((xfs_daddr_t)(1 << (mp)->m_sectbb_log))
 #define        XFS_AGF_BLOCK(mp)       XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
@@ -189,6 +193,7 @@ typedef struct xfs_perag
        xfs_extlen_t    pagf_freeblks;  /* total free blocks */
        xfs_extlen_t    pagf_longest;   /* longest free space */
        __uint32_t      pagf_btreeblks; /* # of blocks held in AGF btrees */
+       __uint32_t      pagf_flags;     /* status flags for AG */
        xfs_agino_t     pagi_freecount; /* number of free inodes */
        xfs_agino_t     pagi_count;     /* number of allocated inodes */
        int             pagb_count;     /* pagb slots in use */
Index: 2.6.x-xfs-new/fs/xfs/xfs_alloc.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_alloc.c       2007-06-05 22:12:50.000000000 
+1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_alloc.c    2007-06-08 23:12:51.256348632 +1000
@@ -2085,6 +2085,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_flags),
                sizeof(xfs_agf_t)
        };
 
@@ -2112,6 +2113,107 @@ xfs_alloc_pagf_init(
        return 0;
 }
 
+#define XFS_AGFLAG_ALLOC_DENY  1
+STATIC void
+xfs_alloc_set_flag_ag(
+       xfs_trans_t     *tp,
+       xfs_buf_t       *agbp,  /* buffer for a.g. freelist header */
+       xfs_perag_t     *pag,
+       int             flag)
+{
+       xfs_agf_t               *agf;   /* a.g. freespace structure */
+
+       agf = XFS_BUF_TO_AGF(agbp);
+       pag->pagf_flags |= flag;
+       agf->agf_flags = cpu_to_be32(pag->pagf_flags);
+
+       xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLAGS);
+}
+
+STATIC void
+xfs_alloc_clear_flag_ag(
+       xfs_trans_t     *tp,
+       xfs_buf_t       *agbp,  /* buffer for a.g. freelist header */
+       xfs_perag_t     *pag,
+       int             flag)
+{
+       xfs_agf_t               *agf;   /* a.g. freespace structure */
+
+       agf = XFS_BUF_TO_AGF(agbp);
+       pag->pagf_flags &= ~flag;
+       agf->agf_flags = cpu_to_be32(pag->pagf_flags);
+
+       xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLAGS);
+}
+
+int
+xfs_alloc_allow_ag(
+       xfs_mount_t     *mp,
+       xfs_agnumber_t  agno)
+{
+       xfs_perag_t     *pag;
+       xfs_buf_t       *bp;
+       int             error;
+       xfs_trans_t     *tp;
+
+       if (agno >= mp->m_sb.sb_agcount)
+               return -EINVAL;
+
+       tp = xfs_trans_alloc(mp, XFS_TRANS_ALLOC_FLAGS);
+       error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 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)
+               return error;
+
+       pag = &mp->m_perag[agno];
+       xfs_alloc_clear_flag_ag(tp, bp, pag, XFS_AGFLAG_ALLOC_DENY);
+
+       xfs_trans_set_sync(tp);
+       xfs_trans_commit(tp, 0);
+
+       return 0;
+
+}
+
+int
+xfs_alloc_deny_ag(
+       xfs_mount_t     *mp,
+       xfs_agnumber_t  agno)
+{
+       xfs_perag_t     *pag;
+       xfs_buf_t       *bp;
+       int             error;
+       xfs_trans_t     *tp;
+
+       if (agno >= mp->m_sb.sb_agcount)
+               return -EINVAL;
+
+       tp = xfs_trans_alloc(mp, XFS_TRANS_ALLOC_FLAGS);
+       error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 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)
+               return error;
+
+       pag = &mp->m_perag[agno];
+       xfs_alloc_set_flag_ag(tp, bp, pag, XFS_AGFLAG_ALLOC_DENY);
+
+       xfs_trans_set_sync(tp);
+       xfs_trans_commit(tp, 0);
+
+       return 0;
+
+}
+
 /*
  * Put the block on the freelist for the allocation group.
  */
@@ -2226,6 +2328,7 @@ xfs_alloc_read_agf(
                pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
                pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
                pag->pagf_longest = be32_to_cpu(agf->agf_longest);
+               pag->pagf_flags = be32_to_cpu(agf->agf_flags);
                pag->pagf_levels[XFS_BTNUM_BNOi] =
                        be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
                pag->pagf_levels[XFS_BTNUM_CNTi] =
Index: 2.6.x-xfs-new/fs/xfs/xfs_trans.h
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_trans.h       2007-06-08 21:41:32.000000000 
+1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_trans.h    2007-06-08 22:50:46.449405162 +1000
@@ -95,7 +95,8 @@ typedef struct xfs_trans_header {
 #define        XFS_TRANS_GROWFSRT_FREE         39
 #define        XFS_TRANS_SWAPEXT               40
 #define        XFS_TRANS_SB_COUNT              41
-#define        XFS_TRANS_TYPE_MAX              41
+#define        XFS_TRANS_ALLOC_FLAGS           42
+#define        XFS_TRANS_TYPE_MAX              42
 /* new transaction types need to be reflected in xfs_logprint(8) */
 
 
Index: 2.6.x-xfs-new/fs/xfs/xfs_fs.h
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_fs.h  2007-06-08 21:46:29.000000000 +1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_fs.h       2007-06-08 23:15:31.755284394 +1000
@@ -493,6 +493,8 @@ 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_ALLOC_DENY_AG       _IOR ('X', 126, __uint32_t)
+#define XFS_IOC_ALLOC_ALLOW_AG      _IOR ('X', 127, __uint32_t)
 /*     XFS_IOC_GETFSUUID ---------- deprecated 140      */
 
 


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