public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Implement ioctl to mark AGs as "don't use/use"
@ 2007-06-27 10:15 Ruben Porras
  2007-06-28  4:50 ` David Chinner
  0 siblings, 1 reply; 6+ messages in thread
From: Ruben Porras @ 2007-06-27 10:15 UTC (permalink / raw)
  To: xfs


[-- Attachment #1.1: Type: text/plain, Size: 341 bytes --]

The patch has the following parts:

- Necessary changes to xfs_ag.h
- two new ioctls
- Changes to the allocation functions to avoid using marked AGs
- Extension to xfs_alloc_log_agf

This should implement the second step on the requirement list to shrink
an xfs filesystem. Comment are welcome.

-- 
Rubén Porras
LinWorks GmbH

[-- Attachment #1.2: patch_markags.diff --]
[-- Type: text/x-patch, Size: 9592 bytes --]

Index: 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
--- xfs/xfs_ag.h	22 May 2007 15:50:48 -0000	1.59
+++ xfs/xfs_ag.h	27 Jun 2007 09:06:39 -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;      /* the AGF is allocatable */
 } xfs_agf_t;
 
 #define	XFS_AGF_MAGICNUM	0x00000001
@@ -196,8 +197,17 @@
 	lock_t		pagb_lock;	/* lock for pagb_list */
 #endif
 	xfs_perag_busy_t *pagb_list;	/* unstable blocks */
+	__u32		 pagf_flags;	/* the AGF is allocatable */
 } 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: 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
--- xfs/xfs_alloc.c	22 May 2007 15:50:48 -0000	1.186
+++ xfs/xfs_alloc.c	27 Jun 2007 09:06:40 -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
@@ -559,6 +560,15 @@
 	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.
 	 */
 	args->wasfromfl = 0;
@@ -2085,6 +2095,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: 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
--- xfs/xfs_fs.h	22 May 2007 15:50:48 -0000	1.33
+++ xfs/xfs_fs.h	27 Jun 2007 09:06:40 -0000
@@ -476,22 +476,24 @@
 #define XFS_IOC_OPEN_BY_HANDLE	     _IOWR('X', 107, struct xfs_fsop_handlereq)
 #define XFS_IOC_READLINK_BY_HANDLE   _IOWR('X', 108, struct xfs_fsop_handlereq)
 #define XFS_IOC_SWAPEXT		     _IOWR('X', 109, struct xfs_swapext)
-#define XFS_IOC_FSGROWFSDATA	     _IOW ('X', 110, struct xfs_growfs_data)
-#define XFS_IOC_FSGROWFSLOG	     _IOW ('X', 111, struct xfs_growfs_log)
-#define XFS_IOC_FSGROWFSRT	     _IOW ('X', 112, struct xfs_growfs_rt)
-#define XFS_IOC_FSCOUNTS	     _IOR ('X', 113, struct xfs_fsop_counts)
-#define XFS_IOC_SET_RESBLKS	     _IOWR('X', 114, struct xfs_fsop_resblks)
-#define XFS_IOC_GET_RESBLKS	     _IOR ('X', 115, struct xfs_fsop_resblks)
-#define XFS_IOC_ERROR_INJECTION	     _IOW ('X', 116, struct xfs_error_injection)
-#define XFS_IOC_ERROR_CLEARALL	     _IOW ('X', 117, struct xfs_error_injection)
-/*	XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 118	 */
-#define XFS_IOC_FREEZE		     _IOWR('X', 119, int)
-#define XFS_IOC_THAW		     _IOWR('X', 120, int)
-#define XFS_IOC_FSSETDM_BY_HANDLE    _IOW ('X', 121, struct xfs_fsop_setdm_handlereq)
-#define XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq)
-#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       _IOW ('X', 110, struct xfs_ioc_agflags)
+#define XFS_IOC_SET_AGF_FLAGS       _IOW ('X', 111, struct xfs_ioc_agflags)
+#define XFS_IOC_FSGROWFSDATA	     _IOW ('X', 111, struct xfs_growfs_data)
+#define XFS_IOC_FSGROWFSLOG	     _IOW ('X', 112, struct xfs_growfs_log)
+#define XFS_IOC_FSGROWFSRT	     _IOW ('X', 113, struct xfs_growfs_rt)
+#define XFS_IOC_FSCOUNTS	     _IOR ('X', 114, struct xfs_fsop_counts)
+#define XFS_IOC_SET_RESBLKS	     _IOWR('X', 115, struct xfs_fsop_resblks)
+#define XFS_IOC_GET_RESBLKS	     _IOR ('X', 116, struct xfs_fsop_resblks)
+#define XFS_IOC_ERROR_INJECTION	     _IOW ('X', 117, struct xfs_error_injection)
+#define XFS_IOC_ERROR_CLEARALL	     _IOW ('X', 118, struct xfs_error_injection)
+/*	XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 119	 */
+#define XFS_IOC_FREEZE		     _IOWR('X', 120, int)
+#define XFS_IOC_THAW		     _IOWR('X', 121, int)
+#define XFS_IOC_FSSETDM_BY_HANDLE    _IOW ('X', 122, struct xfs_fsop_setdm_handlereq)
+#define XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 123, struct xfs_fsop_attrlist_handlereq)
+#define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 124, struct xfs_fsop_attrmulti_handlereq)
+#define XFS_IOC_FSGEOMETRY	     _IOR ('X', 125, struct xfs_fsop_geom)
+#define XFS_IOC_GOINGDOWN	     _IOR ('X', 126, __uint32_t)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
Index: 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
--- xfs/xfs_fsops.c	8 Jun 2007 16:03:59 -0000	1.126
+++ xfs/xfs_fsops.c	27 Jun 2007 09:06:40 -0000
@@ -649,3 +649,80 @@
 
 	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_TRANS_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,
+	__u32			*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];
+	*flags = xfs_ag_get_flags_private(pag);
+	return 0;
+}
Index: 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
--- xfs/xfs_fsops.h	21 Nov 2005 14:42:36 -0000	1.29
+++ xfs/xfs_fsops.h	27 Jun 2007 09:06:40 -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, __u32 *flags);
+
 #endif	/* __XFS_FSOPS_H__ */
Index: 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
--- xfs/xfs_trans.h	22 May 2007 15:50:48 -0000	1.145
+++ xfs/xfs_trans.h	27 Jun 2007 09:06:41 -0000
@@ -418,6 +418,10 @@
 #define	XFS_TRANS_SB_REXTENTS		0x00001000
 #define	XFS_TRANS_SB_REXTSLOG		0x00002000
 
+/*
+ * Value for xfs_trans_mod_agf
+ */
+#define XFS_TRANS_AGF_FLAGS             0x00004000
 
 /*
  * Various log reservation values.
Index: 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
--- xfs/linux-2.6/xfs_ioctl.c	7 Feb 2007 02:50:13 -0000	1.144
+++ xfs/linux-2.6/xfs_ioctl.c	27 Jun 2007 09:06:41 -0000
@@ -860,6 +860,38 @@
 		return 0;
 	}
 
+	case XFS_IOC_GET_AGF_FLAGS: {
+		xfs_ioc_agflags_t in;
+               __u32 out;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (copy_from_user(&in, arg, sizeof(in)))
+			return -XFS_ERROR(EFAULT);
+
+		error = xfs_ag_get_flags(mp, &in, &out);
+		if (error)
+			return -error;
+
+		if (copy_to_user(arg, &out, sizeof(out)))
+			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;
 

[-- Attachment #2: Dies ist ein digital signierter Nachrichtenteil --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Implement ioctl to mark AGs as "don't use/use"
  2007-06-27 10:15 [PATCH] Implement ioctl to mark AGs as "don't use/use" Ruben Porras
@ 2007-06-28  4:50 ` David Chinner
  2007-06-28 10:25   ` Ruben Porras
  0 siblings, 1 reply; 6+ messages in thread
From: David Chinner @ 2007-06-28  4:50 UTC (permalink / raw)
  To: Ruben Porras; +Cc: xfs

On Wed, Jun 27, 2007 at 12:15:25PM +0200, Ruben Porras wrote:
> The patch has the following parts:
> 
> - Necessary changes to xfs_ag.h
> - two new ioctls
> - Changes to the allocation functions to avoid using marked AGs
> - Extension to xfs_alloc_log_agf
> 
> This should implement the second step on the requirement list to shrink
> an xfs filesystem. Comment are welcome.

It's a good first cut - comments are inline in the patch below.

> Index: 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
> --- xfs/xfs_ag.h	22 May 2007 15:50:48 -0000	1.59
> +++ xfs/xfs_ag.h	27 Jun 2007 09:06:39 -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;      /* the AGF is allocatable */

The comment should say "persistent AG state flags" or something
similar - it's not just for allocation ;)

>  } xfs_agf_t;
>  
>  #define	XFS_AGF_MAGICNUM	0x00000001
> @@ -196,8 +197,17 @@
>  	lock_t		pagb_lock;	/* lock for pagb_list */
>  #endif
>  	xfs_perag_busy_t *pagb_list;	/* unstable blocks */
> +	__u32		 pagf_flags;	/* the AGF is allocatable */

Ditto.

> --- xfs/xfs_alloc.c	22 May 2007 15:50:48 -0000	1.186
> +++ xfs/xfs_alloc.c	27 Jun 2007 09:06:40 -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
> @@ -559,6 +560,15 @@
>  	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.
>  	 */
>  	args->wasfromfl = 0;

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 ;)


> Index: 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
> --- xfs/xfs_fs.h	22 May 2007 15:50:48 -0000	1.33
> +++ xfs/xfs_fs.h	27 Jun 2007 09:06:40 -0000
> @@ -476,22 +476,24 @@
>  #define XFS_IOC_OPEN_BY_HANDLE	     _IOWR('X', 107, struct xfs_fsop_handlereq)
>  #define XFS_IOC_READLINK_BY_HANDLE   _IOWR('X', 108, struct xfs_fsop_handlereq)
>  #define XFS_IOC_SWAPEXT		     _IOWR('X', 109, struct xfs_swapext)
> -#define XFS_IOC_FSGROWFSDATA	     _IOW ('X', 110, struct xfs_growfs_data)
> -#define XFS_IOC_FSGROWFSLOG	     _IOW ('X', 111, struct xfs_growfs_log)
> -#define XFS_IOC_FSGROWFSRT	     _IOW ('X', 112, struct xfs_growfs_rt)
> -#define XFS_IOC_FSCOUNTS	     _IOR ('X', 113, struct xfs_fsop_counts)
> -#define XFS_IOC_SET_RESBLKS	     _IOWR('X', 114, struct xfs_fsop_resblks)
> -#define XFS_IOC_GET_RESBLKS	     _IOR ('X', 115, struct xfs_fsop_resblks)
> -#define XFS_IOC_ERROR_INJECTION	     _IOW ('X', 116, struct xfs_error_injection)
> -#define XFS_IOC_ERROR_CLEARALL	     _IOW ('X', 117, struct xfs_error_injection)
> -/*	XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 118	 */
> -#define XFS_IOC_FREEZE		     _IOWR('X', 119, int)
> -#define XFS_IOC_THAW		     _IOWR('X', 120, int)
> -#define XFS_IOC_FSSETDM_BY_HANDLE    _IOW ('X', 121, struct xfs_fsop_setdm_handlereq)
> -#define XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq)
> -#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       _IOW ('X', 110, struct xfs_ioc_agflags)
> +#define XFS_IOC_SET_AGF_FLAGS       _IOW ('X', 111, struct xfs_ioc_agflags)
> +#define XFS_IOC_FSGROWFSDATA	     _IOW ('X', 111, struct xfs_growfs_data)
> +#define XFS_IOC_FSGROWFSLOG	     _IOW ('X', 112, struct xfs_growfs_log)
> +#define XFS_IOC_FSGROWFSRT	     _IOW ('X', 113, struct xfs_growfs_rt)
> +#define XFS_IOC_FSCOUNTS	     _IOR ('X', 114, struct xfs_fsop_counts)
> +#define XFS_IOC_SET_RESBLKS	     _IOWR('X', 115, struct xfs_fsop_resblks)
> +#define XFS_IOC_GET_RESBLKS	     _IOR ('X', 116, struct xfs_fsop_resblks)
> +#define XFS_IOC_ERROR_INJECTION	     _IOW ('X', 117, struct xfs_error_injection)
> +#define XFS_IOC_ERROR_CLEARALL	     _IOW ('X', 118, struct xfs_error_injection)
> +/*	XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 119	 */
> +#define XFS_IOC_FREEZE		     _IOWR('X', 120, int)
> +#define XFS_IOC_THAW		     _IOWR('X', 121, int)
> +#define XFS_IOC_FSSETDM_BY_HANDLE    _IOW ('X', 122, struct xfs_fsop_setdm_handlereq)
> +#define XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 123, struct xfs_fsop_attrlist_handlereq)
> +#define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 124, struct xfs_fsop_attrmulti_handlereq)
> +#define XFS_IOC_FSGEOMETRY	     _IOR ('X', 125, struct xfs_fsop_geom)
> +#define XFS_IOC_GOINGDOWN	     _IOR ('X', 126, __uint32_t)

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 ;)

Also, XFS_IOC_GET_AGF_FLAGS needs to be _IOWR as it has input and
output parameters that need to be copied in and out. We only need to
copy in for XFS_IOC_SET_AGF_FLAGS, so _IOW is right for that.
(I think I got that the right way around....)

> +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_TRANS_AGF_FLAGS);

XFS_TRANS_AGF_FLAGS doesn't match with the other AGF log flags.
They are defined in fs/xfs/xfs_ag.h. Search for XFS_AGF_BTREEBLKS
(which is a flag passed to xfs_alloc_log_agf()). You'll also
need to increment XFS_AGF_NUM_BITS....

> +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);

Ah, i see the confusion now...

Ok, so the transaction type definition is different to the field in a
structure that is being logged. The flag passed into xfs_trans_alloc() is
placed in the transaction header in the log to describe the type of
transaction that needs to be recovered. Some transaction types require special
handling and so we ned to be able to tell what type of transaction it is in
the log. These are defined in fs/xfs/xfs_trans.h (search for
XFS_TRANS_SB_COUNT).

The flag passed to xfs_alloc_log_agf() tells the transaction which
bits in the AGF are being modified as only the modified bits of
the AGF are logged in the transaction. it is only used within
the xfs_alloc_log_agf() function and is used to look up the
offset into the AGF of the modified field(s).

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.

> Index: 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
> --- xfs/xfs_trans.h	22 May 2007 15:50:48 -0000	1.145
> +++ xfs/xfs_trans.h	27 Jun 2007 09:06:41 -0000
> @@ -418,6 +418,10 @@
>  #define	XFS_TRANS_SB_REXTENTS		0x00001000
>  #define	XFS_TRANS_SB_REXTSLOG		0x00002000
>  
> +/*
> + * Value for xfs_trans_mod_agf
> + */
> +#define XFS_TRANS_AGF_FLAGS             0x00004000

This is the transaction type, and so needs to be defined as
the next transaction after XFS_TRANS_SB_COUNT.

> @@ -860,6 +860,38 @@
>  		return 0;
>  	}
>  
> +	case XFS_IOC_GET_AGF_FLAGS: {
> +		xfs_ioc_agflags_t in;
> +               __u32 out;
> +
> +		if (!capable(CAP_SYS_ADMIN))
> +			return -EPERM;
> +
> +		if (copy_from_user(&in, arg, sizeof(in)))
> +			return -XFS_ERROR(EFAULT);
> +
> +		error = xfs_ag_get_flags(mp, &in, &out);
> +		if (error)
> +			return -error;
> +
> +		if (copy_to_user(arg, &out, sizeof(out)))
> +			return -XFS_ERROR(EFAULT);

I'm don't think that is correct - the flags need to be placed into
the structure that was passed in, not completely overwritten.

That is:

+	case XFS_IOC_GET_AGF_FLAGS: {
+		xfs_ioc_agflags_t inout;
+               __u32 out;
+
+		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, &out);
+		if (error)
+			return -error;
+
+		inout->flags = out;
+		if (copy_to_user(arg, &inout, sizeof(inout)))
+			return -XFS_ERROR(EFAULT);

Basically, our input structure is also the output structure, and
we need to put the flags:

+typedef struct xfs_ioc_agflags
+{
+       xfs_agnumber_t  ag;
+       __u32           flags;     <<<<<<<< here
+} xfs_ioc_agflags_t;



Cheers,

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Implement ioctl to mark AGs as "don't use/use"
  2007-06-28  4:50 ` David Chinner
@ 2007-06-28 10:25   ` Ruben Porras
  2007-06-29  0:35     ` David Chinner
  2007-06-29  0:54     ` David Chinner
  0 siblings, 2 replies; 6+ messages in thread
From: Ruben Porras @ 2007-06-28 10:25 UTC (permalink / raw)
  Cc: xfs

[-- Attachment #1: Type: text/plain, Size: 1886 bytes --]

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


[-- Attachment #2: patch_markags1.diff --]
[-- Type: text/x-patch, Size: 7385 bytes --]

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;
 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Implement ioctl to mark AGs as "don't use/use"
  2007-06-28 10:25   ` Ruben Porras
@ 2007-06-29  0:35     ` David Chinner
  2007-06-29  0:54     ` David Chinner
  1 sibling, 0 replies; 6+ messages in thread
From: David Chinner @ 2007-06-29  0:35 UTC (permalink / raw)
  To: Ruben Porras; +Cc: xfs

On Thu, Jun 28, 2007 at 12:25:50PM +0200, Ruben Porras wrote:
> David Chinner wrote:
> Ok, thank you for the explanation, I think that now I got it right.
> Attached is a new patch.

Ok, I'll have a look in a little while ;)

> 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);
> }

Yes, you could do that but I don't think it make sense. We also
log the dirty buffer in th context in which it got dirtied, and
in this case it is xfs_alloc_set_flag_ag(). it also saves having
to rememeber that you ahve to call xfs_alloc_log_agf() after a
call to xfs_alloc_set_flag_ag(). If you need to change multiple flags,
batch them up and do a single xfs_alloc_set_flag_ag() call...

Cheers,

Dave.


-- 
Dave Chinner
Principal Engineer
SGI Australian Software Group

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Implement ioctl to mark AGs as "don't use/use"
  2007-06-28 10:25   ` Ruben Porras
  2007-06-29  0:35     ` David Chinner
@ 2007-06-29  0:54     ` David Chinner
  2007-09-03  9:20       ` Ruben Porras
  1 sibling, 1 reply; 6+ messages in thread
From: David Chinner @ 2007-06-29  0:54 UTC (permalink / raw)
  To: Ruben Porras; +Cc: xfs

On Thu, Jun 28, 2007 at 12:25:50PM +0200, Ruben Porras wrote:
> Ok, thank you for the explanation, I think that now I got it right.
> Attached is a new patch.

Only one minor nit:

> @@ -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);

Kill the () here.

Otherwise, looks good.

OOC, do you have any test code for this? xfs_io would be the tool to
teach this ioctl to....

Cheers,

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Implement ioctl to mark AGs as "don't use/use"
  2007-06-29  0:54     ` David Chinner
@ 2007-09-03  9:20       ` Ruben Porras
  0 siblings, 0 replies; 6+ messages in thread
From: Ruben Porras @ 2007-09-03  9:20 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: Type: text/plain, Size: 471 bytes --]

David Chinner wrote:
> OOC, do you have any test code for this? xfs_io would be the tool to
> teach this ioctl to....
>   
I've implemented this on xfs_io, and tested, and it works :)

Attached are the modifications needed to the xfsprogs source tree in form of a diff against the CVS tree.

In a short time all the patches that I submitted will be available together under an url, so that they are not scattered across the mailing list.

-- 
Rubén Porras
LinWorks GmbH


[-- Attachment #2: xfsprogs.diff --]
[-- Type: text/x-patch, Size: 7108 bytes --]

diff -rNu xfs-cmds/xfsprogs/include/xfs_ag.h /home/ldap/campo/xfs-cmds/xfsprogs/include/xfs_ag.h
--- xfs-cmds/xfsprogs/include/xfs_ag.h	2007-05-22 17:59:41.000000000 +0200
+++ /home/ldap/campo/xfs-cmds/xfsprogs/include/xfs_ag.h	2007-08-31 14:08:51.975160695 +0200
@@ -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)))
diff -rNu xfs-cmds/xfsprogs/include/xfs_fs.h /home/ldap/campo/xfs-cmds/xfsprogs/include/xfs_fs.h
--- xfs-cmds/xfsprogs/include/xfs_fs.h	2007-06-28 18:00:13.000000000 +0200
+++ /home/ldap/campo/xfs-cmds/xfsprogs/include/xfs_fs.h	2007-08-31 15:19:21.107148402 +0200
@@ -499,6 +499,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	 */
 
 
diff -rNu xfs-cmds/xfsprogs/io/agflags.c /home/ldap/campo/xfs-cmds/xfsprogs/io/agflags.c
--- xfs-cmds/xfsprogs/io/agflags.c	1970-01-01 01:00:00.000000000 +0100
+++ /home/ldap/campo/xfs-cmds/xfsprogs/io/agflags.c	2007-08-31 13:56:48.861921728 +0200
@@ -0,0 +1,126 @@
+ /*
+ * Copyright (c) 2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <xfs/xfs.h>
+#include <xfs/command.h>
+#include <xfs/input.h>
+#include <xfs/xfs_types.h>
+#include <xfs/xfs_inum.h>
+#include <xfs/xfs_ag.h>
+#include "init.h"
+#include "io.h"
+
+static cmdinfo_t agflags_cmd;
+
+static void
+agflags_help(void)
+{
+	printf(_(
+"\n"
+" get or set the diferent flags of a given AG\n"
+"\n"
+" Example:\n"
+" 'agflags -d 0 -a 10' - unset the flag XFS_AGF_FLAGS_ALLOC_DENY from the AG\n"
+" number 10\n"
+"\n"));
+}
+
+int
+agflags_valid_ag(
+		 int ag)
+{
+  xfs_fsop_geom_t fsgeo;
+
+  if (ag < 0) 
+	  return 0;
+
+  if (xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY, &fsgeo) < 0) {
+	  fprintf(stderr, _("%s: cannot get geometry of fs: %s\n"),
+		  progname, strerror(errno));
+	  exitcode = 1;
+	  return 0;
+  }
+  
+  return (ag <= fsgeo.agcount);
+}
+
+int
+agflags_f(
+	  int		argc,
+	  char		**argv)
+{
+	xfs_ioc_agflags_t	ioc_flags;
+	unsigned int		dflag;
+	int			opt;
+	int			set = 0;
+
+	while ((opt = getopt(argc, argv, "d:a:")) != -1) {
+		switch (opt) {
+		case 'a': /* AG number. */
+			ioc_flags.ag = atoi(optarg);
+			break;
+		case 'd': /* (Un)set XFS_AGF_FLAGS_ALLOC_DENY */
+			dflag = atoi(optarg);
+                        if (dflag != 0 && dflag != 1)
+                                return command_usage(&agflags_cmd);
+			set = 1;
+			break;
+		default: /* ? */
+			return command_usage(&agflags_cmd);
+		}
+	}
+
+        if (! agflags_valid_ag(ioc_flags.ag)) {
+                fprintf(stderr, _("%s: AG number %d is not valid\n"),
+                        progname, ioc_flags.ag);
+                return 0;
+        }
+
+        if (set)
+                ioc_flags.flags = dflag;
+
+        int ioctl;
+	ioctl = set ? XFS_IOC_SET_AGF_FLAGS : XFS_IOC_GET_AGF_FLAGS;
+
+	if (xfsctl(file->name, file->fd, ioctl, &ioc_flags) < 0) {
+		fprintf(stderr,
+			_("%s: cannot %s flags %d on ag %d at %s: %s\n"),
+			progname, set ? "get" : "set", ioc_flags.flags,
+			ioc_flags.ag, file->name, strerror(errno));
+		exitcode = 1;
+		return 0;
+	}
+
+	return 0;
+}
+
+void
+agflags_init(void)
+{
+	agflags_cmd.name    = _("agflags");
+	agflags_cmd.cfunc   = agflags_f;
+	agflags_cmd.argmin  = 2;
+	agflags_cmd.argmax  = 4;
+	agflags_cmd.flags   = CMD_NOMAP_OK;
+	agflags_cmd.args    = _("[-d 0|1] -a agno");
+	agflags_cmd.oneline = _("Get or set the flags of an AG");
+	agflags_cmd.help    = agflags_help;
+
+	if (expert)
+		add_command(&agflags_cmd);
+}
diff -rNu xfs-cmds/xfsprogs/io/init.c /home/ldap/campo/xfs-cmds/xfsprogs/io/init.c
--- xfs-cmds/xfsprogs/io/init.c	2007-07-24 18:07:17.000000000 +0200
+++ /home/ldap/campo/xfs-cmds/xfsprogs/io/init.c	2007-08-31 14:10:19.697443490 +0200
@@ -54,6 +54,7 @@
 static void
 init_commands(void)
 {
+	agflags_init();
 	attr_init();
 	bmap_init();
 	fadvise_init();
diff -rNu xfs-cmds/xfsprogs/io/Makefile /home/ldap/campo/xfs-cmds/xfsprogs/io/Makefile
--- xfs-cmds/xfsprogs/io/Makefile	2006-06-17 08:12:23.000000000 +0200
+++ /home/ldap/campo/xfs-cmds/xfsprogs/io/Makefile	2007-08-13 10:42:08.536364577 +0200
@@ -10,7 +10,8 @@
 HFILES = init.h io.h
 CFILES = init.c \
 	attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c mmap.c \
-	open.c parent.c pread.c prealloc.c pwrite.c shutdown.c truncate.c
+	open.c parent.c pread.c prealloc.c pwrite.c shutdown.c truncate.c \
+	agflags.c
 
 LLDLIBS = $(LIBXCMD) $(LIBHANDLE)
 LTDEPENDENCIES = $(LIBXCMD) $(LIBHANDLE)
diff -rNu xfs-cmds/xfsprogs/man/man8/xfs_io.8 /home/ldap/campo/xfs-cmds/xfsprogs/man/man8/xfs_io.8
--- xfs-cmds/xfsprogs/man/man8/xfs_io.8	2007-07-27 17:49:00.000000000 +0200
+++ /home/ldap/campo/xfs-cmds/xfsprogs/man/man8/xfs_io.8	2007-08-31 14:05:51.175595207 +0200
@@ -524,6 +524,15 @@
 .IP
 .B [NOTE: Not currently operational on Linux.]
 .PD
+.TP
+.BR agflags " [ \-d " 0|1 " ] \-a " agno
+This command get or set the different flags of the given AG. In moment the
+only modifiable flag is XFS_AGF_FLAGS_ALLOC_DENY.
+.RS 1.0i
+.PD 0
+.TP 0.4i
+.B \-d 
+0 or 1 to (un)set XFS_AGF_FLAGS_ALLOC_DENY.
 
 .SH SEE ALSO
 .BR mkfs.xfs (8),

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-09-03  9:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-27 10:15 [PATCH] Implement ioctl to mark AGs as "don't use/use" Ruben Porras
2007-06-28  4:50 ` David Chinner
2007-06-28 10:25   ` Ruben Porras
2007-06-29  0:35     ` David Chinner
2007-06-29  0:54     ` David Chinner
2007-09-03  9:20       ` Ruben Porras

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox