Implement ioctl to mark AGs as "don't use/use"
PATCH 1/1 Implement ioctl to mark AGs as "don't use/use"
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.
Signature · 2 lines
Rubén Porras LinWorks GmbH
Index: xfs/xfs_ag.h
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_ag.h,v
retrieving revision 1.59
xfs_ag.h +10 -0
@@ -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
xfs_alloc.c +11 -0
@@ -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
xfs_fs.h +18 -16
@@ -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
xfs_fsops.c +77 -0
80 lines not on this page · raw message
Index: xfs/xfs_fsops.h
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_fsops.h,v
retrieving revision 1.29
xfs_fsops.h +3 -0
@@ -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
xfs_trans.h +4 -0
@@ -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
linux-2.6/xfs_ioctl.c +32 -0
@@ -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;
Quoted 9 lines · Ruben Porras
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 toxfs_alloc_log_agfThis 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.
xfs_ag.h line 72
Quoted 12 lines
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.59xfs_ag.hxfs_ag.h +1
-0@@ -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_ag.h line 200
Quoted 8 lines
xfs_ag.h +1
-0} 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.
Quoted 16 lines
xfs_alloc.c +3
-0@@ -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.
xfs_alloc.c line 574
Quoted 10 lines
xfs_alloc.c +7
-0+*/ + 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 ;)
Quoted 35 lines
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.33xfs_fs.hxfs_fs.h +8
-16@@ -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)
xfs_fs.h line 496
Quoted 10 lines
xfs_fs.h +10
-0+#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....)
Quoted 4 lines
xfs_fs.h +4
-0+STATIC void +xfs_ag_set_flags_private( + xfs_trans_t *tp, + xfs_buf_t *agbp, /* buffer for a.g. freelist header */
xfs_fs.h
Quoted 10 lines
xfs_fs.h +10
-0+ 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....
Quoted 6 lines
xfs_fs.h +6
-0+int +xfs_ag_set_flags ( +xfs_mount_t *mp, +xfs_ioc_agflags_t *ioc_flags) +{ +xfs_agnumber_t agno;
xfs_fs.h
Quoted 10 lines
xfs_fs.h +10
-0+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.
Quoted 8 lines
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.145xfs_trans.h
xfs_trans.h line 424
Quoted 7 lines
xfs_trans.h +4
-0@@ -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.
Quoted 10 lines
xfs_trans.h +6
-0@@ -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 ;
xfs_trans.h line 878
Quoted 10 lines
xfs_trans.h +10
-0+ +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.
Signature · 3 lines
Dave Chinner Principal Engineer SGI Australian Software Group
Quoted 4 lines · David Chinner
It's a good first cut - comments are inline in the patch below.
Quoted 8 lines
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 ;)
Quoted 11 lines
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 toxfs_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
Signature · 2 lines
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
xfs/xfs_ag.h +12 -1
@@ -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
xfs/xfs_alloc.c +13 -0
@@ -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
xfs/xfs_fs.h +2 -0
@@ -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
xfs/xfs_fsops.c +76 -0
79 lines not on this page · raw message
Index: fs/xfs/xfs_fsops.h
===================================================================
RCS file: /cvs/linux-2.6-xfs/fs/xfs/xfs_fsops.h,v
retrieving revision 1.29
xfs/xfs_fsops.h +3 -0
@@ -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
xfs/xfs_trans.h +2 -1
@@ -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
xfs/linux-2.6/xfs_ioctl.c +31 -0
@@ -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;
Quoted 3 lines · Ruben Porras
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 ;)
Quoted 27 lines
There is one question that I would like to ask: when you sketched the
xfs_alloc_set_flag_agfunction, you put inside it the call to the funcintionxfs_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(...)
Quoted 8 lines
{
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.
Signature · 3 lines
Dave Chinner Principal Engineer SGI Australian Software Group
Quoted 2 lines · Ruben Porras
Ok, thank you for the explanation, I think that now I got it right. Attached is a new patch.
Only one minor nit:
xfs/xfs_alloc.c line 567
Quoted 10 lines
xfs/xfs_alloc.c +6
-0@@ -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.
Signature · 3 lines
Dave Chinner Principal Engineer SGI Australian Software Group
Quoted 3 lines · David Chinner
OOC, do you have any test code for this?
xfs_iowould 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.
Signature · 2 lines
Rubén Porras LinWorks GmbH
home/ldap/campo/xfs-cmds/xfsprogs/include/xfs_ag.h renamed from xfsprogs/include/xfs_ag.h +12 -1
@@ -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)))
home/ldap/campo/xfs-cmds/xfsprogs/include/xfs_fs.h renamed from xfsprogs/include/xfs_fs.h +2 -0
@@ -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 */
home/ldap/campo/xfs-cmds/xfsprogs/io/agflags.c renamed from xfsprogs/io/agflags.c +126 -0
126 lines not on this page · raw message
home/ldap/campo/xfs-cmds/xfsprogs/io/init.c renamed from xfsprogs/io/init.c +1 -0
@@ -54,6 +54,7 @@static void init_commands (void ) { +agflags_init ();attr_init ();bmap_init ();fadvise_init ();
home/ldap/campo/xfs-cmds/xfsprogs/io/Makefile renamed from xfsprogs/io/Makefile +2 -1
@@ -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)
home/ldap/campo/xfs-cmds/xfsprogs/man/man8/xfs_io.8 renamed from xfsprogs/man/man8/xfs_io.8 +9 -0
@@ -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),