aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-08-23 22:02:11 -0400
committerAlex Elder <aelder@sgi.com>2010-10-18 16:07:25 -0400
commit447223520520b17d3b6d0631aa4838fbaf8eddb4 (patch)
tree068716a0537e0f7007a037073c4b7bc608233c1e
parent3ae4c9deb30a8d5ee305b461625dcb298c9804a9 (diff)
xfs: Introduce XFS_IOC_ZERO_RANGE
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. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c1
-rw-r--r--fs/xfs/xfs_bmap.c12
-rw-r--r--fs/xfs/xfs_bmap.h9
-rw-r--r--fs/xfs/xfs_fs.h1
-rw-r--r--fs/xfs/xfs_vnodeops.c10
6 files changed, 27 insertions, 9 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 3b9e626f7cd1..03aa908a9cb9 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1301,7 +1301,8 @@ xfs_file_ioctl(
1301 case XFS_IOC_ALLOCSP64: 1301 case XFS_IOC_ALLOCSP64:
1302 case XFS_IOC_FREESP64: 1302 case XFS_IOC_FREESP64:
1303 case XFS_IOC_RESVSP64: 1303 case XFS_IOC_RESVSP64:
1304 case XFS_IOC_UNRESVSP64: { 1304 case XFS_IOC_UNRESVSP64:
1305 case XFS_IOC_ZERO_RANGE: {
1305 xfs_flock64_t bf; 1306 xfs_flock64_t bf;
1306 1307
1307 if (copy_from_user(&bf, arg, sizeof(bf))) 1308 if (copy_from_user(&bf, arg, sizeof(bf)))
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 6c83f7f62dc9..464bcc76e980 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -574,6 +574,7 @@ xfs_file_compat_ioctl(
574 case XFS_IOC_FSGEOMETRY_V1: 574 case XFS_IOC_FSGEOMETRY_V1:
575 case XFS_IOC_FSGROWFSDATA: 575 case XFS_IOC_FSGROWFSDATA:
576 case XFS_IOC_FSGROWFSRT: 576 case XFS_IOC_FSGROWFSRT:
577 case XFS_IOC_ZERO_RANGE:
577 return xfs_file_ioctl(filp, cmd, p); 578 return xfs_file_ioctl(filp, cmd, p);
578#else 579#else
579 case XFS_IOC_ALLOCSP_32: 580 case XFS_IOC_ALLOCSP_32:
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index f90dadd5a968..5e33b7862d41 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4744,8 +4744,12 @@ xfs_bmapi(
4744 * Check if writing previously allocated but 4744 * Check if writing previously allocated but
4745 * unwritten extents. 4745 * unwritten extents.
4746 */ 4746 */
4747 if (wr && mval->br_state == XFS_EXT_UNWRITTEN && 4747 if (wr &&
4748 ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) { 4748 ((mval->br_state == XFS_EXT_UNWRITTEN &&
4749 ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) ||
4750 (mval->br_state == XFS_EXT_NORM &&
4751 ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT)) ==
4752 (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT))))) {
4749 /* 4753 /*
4750 * Modify (by adding) the state flag, if writing. 4754 * Modify (by adding) the state flag, if writing.
4751 */ 4755 */
@@ -4757,7 +4761,9 @@ xfs_bmapi(
4757 *firstblock; 4761 *firstblock;
4758 cur->bc_private.b.flist = flist; 4762 cur->bc_private.b.flist = flist;
4759 } 4763 }
4760 mval->br_state = XFS_EXT_NORM; 4764 mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
4765 ? XFS_EXT_NORM
4766 : XFS_EXT_UNWRITTEN;
4761 error = xfs_bmap_add_extent(ip, lastx, &cur, mval, 4767 error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
4762 firstblock, flist, &tmp_logflags, 4768 firstblock, flist, &tmp_logflags,
4763 whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); 4769 whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index b13569a6179b..71ec9b6ecdfc 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -74,9 +74,12 @@ typedef struct xfs_bmap_free
74#define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */ 74#define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */
75 /* combine contig. space */ 75 /* combine contig. space */
76#define XFS_BMAPI_CONTIG 0x100 /* must allocate only one extent */ 76#define XFS_BMAPI_CONTIG 0x100 /* must allocate only one extent */
77#define XFS_BMAPI_CONVERT 0x200 /* unwritten extent conversion - */ 77/*
78 /* need write cache flushing and no */ 78 * unwritten extent conversion - this needs write cache flushing and no additional
79 /* additional allocation alignments */ 79 * allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts
80 * from written to unwritten, otherwise convert from unwritten to written.
81 */
82#define XFS_BMAPI_CONVERT 0x200
80 83
81#define XFS_BMAPI_FLAGS \ 84#define XFS_BMAPI_FLAGS \
82 { XFS_BMAPI_WRITE, "WRITE" }, \ 85 { XFS_BMAPI_WRITE, "WRITE" }, \
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 87c2e9d02288..10f6093671b0 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -448,6 +448,7 @@ typedef struct xfs_handle {
448/* XFS_IOC_SETBIOSIZE ---- deprecated 46 */ 448/* XFS_IOC_SETBIOSIZE ---- deprecated 46 */
449/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */ 449/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */
450#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap) 450#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)
451#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64)
451 452
452/* 453/*
453 * ioctl commands that replace IRIX syssgi()'s 454 * ioctl commands that replace IRIX syssgi()'s
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 4c7c7bfb2b2f..dc6e4fb8bbc9 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -2272,7 +2272,7 @@ xfs_alloc_file_space(
2272 count = len; 2272 count = len;
2273 imapp = &imaps[0]; 2273 imapp = &imaps[0];
2274 nimaps = 1; 2274 nimaps = 1;
2275 bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); 2275 bmapi_flag = XFS_BMAPI_WRITE | alloc_type;
2276 startoffset_fsb = XFS_B_TO_FSBT(mp, offset); 2276 startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
2277 allocatesize_fsb = XFS_B_TO_FSB(mp, count); 2277 allocatesize_fsb = XFS_B_TO_FSB(mp, count);
2278 2278
@@ -2711,6 +2711,7 @@ xfs_change_file_space(
2711 xfs_off_t llen; 2711 xfs_off_t llen;
2712 xfs_trans_t *tp; 2712 xfs_trans_t *tp;
2713 struct iattr iattr; 2713 struct iattr iattr;
2714 int prealloc_type;
2714 2715
2715 if (!S_ISREG(ip->i_d.di_mode)) 2716 if (!S_ISREG(ip->i_d.di_mode))
2716 return XFS_ERROR(EINVAL); 2717 return XFS_ERROR(EINVAL);
@@ -2753,12 +2754,17 @@ xfs_change_file_space(
2753 * size to be changed. 2754 * size to be changed.
2754 */ 2755 */
2755 setprealloc = clrprealloc = 0; 2756 setprealloc = clrprealloc = 0;
2757 prealloc_type = XFS_BMAPI_PREALLOC;
2756 2758
2757 switch (cmd) { 2759 switch (cmd) {
2760 case XFS_IOC_ZERO_RANGE:
2761 prealloc_type |= XFS_BMAPI_CONVERT;
2762 xfs_tosspages(ip, startoffset, startoffset + bf->l_len, 0);
2763 /* FALLTHRU */
2758 case XFS_IOC_RESVSP: 2764 case XFS_IOC_RESVSP:
2759 case XFS_IOC_RESVSP64: 2765 case XFS_IOC_RESVSP64:
2760 error = xfs_alloc_file_space(ip, startoffset, bf->l_len, 2766 error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
2761 1, attr_flags); 2767 prealloc_type, attr_flags);
2762 if (error) 2768 if (error)
2763 return error; 2769 return error;
2764 setprealloc = 1; 2770 setprealloc = 1;