xfs: Fast zeroing of allocated space
cover xfs: Fast zeroing of allocated space
These two patches allow conversion of a written range of a file into back into unwritten state. The first patch converts page cache helper functions to use the correct range primitives as we need to be able to toss (invalidate) pages only within the range specified, not to to the end of the file as it currently uses.
The actual conversion also preallocates any holes in the range, so it turns the entire range requested into allocated, unwritten extents.
Version 2:
o removed stray debugging printks
o truncate_inode_pages_range doesn't handle partial tail pages, so the range needs to be tossed appropriately.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 1/2 xfs: use range primitives for xfs page cache operations
From: Dave Chinner <[email protected]>
While XFS passes ranges to operate on from the core code, the functions being called ignore the either the entire range or the end of the range. This is historical because when the function were written linux didn't have the necessary range operations. Update the functions to use the correct operations.
--- fs/xfs/linux-2.6/xfs_fs_subr.c | 31 +++++++++++++++---------------- 1 files changed, 15 insertions(+), 16 deletions(-)
fs/xfs/linux-2.6/xfs_fs_subr.c +15 -16
@@ -32,10 +32,9 @@ xfs_tosspages( xfs_off_t last, int fiopt) { -struct address_space *mapping =VFS_I (ip)->i_mapping; - -if (mapping->nrpages) -truncate_inode_pages (mapping, first); +/* can't toss partial tail pages, so mask them out */ + last &= ~(PAGE_SIZE -1 ); +truncate_inode_pages_range (VFS_I (ip)->i_mapping, first, last); }int
@@ -50,12 +49,11 @@ xfs_flushinval_pages(trace_xfs_pagecache_inval (ip, first, last); -if (mapping->nrpages) { -xfs_iflags_clear (ip,XFS_ITRUNCATED ); - ret =filemap_write_and_wait (mapping); -if (!ret) -truncate_inode_pages (mapping, first); - } +xfs_iflags_clear (ip,XFS_ITRUNCATED ); + ret =filemap_write_and_wait_range (mapping, first, + last ==-1 ?LLONG_MAX : last); +if (!ret) +truncate_inode_pages_range (mapping, first, last);return -ret; }
@@ -71,10 +69,9 @@ xfs_flush_pages(int ret =0 ;int ret2; -if (mapping_tagged (mapping,PAGECACHE_TAG_DIRTY )) { -xfs_iflags_clear (ip,XFS_ITRUNCATED ); - ret = -filemap_fdatawrite (mapping); - } +xfs_iflags_clear (ip,XFS_ITRUNCATED ); + ret = -filemap_fdatawrite_range (mapping, first, + last ==-1 ?LLONG_MAX : last);if (flags &XBF_ASYNC )return ret; ret2 =xfs_wait_on_pages (ip, first, last);
@@ -91,7 +88,9 @@ xfs_wait_on_pages( {struct address_space *mapping =VFS_I (ip)->i_mapping; -if (mapping_tagged (mapping,PAGECACHE_TAG_WRITEBACK )) -return -filemap_fdatawait (mapping); +if (mapping_tagged (mapping,PAGECACHE_TAG_WRITEBACK )) { +return -filemap_fdatawait_range (mapping, first, + last ==-1 ? ip->i_size -1 : last); + }return 0 ; }
Signature · 6 lines
1.7.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 1/2] xfs: use range primitives for xfs page cache operations
Quoted 7 lines · Dave Chinner
From: Dave Chinner <[email protected]>
While XFS passes ranges to operate on from the core code, the functions being called ignore the either the entire range or the end of the range. This is historical because when the function were written linux didn't have the necessary range operations. Update the functions to use the correct operations.
Looks good,
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 2/2 xfs: Introduce XFS_IOC_ZERO_RANGE
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
XFS_IOC_ZERO_RANGE is the equivalent of an atomic XFS_IOC_UNRESVSP/ XFS_IOC_RESVSP call pair. It enabled ranges of written data to be turned into zeroes without requiring IO or having to free and reallocate the extents in the range given as would occur if we had to punch and then preallocate them separately. This enables applications to zero parts of files very quickly without changing the layout of the files in any way.
--- fs/xfs/linux-2.6/xfs_ioctl.c | 3 ++- fs/xfs/linux-2.6/xfs_ioctl32.c | 1 + fs/xfs/xfs_bmap.c | 12 +++++++++--- fs/xfs/xfs_bmap.h | 9 ++++++--- fs/xfs/xfs_fs.h | 1 + fs/xfs/xfs_vnodeops.c | 10 ++++++++-- 6 files changed, 27 insertions(+), 9 deletions(-)
fs/xfs/linux-2.6/xfs_ioctl.c +2 -1
@@ -1292,7 +1292,8 @@ xfs_file_ioctl(case XFS_IOC_ALLOCSP64 :case XFS_IOC_FREESP64 :case XFS_IOC_RESVSP64 : -case XFS_IOC_UNRESVSP64 : { +case XFS_IOC_UNRESVSP64 : +case XFS_IOC_ZERO_RANGE : {xfs_flock64_t bf;if (copy_from_user (&bf, arg,sizeof (bf)))
fs/xfs/linux-2.6/xfs_ioctl32.c +1 -0
@@ -574,6 +574,7 @@ xfs_file_compat_ioctl(case XFS_IOC_FSGEOMETRY_V1 :case XFS_IOC_FSGROWFSDATA :case XFS_IOC_FSGROWFSRT : +case XFS_IOC_ZERO_RANGE :return xfs_file_ioctl (filp, cmd, p);#else case XFS_IOC_ALLOCSP_32 :
fs/xfs/xfs_bmap.c +9 -3
@@ -4744,8 +4744,12 @@ xfs_bmapi(* Check if writing previously allocated but * unwritten extents. */ -if (wr && mval->br_state ==XFS_EXT_UNWRITTEN && - ((flags & (XFS_BMAPI_PREALLOC |XFS_BMAPI_DELAY )) ==0 )) { +if (wr && + ((mval->br_state ==XFS_EXT_UNWRITTEN && + ((flags & (XFS_BMAPI_PREALLOC |XFS_BMAPI_DELAY )) ==0 )) || + (mval->br_state ==XFS_EXT_NORM && + ((flags & (XFS_BMAPI_PREALLOC |XFS_BMAPI_CONVERT )) == + (XFS_BMAPI_PREALLOC |XFS_BMAPI_CONVERT ))))) {/* * Modify (by adding) the state flag, if writing. */
@@ -4757,7 +4761,9 @@ xfs_bmapi( *firstblock; cur->bc_private.b.flist = flist; } - mval->br_state =XFS_EXT_NORM ; + mval->br_state = (mval->br_state ==XFS_EXT_UNWRITTEN ) + ?XFS_EXT_NORM + :XFS_EXT_UNWRITTEN ; error =xfs_bmap_add_extent (ip, lastx, &cur, mval, firstblock, flist, &tmp_logflags, whichfork, (flags &XFS_BMAPI_RSVBLOCKS ));
fs/xfs/xfs_bmap.h +6 -3
@@ -74,9 +74,12 @@ typedef struct xfs_bmap_free#define XFS_BMAPI_IGSTATE 0x080/* Ignore state - */ /* combine contig. space */ #define XFS_BMAPI_CONTIG 0x100/* must allocate only one extent */ -#define XFS_BMAPI_CONVERT 0x200/* unwritten extent conversion - */ -/* need write cache flushing and no */ -/* additional allocation alignments */ +/* +* unwritten extent conversion - this needs write cache flushing and no additional +* allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts +* from written to unwritten, otherwise convert from unwritten to written. +*/ +#define XFS_BMAPI_CONVERT 0x200#define XFS_BMAPI_FLAGS \ { XFS_BMAPI_WRITE, "WRITE" }, \
fs/xfs/xfs_fs.h +1 -0
@@ -446,6 +446,7 @@ typedef struct xfs_handle {/* XFS_IOC_SETBIOSIZE ---- deprecated 46 */ /* 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)/* * ioctl commands that replace IRIX syssgi()'s
fs/xfs/xfs_vnodeops.c +8 -2
@@ -2270,7 +2270,7 @@ xfs_alloc_file_space( count = len; imapp = &imaps[0 ]; nimaps =1 ; - bmapi_flag =XFS_BMAPI_WRITE | (alloc_type ?XFS_BMAPI_PREALLOC :0 ); + bmapi_flag =XFS_BMAPI_WRITE | alloc_type; startoffset_fsb =XFS_B_TO_FSBT (mp, offset); allocatesize_fsb =XFS_B_TO_FSB (mp, count);
@@ -2702,6 +2702,7 @@ xfs_change_file_space(xfs_off_t llen;xfs_trans_t *tp;struct iattr iattr; +int prealloc_type;if (!S_ISREG (ip->i_d.di_mode))return XFS_ERROR (EINVAL );
@@ -2744,12 +2745,17 @@ xfs_change_file_space(* size to be changed. */ setprealloc = clrprealloc =0 ; + prealloc_type =XFS_BMAPI_PREALLOC ;switch (cmd) { +case XFS_IOC_ZERO_RANGE : + prealloc_type |=XFS_BMAPI_CONVERT ; +xfs_tosspages (ip, startoffset, startoffset + bf->l_len,0 ); +/* FALLTHRU */ case XFS_IOC_RESVSP :case XFS_IOC_RESVSP64 : error =xfs_alloc_file_space (ip, startoffset, bf->l_len, -1 , attr_flags); + prealloc_type, attr_flags);if (error)return error; setprealloc =1 ;
Signature · 6 lines
1.7.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 2/2] xfs: Introduce XFS_IOC_ZERO_RANGE
Quoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
XFS_IOC_ZERO_RANGEis the equivalent of an atomic XFS_IOC_UNRESVSP/XFS_IOC_RESVSPcall pair. It enabled ranges of written data to be turned into zeroes without requiring IO or having to free and reallocate the extents in the range given as would occur if we had to punch and then preallocate them separately. This enables applications to zero parts of files very quickly without changing the layout of the files in any way.
Looks good,
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs