diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 368 |
1 files changed, 312 insertions, 56 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index f34bd010eb51..c6399b2cf17c 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -1179,85 +1179,85 @@ xfs_ioc_fsgetxattr( | |||
1179 | } | 1179 | } |
1180 | 1180 | ||
1181 | STATIC int | 1181 | STATIC int |
1182 | xfs_ioc_xattr( | 1182 | xfs_ioc_fssetxattr( |
1183 | xfs_inode_t *ip, | 1183 | xfs_inode_t *ip, |
1184 | struct file *filp, | 1184 | struct file *filp, |
1185 | unsigned int cmd, | ||
1186 | void __user *arg) | 1185 | void __user *arg) |
1187 | { | 1186 | { |
1188 | struct fsxattr fa; | 1187 | struct fsxattr fa; |
1189 | struct bhv_vattr *vattr; | 1188 | struct bhv_vattr *vattr; |
1190 | int error = 0; | 1189 | int error; |
1191 | int attr_flags; | 1190 | int attr_flags; |
1192 | unsigned int flags; | 1191 | |
1192 | if (copy_from_user(&fa, arg, sizeof(fa))) | ||
1193 | return -EFAULT; | ||
1193 | 1194 | ||
1194 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); | 1195 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
1195 | if (unlikely(!vattr)) | 1196 | if (unlikely(!vattr)) |
1196 | return -ENOMEM; | 1197 | return -ENOMEM; |
1197 | 1198 | ||
1198 | switch (cmd) { | 1199 | attr_flags = 0; |
1199 | case XFS_IOC_FSSETXATTR: { | 1200 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
1200 | if (copy_from_user(&fa, arg, sizeof(fa))) { | 1201 | attr_flags |= ATTR_NONBLOCK; |
1201 | error = -EFAULT; | ||
1202 | break; | ||
1203 | } | ||
1204 | 1202 | ||
1205 | attr_flags = 0; | 1203 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; |
1206 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 1204 | vattr->va_xflags = fa.fsx_xflags; |
1207 | attr_flags |= ATTR_NONBLOCK; | 1205 | vattr->va_extsize = fa.fsx_extsize; |
1206 | vattr->va_projid = fa.fsx_projid; | ||
1208 | 1207 | ||
1209 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; | 1208 | error = -xfs_setattr(ip, vattr, attr_flags, NULL); |
1210 | vattr->va_xflags = fa.fsx_xflags; | 1209 | if (!error) |
1211 | vattr->va_extsize = fa.fsx_extsize; | 1210 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ |
1212 | vattr->va_projid = fa.fsx_projid; | 1211 | kfree(vattr); |
1212 | return 0; | ||
1213 | } | ||
1213 | 1214 | ||
1214 | error = xfs_setattr(ip, vattr, attr_flags, NULL); | 1215 | STATIC int |
1215 | if (likely(!error)) | 1216 | xfs_ioc_getxflags( |
1216 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | 1217 | xfs_inode_t *ip, |
1217 | error = -error; | 1218 | void __user *arg) |
1218 | break; | 1219 | { |
1219 | } | 1220 | unsigned int flags; |
1220 | 1221 | ||
1221 | case XFS_IOC_GETXFLAGS: { | 1222 | flags = xfs_di2lxflags(ip->i_d.di_flags); |
1222 | flags = xfs_di2lxflags(ip->i_d.di_flags); | 1223 | if (copy_to_user(arg, &flags, sizeof(flags))) |
1223 | if (copy_to_user(arg, &flags, sizeof(flags))) | 1224 | return -EFAULT; |
1224 | error = -EFAULT; | 1225 | return 0; |
1225 | break; | 1226 | } |
1226 | } | ||
1227 | 1227 | ||
1228 | case XFS_IOC_SETXFLAGS: { | 1228 | STATIC int |
1229 | if (copy_from_user(&flags, arg, sizeof(flags))) { | 1229 | xfs_ioc_setxflags( |
1230 | error = -EFAULT; | 1230 | xfs_inode_t *ip, |
1231 | break; | 1231 | struct file *filp, |
1232 | } | 1232 | void __user *arg) |
1233 | { | ||
1234 | struct bhv_vattr *vattr; | ||
1235 | unsigned int flags; | ||
1236 | int attr_flags; | ||
1237 | int error; | ||
1233 | 1238 | ||
1234 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ | 1239 | if (copy_from_user(&flags, arg, sizeof(flags))) |
1235 | FS_NOATIME_FL | FS_NODUMP_FL | \ | 1240 | return -EFAULT; |
1236 | FS_SYNC_FL)) { | ||
1237 | error = -EOPNOTSUPP; | ||
1238 | break; | ||
1239 | } | ||
1240 | 1241 | ||
1241 | attr_flags = 0; | 1242 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ |
1242 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 1243 | FS_NOATIME_FL | FS_NODUMP_FL | \ |
1243 | attr_flags |= ATTR_NONBLOCK; | 1244 | FS_SYNC_FL)) |
1245 | return -EOPNOTSUPP; | ||
1244 | 1246 | ||
1245 | vattr->va_mask = XFS_AT_XFLAGS; | 1247 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
1246 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, | 1248 | if (unlikely(!vattr)) |
1247 | xfs_ip2xflags(ip)); | 1249 | return -ENOMEM; |
1248 | 1250 | ||
1249 | error = xfs_setattr(ip, vattr, attr_flags, NULL); | 1251 | attr_flags = 0; |
1250 | if (likely(!error)) | 1252 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
1251 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | 1253 | attr_flags |= ATTR_NONBLOCK; |
1252 | error = -error; | ||
1253 | break; | ||
1254 | } | ||
1255 | 1254 | ||
1256 | default: | 1255 | vattr->va_mask = XFS_AT_XFLAGS; |
1257 | error = -ENOTTY; | 1256 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); |
1258 | break; | ||
1259 | } | ||
1260 | 1257 | ||
1258 | error = -xfs_setattr(ip, vattr, attr_flags, NULL); | ||
1259 | if (likely(!error)) | ||
1260 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | ||
1261 | kfree(vattr); | 1261 | kfree(vattr); |
1262 | return error; | 1262 | return error; |
1263 | } | 1263 | } |
@@ -1332,3 +1332,259 @@ xfs_ioc_getbmapx( | |||
1332 | 1332 | ||
1333 | return 0; | 1333 | return 0; |
1334 | } | 1334 | } |
1335 | |||
1336 | int | ||
1337 | xfs_ioctl( | ||
1338 | xfs_inode_t *ip, | ||
1339 | struct file *filp, | ||
1340 | int ioflags, | ||
1341 | unsigned int cmd, | ||
1342 | void __user *arg) | ||
1343 | { | ||
1344 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1345 | xfs_mount_t *mp = ip->i_mount; | ||
1346 | int error; | ||
1347 | |||
1348 | xfs_itrace_entry(XFS_I(inode)); | ||
1349 | switch (cmd) { | ||
1350 | |||
1351 | case XFS_IOC_ALLOCSP: | ||
1352 | case XFS_IOC_FREESP: | ||
1353 | case XFS_IOC_RESVSP: | ||
1354 | case XFS_IOC_UNRESVSP: | ||
1355 | case XFS_IOC_ALLOCSP64: | ||
1356 | case XFS_IOC_FREESP64: | ||
1357 | case XFS_IOC_RESVSP64: | ||
1358 | case XFS_IOC_UNRESVSP64: | ||
1359 | /* | ||
1360 | * Only allow the sys admin to reserve space unless | ||
1361 | * unwritten extents are enabled. | ||
1362 | */ | ||
1363 | if (!xfs_sb_version_hasextflgbit(&mp->m_sb) && | ||
1364 | !capable(CAP_SYS_ADMIN)) | ||
1365 | return -EPERM; | ||
1366 | |||
1367 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg); | ||
1368 | |||
1369 | case XFS_IOC_DIOINFO: { | ||
1370 | struct dioattr da; | ||
1371 | xfs_buftarg_t *target = | ||
1372 | XFS_IS_REALTIME_INODE(ip) ? | ||
1373 | mp->m_rtdev_targp : mp->m_ddev_targp; | ||
1374 | |||
1375 | da.d_mem = da.d_miniosz = 1 << target->bt_sshift; | ||
1376 | da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); | ||
1377 | |||
1378 | if (copy_to_user(arg, &da, sizeof(da))) | ||
1379 | return -XFS_ERROR(EFAULT); | ||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1383 | case XFS_IOC_FSBULKSTAT_SINGLE: | ||
1384 | case XFS_IOC_FSBULKSTAT: | ||
1385 | case XFS_IOC_FSINUMBERS: | ||
1386 | return xfs_ioc_bulkstat(mp, cmd, arg); | ||
1387 | |||
1388 | case XFS_IOC_FSGEOMETRY_V1: | ||
1389 | return xfs_ioc_fsgeometry_v1(mp, arg); | ||
1390 | |||
1391 | case XFS_IOC_FSGEOMETRY: | ||
1392 | return xfs_ioc_fsgeometry(mp, arg); | ||
1393 | |||
1394 | case XFS_IOC_GETVERSION: | ||
1395 | return put_user(inode->i_generation, (int __user *)arg); | ||
1396 | |||
1397 | case XFS_IOC_FSGETXATTR: | ||
1398 | return xfs_ioc_fsgetxattr(ip, 0, arg); | ||
1399 | case XFS_IOC_FSGETXATTRA: | ||
1400 | return xfs_ioc_fsgetxattr(ip, 1, arg); | ||
1401 | case XFS_IOC_FSSETXATTR: | ||
1402 | return xfs_ioc_fssetxattr(ip, filp, arg); | ||
1403 | case XFS_IOC_GETXFLAGS: | ||
1404 | return xfs_ioc_getxflags(ip, arg); | ||
1405 | case XFS_IOC_SETXFLAGS: | ||
1406 | return xfs_ioc_setxflags(ip, filp, arg); | ||
1407 | |||
1408 | case XFS_IOC_FSSETDM: { | ||
1409 | struct fsdmidata dmi; | ||
1410 | |||
1411 | if (copy_from_user(&dmi, arg, sizeof(dmi))) | ||
1412 | return -XFS_ERROR(EFAULT); | ||
1413 | |||
1414 | error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, | ||
1415 | dmi.fsd_dmstate); | ||
1416 | return -error; | ||
1417 | } | ||
1418 | |||
1419 | case XFS_IOC_GETBMAP: | ||
1420 | case XFS_IOC_GETBMAPA: | ||
1421 | return xfs_ioc_getbmap(ip, ioflags, cmd, arg); | ||
1422 | |||
1423 | case XFS_IOC_GETBMAPX: | ||
1424 | return xfs_ioc_getbmapx(ip, arg); | ||
1425 | |||
1426 | case XFS_IOC_FD_TO_HANDLE: | ||
1427 | case XFS_IOC_PATH_TO_HANDLE: | ||
1428 | case XFS_IOC_PATH_TO_FSHANDLE: | ||
1429 | return xfs_find_handle(cmd, arg); | ||
1430 | |||
1431 | case XFS_IOC_OPEN_BY_HANDLE: | ||
1432 | return xfs_open_by_handle(mp, arg, filp, inode); | ||
1433 | |||
1434 | case XFS_IOC_FSSETDM_BY_HANDLE: | ||
1435 | return xfs_fssetdm_by_handle(mp, arg, inode); | ||
1436 | |||
1437 | case XFS_IOC_READLINK_BY_HANDLE: | ||
1438 | return xfs_readlink_by_handle(mp, arg, inode); | ||
1439 | |||
1440 | case XFS_IOC_ATTRLIST_BY_HANDLE: | ||
1441 | return xfs_attrlist_by_handle(mp, arg, inode); | ||
1442 | |||
1443 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | ||
1444 | return xfs_attrmulti_by_handle(mp, arg, inode); | ||
1445 | |||
1446 | case XFS_IOC_SWAPEXT: { | ||
1447 | error = xfs_swapext((struct xfs_swapext __user *)arg); | ||
1448 | return -error; | ||
1449 | } | ||
1450 | |||
1451 | case XFS_IOC_FSCOUNTS: { | ||
1452 | xfs_fsop_counts_t out; | ||
1453 | |||
1454 | error = xfs_fs_counts(mp, &out); | ||
1455 | if (error) | ||
1456 | return -error; | ||
1457 | |||
1458 | if (copy_to_user(arg, &out, sizeof(out))) | ||
1459 | return -XFS_ERROR(EFAULT); | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | case XFS_IOC_SET_RESBLKS: { | ||
1464 | xfs_fsop_resblks_t inout; | ||
1465 | __uint64_t in; | ||
1466 | |||
1467 | if (!capable(CAP_SYS_ADMIN)) | ||
1468 | return -EPERM; | ||
1469 | |||
1470 | if (copy_from_user(&inout, arg, sizeof(inout))) | ||
1471 | return -XFS_ERROR(EFAULT); | ||
1472 | |||
1473 | /* input parameter is passed in resblks field of structure */ | ||
1474 | in = inout.resblks; | ||
1475 | error = xfs_reserve_blocks(mp, &in, &inout); | ||
1476 | if (error) | ||
1477 | return -error; | ||
1478 | |||
1479 | if (copy_to_user(arg, &inout, sizeof(inout))) | ||
1480 | return -XFS_ERROR(EFAULT); | ||
1481 | return 0; | ||
1482 | } | ||
1483 | |||
1484 | case XFS_IOC_GET_RESBLKS: { | ||
1485 | xfs_fsop_resblks_t out; | ||
1486 | |||
1487 | if (!capable(CAP_SYS_ADMIN)) | ||
1488 | return -EPERM; | ||
1489 | |||
1490 | error = xfs_reserve_blocks(mp, NULL, &out); | ||
1491 | if (error) | ||
1492 | return -error; | ||
1493 | |||
1494 | if (copy_to_user(arg, &out, sizeof(out))) | ||
1495 | return -XFS_ERROR(EFAULT); | ||
1496 | |||
1497 | return 0; | ||
1498 | } | ||
1499 | |||
1500 | case XFS_IOC_FSGROWFSDATA: { | ||
1501 | xfs_growfs_data_t in; | ||
1502 | |||
1503 | if (!capable(CAP_SYS_ADMIN)) | ||
1504 | return -EPERM; | ||
1505 | |||
1506 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1507 | return -XFS_ERROR(EFAULT); | ||
1508 | |||
1509 | error = xfs_growfs_data(mp, &in); | ||
1510 | return -error; | ||
1511 | } | ||
1512 | |||
1513 | case XFS_IOC_FSGROWFSLOG: { | ||
1514 | xfs_growfs_log_t in; | ||
1515 | |||
1516 | if (!capable(CAP_SYS_ADMIN)) | ||
1517 | return -EPERM; | ||
1518 | |||
1519 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1520 | return -XFS_ERROR(EFAULT); | ||
1521 | |||
1522 | error = xfs_growfs_log(mp, &in); | ||
1523 | return -error; | ||
1524 | } | ||
1525 | |||
1526 | case XFS_IOC_FSGROWFSRT: { | ||
1527 | xfs_growfs_rt_t in; | ||
1528 | |||
1529 | if (!capable(CAP_SYS_ADMIN)) | ||
1530 | return -EPERM; | ||
1531 | |||
1532 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1533 | return -XFS_ERROR(EFAULT); | ||
1534 | |||
1535 | error = xfs_growfs_rt(mp, &in); | ||
1536 | return -error; | ||
1537 | } | ||
1538 | |||
1539 | case XFS_IOC_FREEZE: | ||
1540 | if (!capable(CAP_SYS_ADMIN)) | ||
1541 | return -EPERM; | ||
1542 | |||
1543 | if (inode->i_sb->s_frozen == SB_UNFROZEN) | ||
1544 | freeze_bdev(inode->i_sb->s_bdev); | ||
1545 | return 0; | ||
1546 | |||
1547 | case XFS_IOC_THAW: | ||
1548 | if (!capable(CAP_SYS_ADMIN)) | ||
1549 | return -EPERM; | ||
1550 | if (inode->i_sb->s_frozen != SB_UNFROZEN) | ||
1551 | thaw_bdev(inode->i_sb->s_bdev, inode->i_sb); | ||
1552 | return 0; | ||
1553 | |||
1554 | case XFS_IOC_GOINGDOWN: { | ||
1555 | __uint32_t in; | ||
1556 | |||
1557 | if (!capable(CAP_SYS_ADMIN)) | ||
1558 | return -EPERM; | ||
1559 | |||
1560 | if (get_user(in, (__uint32_t __user *)arg)) | ||
1561 | return -XFS_ERROR(EFAULT); | ||
1562 | |||
1563 | error = xfs_fs_goingdown(mp, in); | ||
1564 | return -error; | ||
1565 | } | ||
1566 | |||
1567 | case XFS_IOC_ERROR_INJECTION: { | ||
1568 | xfs_error_injection_t in; | ||
1569 | |||
1570 | if (!capable(CAP_SYS_ADMIN)) | ||
1571 | return -EPERM; | ||
1572 | |||
1573 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1574 | return -XFS_ERROR(EFAULT); | ||
1575 | |||
1576 | error = xfs_errortag_add(in.errtag, mp); | ||
1577 | return -error; | ||
1578 | } | ||
1579 | |||
1580 | case XFS_IOC_ERROR_CLEARALL: | ||
1581 | if (!capable(CAP_SYS_ADMIN)) | ||
1582 | return -EPERM; | ||
1583 | |||
1584 | error = xfs_errortag_clearall(mp, 1); | ||
1585 | return -error; | ||
1586 | |||
1587 | default: | ||
1588 | return -ENOTTY; | ||
1589 | } | ||
1590 | } | ||