xfs: add support for tracking inodes with post-EOF speculative preallocation
cover xfs: add support for tracking inodes with post-EOF speculative preallocation
Hi all,
The following patchset adds support for tracking and clearing inodes with post-EOF space due to speculative preallocation. The purpose of this work is to add some flexibility and management control over inodes in this state. The specific impetus for this work is to support improved quota management in the glusterfs cluster filesystem. For example, this provides the ability to potentially free up a significant amount of unwritten space when at or near EDQUOT (FWIW, I'm also working on a patch to support prealloc throttling near EDQUOT, but I'm considering that separate). Despite the motivation, this work is intended to be generic and hopefully useful for other XFS users.
We track inodes with post-EOF space via a new tag in the per-ag inode radix tree. The tag management, introduced in patch 1, is generally lazy in an attempt to keep things simple. Patch 2 implements scanning functionality to locate and potentially trim inodes with post-EOF space. Patch 3 adds a new ioctl() to extend support to userspace. Patch 4 adds background scanning based on the existing syncd workqueue.
This patchset is marked RFC because aside from general review, I have some questions on the best approach for several bits (marked with 'TODO' comments), most notably whether we should include new tunables for the background scanning. Some further testing is warranted, but I suspect that using the syncd default of 30s might be a bit too aggressive for large files.
These patches have been lightly unit tested and run through xfstests. Thoughts appreciated.
Brian
P.S., Credit to Dave Chinner for early review and guidance on design.
Brian Foster (4):
xfs: add EOFBLOCKS inode tagging/untagging
xfs: create function to scan and clear EOFBLOCKS inodes
xfs: add FREE_EOFBLOCKS ioctl
xfs: add background scanning to clear EOFBLOCKS inodes
fs/xfs/xfs_ag.h | 1 + fs/xfs/xfs_fs.h | 10 ++ fs/xfs/xfs_inode.h | 8 ++- fs/xfs/xfs_ioctl.c | 25 +++++ fs/xfs/xfs_iomap.c | 7 ++ fs/xfs/xfs_iops.c | 3 + fs/xfs/xfs_mount.h | 2 + fs/xfs/xfs_quota.h | 1 + fs/xfs/xfs_quotaops.c | 2 +- fs/xfs/xfs_sync.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_sync.h | 9 ++ fs/xfs/xfs_trace.h | 5 + fs/xfs/xfs_vnodeops.c | 16 ++- fs/xfs/xfs_vnodeops.h | 2 + 14 files changed, 362 insertions(+), 6 deletions(-)
Signature · 6 lines
1.7.7.6 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
RFC PATCH 1/4 xfs: add EOFBLOCKS inode tagging/untagging
Add the XFS_ICI_EOFBLOCKS_TAG inode tag to identify inodes with speculatively preallocated blocks beyond EOF. An inode is tagged when speculative preallocation occurs and untagged either via truncate down or when post-EOF blocks are freed via release or reclaim.
The tag management is intentionally not aggressive to prefer simplicity over the complexity of handling all the corner cases under which post-EOF blocks could be freed (i.e., forward truncation, fallocate, write error conditions, etc.). This means that a tagged inode may or may not have post-EOF blocks after a period of time. The tag is eventually cleared when the inode is released or reclaimed.
--- fs/xfs/xfs_ag.h | 1 + fs/xfs/xfs_inode.h | 8 ++++- fs/xfs/xfs_iomap.c | 7 ++++ fs/xfs/xfs_iops.c | 3 ++ fs/xfs/xfs_sync.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_sync.h | 3 ++ fs/xfs/xfs_trace.h | 5 +++ fs/xfs/xfs_vnodeops.c | 3 ++ 8 files changed, 105 insertions(+), 1 deletions(-)
fs/xfs/xfs_ag.h +1 -0
@@ -233,6 +233,7 @@ typedef struct xfs_perag {#define XFS_ICI_NO_TAG (-1)/* special flag for an untagged lookup in xfs_inode_ag_iterator */ #define XFS_ICI_RECLAIM_TAG 0/* inode is to be reclaimed */ +#define XFS_ICI_EOFBLOCKS_TAG 1/* inode has blocks beyond EOF */ #define XFS_AG_MAXLEVELS (mp) ((mp)->m_ag_maxlevels)#define XFS_MIN_FREELIST_RAW (bl,cl,mp) \
fs/xfs/xfs_inode.h +7 -1
@@ -305,10 +305,16 @@ xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) }static inline void +__xfs_iflags_clear (xfs_inode_t *ip,unsigned short flags) +{ + ip->i_flags &= ~flags; +} + +static inline void xfs_iflags_clear (xfs_inode_t *ip,unsigned short flags) {spin_lock (&ip->i_flags_lock); - ip->i_flags &= ~flags; +__xfs_iflags_clear (ip, flags);spin_unlock (&ip->i_flags_lock); }
fs/xfs/xfs_iomap.c +7 -0
@@ -459,6 +459,13 @@ retry:if (!(imap[0 ].br_startblock ||XFS_IS_REALTIME_INODE (ip)))return xfs_alert_fsblock_zero (ip, &imap[0 ]); +/* +* Tag the inode as speculatively preallocated so we can reclaim this +* space on demand, if necessary. +*/ +if (prealloc) +xfs_inode_set_eofblocks_tag (ip); + *ret_imap = imap[0 ];return 0 ; }
fs/xfs/xfs_iops.c +3 -0
@@ -854,6 +854,9 @@ xfs_setattr_size(* and do not wait the usual (long) time for writeout. */ xfs_iflags_set (ip,XFS_ITRUNCATED ); + +/* A truncate down always removes post-EOF blocks. */ +xfs_inode_clear_eofblocks_tag (ip); }if (mask &ATTR_CTIME ) {
fs/xfs/xfs_sync.c +76 -0
79 lines not on this page · raw message
fs/xfs/xfs_sync.h +3 -0
@@ -43,6 +43,9 @@ void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);void __xfs_inode_clear_reclaim_tag (struct xfs_mount *mp,struct xfs_perag *pag,struct xfs_inode *ip); +void xfs_inode_set_eofblocks_tag (struct xfs_inode *ip); +void xfs_inode_clear_eofblocks_tag (struct xfs_inode *ip); +int xfs_sync_inode_grab (struct xfs_inode *ip); int xfs_inode_ag_iterator(struct xfs_mount *mp, int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
fs/xfs/xfs_trace.h +5 -0
@@ -129,6 +129,8 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_get_tag);DEFINE_PERAG_REF_EVENT (xfs_perag_put);DEFINE_PERAG_REF_EVENT (xfs_perag_set_reclaim);DEFINE_PERAG_REF_EVENT (xfs_perag_clear_reclaim); +DEFINE_PERAG_REF_EVENT (xfs_perag_set_eofblocks); +DEFINE_PERAG_REF_EVENT (xfs_perag_clear_eofblocks); TRACE_EVENT(xfs_attr_list_node_descend, TP_PROTO(struct xfs_attr_list_context *ctx,
@@ -584,6 +586,9 @@ DEFINE_INODE_EVENT(xfs_update_time);DEFINE_INODE_EVENT (xfs_dquot_dqalloc);DEFINE_INODE_EVENT (xfs_dquot_dqdetach); +DEFINE_INODE_EVENT (xfs_set_eofblocks_tag); +DEFINE_INODE_EVENT (xfs_clear_eofblocks_tag); + DECLARE_EVENT_CLASS(xfs_iref_class, TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), TP_ARGS(ip, caller_ip),
fs/xfs/xfs_vnodeops.c +3 -0
@@ -467,6 +467,8 @@ xfs_release(if (error)return error; +xfs_inode_clear_eofblocks_tag (ip); +/* delalloc blocks after truncation means it really is dirty */ if (ip->i_delayed_blks)xfs_iflags_set (ip,XFS_IDIRTY_RELEASE );
@@ -523,6 +525,7 @@ xfs_inactive( error =xfs_free_eofblocks (mp, ip, false);if (error)return VN_INACTIVE_CACHE ; +xfs_inode_clear_eofblocks_tag (ip); } goto out; }
Signature · 6 lines
1.7.7.6 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 1/4] xfs: add EOFBLOCKS inode tagging/untagging
Quoted 15 lines · Brian Foster
Add the
XFS_ICI_EOFBLOCKS_TAGinode tag to identify inodes with speculatively preallocated blocks beyond EOF. An inode is tagged when speculative preallocation occurs and untagged either via truncate down or when post-EOF blocks are freed via release or reclaim.The tag management is intentionally not aggressive to prefer simplicity over the complexity of handling all the corner cases under which post-EOF blocks could be freed (i.e., forward truncation, fallocate, write error conditions, etc.). This means that a tagged inode may or may not have post-EOF blocks after a period of time. The tag is eventually cleared when the inode is released or reclaimed.
Signed-off-by Brian Foster <[email protected]>
.....
Quoted 11 lines
fs/xfs/xfs_inode.h +3
-0@@ -305,10 +305,16 @@ xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) }static inline void +__xfs_iflags_clear (xfs_inode_t *ip,unsigned short flags) +{ + ip->i_flags &= ~flags;
fs/xfs/xfs_inode.h xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) · line 319
Quoted 10 lines
fs/xfs/xfs_inode.h +4
-1+} + +static inline void xfs_iflags_clear (xfs_inode_t *ip,unsigned short flags) {spin_lock (&ip->i_flags_lock); - ip->i_flags &= ~flags; +__xfs_iflags_clear (ip, flags);spin_unlock (&ip->i_flags_lock); }
Left overs from a previous version?
Quoted 70 lines
fs/xfs/xfs_iomap.c +7
-0@@ -459,6 +459,13 @@ retry:if (!(imap[0 ].br_startblock ||XFS_IS_REALTIME_INODE (ip)))return xfs_alert_fsblock_zero (ip, &imap[0 ]); +/* +* Tag the inode as speculatively preallocated so we can reclaim this +* space on demand, if necessary. +*/ +if (prealloc) +xfs_inode_set_eofblocks_tag (ip); + *ret_imap = imap[0 ];return 0 ; }fs/xfs/xfs_iops.c +3
-0@@ -854,6 +854,9 @@ xfs_setattr_size(* and do not wait the usual (long) time for writeout. */ xfs_iflags_set (ip,XFS_ITRUNCATED ); + +/* A truncate down always removes post-EOF blocks. */ +xfs_inode_clear_eofblocks_tag (ip); }if (mask &ATTR_CTIME ) {fs/xfs/xfs_sync.c +29
-0@@ -971,3 +971,79 @@ xfs_reclaim_inodes_count(return reclaimable; } +STATIC void +__xfs_inode_set_eofblocks_tag ( +struct xfs_perag *pag, +struct xfs_inode *ip) +{ +int tagged =radix_tree_tagged (&pag->pag_ici_root, +XFS_ICI_EOFBLOCKS_TAG ); + +radix_tree_tag_set (&pag->pag_ici_root, +XFS_INO_TO_AGINO (ip->i_mount, ip->i_ino), +XFS_ICI_EOFBLOCKS_TAG ); + +if (!tagged) { +/* propagate the eofblocks tag up into the perag radix tree */ +spin_lock (&ip->i_mount->m_perag_lock); +radix_tree_tag_set (&ip->i_mount->m_perag_tree, +XFS_INO_TO_AGNO (ip->i_mount, ip->i_ino), +XFS_ICI_EOFBLOCKS_TAG ); +spin_unlock (&ip->i_mount->m_perag_lock); + +trace_xfs_perag_set_eofblocks (ip->i_mount, pag->pag_agno, +-1 , _RET_IP_); + } +} + +void +xfs_inode_set_eofblocks_tag ( +xfs_inode_t *ip) +{
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1012
Quoted 10 lines
fs/xfs/xfs_sync.c +10
-0+struct xfs_mount *mp = ip->i_mount; +struct xfs_perag *pag; + + pag =xfs_perag_get (mp,XFS_INO_TO_AGNO (mp, ip->i_ino)); +spin_lock (&pag->pag_ici_lock); +trace_xfs_set_eofblocks_tag (ip); +__xfs_inode_set_eofblocks_tag (pag, ip); +spin_unlock (&pag->pag_ici_lock); +xfs_perag_put (pag); +}
I know the code you copied had this two-function structure, but that was because it has callers of the __ versions of the functions. I'd just make these a single function.
Quoted 26 lines
fs/xfs/xfs_sync.c +26
-0+ +STATIC void +__xfs_inode_clear_eofblocks ( +xfs_perag_t *pag, +xfs_inode_t *ip) +{ +radix_tree_tag_clear (&pag->pag_ici_root, +XFS_INO_TO_AGINO (ip->i_mount, ip->i_ino), +XFS_ICI_EOFBLOCKS_TAG ); + +if (!radix_tree_tagged (&pag->pag_ici_root,XFS_ICI_EOFBLOCKS_TAG )) { +/* clear the eofblocks tag from the perag radix tree */ +spin_lock (&ip->i_mount->m_perag_lock); +radix_tree_tag_clear (&ip->i_mount->m_perag_tree, +XFS_INO_TO_AGNO (ip->i_mount, ip->i_ino), +XFS_ICI_EOFBLOCKS_TAG ); +spin_unlock (&ip->i_mount->m_perag_lock); +trace_xfs_perag_clear_eofblocks (ip->i_mount, pag->pag_agno, +-1 , _RET_IP_); + } +} + +void +xfs_inode_clear_eofblocks_tag ( +xfs_inode_t *ip) +{
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1048
Quoted 10 lines
fs/xfs/xfs_sync.c +10
-0+struct xfs_mount *mp = ip->i_mount; +struct xfs_perag *pag; + + pag =xfs_perag_get (mp,XFS_INO_TO_AGNO (mp, ip->i_ino)); +spin_lock (&pag->pag_ici_lock); +trace_xfs_clear_eofblocks_tag (ip); +__xfs_inode_clear_eofblocks (pag, ip); +spin_unlock (&pag->pag_ici_lock); +xfs_perag_put (pag); +}
Same here.
Quoted 14 lines
fs/xfs/xfs_vnodeops.c +2
-0@@ -467,6 +467,8 @@ xfs_release(if (error)return error; +xfs_inode_clear_eofblocks_tag (ip); +/* delalloc blocks after truncation means it really is dirty */ if (ip->i_delayed_blks)xfs_iflags_set (ip,XFS_IDIRTY_RELEASE );
fs/xfs/xfs_vnodeops.c xfs_inactive( · line 530
Quoted 6 lines
fs/xfs/xfs_vnodeops.c +1
-0@@ -523,6 +525,7 @@ xfs_inactive( error =xfs_free_eofblocks (mp, ip, false);if (error)return VN_INACTIVE_CACHE ; +xfs_inode_clear_eofblocks_tag (ip); } goto out;
I think it's better to call xfs_inode_clear_eofblocks_tag() inside xfs_free_eofblocks() - that's where the blocks are being freed, after all.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
RFC PATCH 2/4 xfs: create function to scan and clear EOFBLOCKS inodes
In reply to Brian Fosterxfs_inodes_free_eofblocks() implements scanning functionality for EOFBLOCKS inodes. It scans the radix tree and frees post-EOF blocks for inodes that meet particular criteria. The scan can be filtered by a particular quota type/id and minimum file size. The scan can also be invoked in trylock mode or wait (force) mode.
The xfs_free_eofblocks() helper is invoked to clear post-EOF space. It is slightly modified to support an output parameter that indicates whether space was freed and helps decide whether the EOFBLOCKS tag should be cleared in trylock scans.
--- fs/xfs/xfs_sync.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_sync.h | 3 + fs/xfs/xfs_vnodeops.c | 17 +++-- fs/xfs/xfs_vnodeops.h | 2 + 4 files changed, 184 insertions(+), 6 deletions(-)
fs/xfs/xfs_sync.c +168 -0
@@ -971,6 +971,174 @@ xfs_reclaim_inodes_count(return reclaimable; } +/* +* Handle an EOFBLOCKS tagged inode. If this is a forced scan, we wait on the +* iolock ourselves rather than rely on the trylock in xfs_free_eofblocks(). +* +* We rely on the output parameter from xfs_free_eofblocks() to determine +* whether we should clear the tag because in the trylock case, it could have +* skipped the inode due to lock contention. +*/ +STATIC int +xfs_inode_free_eofblocks ( +struct xfs_inode *ip, +int flags) +{ +int ret =0 ; +bool freed = false; +bool wait_iolock = (flags &EOFBLOCKS_WAIT ) ? true : false; + +if (wait_iolock) +xfs_ilock (ip,XFS_IOLOCK_EXCL ); + +if ((S_ISREG (ip->i_d.di_mode) && + (VFS_I (ip)->i_size >0 || + (VN_CACHED (VFS_I (ip)) >0 || ip->i_delayed_blks >0 )) && + (ip->i_df.if_flags &XFS_IFEXTENTS )) && + (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC |XFS_DIFLAG_APPEND )))) { +/* !wait_iolock == need_iolock in xfs_free_eofblocks() */ + ret =xfs_free_eofblocks (ip->i_mount, ip, !wait_iolock, &freed); +if (freed) +xfs_inode_clear_eofblocks_tag (ip); + }else { +/* inode could be preallocated or append-only */ +xfs_inode_clear_eofblocks_tag (ip); + } + +if (wait_iolock) +xfs_iunlock (ip,XFS_IOLOCK_EXCL ); + +return ret; +} + +/* +* Determine whether an inode matches a particular qouta id. +*/ +STATIC int +xfs_inode_match_quota_id ( +struct xfs_inode *ip, +int qtype, +uint32_t id) +{ +switch (qtype) { +case XFS_DQ_USER : +return ip->i_d.di_uid == id; +case XFS_DQ_GROUP : +return ip->i_d.di_gid == id; +default : +return xfs_get_projid (ip) == id; + } + +return 0 ; +} + +/* +* This is mostly copied from xfs_reclaim_inodes_ag(). +* +* TODO: +* - Could we enhance ag_iterator to support a tag and use it instead of this? +*/ +int +xfs_inodes_free_eofblocks ( +struct xfs_mount *mp, +int qtype, +uint32_t id, +uint64_t min_file_size, +int flags) +{ +struct xfs_perag *pag; +int error =0 ; +int last_error =0 ; +xfs_agnumber_t ag; + + ag =0 ; +while ((pag =xfs_perag_get_tag (mp, ag,XFS_ICI_EOFBLOCKS_TAG ))) { +unsigned long first_index =0 ; +int nr_found =0 ; +int done =0 ; + + ag = pag->pag_agno +1 ; + +do { +struct xfs_inode *batch[XFS_LOOKUP_BATCH ]; +int i; + +rcu_read_lock (); + nr_found =radix_tree_gang_lookup_tag ( + &pag->pag_ici_root, + (void **)batch, first_index, +XFS_LOOKUP_BATCH , +XFS_ICI_EOFBLOCKS_TAG ); +if (!nr_found) { +rcu_read_unlock (); +break ; + } + +/* +* Grab the inodes before we drop the lock. if we found +* nothing, nr == 0 and the loop will be skipped. +*/ +for (i =0 ; i < nr_found; i++) { +struct xfs_inode *ip = batch[i]; + +if (done ||xfs_inode_ag_walk_grab (ip)) + batch[i] =NULL ; + +/* +* Update the index for the next lookup. Catch +* overflows into the next AG range which can occur if +* we have inodes in the last block of the AG and we +* are currently pointing to the last inode. +* +* Because we may see inodes that are from the wrong AG +* due to RCU freeing and reallocation, only update the +* index if it lies in this AG. It was a race that lead +* us to see this inode, so another lookup from the +* same index will not find it again. +*/ +if (XFS_INO_TO_AGNO (mp, ip->i_ino) != + pag->pag_agno) +continue ; + first_index =XFS_INO_TO_AGINO (mp, ip->i_ino +1 ); +if (first_index <XFS_INO_TO_AGINO (mp, ip->i_ino)) + done =1 ; + } + +/* unlock now we've grabbed the inodes. */ +rcu_read_unlock (); + +for (i =0 ; i < nr_found; i++) { +if (!batch[i]) +continue ; + +/* default projid represents a full scan */ +if ((!(qtype ==XFS_DQ_PROJ && + id ==XFS_PROJID_DEFAULT ) && + !xfs_inode_match_quota_id (batch[i], qtype, + id)) || + (min_file_size &&XFS_ISIZE (batch[i]) < + min_file_size) + ) { +IRELE (batch[i]); +continue ; + } + + error =xfs_inode_free_eofblocks (batch[i], flags); +IRELE (batch[i]); +if (error) + last_error = error; + } + +cond_resched (); + + }while (nr_found && !done); + +xfs_perag_put (pag); + } + +return XFS_ERROR (last_error); +} + STATIC void __xfs_inode_set_eofblocks_tag( struct xfs_perag *pag,
fs/xfs/xfs_sync.h +3 -0
@@ -43,8 +43,11 @@ void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);void __xfs_inode_clear_reclaim_tag (struct xfs_mount *mp,struct xfs_perag *pag,struct xfs_inode *ip); +#define EOFBLOCKS_WAIT 0x0001 +void xfs_inode_set_eofblocks_tag (struct xfs_inode *ip);void xfs_inode_clear_eofblocks_tag (struct xfs_inode *ip); +int xfs_inodes_free_eofblocks (struct xfs_mount *,int ,uint32_t ,uint64_t ,int );int xfs_sync_inode_grab (struct xfs_inode *ip); int xfs_inode_ag_iterator(struct xfs_mount *mp,
fs/xfs/xfs_vnodeops.c +11 -6
@@ -150,11 +150,12 @@ xfs_readlink(* when the link count isn't zero and by xfs_dm_punch_hole() when * punching a hole to EOF. */ -STATIC int +int xfs_free_eofblocks (xfs_mount_t *mp,xfs_inode_t *ip, -bool need_iolock) +bool need_iolock, +bool *blocks_freed) {xfs_trans_t *tp;int error;
@@ -237,6 +238,9 @@ xfs_free_eofblocks( }else { error =xfs_trans_commit (tp,XFS_TRANS_RELEASE_LOG_RES ); +if (blocks_freed) + *blocks_freed = true; + }xfs_iunlock (ip,XFS_ILOCK_EXCL );
@@ -391,6 +395,7 @@ xfs_release( {xfs_mount_t *mp = ip->i_mount;int error; +bool freed = false;if (!S_ISREG (ip->i_d.di_mode) || (ip->i_d.di_mode ==0 ))return 0 ;
@@ -463,11 +468,11 @@ xfs_release(if (xfs_iflags_test (ip,XFS_IDIRTY_RELEASE ))return 0 ; - error =xfs_free_eofblocks (mp, ip, true); + error =xfs_free_eofblocks (mp, ip, true, &freed);if (error)return error; - -xfs_inode_clear_eofblocks_tag (ip); +if (freed) +xfs_inode_clear_eofblocks_tag (ip);/* delalloc blocks after truncation means it really is dirty */ if (ip->i_delayed_blks)
@@ -522,7 +527,7 @@ xfs_inactive( (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || ip->i_delayed_blks != 0))) { - error =xfs_free_eofblocks (mp, ip, false); + error =xfs_free_eofblocks (mp, ip, false,NULL );if (error)return VN_INACTIVE_CACHE ;xfs_inode_clear_eofblocks_tag (ip);
fs/xfs/xfs_vnodeops.h +2 -0
@@ -57,5 +57,7 @@ int xfs_flush_pages(struct xfs_inode *ip, xfs_off_t first,int xfs_wait_on_pages (struct xfs_inode *ip,xfs_off_t first,xfs_off_t last);int xfs_zero_eof (struct xfs_inode *,xfs_off_t ,xfs_fsize_t ); +int xfs_free_eofblocks (struct xfs_mount *,struct xfs_inode *,bool ,bool *); +#endif /* _XFS_VNODEOPS_H */
Signature · 6 lines
1.7.7.6 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 2/4] xfs: create function to scan and clear EOFBLOCKS inodes
Quoted 36 lines · Brian Foster
xfs_inodes_free_eofblocks()implements scanning functionality for EOFBLOCKS inodes. It scans the radix tree and frees post-EOF blocks for inodes that meet particular criteria. The scan can be filtered by a particular quota type/id and minimum file size. The scan can also be invoked in trylock mode or wait (force) mode.The
xfs_free_eofblocks()helper is invoked to clear post-EOF space. It is slightly modified to support an output parameter that indicates whether space was freed and helps decide whether the EOFBLOCKS tag should be cleared in trylock scans.Signed-off-by Brian Foster <[email protected]>--- fs/xfs/xfs_sync.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_sync.h | 3 + fs/xfs/xfs_vnodeops.c | 17 +++-- fs/xfs/xfs_vnodeops.h | 2 + 4 files changed, 184 insertions(+), 6 deletions(-)fs/xfs/xfs_sync.c +9
-0@@ -971,6 +971,174 @@ xfs_reclaim_inodes_count(return reclaimable; } +/* +* Handle an EOFBLOCKS tagged inode. If this is a forced scan, we wait on the +* iolock ourselves rather than rely on the trylock in xfs_free_eofblocks(). +* +* We rely on the output parameter from xfs_free_eofblocks() to determine +* whether we should clear the tag because in the trylock case, it could have +* skipped the inode due to lock contention. +*/ +STATIC int
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 992
Quoted 10 lines
fs/xfs/xfs_sync.c +10
-0+xfs_inode_free_eofblocks ( + struct xfs_inode *ip, + int flags) +{ + int ret = 0; +bool freed = false; +bool wait_iolock = (flags &EOFBLOCKS_WAIT ) ? true : false; + +if (wait_iolock) +xfs_ilock (ip,XFS_IOLOCK_EXCL );
Why do we need the IO lock here? xfs_free_eofblocks() does all the necessary locking....
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 998
Quoted 6 lines
fs/xfs/xfs_sync.c +6
-0+ +if ((S_ISREG (ip->i_d.di_mode) && + (VFS_I (ip)->i_size >0 || + (VN_CACHED (VFS_I (ip)) >0 || ip->i_delayed_blks >0 )) && + (ip->i_df.if_flags &XFS_IFEXTENTS )) && + (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC |XFS_DIFLAG_APPEND )))) {
This check is now repeated in 3 places - xfs_inactive, xfs_release and now here. I think it needs a helper.
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1002
Quoted 4 lines
fs/xfs/xfs_sync.c +4
-0+/* !wait_iolock == need_iolock in xfs_free_eofblocks() */ + ret =xfs_free_eofblocks (ip->i_mount, ip, !wait_iolock, &freed); +if (freed) +xfs_inode_clear_eofblocks_tag (ip);
If you move xfs_inode_clear_eofblocks_tag() inside xfs_free_eofblocks(), there's no need for this extra return value.
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1005
Quoted 3 lines
fs/xfs/xfs_sync.c +3
-0+ }else { +/* inode could be preallocated or append-only */ +xfs_inode_clear_eofblocks_tag (ip);
This should be a rare event - it's probably worth adding a pair of trace events here for the two cases so we can see if there is ever a significant number of inodes being scanned for prealloc that can't be cleared...
(e.g 'perf top -e xfs:xfs_i*' to count all the inode events)
Quoted 18 lines
fs/xfs/xfs_sync.c +18
-0+ } + +if (wait_iolock) +xfs_iunlock (ip,XFS_IOLOCK_EXCL ); + +return ret; +} + +/* +* Determine whether an inode matches a particular qouta id. +*/ +STATIC int +xfs_inode_match_quota_id ( +struct xfs_inode *ip, +int qtype, +uint32_t id) +{ +switch (qtype) {
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1033
Quoted 10 lines
fs/xfs/xfs_sync.c +10
-0+case XFS_DQ_USER : +return ip->i_d.di_uid == id; +case XFS_DQ_GROUP : +return ip->i_d.di_gid == id; +default : +return xfs_get_projid (ip) == id; + } + +return 0 ; +}
There's nothing really quota specific about this scan. I'd leave this functionality to a separate patch once all the core infrastructure is in place.
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1039
Quoted 6 lines
fs/xfs/xfs_sync.c +6
-0+ +/* +* This is mostly copied from xfs_reclaim_inodes_ag(). +* +* TODO: +* - Could we enhance ag_iterator to support a tag and use it instead of this?
Yes. This code is too tricky to duplicate for every use case, and this doesn't have special case requirements like the reclaim code.
i.e. the xfs_inode_free_eofblocks() becomes the execute function (and the quota checks move inside that eventually). Passing a tag of "-1" would indicate a non-tag lookup, otherwise use a tag based lookup. Given the extra fields that this version uses, passing a void *args is probably necessary so that a structure can be passed to the execute function along with the flags....
I'd suggest this conversion should be done in a patch prior to introducing this scanner.
FWIW, this is going to conflict with my "get rid of xfs-sync.c patch series, so we'll need to work out who rebases what at some point.
Quoted 9 lines
fs/xfs/xfs_sync.c +9
-0+*/ +int +xfs_inodes_free_eofblocks ( +struct xfs_mount *mp, +int qtype, +uint32_t id, +uint64_t min_file_size, +int flags) +{
.....
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1114
Quoted 5 lines
fs/xfs/xfs_sync.c +5
-0+for (i =0 ; i < nr_found; i++) { +if (!batch[i]) +continue ; + +/* default projid represents a full scan */
I don't think thats a good idea. From a normal users perspective, the background trimming will occur irrespective of the quota groups the inode is part of. Background trimming defines the default behaviour, because that's what 99.99% of users will see active, not quota/application specific events driven through ioctls.
IOWs, selecting inodes by quota type/id for pruning is a secondary function of the execute implementation, not a primary concern of the infrastructure.
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1124
Quoted 11 lines
fs/xfs/xfs_sync.c +10
-0+if ((!(qtype ==XFS_DQ_PROJ && + id ==XFS_PROJID_DEFAULT ) && + !xfs_inode_match_quota_id (batch[i], qtype, + id)) || + (min_file_size &&XFS_ISIZE (batch[i]) < + min_file_size) + ) { +IRELE (batch[i]); +continue ; + }
Moving this check to the execute function will get rid of the indent mess....
Quoted 25 lines
fs/xfs/xfs_sync.c +17
-0+ + error =xfs_inode_free_eofblocks (batch[i], flags); +IRELE (batch[i]); +if (error) + last_error = error; + } + +cond_resched (); + + }while (nr_found && !done); + +xfs_perag_put (pag); + } + +return XFS_ERROR (last_error); +} + STATIC void __xfs_inode_set_eofblocks_tag( struct xfs_perag *pag,fs/xfs/xfs_sync.h +0
-0
fs/xfs/xfs_sync.h void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip); · line 46
Quoted 4 lines
fs/xfs/xfs_sync.h +1
-0@@ -43,8 +43,11 @@ void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);void __xfs_inode_clear_reclaim_tag (struct xfs_mount *mp,struct xfs_perag *pag,struct xfs_inode *ip); +#define EOFBLOCKS_WAIT 0x0001
I'd just reuse SYNC_WAIT and SYNC_TRYLOCK which are already defined and used by the sync and reclaim iterators.
Quoted 13 lines
fs/xfs/xfs_sync.h +2
-0+void xfs_inode_set_eofblocks_tag (struct xfs_inode *ip);void xfs_inode_clear_eofblocks_tag (struct xfs_inode *ip); +int xfs_inodes_free_eofblocks (struct xfs_mount *,int ,uint32_t ,uint64_t ,int );int xfs_sync_inode_grab (struct xfs_inode *ip); int xfs_inode_ag_iterator(struct xfs_mount *mp,fs/xfs/xfs_vnodeops.c +0
-0@@ -150,11 +150,12 @@ xfs_readlink(* when the link count isn't zero and by xfs_dm_punch_hole() when
fs/xfs/xfs_vnodeops.c xfs_readlink( · line 158
Quoted 10 lines
fs/xfs/xfs_vnodeops.c +3
-2* punching a hole to EOF. */ -STATIC int +int xfs_free_eofblocks (xfs_mount_t *mp,xfs_inode_t *ip, -bool need_iolock) +bool need_iolock, +bool *blocks_freed)
I don't really see a point to adding this. Either we removed all the EOF blocks or we didn't, and that means we should just clear the tags directly in this function if it is appropriate.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 2/4] xfs: create function to scan and clear EOFBLOCKS inodes
Quoted 1 line · Dave Chinner
On Mon, Aug 27, 2012 at 03:51:49PM -0400, Brian Foster wrote:
...
Quoted 14 lines
Quoted 14 lines
fs/xfs/xfs_sync.c +14
-0+/* +* Handle an EOFBLOCKS tagged inode. If this is a forced scan, we wait on the +* iolock ourselves rather than rely on the trylock in xfs_free_eofblocks(). +* +* We rely on the output parameter from xfs_free_eofblocks() to determine +* whether we should clear the tag because in the trylock case, it could have +* skipped the inode due to lock contention. +*/ +STATIC int +xfs_inode_free_eofblocks ( +struct xfs_inode *ip, +int flags) +{ +int ret =0 ;
Quoted 9 lines
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 992
Quoted 5 lines
fs/xfs/xfs_sync.c +5
-0+bool freed = false; +bool wait_iolock = (flags &EOFBLOCKS_WAIT ) ? true : false; + +if (wait_iolock) +xfs_ilock (ip,XFS_IOLOCK_EXCL );Why do we need the IO lock here?
xfs_free_eofblocks()does all the necessary locking....
This was for the wait case (e.g., xfs_free_eofblocks() does a trylock on the IO lock and we want to wait for the lock in this case).
Brian
Quoted 187 lines
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 998
Quoted 6 lines
fs/xfs/xfs_sync.c +6
-0+ +if ((S_ISREG (ip->i_d.di_mode) && + (VFS_I (ip)->i_size >0 || + (VN_CACHED (VFS_I (ip)) >0 || ip->i_delayed_blks >0 )) && + (ip->i_df.if_flags &XFS_IFEXTENTS )) && + (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC |XFS_DIFLAG_APPEND )))) {This check is now repeated in 3 places -
xfs_inactive,xfs_releaseand now here. I think it needs a helper.fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1002
Quoted 4 lines
fs/xfs/xfs_sync.c +4
-0+/* !wait_iolock == need_iolock in xfs_free_eofblocks() */ + ret =xfs_free_eofblocks (ip->i_mount, ip, !wait_iolock, &freed); +if (freed) +xfs_inode_clear_eofblocks_tag (ip);If you move
xfs_inode_clear_eofblocks_tag()insidexfs_free_eofblocks(), there's no need for this extra return value.fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1005
Quoted 3 lines
fs/xfs/xfs_sync.c +3
-0+ }else { +/* inode could be preallocated or append-only */ +xfs_inode_clear_eofblocks_tag (ip);This should be a rare event - it's probably worth adding a pair of trace events here for the two cases so we can see if there is ever a significant number of inodes being scanned for prealloc that can't be cleared...
(e.g 'perf top -e xfs:xfs_i*' to count all the inode events)
Quoted 18 lines
fs/xfs/xfs_sync.c +18
-0+ } + +if (wait_iolock) +xfs_iunlock (ip,XFS_IOLOCK_EXCL ); + +return ret; +} + +/* +* Determine whether an inode matches a particular qouta id. +*/ +STATIC int +xfs_inode_match_quota_id ( +struct xfs_inode *ip, +int qtype, +uint32_t id) +{ +switch (qtype) {fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1033
Quoted 10 lines
fs/xfs/xfs_sync.c +10
-0+case XFS_DQ_USER : +return ip->i_d.di_uid == id; +case XFS_DQ_GROUP : +return ip->i_d.di_gid == id; +default : +return xfs_get_projid (ip) == id; + } + +return 0 ; +}There's nothing really quota specific about this scan. I'd leave this functionality to a separate patch once all the core infrastructure is in place.
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1039
Quoted 6 lines
fs/xfs/xfs_sync.c +6
-0+ +/* +* This is mostly copied from xfs_reclaim_inodes_ag(). +* +* TODO: +* - Could we enhance ag_iterator to support a tag and use it instead of this? Yes. This code is too tricky to duplicate for every use case, and this doesn't have special case requirements like the reclaim code.
i.e. the
xfs_inode_free_eofblocks()becomes the execute function (and the quota checks move inside that eventually). Passing a tag of "-1" would indicate a non-tag lookup, otherwise use a tag based lookup. Given the extra fields that this version uses, passing a void *args is probably necessary so that a structure can be passed to the execute function along with the flags....I'd suggest this conversion should be done in a patch prior to introducing this scanner.
FWIW, this is going to conflict with my "get rid of
xfs-sync.cpatch series, so we'll need to work out who rebases what at some point.Quoted 9 lines
+ */
fs/xfs/xfs_sync.c +8
-0+int +xfs_inodes_free_eofblocks ( +struct xfs_mount *mp, +int qtype, +uint32_t id, +uint64_t min_file_size, +int flags) +{.....
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1114
Quoted 5 lines
fs/xfs/xfs_sync.c +5
-0+for (i =0 ; i < nr_found; i++) { +if (!batch[i]) +continue ; + +/* default projid represents a full scan */ I don't think thats a good idea. From a normal users perspective, the background trimming will occur irrespective of the quota groups the inode is part of. Background trimming defines the default behaviour, because that's what 99.99% of users will see active, not quota/application specific events driven through ioctls.
IOWs, selecting inodes by quota type/id for pruning is a secondary function of the execute implementation, not a primary concern of the infrastructure.
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 1124
Quoted 11 lines
fs/xfs/xfs_sync.c +10
-0+if ((!(qtype ==XFS_DQ_PROJ && + id ==XFS_PROJID_DEFAULT ) && + !xfs_inode_match_quota_id (batch[i], qtype, + id)) || + (min_file_size &&XFS_ISIZE (batch[i]) < + min_file_size) + ) { +IRELE (batch[i]); +continue ; + }Moving this check to the execute function will get rid of the indent mess....
Quoted 25 lines
fs/xfs/xfs_sync.c +17
-0+ + error =xfs_inode_free_eofblocks (batch[i], flags); +IRELE (batch[i]); +if (error) + last_error = error; + } + +cond_resched (); + + }while (nr_found && !done); + +xfs_perag_put (pag); + } + +return XFS_ERROR (last_error); +} + STATIC void __xfs_inode_set_eofblocks_tag( struct xfs_perag *pag,fs/xfs/xfs_sync.h +0
-0fs/xfs/xfs_sync.h void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip); · line 46
Quoted 4 lines
fs/xfs/xfs_sync.h +1
-0@@ -43,8 +43,11 @@ void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);void __xfs_inode_clear_reclaim_tag (struct xfs_mount *mp,struct xfs_perag *pag,struct xfs_inode *ip); +#define EOFBLOCKS_WAIT 0x0001I'd just reuse
SYNC_WAITandSYNC_TRYLOCKwhich are already defined and used by the sync and reclaim iterators.Quoted 13 lines
fs/xfs/xfs_sync.h +2
-0+void xfs_inode_set_eofblocks_tag (struct xfs_inode *ip);void xfs_inode_clear_eofblocks_tag (struct xfs_inode *ip); +int xfs_inodes_free_eofblocks (struct xfs_mount *,int ,uint32_t ,uint64_t ,int );int xfs_sync_inode_grab (struct xfs_inode *ip); int xfs_inode_ag_iterator(struct xfs_mount *mp,fs/xfs/xfs_vnodeops.c +0
-0@@ -150,11 +150,12 @@ xfs_readlink(* when the link count isn't zero and by xfs_dm_punch_hole() when fs/xfs/xfs_vnodeops.c xfs_readlink( · line 158
Quoted 10 lines
fs/xfs/xfs_vnodeops.c +3
-2* punching a hole to EOF. */ -STATIC int +int xfs_free_eofblocks (xfs_mount_t *mp,xfs_inode_t *ip, -bool need_iolock) +bool need_iolock, +bool *blocks_freed)I don't really see a point to adding this. Either we removed all the EOF blocks or we didn't, and that means we should just clear the tags directly in this function if it is appropriate.
Quoted 4 lines
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 2/4] xfs: create function to scan and clear EOFBLOCKS inodes
Quoted 27 lines · Brian Foster
Quoted 1 line · Dave Chinner
On Mon, Aug 27, 2012 at 03:51:49PM -0400, Brian Foster wrote:
...
Quoted 14 lines
Quoted 14 lines
fs/xfs/xfs_sync.c +14
-0+/* +* Handle an EOFBLOCKS tagged inode. If this is a forced scan, we wait on the +* iolock ourselves rather than rely on the trylock in xfs_free_eofblocks(). +* +* We rely on the output parameter from xfs_free_eofblocks() to determine +* whether we should clear the tag because in the trylock case, it could have +* skipped the inode due to lock contention. +*/ +STATIC int +xfs_inode_free_eofblocks ( +struct xfs_inode *ip, +int flags) +{ +int ret =0 ;Quoted 9 lines
fs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 992
Quoted 5 lines
fs/xfs/xfs_sync.c +5
-0+bool freed = false; +bool wait_iolock = (flags &EOFBLOCKS_WAIT ) ? true : false; + +if (wait_iolock) +xfs_ilock (ip,XFS_IOLOCK_EXCL );Why do we need the IO lock here?
xfs_free_eofblocks()does all the necessary locking....
Quoted 2 lines
This was for the wait case (e.g.,
xfs_free_eofblocks()does a trylock on the IO lock and we want to wait for the lock in this case).
Does it really matter if we can't get the iolock and skip the inode?
Note that xfs_inode_ag_walk() will keep a skipped count if you return EAGAIN, and re-run the walk on the AG if any inodes are skipped. This is done to prevent blocking on locks slowing down the scan - instead of blocking we move on to the next inode, and revist the blocked inodes again in a later pass.
IOWs, if you convert the code to use the generic walk and make xfs_free_eofblocks() return EAGAIN when it can't get the io lock, you get the retry for free...
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 2/4] xfs: create function to scan and clear EOFBLOCKS inodes
Quoted 28 lines · Dave Chinner
Quoted 27 lines · Brian Foster
Quoted 1 line · Dave Chinner
On Mon, Aug 27, 2012 at 03:51:49PM -0400, Brian Foster wrote:
...
Quoted 23 lines
Quoted 9 lines
fs/xfs/xfs_sync.c +9
-0+/* +* Handle an EOFBLOCKS tagged inode. If this is a forced scan, we wait on the +* iolock ourselves rather than rely on the trylock in xfs_free_eofblocks(). +* +* We rely on the output parameter from xfs_free_eofblocks() to determine +* whether we should clear the tag because in the trylock case, it could have +* skipped the inode due to lock contention. +*/ +STATIC intfs/xfs/xfs_sync.c xfs_reclaim_inodes_count( · line 992
Quoted 10 lines
fs/xfs/xfs_sync.c +10
-0+xfs_inode_free_eofblocks ( + struct xfs_inode *ip, + int flags) +{ + int ret = 0; +bool freed = false; +bool wait_iolock = (flags &EOFBLOCKS_WAIT ) ? true : false; + +if (wait_iolock) +xfs_ilock (ip,XFS_IOLOCK_EXCL );Why do we need the IO lock here?
xfs_free_eofblocks()does all the necessary locking....
Quoted 5 lines
Quoted 2 lines
This was for the wait case (e.g.,
xfs_free_eofblocks()does a trylock on the IO lock and we want to wait for the lock in this case).Does it really matter if we can't get the iolock and skip the inode?
Well I thought that was the point of the force/wait scan as opposed to the best effort scan. But...
Quoted 10 lines
Note that
xfs_inode_ag_walk()will keep a skipped count if you return EAGAIN, and re-run the walk on the AG if any inodes are skipped. This is done to prevent blocking on locks slowing down the scan - instead of blocking we move on to the next inode, and revist the blocked inodes again in a later pass.IOWs, if you convert the code to use the generic walk and make
xfs_free_eofblocks()return EAGAIN when it can't get the io lock, you get the retry for free...
This sounds more efficient. ;) I'll move it to this approach. Thanks.
Brian
Quoted 4 lines
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
RFC PATCH 3/4 xfs: add FREE_EOFBLOCKS ioctl
In reply to Brian FosterThe XFS_IOC_FREE_EOFBLOCKS ioctl allows users to invoke an EOFBLOCKS scan. The xfs_eofblocks structure is defined to support the command parameters (quota type/id and minimum file size).
--- fs/xfs/xfs_fs.h | 10 ++++++++++ fs/xfs/xfs_ioctl.c | 25 +++++++++++++++++++++++++ fs/xfs/xfs_quota.h | 1 + fs/xfs/xfs_quotaops.c | 2 +- 4 files changed, 37 insertions(+), 1 deletions(-)
fs/xfs/xfs_fs.h +10 -0
@@ -339,6 +339,15 @@ typedef struct xfs_error_injection {/* +* Speculative preallocation trimming. +*/ +typedef struct xfs_eofblocks { +__u32 id;/* quota id */ +__u32 qtype;/* quota type */ +__u64 min_file_size;/* minimum file size */ +}xfs_eofblocks_t ; + +/* * The user-level Handle Request interface structure. */ typedef struct xfs_fsop_handlereq {
@@ -456,6 +465,7 @@ typedef struct xfs_handle {/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */ #define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64) +#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_eofblocks)/* * ioctl commands that replace IRIX syssgi()'s
fs/xfs/xfs_ioctl.c +25 -0
@@ -1602,6 +1602,31 @@ xfs_file_ioctl( error =xfs_errortag_clearall (mp,1 );return -error; +case XFS_IOC_FREE_EOFBLOCKS : { +struct xfs_eofblocks eofb; +int qtype; + +if (copy_from_user (&eofb, arg,sizeof (eofb))) +return -XFS_ERROR (EFAULT ); + + qtype =xfs_quota_type (eofb.qtype); + +/* +* TODO: The filtering code currently uses the id in the inode. +* Therefore, I don't think it really matters whether the +* particular quota type is enabled (and the dquot is attached). +* +* Alternatively, we could filter by dquot type. This would +* mean we might have to make sure dquot's are attached during +* the scan and that the particular quota type is enabled. I'm +* not sure that this buys us anything. +*/ + +/* TODO: might want to just use the eofb structure here */ + error =xfs_inodes_free_eofblocks (mp, qtype, eofb.id, eofb.min_file_size,EOFBLOCKS_WAIT ); +return -error; + } +default :return -ENOTTY ; }
fs/xfs/xfs_quota.h +1 -0
@@ -379,6 +379,7 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,extern int xfs_qm_dqcheck (struct xfs_mount *,xfs_disk_dquot_t *,xfs_dqid_t ,uint ,uint ,char *);extern int xfs_mount_reset_sbqflags (struct xfs_mount *); +int xfs_quota_type (int );#endif /* __KERNEL__ */ #endif /* __XFS_QUOTA_H__ */
fs/xfs/xfs_quotaops.c +1 -1
@@ -28,7 +28,7 @@#include <linux/quota.h> -STATIC int +int xfs_quota_type (int type) {switch (type) {
Signature · 6 lines
1.7.7.6 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 3/4] xfs: add FREE_EOFBLOCKS ioctl
Quoted 17 lines · Brian Foster
The
XFS_IOC_FREE_EOFBLOCKSioctl allows users to invoke an EOFBLOCKS scan. Thexfs_eofblocksstructure is defined to support the command parameters (quota type/id and minimum file size).Signed-off-by Brian Foster <[email protected]>--- fs/xfs/xfs_fs.h | 10 ++++++++++ fs/xfs/xfs_ioctl.c | 25 +++++++++++++++++++++++++ fs/xfs/xfs_quota.h | 1 + fs/xfs/xfs_quotaops.c | 2 +- 4 files changed, 37 insertions(+), 1 deletions(-)fs/xfs/xfs_fs.h +0
-0
fs/xfs/xfs_fs.h typedef struct xfs_error_injection { · line 348
Quoted 10 lines
fs/xfs/xfs_fs.h +7
-0@@ -339,6 +339,15 @@ typedef struct xfs_error_injection {/* +* Speculative preallocation trimming. +*/ +typedef struct xfs_eofblocks { +__u32 id;/* quota id */ +__u32 qtype;/* quota type */ +__u64 min_file_size;/* minimum file size */ +}xfs_eofblocks_t ;
No typedefs.
Additionally: this is a user facing API for functionality that has wider potential use than quota. For example, xfs_fsr runs out of space in an AG, but it really wants to put a file there, so it calls XFS_IOC_FREE_EOFBLOCKS to specify the AG it wants all the prealloc removed from.
So, the structure needs a version number so the kernel knows what fields the application is aware of, a flags field to say what operation is being done (i.e. flush by projid) rather than a "qtype" and a bunch of padding so that we can add new elements to it as need arises without breaking existing user binaries.
Quoted 18 lines
fs/xfs/xfs_fs.h +0
-0* ioctl commands that replace IRIX syssgi()'s fs/xfs/xfs_ioctl.c +9
-0@@ -1602,6 +1602,31 @@ xfs_file_ioctl( error =xfs_errortag_clearall (mp,1 );return -error; +case XFS_IOC_FREE_EOFBLOCKS : { +struct xfs_eofblocks eofb; +int qtype; + +if (copy_from_user (&eofb, arg,sizeof (eofb))) +return -XFS_ERROR (EFAULT ); + + qtype =xfs_quota_type (eofb.qtype); +
fs/xfs/xfs_ioctl.c xfs_file_ioctl( · line 1623
Quoted 10 lines
fs/xfs/xfs_ioctl.c +10
-0+/* +* TODO: The filtering code currently uses the id in the inode. +* Therefore, I don't think it really matters whether the +* particular quota type is enabled (and the dquot is attached). +* +* Alternatively, we could filter by dquot type. This would +* mean we might have to make sure dquot's are attached during +* the scan and that the particular quota type is enabled. I'm +* not sure that this buys us anything. +*/
If quota is not enabled, then a request to free blocks determined by a quota ID is invalid and should be rejected. It's a user API - what is and isn't supported needs to be written down in black and white (i.e. in the xfsctl man page).
fs/xfs/xfs_ioctl.c xfs_file_ioctl( · line 1626
Quoted 2 lines
fs/xfs/xfs_ioctl.c +2
-0+/* TODO: might want to just use the eofb structure here */ + error =xfs_inodes_free_eofblocks (mp, qtype, eofb.id, eofb.min_file_size,EOFBLOCKS_WAIT );
Yes, just pass the structure - it means it can be passed all the way down to the execute function, and only that code needs to handle different versions of the structure.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 3/4] xfs: add FREE_EOFBLOCKS ioctl
Quoted 20 lines · Dave Chinner
Quoted 19 lines · Brian Foster
The
XFS_IOC_FREE_EOFBLOCKSioctl allows users to invoke an EOFBLOCKS scan. Thexfs_eofblocksstructure is defined to support the command parameters (quota type/id and minimum file size).Signed-off-by Brian Foster <[email protected]>--- fs/xfs/xfs_fs.h | 10 ++++++++++ fs/xfs/xfs_ioctl.c | 25 +++++++++++++++++++++++++ fs/xfs/xfs_quota.h | 1 + fs/xfs/xfs_quotaops.c | 2 +- 4 files changed, 37 insertions(+), 1 deletions(-)fs/xfs/xfs_fs.h +0
-0@@ -339,6 +339,15 @@ typedef struct xfs_error_injection {
Quoted 11 lines
fs/xfs/xfs_fs.h typedef struct xfs_error_injection { · line 348
Quoted 8 lines
fs/xfs/xfs_fs.h +7
-0/* +* Speculative preallocation trimming. +*/ +typedef struct xfs_eofblocks { +__u32 id;/* quota id */ +__u32 qtype;/* quota type */ +__u64 min_file_size;/* minimum file size */ +}xfs_eofblocks_t ;No typedefs.
This is something I see throughout the code that I haven't quite followed (i.e., using the _t typedefs vs. not). Is the general consensus to move away from typedefs when possible?
...
Quoted 16 lines
Quoted 16 lines
fs/xfs/xfs_fs.h +16
-0+case XFS_IOC_FREE_EOFBLOCKS : { +struct xfs_eofblocks eofb; +int qtype; + +if (copy_from_user (&eofb, arg,sizeof (eofb))) +return -XFS_ERROR (EFAULT ); + + qtype =xfs_quota_type (eofb.qtype); + +/* +* TODO: The filtering code currently uses the id in the inode. +* Therefore, I don't think it really matters whether the +* particular quota type is enabled (and the dquot is attached). +* +* Alternatively, we could filter by dquot type. This would +* mean we might have to make sure dquot's are attached during
Quoted 9 lines
fs/xfs/xfs_fs.h
Quoted 3 lines
fs/xfs/xfs_fs.h +3
-0+* the scan and that the particular quota type is enabled. I'm +* not sure that this buys us anything. +*/ If quota is not enabled, then a request to free blocks determined by a quota ID is invalid and should be rejected. It's a user API - what is and isn't supported needs to be written down in black and white (i.e. in the xfsctl man page).
Ok. I was thinking that we could support the ability to scan by uid/gid regardless of whether quota is enabled, but perhaps there's no purpose to that if a quota isn't enabled.
Brian
Quoted 11 lines
fs/xfs/xfs_fs.h
Quoted 2 lines
fs/xfs/xfs_fs.h +2
-0+/* TODO: might want to just use the eofb structure here */ + error =xfs_inodes_free_eofblocks (mp, qtype, eofb.id, eofb.min_file_size,EOFBLOCKS_WAIT );Yes, just pass the structure - it means it can be passed all the way down to the execute function, and only that code needs to handle different versions of the structure.
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 3/4] xfs: add FREE_EOFBLOCKS ioctl
Quoted 33 lines · Brian Foster
Quoted 20 lines · Dave Chinner
Quoted 19 lines · Brian Foster
The
XFS_IOC_FREE_EOFBLOCKSioctl allows users to invoke an EOFBLOCKS scan. Thexfs_eofblocksstructure is defined to support the command parameters (quota type/id and minimum file size).Signed-off-by Brian Foster <[email protected]>--- fs/xfs/xfs_fs.h | 10 ++++++++++ fs/xfs/xfs_ioctl.c | 25 +++++++++++++++++++++++++ fs/xfs/xfs_quota.h | 1 + fs/xfs/xfs_quotaops.c | 2 +- 4 files changed, 37 insertions(+), 1 deletions(-)fs/xfs/xfs_fs.h +0
-0@@ -339,6 +339,15 @@ typedef struct xfs_error_injection {Quoted 11 lines
fs/xfs/xfs_fs.h typedef struct xfs_error_injection { · line 348
Quoted 8 lines
fs/xfs/xfs_fs.h +7
-0/* +* Speculative preallocation trimming. +*/ +typedef struct xfs_eofblocks { +__u32 id;/* quota id */ +__u32 qtype;/* quota type */ +__u64 min_file_size;/* minimum file size */ +}xfs_eofblocks_t ;No typedefs.
Quoted 3 lines
This is something I see throughout the code that I haven't quite followed (i.e., using the _t typedefs vs. not). Is the general consensus to move away from typedefs when possible?
Yes. The Irix code that XFS came from was full of typedefs - part of it was to try to strictly type check things that were the same storage size or on-disk vs in-memory. We've got other ways of doing that better (e.g. the endian checking sparse does), and typedefs are generally frowned upon in the main kernel code because they often obfuscate the code rather than improve it, so we're removing them as we modify code or write new code.
Quoted 18 lines
Quoted 8 lines
Quoted 8 lines
fs/xfs/xfs_fs.h +8
-0+ +/* +* TODO: The filtering code currently uses the id in the inode. +* Therefore, I don't think it really matters whether the +* particular quota type is enabled (and the dquot is attached). +* +* Alternatively, we could filter by dquot type. This would +* mean we might have to make sure dquot's are attached during Quoted 9 lines
fs/xfs/xfs_fs.h
Quoted 3 lines
fs/xfs/xfs_fs.h +3
-0+* the scan and that the particular quota type is enabled. I'm +* not sure that this buys us anything. +*/ If quota is not enabled, then a request to free blocks determined by a quota ID is invalid and should be rejected. It's a user API - what is and isn't supported needs to be written down in black and white (i.e. in the xfsctl man page).
Quoted 3 lines
Ok. I was thinking that we could support the ability to scan by uid/gid regardless of whether quota is enabled, but perhaps there's no purpose to that if a quota isn't enabled.
I can't really think of a use case for doing this. Making the API more expansive in future if someone needs this can be done - it's removing stuff that is really hard to do. Hence, don't add it if it is not going to be used immediately. :)
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 3/4] xfs: add FREE_EOFBLOCKS ioctl
Quoted 3 lines · Dave Chinner
Quoted 2 lines · Brian Foster
Quoted 1 line · Dave Chinner
On Mon, Aug 27, 2012 at 03:51:50PM -0400, Brian Foster wrote:
...
Quoted 4 lines
Quoted 3 lines
This is something I see throughout the code that I haven't quite followed (i.e., using the _t typedefs vs. not). Is the general consensus to move away from typedefs when possible?
Quoted 8 lines
Yes. The Irix code that XFS came from was full of typedefs - part of it was to try to strictly type check things that were the same storage size or on-disk vs in-memory. We've got other ways of doing that better (e.g. the endian checking sparse does), and typedefs are generally frowned upon in the main kernel code because they often obfuscate the code rather than improve it, so we're removing them as we modify code or write new code.
Good to know.
...
Quoted 9 lines
Quoted 3 lines
Ok. I was thinking that we could support the ability to scan by uid/gid regardless of whether quota is enabled, but perhaps there's no purpose to that if a quota isn't enabled.
I can't really think of a use case for doing this. Making the API more expansive in future if someone needs this can be done - it's removing stuff that is really hard to do. Hence, don't add it if it is not going to be used immediately. :)
Ok.
Brian
Quoted 4 lines
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
RFC PATCH 4/4 xfs: add background scanning to clear EOFBLOCKS inodes
In reply to Brian FosterCreate a delayed_work to enable background scanning and freeing of EOFBLOCKS inodes. The scanner kicks in once speculative preallocation occurs and stops requeueing itself when no EOFBLOCKS inodes exist.
Scans are queued on the existing syncd workqueue and the interval is tied to the syncd interval, which is a default of 30s. The minimum file size for a background scan is hardcoded to 100MB.
--- fs/xfs/xfs_mount.h | 2 ++ fs/xfs/xfs_sync.c | 33 +++++++++++++++++++++++++++++++++ fs/xfs/xfs_sync.h | 3 +++ 3 files changed, 38 insertions(+), 0 deletions(-)
fs/xfs/xfs_mount.h +2 -0
@@ -204,6 +204,8 @@ typedef struct xfs_mount {struct xfs_mru_cache *m_filestream;/* per-mount filestream data */ struct delayed_work m_sync_work;/* background sync work */ struct delayed_work m_reclaim_work;/* background inode reclaim */ +struct delayed_work m_eofblocks_work;/* background eof blocks +trimming */ struct work_struct m_flush_work;/* background inode flush */ __int64_t m_update_flags;/* sb flags we need to update on the next remount,rw */
fs/xfs/xfs_sync.c +33 -0
@@ -489,6 +489,34 @@ xfs_flush_worker(xfs_sync_data (mp,SYNC_TRYLOCK |SYNC_WAIT ); } +/* +* Background scanning to trim post-EOF preallocated space. This is queued +* based on the syncd tunable (30s by default). +* +* TODO: Do we want an independent tunable (and default.. off by default)? +*/ +STATIC void +xfs_queue_eofblocks ( +struct xfs_mount *mp) +{ +rcu_read_lock (); +if (radix_tree_tagged (&mp->m_perag_tree,XFS_ICI_EOFBLOCKS_TAG )) +queue_delayed_work (xfs_syncd_wq, &mp->m_eofblocks_work, +msecs_to_jiffies (xfs_syncd_centisecs *10 )); +rcu_read_unlock (); +} + +STATIC void +xfs_eofblocks_worker ( +struct work_struct *work) +{ +struct xfs_mount *mp =container_of (to_delayed_work (work), + struct xfs_mount, m_eofblocks_work); +xfs_inodes_free_eofblocks (mp,XFS_DQ_PROJ ,XFS_PROJID_DEFAULT , +XFS_EOFBLOCKS_DEFAULT_MINFILESIZE ,0 ); +xfs_queue_eofblocks (mp); +} +int xfs_syncd_init (struct xfs_mount *mp)
@@ -496,6 +524,7 @@ xfs_syncd_init(INIT_WORK (&mp->m_flush_work, xfs_flush_worker);INIT_DELAYED_WORK (&mp->m_sync_work, xfs_sync_worker);INIT_DELAYED_WORK (&mp->m_reclaim_work, xfs_reclaim_worker); +INIT_DELAYED_WORK (&mp->m_eofblocks_work, xfs_eofblocks_worker);xfs_syncd_queue_sync (mp);
@@ -508,6 +537,7 @@ xfs_syncd_stop( {cancel_delayed_work_sync (&mp->m_sync_work);cancel_delayed_work_sync (&mp->m_reclaim_work); +cancel_delayed_work_sync (&mp->m_eofblocks_work);cancel_work_sync (&mp->m_flush_work); }
@@ -1159,6 +1189,9 @@ __xfs_inode_set_eofblocks_tag( XFS_ICI_EOFBLOCKS_TAG);spin_unlock (&ip->i_mount->m_perag_lock); +/* kick off background trimming */ +xfs_queue_eofblocks (ip->i_mount); +trace_xfs_perag_set_eofblocks (ip->i_mount, pag->pag_agno,-1 , _RET_IP_); }
fs/xfs/xfs_sync.h +3 -0
@@ -45,6 +45,9 @@ void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,#define EOFBLOCKS_WAIT 0x0001 +/* TODO: should we have a tunable? */ +#define XFS_EOFBLOCKS_DEFAULT_MINFILESIZE 1024 * 1024 * 100 +void xfs_inode_set_eofblocks_tag (struct xfs_inode *ip);void xfs_inode_clear_eofblocks_tag (struct xfs_inode *ip);int xfs_inodes_free_eofblocks (struct xfs_mount *,int ,uint32_t ,uint64_t ,int );
Signature · 6 lines
1.7.7.6 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 4/4] xfs: add background scanning to clear EOFBLOCKS inodes
Quoted 8 lines · Brian Foster
Create a
delayed_workto enable background scanning and freeing of EOFBLOCKS inodes. The scanner kicks in once speculative preallocation occurs and stops requeueing itself when no EOFBLOCKS inodes exist.Scans are queued on the existing syncd workqueue and the interval is tied to the syncd interval, which is a default of 30s. The minimum file size for a background scan is hardcoded to 100MB.
I'd set it to be much longer than the xfs_syncd_centisecs period. The data may not be written back for a long while, and a file that is open, written and closed repeatedly (NFS write patterns for large and/or slowly written files) should not have it's preallocation truncated every 30s.
I'd suggest that a 5 minute sweep is probably sufficiently frequent to avoid most fragmentation issues and long term buildup of speculative preallocation whilst not perturbing large/slow writers too much....
Apart from that, there isn't anything wrong with the code, except I'll note again that it conflicts with my syncd removal patchset....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 4/4] xfs: add background scanning to clear EOFBLOCKS inodes
Quoted 16 lines · Dave Chinner
Quoted 8 lines · Brian Foster
Create a
delayed_workto enable background scanning and freeing of EOFBLOCKS inodes. The scanner kicks in once speculative preallocation occurs and stops requeueing itself when no EOFBLOCKS inodes exist.Scans are queued on the existing syncd workqueue and the interval is tied to the syncd interval, which is a default of 30s. The minimum file size for a background scan is hardcoded to 100MB.
I'd set it to be much longer than the
xfs_syncd_centisecsperiod. The data may not be written back for a long while, and a file that is open, written and closed repeatedly (NFS write patterns for large and/or slowly written files) should not have it's preallocation truncated every 30s.
Quoted 4 lines
I'd suggest that a 5 minute sweep is probably sufficiently frequent to avoid most fragmentation issues and long term buildup of speculative preallocation whilst not perturbing large/slow writers too much....
Any thoughts on having tunables for both values (time and min size?) on the background scanning?
Quoted 3 lines
Apart from that, there isn't anything wrong with the code, except I'll note again that it conflicts with my syncd removal patchset....
Yeah, I skimmed through those patches and noticed it would shuffle this code around. Thanks for pointing it out. I'll keep an eye on that set.
Thanks for the review. I'll follow up with a patchset that incorporates the feedback.
Brian
Quoted 4 lines
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 4/4] xfs: add background scanning to clear EOFBLOCKS inodes
Quoted 17 lines · Brian Foster
Quoted 16 lines · Dave Chinner
Quoted 8 lines · Brian Foster
Create a
delayed_workto enable background scanning and freeing of EOFBLOCKS inodes. The scanner kicks in once speculative preallocation occurs and stops requeueing itself when no EOFBLOCKS inodes exist.Scans are queued on the existing syncd workqueue and the interval is tied to the syncd interval, which is a default of 30s. The minimum file size for a background scan is hardcoded to 100MB.
I'd set it to be much longer than the
xfs_syncd_centisecsperiod. The data may not be written back for a long while, and a file that is open, written and closed repeatedly (NFS write patterns for large and/or slowly written files) should not have it's preallocation truncated every 30s.
Quoted 7 lines
Quoted 4 lines
I'd suggest that a 5 minute sweep is probably sufficiently frequent to avoid most fragmentation issues and long term buildup of speculative preallocation whilst not perturbing large/slow writers too much....
Any thoughts on having tunables for both values (time and min size?) on the background scanning?
Well, my suggestion for timing is as per above (xfs_syncd_centisecs
* 100), but I don't really have any good rule of thumb for the minimum size. What threshold do people start to notice this?
I'd SWAG that something like 32MB is a good size to start at because most IO subsystems will still be able to reach full bandwidth with extents of this size when reading files.
Alternatively, if you can determine if the inode is still in use at the time of the scan (e.g. elevated reference count due to an open fd) and skip the truncation for those inodes, then a minimum size is not really needed, right?
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 4/4] xfs: add background scanning to clear EOFBLOCKS inodes
Quoted 3 lines · Dave Chinner
Quoted 2 lines · Brian Foster
Quoted 1 line · Dave Chinner
On Mon, Aug 27, 2012 at 03:51:51PM -0400, Brian Foster wrote:
...
Quoted 8 lines
Quoted 3 lines
Any thoughts on having tunables for both values (time and min size?) on the background scanning?
Well, my suggestion for timing is as per above (
xfs_syncd_centisecs
* 100), but I don't really have any good rule of thumb for the minimum size. What threshold do people start to notice this?
For the testing I've done so far, I'm hitting EDQUOT with 20-30GB of space left while sequentially writing to many large files. I'm really just trying to get used space before failure more in the ball park of the limit, so I'm not going to complain too much over leaving a few hundred MB or so around on an otherwise full quota. ;) From where I sit, the problem is more when we extend a file by 2, 4, 8GB and consume a large amount of limited available space.
I suppose for the background scanning, it's more about just using a value that doesn't get in the way of general behavior/performance. I'll do some more testing in this area.
Quoted 9 lines
I'd SWAG that something like 32MB is a good size to start at because most IO subsystems will still be able to reach full bandwidth with extents of this size when reading files.
Alternatively, if you can determine if the inode is still in use at the time of the scan (e.g. elevated reference count due to an open fd) and skip the truncation for those inodes, then a minimum size is not really needed, right?
Hmm, good idea. Though perhaps I can use the min_size as a force parameter (i.e., trim anything over this size), and the inode in use check allows a more conservative default. I'll have to play around with the right time/size values some more to get a better feel for it. I'll probably include tunables at least for testing purposes, and they can always be removed later. Thanks.
Brian
Quoted 4 lines
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [RFC PATCH 4/4] xfs: add background scanning to clear EOFBLOCKS inodes
Quoted 9 lines · Brian Foster
Quoted 3 lines · Dave Chinner
Quoted 2 lines · Brian Foster
Quoted 1 line · Dave Chinner
On Mon, Aug 27, 2012 at 03:51:51PM -0400, Brian Foster wrote:
...
Quoted 4 lines
Quoted 3 lines
Any thoughts on having tunables for both values (time and min size?) on the background scanning?
Quoted 7 lines
Quoted 4 lines
Well, my suggestion for timing is as per above (
xfs_syncd_centisecs
* 100), but I don't really have any good rule of thumb for the minimum size. What threshold do people start to notice this?For the testing I've done so far, I'm hitting EDQUOT with 20-30GB of space left while sequentially writing to many large files.
Sure, background scanning won't prevent that, though. The background scan is to catch preallocation that is no longer needed. i.e. the files are no longer being written and have no dirty date but due to the access nature, xfs_release() didn't free the unused preallocation. The background scan will clean that up faster than waiting for the inodes to cycle through the cache....
Quoted 3 lines
I'm really
just trying to get used space before failure more in the ball park of the limit,
That's what prealloc size throttling is for. ;)
Quoted 8 lines
so I'm not going to complain too much over leaving a few hundred MB or so around on an otherwise full quota. ;) From where I sit, the problem is more when we extend a file by 2, 4, 8GB and consume a large amount of limited available space.
I suppose for the background scanning, it's more about just using a value that doesn't get in the way of general behavior/performance. I'll do some more testing in this area.
Right.
Quoted 4 lines
Quoted 4 lines
I'd SWAG that something like 32MB is a good size to start at because most IO subsystems will still be able to reach full bandwidth with extents of this size when reading files.
Quoted 8 lines
Quoted 5 lines
Alternatively, if you can determine if the inode is still in use at the time of the scan (e.g. elevated reference count due to an open fd) and skip the truncation for those inodes, then a minimum size is not really needed, right?
Hmm, good idea. Though perhaps I can use the
min_sizeas a force parameter (i.e., trim anything over this size),
If it's a background scan, we don't want to trim active preallocations.
Quoted 2 lines
and the inode in use
check allows a more conservative default.
I just thought of a better check than an in-use check - if the inode has a dirty page cache, don't trim it as the speculative prealloc is still useful. If the inode is clean, it has not recently been written to so we can remove the speculative prealloc and we are unlikely to suffer any penalty from doing so....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs