diff options
Diffstat (limited to 'fs/xfs/xfs_bmap_util.c')
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 178 |
1 files changed, 1 insertions, 177 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 7e1c2ae81c35..45cf5a2fd1bf 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -1385,7 +1385,7 @@ xfs_free_file_space( | |||
1385 | } | 1385 | } |
1386 | 1386 | ||
1387 | 1387 | ||
1388 | STATIC int | 1388 | int |
1389 | xfs_zero_file_space( | 1389 | xfs_zero_file_space( |
1390 | struct xfs_inode *ip, | 1390 | struct xfs_inode *ip, |
1391 | xfs_off_t offset, | 1391 | xfs_off_t offset, |
@@ -1446,182 +1446,6 @@ out: | |||
1446 | } | 1446 | } |
1447 | 1447 | ||
1448 | /* | 1448 | /* |
1449 | * xfs_change_file_space() | ||
1450 | * This routine allocates or frees disk space for the given file. | ||
1451 | * The user specified parameters are checked for alignment and size | ||
1452 | * limitations. | ||
1453 | * | ||
1454 | * RETURNS: | ||
1455 | * 0 on success | ||
1456 | * errno on error | ||
1457 | * | ||
1458 | */ | ||
1459 | int | ||
1460 | xfs_change_file_space( | ||
1461 | xfs_inode_t *ip, | ||
1462 | int cmd, | ||
1463 | xfs_flock64_t *bf, | ||
1464 | xfs_off_t offset, | ||
1465 | int attr_flags) | ||
1466 | { | ||
1467 | xfs_mount_t *mp = ip->i_mount; | ||
1468 | int clrprealloc; | ||
1469 | int error; | ||
1470 | xfs_fsize_t fsize; | ||
1471 | int setprealloc; | ||
1472 | xfs_off_t startoffset; | ||
1473 | xfs_trans_t *tp; | ||
1474 | struct iattr iattr; | ||
1475 | |||
1476 | if (!S_ISREG(ip->i_d.di_mode)) | ||
1477 | return XFS_ERROR(EINVAL); | ||
1478 | |||
1479 | switch (bf->l_whence) { | ||
1480 | case 0: /*SEEK_SET*/ | ||
1481 | break; | ||
1482 | case 1: /*SEEK_CUR*/ | ||
1483 | bf->l_start += offset; | ||
1484 | break; | ||
1485 | case 2: /*SEEK_END*/ | ||
1486 | bf->l_start += XFS_ISIZE(ip); | ||
1487 | break; | ||
1488 | default: | ||
1489 | return XFS_ERROR(EINVAL); | ||
1490 | } | ||
1491 | |||
1492 | /* | ||
1493 | * length of <= 0 for resv/unresv/zero is invalid. length for | ||
1494 | * alloc/free is ignored completely and we have no idea what userspace | ||
1495 | * might have set it to, so set it to zero to allow range | ||
1496 | * checks to pass. | ||
1497 | */ | ||
1498 | switch (cmd) { | ||
1499 | case XFS_IOC_ZERO_RANGE: | ||
1500 | case XFS_IOC_RESVSP: | ||
1501 | case XFS_IOC_RESVSP64: | ||
1502 | case XFS_IOC_UNRESVSP: | ||
1503 | case XFS_IOC_UNRESVSP64: | ||
1504 | if (bf->l_len <= 0) | ||
1505 | return XFS_ERROR(EINVAL); | ||
1506 | break; | ||
1507 | default: | ||
1508 | bf->l_len = 0; | ||
1509 | break; | ||
1510 | } | ||
1511 | |||
1512 | if (bf->l_start < 0 || | ||
1513 | bf->l_start > mp->m_super->s_maxbytes || | ||
1514 | bf->l_start + bf->l_len < 0 || | ||
1515 | bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) | ||
1516 | return XFS_ERROR(EINVAL); | ||
1517 | |||
1518 | bf->l_whence = 0; | ||
1519 | |||
1520 | startoffset = bf->l_start; | ||
1521 | fsize = XFS_ISIZE(ip); | ||
1522 | |||
1523 | setprealloc = clrprealloc = 0; | ||
1524 | switch (cmd) { | ||
1525 | case XFS_IOC_ZERO_RANGE: | ||
1526 | error = xfs_zero_file_space(ip, startoffset, bf->l_len); | ||
1527 | if (error) | ||
1528 | return error; | ||
1529 | setprealloc = 1; | ||
1530 | break; | ||
1531 | |||
1532 | case XFS_IOC_RESVSP: | ||
1533 | case XFS_IOC_RESVSP64: | ||
1534 | error = xfs_alloc_file_space(ip, startoffset, bf->l_len, | ||
1535 | XFS_BMAPI_PREALLOC); | ||
1536 | if (error) | ||
1537 | return error; | ||
1538 | setprealloc = 1; | ||
1539 | break; | ||
1540 | |||
1541 | case XFS_IOC_UNRESVSP: | ||
1542 | case XFS_IOC_UNRESVSP64: | ||
1543 | error = xfs_free_file_space(ip, startoffset, bf->l_len); | ||
1544 | if (error) | ||
1545 | return error; | ||
1546 | break; | ||
1547 | |||
1548 | case XFS_IOC_ALLOCSP: | ||
1549 | case XFS_IOC_ALLOCSP64: | ||
1550 | case XFS_IOC_FREESP: | ||
1551 | case XFS_IOC_FREESP64: | ||
1552 | /* | ||
1553 | * These operations actually do IO when extending the file, but | ||
1554 | * the allocation is done seperately to the zeroing that is | ||
1555 | * done. This set of operations need to be serialised against | ||
1556 | * other IO operations, such as truncate and buffered IO. We | ||
1557 | * need to take the IOLOCK here to serialise the allocation and | ||
1558 | * zeroing IO to prevent other IOLOCK holders (e.g. getbmap, | ||
1559 | * truncate, direct IO) from racing against the transient | ||
1560 | * allocated but not written state we can have here. | ||
1561 | */ | ||
1562 | if (startoffset > fsize) { | ||
1563 | error = xfs_alloc_file_space(ip, fsize, | ||
1564 | startoffset - fsize, 0); | ||
1565 | if (error) | ||
1566 | break; | ||
1567 | } | ||
1568 | |||
1569 | iattr.ia_valid = ATTR_SIZE; | ||
1570 | iattr.ia_size = startoffset; | ||
1571 | |||
1572 | error = xfs_setattr_size(ip, &iattr); | ||
1573 | |||
1574 | if (error) | ||
1575 | return error; | ||
1576 | |||
1577 | clrprealloc = 1; | ||
1578 | break; | ||
1579 | |||
1580 | default: | ||
1581 | ASSERT(0); | ||
1582 | return XFS_ERROR(EINVAL); | ||
1583 | } | ||
1584 | |||
1585 | /* | ||
1586 | * update the inode timestamp, mode, and prealloc flag bits | ||
1587 | */ | ||
1588 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID); | ||
1589 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0); | ||
1590 | if (error) { | ||
1591 | xfs_trans_cancel(tp, 0); | ||
1592 | return error; | ||
1593 | } | ||
1594 | |||
1595 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
1596 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
1597 | |||
1598 | if ((attr_flags & XFS_ATTR_DMI) == 0) { | ||
1599 | ip->i_d.di_mode &= ~S_ISUID; | ||
1600 | |||
1601 | /* | ||
1602 | * Note that we don't have to worry about mandatory | ||
1603 | * file locking being disabled here because we only | ||
1604 | * clear the S_ISGID bit if the Group execute bit is | ||
1605 | * on, but if it was on then mandatory locking wouldn't | ||
1606 | * have been enabled. | ||
1607 | */ | ||
1608 | if (ip->i_d.di_mode & S_IXGRP) | ||
1609 | ip->i_d.di_mode &= ~S_ISGID; | ||
1610 | |||
1611 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
1612 | } | ||
1613 | if (setprealloc) | ||
1614 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | ||
1615 | else if (clrprealloc) | ||
1616 | ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; | ||
1617 | |||
1618 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
1619 | if (attr_flags & XFS_ATTR_SYNC) | ||
1620 | xfs_trans_set_sync(tp); | ||
1621 | return xfs_trans_commit(tp, 0); | ||
1622 | } | ||
1623 | |||
1624 | /* | ||
1625 | * We need to check that the format of the data fork in the temporary inode is | 1449 | * We need to check that the format of the data fork in the temporary inode is |
1626 | * valid for the target inode before doing the swap. This is not a problem with | 1450 | * valid for the target inode before doing the swap. This is not a problem with |
1627 | * attr1 because of the fixed fork offset, but attr2 has a dynamically sized | 1451 | * attr1 because of the fixed fork offset, but attr2 has a dynamically sized |