xfs: Add xfs_log_rlimit.[c|h]
PATCH v2 7/8 xfs: Add xfs_log_rlimit.[c|h]
From: Jie Liu <[email protected]>
Add source files for xfs_log_rlimit.[c|h].
The new source would be used for the log space validation.
--- fs/xfs/Makefile | 3 +- fs/xfs/xfs_log_rlimit.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_log_rlimit.h | 25 ++++++++ fs/xfs/xfs_mount.h | 3 + 4 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/xfs_log_rlimit.c create mode 100644 fs/xfs/xfs_log_rlimit.h
fs/xfs/Makefile +2 -1
@@ -75,7 +75,8 @@ xfs-y += xfs_alloc.o \ xfs_log_recover.o \ xfs_mount.o \ xfs_symlink.o \ - xfs_trans.o + xfs_trans.o \ + xfs_log_rlimit.o # low-level transaction/log code xfs-y += xfs_log.o \
fs/xfs/xfs_log_rlimit.c new file +148 -0
148 lines not on this page · raw message
fs/xfs/xfs_log_rlimit.h new file +25 -0
@@ -0,0 +1,25 @@ +/* +* Copyright (c) 2013 Jie Liu. +* 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 +*/ +#ifndef __XFS_LOG_RLIMIT_H__ +#define __XFS_LOG_RLIMIT_H__ + +void xfs_log_adjust_max_attrsetm_res (struct xfs_mount *); +void xfs_log_get_max_trans_res (struct xfs_mount *,struct xfs_trans_res *); +void xfs_log_validate_logspace (struct xfs_mount *); + +#endif /* __XFS_LOG_PRIV_H__ */
fs/xfs/xfs_mount.h +3 -0
@@ -62,6 +62,9 @@ typedef struct xfs_trans_reservations {struct xfs_trans_res tr_fsyncts;/* update timestamps on fsync */ } xfs_trans_reservations_t; +#define XFS_TRANS_RES_NUM (sizeof(struct xfs_trans_reservations) / \ + sizeof(struct xfs_trans_res)) +#ifndef __KERNEL__#define xfs_daddr_to_agno (mp,d) \
Signature · 6 lines
1.7.9.5 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
How do I get this to build? With gcc-4.8.0, the kernel build ends like this:
LINK vmlinux
LD vmlinux.o
MODPOST vmlinux.o
GEN .version CHK include/generated/compile.h UPD include/generated/compile.h CC init/version.o LD init/built-in.o
fs/built-in.o: In function `xfs_log_validate_logspace':/usr/src/kernel-git/linux/fs/xfs/xfs_log_rlimit.c:130: undefined reference to `__udivdi3'
make: *** [vmlinux] Error 1
The fs/xfs section of the kernel did build without errors, though.
Thanks!
Michael
Quoted 221 lines · Jeff Liu
From: Jie Liu <[email protected]>
Add source files for xfs_log_rlimit.[c|h].
The new source would be used for the log space validation.Signed-off-by Jie Liu <[email protected]>--- fs/xfs/Makefile | 3 +- fs/xfs/xfs_log_rlimit.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_log_rlimit.h | 25 ++++++++ fs/xfs/xfs_mount.h | 3 + 4 files changed, 178 insertions(+), 1 deletion(-)create mode 100644
fs/xfs/xfs_log_rlimit.c
create mode 100644fs/xfs/xfs_log_rlimit.hfs/xfs/Makefile +2
-1@@ -75,7 +75,8 @@ xfs-y += xfs_alloc.o \ xfs_log_recover.o \ xfs_mount.o \ xfs_symlink.o \ - xfs_trans.o + xfs_trans.o \ + xfs_log_rlimit.o # low-level transaction/log code xfs-y += xfs_log.o \fs/xfs/xfs_log_rlimit.c new file +148
-0@@ -0,0 +1,148 @@ +/* +* Copyright (c) 2013 Jie Liu. +* 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.h" +#include "xfs_fs.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_trans_space.h" +#include "xfs_bmap_btree.h" +#include "xfs_inode.h" +#include "xfs_log.h" +#include "xfs_log_priv.h" +#include "xfs_da_btree.h" +#include "xfs_attr_leaf.h" + +void +xfs_log_adjust_max_attrsetm_res ( +struct xfs_mount *mp) +{ +int size; +int nblks; +int res; + +/* +* Calculate the maximum length in bytes that would be required +* for a local attribute value as large attributes out of line +* are not logged. +*/ + size =xfs_attr_leaf_entsize_local_max (mp->m_sb.sb_blocksize) - +MAXNAMELEN -1 ; + nblks =XFS_DAENTER_SPACE_RES (mp,XFS_ATTR_FORK ); + nblks +=XFS_B_TO_FSB (mp, size); + nblks +=XFS_NEXTENTADD_SPACE_RES (mp, size,XFS_ATTR_FORK ); + + res =m_tresp (mp)->tr_attrsetm.tr_logres + +m_tresp (mp)->tr_attrsetrt.tr_logres * nblks; + mp->m_reservations.tr_attrsetm.tr_logres = res; +} + +/* +* Iterate over the log space reservation table to figure out and return +* the maximum one in terms of the pre-calculated values which were done +* at mount time. +*/ +void +xfs_log_get_max_trans_res ( +struct xfs_mount *mp, +struct xfs_trans_res *max_tresp) +{ +struct xfs_trans_reservations *mtresp =m_tresp (mp); +struct xfs_trans_res tres_items[XFS_TRANS_RES_NUM ]; +struct xfs_trans_res *tresp; +int i, logspace =0 ; + +xfs_log_adjust_max_attrsetm_res (mp); + +memcpy (tres_items, mtresp,sizeof (*mtresp)); +for (i =0 ; i <ARRAY_SIZE (tres_items); i++) { +struct xfs_trans_res *p = &tres_items[i]; +int tmp = p->tr_logcount >1 ? + p->tr_logres * p->tr_logcount : + p->tr_logres; +if (logspace < tmp) { + logspace = tmp; + tresp = p; + } + } + + *max_tresp = *tresp; +} + +/* +* Verify if the configured log space is sufficient or not for the specified +* log stripe unit. +*/ +void +xfs_log_validate_logspace ( +struct xfs_mount *mp) +{ +struct xlog *log = mp->m_log; +struct xfs_trans_res tres; +int maxlres; +int minlblks =0 , lsunit =0 ; + +xfs_log_get_max_trans_res (mp, &tres); + + maxlres =xfs_log_calc_unit_res (mp, tres.tr_logres); + maxlres = tres.tr_logcount >1 ? maxlres * tres.tr_logcount : maxlres; + +if (xfs_sb_version_haslogv2 (&log->l_mp->m_sb) && + log->l_mp->m_sb.sb_logsunit >1 ) + lsunit =BTOBB (log->l_mp->m_sb.sb_logsunit); + +/* +* Two factors should be taken into account for calculating the minimum +* log space. +* 1) The fundamental limitation is that no single transaction can be +* larger than half size of the log. +* 2) If the lsunit option is specified, a transaction requires 2 LSU +* for the reservation because there are two log writes that can +* require padding - the transaction data and the commit record which +* are written separately and both can require padding to the LSU. +* Consider that we can have an active CIL reservation holding 2*LSU, +* but the CIL is not over a push threshold, in this case, if we +* don't have enough log space for at one new transaction, which +* includes another 2*LSU in the reservation, we will run into dead +* loop situation in log space grant procedure. i.e. +* xlog_grant_head_wait(). +* +* Hence the log size needs to be able to contain two maximally sized +* and padded transactions, which is (2 * (2 * LSU + maxlres)). +* +* Also, the log size should be a multiple of the log stripe unit, round +* it up to lsunit boundary if lsunit is specified. +*/ + minlblks = lsunit ? (roundup (BTOBB (maxlres), lsunit) +2 * lsunit) *2 : +BTOBB (maxlres) *2 ; + +if (log->l_logBBsize < minlblks) { +xfs_crit (mp, +"Log size %d blocks too small, minimu size is %d blocks" , + log->l_logBBsize, minlblks); + } +if (log->l_logBBsize >XFS_MAX_LOG_BLOCKS ) { +xfs_crit (mp, +"Log size %d blocks too large, maximum size is %lld blocks" , + log->l_logBBsize,XFS_MAX_LOG_BLOCKS ); + } +if (log->l_logsize >XFS_MAX_LOG_BYTES ) { +xfs_crit (mp, +"log size %lld bytes too large, maximum size is %lld bytes" , + (long long )(log->l_logsize),XFS_MAX_LOG_BYTES ); + } +}fs/xfs/xfs_log_rlimit.h new file +25
-0@@ -0,0 +1,25 @@ +/* +* Copyright (c) 2013 Jie Liu. +* 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 +*/ +#ifndef __XFS_LOG_RLIMIT_H__ +#define __XFS_LOG_RLIMIT_H__ + +void xfs_log_adjust_max_attrsetm_res (struct xfs_mount *); +void xfs_log_get_max_trans_res (struct xfs_mount *,struct xfs_trans_res *); +void xfs_log_validate_logspace (struct xfs_mount *); + +#endif /* __XFS_LOG_PRIV_H__ */ fs/xfs/xfs_mount.h +0
-0
fs/xfs/xfs_mount.h typedef struct xfs_trans_reservations { · line 70
Quoted 9 lines
fs/xfs/xfs_mount.h +3
-0@@ -62,6 +62,9 @@ typedef struct xfs_trans_reservations {struct xfs_trans_res tr_fsyncts;/* update timestamps on fsync */ } xfs_trans_reservations_t; +#define XFS_TRANS_RES_NUM (sizeof(struct xfs_trans_reservations) / \ + sizeof(struct xfs_trans_res)) +#ifndef __KERNEL__#define xfs_daddr_to_agno (mp,d) \
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 4 lines · Jeff Liu
From: Jie Liu <[email protected]>
Add source files for xfs_log_rlimit.[c|h].
The new source would be used for the log space validation.
Update: To build the kernel, I'm getting by on a sysadmin hack that looks like this:
fs/xfs/xfs_log_rlimit.c renamed from fs/xfs/xfs_log_rlimit.c.orig +4 -2
@@ -127,8 +127,10 @@* Also, the log size should be a multiple of the log stripe unit, round * it up to lsunit boundary if lsunit is specified. */ - minlblks = lsunit ? (roundup (BTOBB (maxlres), lsunit) +2 * lsunit) *2 : -BTOBB (maxlres) *2 ; + minlblks = lsunit ? + (roundup ((const int )(BTOBB (maxlres)), lsunit) + +2 * lsunit) *2 : +BTOBB (maxlres) *2 ;if (log->l_logBBsize < minlblks) { xfs_crit(mp,
However, that makes no sense. There is a roundup in <linux/kernel.h> that goes like this:
/* The `const' in roundup() prevents gcc-3.3 from calling __divdi3 */
#define roundup(x, y) ( \
{ \
const typeof(y) __y = y; \
(((x) + (__y - 1)) / __y) * __y; \
} \)
Okay, so that gave me the inspiration to cast the type so gcc-4.8.0 wouldn't call __divdi3. But why did this make a difference?
Disclaimer: I'm not a C macro guru, so I don't know which random sequence of punctuation keys would make roundup() happy.
Michael
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Hi Michael,
Are you compiling kernel on 32-bit system?
Looks this issue is regarding 64-bit division at roundup() on 32-bit if so.
Could you please try below fix?
fs/xfs/xfs_log_rlimit.c +1 -1
@@ -127,7 +127,7 @@ xfs_log_validate_logspace(* Also, the log size should be a multiple of the log stripe unit, round * it up to lsunit boundary if lsunit is specified. */ - minlblks = lsunit ? (roundup (BTOBB (maxlres), lsunit) +2 * lsunit) *2 : + minlblks = lsunit ? (roundup ((int )BTOBB (maxlres), lsunit) +2 * lsunit) *2 :BTOBB (maxlres) *2 ;if (log->l_logBBsize < minlblks) {
Thanks,
-Jeff
Quoted 43 lines · Michael L. Semon
Quoted 4 lines · Jeff Liu
From: Jie Liu <[email protected]>
Add source files for xfs_log_rlimit.[c|h].
The new source would be used for the log space validation.Update: To build the kernel, I'm getting by on a sysadmin hack that looks like this:
fs/xfs/xfs_log_rlimit.c renamed from fs/xfs/xfs_log_rlimit.c.orig +4
-2@@ -127,8 +127,10 @@* Also, the log size should be a multiple of the log stripe unit, round * it up to lsunit boundary if lsunit is specified. */ - minlblks = lsunit ? (roundup (BTOBB (maxlres), lsunit) +2 * lsunit) *2 : -BTOBB (maxlres) *2 ; + minlblks = lsunit ? + (roundup ((const int )(BTOBB (maxlres)), lsunit) + +2 * lsunit) *2 : +BTOBB (maxlres) *2 ;if (log->l_logBBsize < minlblks) { xfs_crit(mp,However, that makes no sense. There is a roundup in <
linux/kernel.h> that goes like this:/* The `const' in
roundup()prevents gcc-3.3 from calling__divdi3*/
#defineroundup(x, y)( \{ \ const typeof(y) __y = y; \ (((x) + (__y - 1)) / __y) * __y; \ } \)
Okay, so that gave me the inspiration to cast the type so gcc-4.8.0 wouldn't call
__divdi3. But why did this make a difference?Disclaimer: I'm not a C macro guru, so I don't know which random sequence of punctuation keys would make
roundup()happy.
Quoted 7 lines
Michael
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 5 lines · Jeff Liu
Hi Michael,
Are you compiling kernel on 32-bit system?
Looks this issue is regarding 64-bit division at
roundup()on 32-bit if so.
roundup_64() is what you want, then.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 8 lines · Dave Chinner
Quoted 5 lines · Jeff Liu
Hi Michael,
Are you compiling kernel on 32-bit system?
Looks this issue is regarding 64-bit division at
roundup()on 32-bit if so.
roundup_64()is what you want, then.
Yep, will take care of it.
Thanks,
-Jeff
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 3 lines · Jeff Liu
Hi Michael,
Are you compiling kernel on 32-bit system?
Yes, this is a 32-bit Pentium 4 system.
Quoted 19 lines
Looks this issue is regarding 64-bit division at
roundup()on 32-bit if so.Could you please try below fix?
fs/xfs/xfs_log_rlimit.c +1
-1@@ -127,7 +127,7 @@ xfs_log_validate_logspace(* Also, the log size should be a multiple of the log stripe unit, round * it up to lsunit boundary if lsunit is specified. */ - minlblks = lsunit ? (roundup (BTOBB (maxlres), lsunit) +2 * lsunit) *2 : + minlblks = lsunit ? (roundup ((int )BTOBB (maxlres), lsunit) +2 * lsunit) *2 :BTOBB (maxlres) *2 ;if (log->l_logBBsize < minlblks) {
Quoted 2 lines
Thanks,
-Jeff
This code works, and my sysadmin-hack use of "const" was not needed after all. If you use Dave's suggestion to use roundup_64(), I'll be happy to apply another patch.
Thanks!
Michael
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs