diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 64 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap.c | 62 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap.h | 11 | ||||
-rw-r--r-- | fs/xfs/xfs_fs.h | 12 |
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 f1bd6c36e6fe..d59705999534 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 | ||
1252 | STATIC int | 1252 | STATIC int |
1253 | xfs_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 | |||
1265 | STATIC int | ||
1253 | xfs_ioc_getbmap( | 1266 | xfs_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 | ||
1282 | STATIC int | 1296 | STATIC int |
1297 | xfs_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 | |||
1308 | STATIC int | ||
1283 | xfs_ioc_getbmapx( | 1309 | xfs_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 c3912213645c..8077580a7199 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -5811,9 +5811,9 @@ error0: | |||
5811 | STATIC int | 5811 | STATIC int |
5812 | xfs_getbmapx_fix_eof_hole( | 5812 | xfs_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 | */ |
5844 | int /* error code */ | 5848 | int /* error code */ |
5845 | xfs_getbmap( | 5849 | xfs_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 7c9d12cd7a47..284571c05ed0 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 */ | ||
360 | typedef 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 | */ |
362 | int /* error code */ | 365 | int /* error code */ |
363 | xfs_getbmap( | 366 | xfs_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 01c0cc88d3f3..df859d62a163 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 |