xfs
[Top] [All Lists]

Re: [PATCH] Implement ioctl to mark AGs as "don't use/use"

Subject: Re: [PATCH] Implement ioctl to mark AGs as "don't use/use"
From: Ruben Porras <ruben.porras@xxxxxxxxxxx>
Date: Thu, 28 Jun 2007 12:25:50 +0200
Cc: xfs@xxxxxxxxxxx
In-reply-to: <20070628045049.GF989688@xxxxxxx>
References: <1182939325.5313.12.camel@localhost> <20070628045049.GF989688@xxxxxxx>
Sender: xfs-bounce@xxxxxxxxxxx
User-agent: Mozilla-Thunderbird 2.0.0.4 (X11/20070618)
David Chinner wrote:
It's a good first cut - comments are inline in the patch below.


Looks like some whitespace problems there (mixing spaces and tabs).
Also, can you include empty lines either side of a unique hunk of code
like this?

I wonder how many other places we are going to have to put this check?
I haven't looked myself, but this is a good place to start ;)


I'm still wondering how should I educate emacs to introduce alsways tabs ;)
You shouldn't renumber the existing ioctls - that changes the
interfaces to userspace and so will break lots of stuff :( Just put
them at the end as 126/127. (Oh, you've got two "111" ioctls in
there, anyway ;)

IOWs, the flag passed to xfs_trans_alloc() defines the type of the
transaction and the flag passed to xfs_alloc_log_agf() defines what
has been modified within the transaction.

Ok, thank you for the explanation, I think that now I got it right.
Attached is a new patch.

There is one question that I would like to ask: when you sketched the xfs_alloc_set_flag_ag function, you put inside it the call to the funcintion xfs_alloc_log_agf (see next code snippet).

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); <-- ***** FROM HERE
}

is it required to do the transaction log right after the change or can it be
done in the caller function right after calling xfs_alloc_set_flag_ag?

For example

caller(...)

{
xfs_alloc_set_flag_ag(tp, bp, pag, XFS_AGFLAG_ALLOC_DENY);

<-- **** TO HERE

xfs_trans_set_sync(tp);
xfs_trans_commit(tp, 0);
}

Thanks

--
Rubén Porras
LinWorks GmbH

Index: fs/xfs/xfs_ag.h
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_ag.h,v
retrieving revision 1.59
diff -u -r1.59 xfs_ag.h
--- fs/xfs/xfs_ag.h     22 May 2007 15:50:48 -0000      1.59
+++ fs/xfs/xfs_ag.h     28 Jun 2007 09:47:41 -0000
@@ -69,6 +69,7 @@
        __be32          agf_freeblks;   /* total free blocks */
        __be32          agf_longest;    /* longest free space */
        __be32          agf_btreeblks;  /* # of blocks held in AGF btrees */
+       __be32          agf_flags;      /* persistent AG state flags */
 } xfs_agf_t;
 
 #define        XFS_AGF_MAGICNUM        0x00000001
@@ -83,7 +84,8 @@
 #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 */
@@ -196,8 +198,17 @@
        lock_t          pagb_lock;      /* lock for pagb_list */
 #endif
        xfs_perag_busy_t *pagb_list;    /* unstable blocks */
+       __u32            pagf_flags;    /* persistent AG state flags */
 } xfs_perag_t;
 
+typedef struct xfs_ioc_agflags
+{
+       xfs_agnumber_t  ag;
+       __u32           flags;
+} xfs_ioc_agflags_t;
+
+#define XFS_AGF_FLAGS_ALLOC_DENY       (1<<0)
+
 #define        XFS_AG_MAXLEVELS(mp)            ((mp)->m_ag_maxlevels)
 #define        XFS_MIN_FREELIST_RAW(bl,cl,mp)  \
        (MIN(bl + 1, XFS_AG_MAXLEVELS(mp)) + MIN(cl + 1, XFS_AG_MAXLEVELS(mp)))
Index: fs/xfs/xfs_alloc.c
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_alloc.c,v
retrieving revision 1.186
diff -u -r1.186 xfs_alloc.c
--- fs/xfs/xfs_alloc.c  22 May 2007 15:50:48 -0000      1.186
+++ fs/xfs/xfs_alloc.c  28 Jun 2007 09:47:44 -0000
@@ -549,6 +549,7 @@
        xfs_alloc_arg_t *args)  /* argument structure for allocation */
 {
        int             error=0;
+       xfs_perag_t     *pag;
 #ifdef XFS_ALLOC_TRACE
        static char     fname[] = "xfs_alloc_ag_vextent";
 #endif
@@ -558,6 +559,17 @@
        ASSERT(args->minlen <= args->maxlen);
        ASSERT(args->mod < args->prod);
        ASSERT(args->alignment > 0);
+
+       /*
+        * Return an error if the a.g. should not be allocated.
+        * This happens normally during a shrink operation.
+        */
+       pag = (args->pag);
+       if (unlikely(pag->pagf_flags & XFS_AGF_FLAGS_ALLOC_DENY)) {
+               args->agbno = NULLAGBLOCK;
+               return 0;
+       }
+
        /*
         * Branch to correct routine based on the type.
         */
@@ -2085,6 +2097,7 @@
                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)
        };
 
Index: fs/xfs/xfs_fs.h
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_fs.h,v
retrieving revision 1.33
diff -u -r1.33 xfs_fs.h
--- fs/xfs/xfs_fs.h     22 May 2007 15:50:48 -0000      1.33
+++ fs/xfs/xfs_fs.h     28 Jun 2007 09:47:44 -0000
@@ -492,6 +492,8 @@
 #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_GET_AGF_FLAGS       _IOWR('X', 126, struct xfs_ioc_agflags)
+#define XFS_IOC_SET_AGF_FLAGS       _IOW ('X', 127, struct xfs_ioc_agflags)
 /*     XFS_IOC_GETFSUUID ---------- deprecated 140      */
 
 
Index: fs/xfs/xfs_fsops.c
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_fsops.c,v
retrieving revision 1.126
diff -u -r1.126 xfs_fsops.c
--- fs/xfs/xfs_fsops.c  8 Jun 2007 16:03:59 -0000       1.126
+++ fs/xfs/xfs_fsops.c  28 Jun 2007 09:47:45 -0000
@@ -649,3 +649,79 @@
 
        return 0;
 }
+
+STATIC void
+xfs_ag_set_flags_private(
+       xfs_trans_t     *tp,
+       xfs_buf_t       *agbp,  /* buffer for a.g. freelist header */
+       xfs_perag_t     *pag,
+       __u32           flags)
+{
+       xfs_agf_t       *agf;   /* a.g. freespace structure */
+
+       agf = XFS_BUF_TO_AGF(agbp);
+       pag->pagf_flags |= flags;
+       agf->agf_flags = cpu_to_be32(pag->pagf_flags);
+
+       xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLAGS);
+}
+
+__u32
+xfs_ag_get_flags_private(
+       xfs_perag_t     *pag)
+{
+       return pag->pagf_flags;
+}
+
+int
+xfs_ag_set_flags(
+       xfs_mount_t             *mp,
+       xfs_ioc_agflags_t       *ioc_flags)
+{
+       xfs_agnumber_t  agno;
+       xfs_perag_t     *pag;
+       xfs_buf_t       *bp;
+       int             error;
+       xfs_trans_t     *tp;
+
+       agno = ioc_flags->ag;
+       if (agno >= mp->m_sb.sb_agcount)
+               return -EINVAL;
+
+       tp = xfs_trans_alloc(mp, XFS_TRANS_AGF_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_ag_set_flags_private(tp, bp, pag, ioc_flags->flags);
+
+       xfs_trans_set_sync(tp);
+       xfs_trans_commit(tp, 0);
+
+       return 0;
+
+}
+
+int
+xfs_ag_get_flags(
+       xfs_mount_t             *mp,
+       xfs_ioc_agflags_t       *ioc_flags)
+{
+       xfs_agnumber_t  agno;
+       xfs_perag_t     *pag;
+
+       agno = ioc_flags->ag;
+       if (agno >= mp->m_sb.sb_agcount)
+               return -EINVAL;
+
+       pag = &mp->m_perag[agno];
+       ioc_flags->flags = xfs_ag_get_flags_private(pag);
+       return 0;
+}
Index: fs/xfs/xfs_fsops.h
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_fsops.h,v
retrieving revision 1.29
diff -u -r1.29 xfs_fsops.h
--- fs/xfs/xfs_fsops.h  21 Nov 2005 14:42:36 -0000      1.29
+++ fs/xfs/xfs_fsops.h  28 Jun 2007 09:47:45 -0000
@@ -27,4 +27,7 @@
 extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags);
 extern void xfs_fs_log_dummy(xfs_mount_t *mp);
 
+extern int xfs_ag_set_flags(xfs_mount_t *mp, xfs_ioc_agflags_t *ioc_flags);
+extern int xfs_ag_get_flags(xfs_mount_t *mp, xfs_ioc_agflags_t *ioc_flags);
+
 #endif /* __XFS_FSOPS_H__ */
Index: fs/xfs/xfs_trans.h
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_trans.h,v
retrieving revision 1.145
diff -u -r1.145 xfs_trans.h
--- fs/xfs/xfs_trans.h  22 May 2007 15:50:48 -0000      1.145
+++ fs/xfs/xfs_trans.h  28 Jun 2007 09:47:46 -0000
@@ -95,7 +95,8 @@
 #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_AGF_FLAGS             42
+#define        XFS_TRANS_TYPE_MAX              42
 /* new transaction types need to be reflected in xfs_logprint(8) */
 
 
Index: fs/xfs/linux-2.6/xfs_ioctl.c
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/linux-2.6/xfs_ioctl.c,v
retrieving revision 1.144
diff -u -r1.144 xfs_ioctl.c
--- fs/xfs/linux-2.6/xfs_ioctl.c        7 Feb 2007 02:50:13 -0000       1.144
+++ fs/xfs/linux-2.6/xfs_ioctl.c        28 Jun 2007 09:47:46 -0000
@@ -860,6 +860,37 @@
                return 0;
        }
 
+       case XFS_IOC_GET_AGF_FLAGS: {
+               xfs_ioc_agflags_t inout;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               if (copy_from_user(&inout, arg, sizeof(inout)))
+                       return -XFS_ERROR(EFAULT);
+
+               error = xfs_ag_get_flags(mp, &inout);
+               if (error)
+                       return -error;
+
+               if (copy_to_user(arg, &inout, sizeof(inout)))
+                       return -XFS_ERROR(EFAULT);
+               return 0;
+       }
+
+       case XFS_IOC_SET_AGF_FLAGS: {
+               xfs_ioc_agflags_t in;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               if (copy_from_user(&in, arg, sizeof(in)))
+                       return -XFS_ERROR(EFAULT);
+
+               error = xfs_ag_set_flags(mp, &in);
+               return -error;
+       }
+
        case XFS_IOC_FSGROWFSDATA: {
                xfs_growfs_data_t in;
 
<Prev in Thread] Current Thread [Next in Thread>