aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c64
-rw-r--r--fs/xfs/xfs_bmap.c62
-rw-r--r--fs/xfs/xfs_bmap.h11
-rw-r--r--fs/xfs/xfs_fs.h12
4 files changed, 71 insertions, 78 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index f1bd6c36e6f..d5970599953 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1250,43 +1250,67 @@ xfs_ioc_setxflags(
1250} 1250}
1251 1251
1252STATIC int 1252STATIC int
1253xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full)
1254{
1255 struct getbmap __user *base = *ap;
1256
1257 /* copy only getbmap portion (not getbmapx) */
1258 if (copy_to_user(base, bmv, sizeof(struct getbmap)))
1259 return XFS_ERROR(EFAULT);
1260
1261 *ap += sizeof(struct getbmap);
1262 return 0;
1263}
1264
1265STATIC int
1253xfs_ioc_getbmap( 1266xfs_ioc_getbmap(
1254 struct xfs_inode *ip, 1267 struct xfs_inode *ip,
1255 int ioflags, 1268 int ioflags,
1256 unsigned int cmd, 1269 unsigned int cmd,
1257 void __user *arg) 1270 void __user *arg)
1258{ 1271{
1259 struct getbmap bm; 1272 struct getbmapx bmx;
1260 int iflags;
1261 int error; 1273 int error;
1262 1274
1263 if (copy_from_user(&bm, arg, sizeof(bm))) 1275 if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
1264 return -XFS_ERROR(EFAULT); 1276 return -XFS_ERROR(EFAULT);
1265 1277
1266 if (bm.bmv_count < 2) 1278 if (bmx.bmv_count < 2)
1267 return -XFS_ERROR(EINVAL); 1279 return -XFS_ERROR(EINVAL);
1268 1280
1269 iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); 1281 bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1270 if (ioflags & IO_INVIS) 1282 if (ioflags & IO_INVIS)
1271 iflags |= BMV_IF_NO_DMAPI_READ; 1283 bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ;
1272 1284
1273 error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags); 1285 error = xfs_getbmap(ip, &bmx, xfs_getbmap_format,
1286 (struct getbmap *)arg+1);
1274 if (error) 1287 if (error)
1275 return -error; 1288 return -error;
1276 1289
1277 if (copy_to_user(arg, &bm, sizeof(bm))) 1290 /* copy back header - only size of getbmap */
1291 if (copy_to_user(arg, &bmx, sizeof(struct getbmap)))
1278 return -XFS_ERROR(EFAULT); 1292 return -XFS_ERROR(EFAULT);
1279 return 0; 1293 return 0;
1280} 1294}
1281 1295
1282STATIC int 1296STATIC int
1297xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full)
1298{
1299 struct getbmapx __user *base = *ap;
1300
1301 if (copy_to_user(base, bmv, sizeof(struct getbmapx)))
1302 return XFS_ERROR(EFAULT);
1303
1304 *ap += sizeof(struct getbmapx);
1305 return 0;
1306}
1307
1308STATIC int
1283xfs_ioc_getbmapx( 1309xfs_ioc_getbmapx(
1284 struct xfs_inode *ip, 1310 struct xfs_inode *ip,
1285 void __user *arg) 1311 void __user *arg)
1286{ 1312{
1287 struct getbmapx bmx; 1313 struct getbmapx bmx;
1288 struct getbmap bm;
1289 int iflags;
1290 int error; 1314 int error;
1291 1315
1292 if (copy_from_user(&bmx, arg, sizeof(bmx))) 1316 if (copy_from_user(&bmx, arg, sizeof(bmx)))
@@ -1295,26 +1319,16 @@ xfs_ioc_getbmapx(
1295 if (bmx.bmv_count < 2) 1319 if (bmx.bmv_count < 2)
1296 return -XFS_ERROR(EINVAL); 1320 return -XFS_ERROR(EINVAL);
1297 1321
1298 /* 1322 if (bmx.bmv_iflags & (~BMV_IF_VALID))
1299 * Map input getbmapx structure to a getbmap
1300 * structure for xfs_getbmap.
1301 */
1302 GETBMAP_CONVERT(bmx, bm);
1303
1304 iflags = bmx.bmv_iflags;
1305
1306 if (iflags & (~BMV_IF_VALID))
1307 return -XFS_ERROR(EINVAL); 1323 return -XFS_ERROR(EINVAL);
1308 1324
1309 iflags |= BMV_IF_EXTENDED; 1325 error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format,
1310 1326 (struct getbmapx *)arg+1);
1311 error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags);
1312 if (error) 1327 if (error)
1313 return -error; 1328 return -error;
1314 1329
1315 GETBMAP_CONVERT(bm, bmx); 1330 /* copy back header */
1316 1331 if (copy_to_user(arg, &bmx, sizeof(struct getbmapx)))
1317 if (copy_to_user(arg, &bmx, sizeof(bmx)))
1318 return -XFS_ERROR(EFAULT); 1332 return -XFS_ERROR(EFAULT);
1319 1333
1320 return 0; 1334 return 0;
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index c3912213645..8077580a719 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -5811,9 +5811,9 @@ error0:
5811STATIC int 5811STATIC int
5812xfs_getbmapx_fix_eof_hole( 5812xfs_getbmapx_fix_eof_hole(
5813 xfs_inode_t *ip, /* xfs incore inode pointer */ 5813 xfs_inode_t *ip, /* xfs incore inode pointer */
5814 struct getbmap *out, /* output structure */ 5814 struct getbmapx *out, /* output structure */
5815 int prealloced, /* this is a file with 5815 int prealloced, /* this is a file with
5816 * preallocated data space */ 5816 * preallocated data space */
5817 __int64_t end, /* last block requested */ 5817 __int64_t end, /* last block requested */
5818 xfs_fsblock_t startblock) 5818 xfs_fsblock_t startblock)
5819{ 5819{
@@ -5839,14 +5839,18 @@ xfs_getbmapx_fix_eof_hole(
5839} 5839}
5840 5840
5841/* 5841/*
5842 * Fcntl interface to xfs_bmapi. 5842 * Get inode's extents as described in bmv, and format for output.
5843 * Calls formatter to fill the user's buffer until all extents
5844 * are mapped, until the passed-in bmv->bmv_count slots have
5845 * been filled, or until the formatter short-circuits the loop,
5846 * if it is tracking filled-in extents on its own.
5843 */ 5847 */
5844int /* error code */ 5848int /* error code */
5845xfs_getbmap( 5849xfs_getbmap(
5846 xfs_inode_t *ip, 5850 xfs_inode_t *ip,
5847 struct getbmap *bmv, /* user bmap structure */ 5851 struct getbmapx *bmv, /* user bmap structure */
5848 void __user *ap, /* pointer to user's array */ 5852 xfs_bmap_format_t formatter, /* format to user */
5849 int interface) /* interface flags */ 5853 void *arg) /* formatter arg */
5850{ 5854{
5851 __int64_t bmvend; /* last block requested */ 5855 __int64_t bmvend; /* last block requested */
5852 int error; /* return value */ 5856 int error; /* return value */
@@ -5859,19 +5863,20 @@ xfs_getbmap(
5859 int nexleft; /* # of user extents left */ 5863 int nexleft; /* # of user extents left */
5860 int subnex; /* # of bmapi's can do */ 5864 int subnex; /* # of bmapi's can do */
5861 int nmap; /* number of map entries */ 5865 int nmap; /* number of map entries */
5862 struct getbmap out; /* output structure */ 5866 struct getbmapx out; /* output structure */
5863 int whichfork; /* data or attr fork */ 5867 int whichfork; /* data or attr fork */
5864 int prealloced; /* this is a file with 5868 int prealloced; /* this is a file with
5865 * preallocated data space */ 5869 * preallocated data space */
5866 int sh_unwritten; /* true, if unwritten */ 5870 int sh_unwritten; /* true, if unwritten */
5867 /* extents listed separately */ 5871 /* extents listed separately */
5872 int iflags; /* interface flags */
5868 int bmapi_flags; /* flags for xfs_bmapi */ 5873 int bmapi_flags; /* flags for xfs_bmapi */
5869 __int32_t oflags; /* getbmapx bmv_oflags field */
5870 5874
5871 mp = ip->i_mount; 5875 mp = ip->i_mount;
5876 iflags = bmv->bmv_iflags;
5872 5877
5873 whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK; 5878 whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
5874 sh_unwritten = (interface & BMV_IF_PREALLOC) != 0; 5879 sh_unwritten = (iflags & BMV_IF_PREALLOC) != 0;
5875 5880
5876 /* If the BMV_IF_NO_DMAPI_READ interface bit specified, do not 5881 /* If the BMV_IF_NO_DMAPI_READ interface bit specified, do not
5877 * generate a DMAPI read event. Otherwise, if the DM_EVENT_READ 5882 * generate a DMAPI read event. Otherwise, if the DM_EVENT_READ
@@ -5886,7 +5891,7 @@ xfs_getbmap(
5886 * could misinterpret holes in a DMAPI file as true holes, 5891 * could misinterpret holes in a DMAPI file as true holes,
5887 * when in fact they may represent offline user data. 5892 * when in fact they may represent offline user data.
5888 */ 5893 */
5889 if ((interface & BMV_IF_NO_DMAPI_READ) == 0 && 5894 if ((iflags & BMV_IF_NO_DMAPI_READ) == 0 &&
5890 DM_EVENT_ENABLED(ip, DM_EVENT_READ) && 5895 DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
5891 whichfork == XFS_DATA_FORK) { 5896 whichfork == XFS_DATA_FORK) {
5892 error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL); 5897 error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
@@ -5993,52 +5998,35 @@ xfs_getbmap(
5993 ASSERT(nmap <= subnex); 5998 ASSERT(nmap <= subnex);
5994 5999
5995 for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) { 6000 for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
5996 nexleft--; 6001 out.bmv_oflags = (map[i].br_state == XFS_EXT_UNWRITTEN) ?
5997 oflags = (map[i].br_state == XFS_EXT_UNWRITTEN) ?
5998 BMV_OF_PREALLOC : 0; 6002 BMV_OF_PREALLOC : 0;
5999 out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff); 6003 out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff);
6000 out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount); 6004 out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
6005 out.bmv_unused1 = out.bmv_unused2 = 0;
6001 ASSERT(map[i].br_startblock != DELAYSTARTBLOCK); 6006 ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);
6002 if (map[i].br_startblock == HOLESTARTBLOCK && 6007 if (map[i].br_startblock == HOLESTARTBLOCK &&
6003 whichfork == XFS_ATTR_FORK) { 6008 whichfork == XFS_ATTR_FORK) {
6004 /* came to the end of attribute fork */ 6009 /* came to the end of attribute fork */
6005 goto unlock_and_return; 6010 goto unlock_and_return;
6006 } else { 6011 } else {
6012 int full = 0; /* user array is full */
6013
6007 if (!xfs_getbmapx_fix_eof_hole(ip, &out, 6014 if (!xfs_getbmapx_fix_eof_hole(ip, &out,
6008 prealloced, bmvend, 6015 prealloced, bmvend,
6009 map[i].br_startblock)) { 6016 map[i].br_startblock)) {
6010 goto unlock_and_return; 6017 goto unlock_and_return;
6011 } 6018 }
6012 6019
6013 /* return either getbmap/getbmapx structure. */ 6020 /* format results & advance arg */
6014 if (interface & BMV_IF_EXTENDED) { 6021 error = formatter(&arg, &out, &full);
6015 struct getbmapx outx; 6022 if (error || full)
6016 6023 goto unlock_and_return;
6017 GETBMAP_CONVERT(out,outx); 6024 nexleft--;
6018 outx.bmv_oflags = oflags;
6019 outx.bmv_unused1 = outx.bmv_unused2 = 0;
6020 if (copy_to_user(ap, &outx,
6021 sizeof(outx))) {
6022 error = XFS_ERROR(EFAULT);
6023 goto unlock_and_return;
6024 }
6025 } else {
6026 if (copy_to_user(ap, &out,
6027 sizeof(out))) {
6028 error = XFS_ERROR(EFAULT);
6029 goto unlock_and_return;
6030 }
6031 }
6032 bmv->bmv_offset = 6025 bmv->bmv_offset =
6033 out.bmv_offset + out.bmv_length; 6026 out.bmv_offset + out.bmv_length;
6034 bmv->bmv_length = MAX((__int64_t)0, 6027 bmv->bmv_length = MAX((__int64_t)0,
6035 (__int64_t)(bmvend - bmv->bmv_offset)); 6028 (__int64_t)(bmvend - bmv->bmv_offset));
6036 bmv->bmv_entries++; 6029 bmv->bmv_entries++;
6037 ap = (interface & BMV_IF_EXTENDED) ?
6038 (void __user *)
6039 ((struct getbmapx __user *)ap + 1) :
6040 (void __user *)
6041 ((struct getbmap __user *)ap + 1);
6042 } 6030 }
6043 } 6031 }
6044 } while (nmap && nexleft && bmv->bmv_length); 6032 } while (nmap && nexleft && bmv->bmv_length);
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 7c9d12cd7a4..284571c05ed 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -356,15 +356,18 @@ xfs_bmap_finish(
356 xfs_bmap_free_t *flist, /* i/o: list extents to free */ 356 xfs_bmap_free_t *flist, /* i/o: list extents to free */
357 int *committed); /* xact committed or not */ 357 int *committed); /* xact committed or not */
358 358
359/* bmap to userspace formatter - copy to user & advance pointer */
360typedef int (*xfs_bmap_format_t)(void **, struct getbmapx *, int *);
361
359/* 362/*
360 * Fcntl interface to xfs_bmapi. 363 * Get inode's extents as described in bmv, and format for output.
361 */ 364 */
362int /* error code */ 365int /* error code */
363xfs_getbmap( 366xfs_getbmap(
364 xfs_inode_t *ip, 367 xfs_inode_t *ip,
365 struct getbmap *bmv, /* user bmap structure */ 368 struct getbmapx *bmv, /* user bmap structure */
366 void __user *ap, /* pointer to user's array */ 369 xfs_bmap_format_t formatter, /* format to user */
367 int iflags); /* interface flags */ 370 void *arg); /* formatter arg */
368 371
369/* 372/*
370 * Check if the endoff is outside the last extent. If so the caller will grow 373 * Check if the endoff is outside the last extent. If so the caller will grow
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 01c0cc88d3f..df859d62a16 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -114,22 +114,10 @@ struct getbmapx {
114#define BMV_IF_NO_DMAPI_READ 0x2 /* Do not generate DMAPI read event */ 114#define BMV_IF_NO_DMAPI_READ 0x2 /* Do not generate DMAPI read event */
115#define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */ 115#define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */
116#define BMV_IF_VALID (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC) 116#define BMV_IF_VALID (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC)
117#ifdef __KERNEL__
118#define BMV_IF_EXTENDED 0x40000000 /* getpmapx if set */
119#endif
120 117
121/* bmv_oflags values - returned for for each non-header segment */ 118/* bmv_oflags values - returned for for each non-header segment */
122#define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ 119#define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */
123 120
124/* Convert getbmap <-> getbmapx - move fields from p1 to p2. */
125#define GETBMAP_CONVERT(p1,p2) { \
126 p2.bmv_offset = p1.bmv_offset; \
127 p2.bmv_block = p1.bmv_block; \
128 p2.bmv_length = p1.bmv_length; \
129 p2.bmv_count = p1.bmv_count; \
130 p2.bmv_entries = p1.bmv_entries; }
131
132
133/* 121/*
134 * Structure for XFS_IOC_FSSETDM. 122 * Structure for XFS_IOC_FSSETDM.
135 * For use by backup and restore programs to set the XFS on-disk inode 123 * For use by backup and restore programs to set the XFS on-disk inode