diff options
author | Christoph Hellwig <hch@infradead.org> | 2013-10-12 03:55:08 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-10-21 17:57:03 -0400 |
commit | 865e9446b4c17f78be0b1387426394b6bfc278f3 (patch) | |
tree | 648e535bbeab231458a57d42bd8341afc53c492f | |
parent | 83aee9e4c2976143f35b3a42ad1faadf58c53ae7 (diff) |
xfs: fold xfs_change_file_space into xfs_ioc_space
Now that only one caller of xfs_change_file_space is left it can be merged
into said caller.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 178 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap_util.h | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 130 | ||||
-rw-r--r-- | fs/xfs/xfs_iops.h | 4 |
4 files changed, 126 insertions, 191 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 |
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 77cf5001719b..900747b25772 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h | |||
@@ -93,13 +93,12 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip, | |||
93 | int *is_empty); | 93 | int *is_empty); |
94 | 94 | ||
95 | /* preallocation and hole punch interface */ | 95 | /* preallocation and hole punch interface */ |
96 | int xfs_change_file_space(struct xfs_inode *ip, int cmd, | ||
97 | xfs_flock64_t *bf, xfs_off_t offset, | ||
98 | int attr_flags); | ||
99 | int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, | 96 | int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, |
100 | xfs_off_t len, int alloc_type); | 97 | xfs_off_t len, int alloc_type); |
101 | int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, | 98 | int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, |
102 | xfs_off_t len); | 99 | xfs_off_t len); |
100 | int xfs_zero_file_space(struct xfs_inode *ip, xfs_off_t offset, | ||
101 | xfs_off_t len); | ||
103 | 102 | ||
104 | /* EOF block manipulation functions */ | 103 | /* EOF block manipulation functions */ |
105 | bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); | 104 | bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 45287419dc37..e448d735346b 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -641,7 +641,11 @@ xfs_ioc_space( | |||
641 | unsigned int cmd, | 641 | unsigned int cmd, |
642 | xfs_flock64_t *bf) | 642 | xfs_flock64_t *bf) |
643 | { | 643 | { |
644 | int attr_flags = 0; | 644 | struct xfs_mount *mp = ip->i_mount; |
645 | struct xfs_trans *tp; | ||
646 | struct iattr iattr; | ||
647 | bool setprealloc = false; | ||
648 | bool clrprealloc = false; | ||
645 | int error; | 649 | int error; |
646 | 650 | ||
647 | /* | 651 | /* |
@@ -661,17 +665,127 @@ xfs_ioc_space( | |||
661 | if (!S_ISREG(inode->i_mode)) | 665 | if (!S_ISREG(inode->i_mode)) |
662 | return -XFS_ERROR(EINVAL); | 666 | return -XFS_ERROR(EINVAL); |
663 | 667 | ||
664 | if (filp->f_flags & O_DSYNC) | ||
665 | attr_flags |= XFS_ATTR_SYNC; | ||
666 | |||
667 | if (ioflags & IO_INVIS) | ||
668 | attr_flags |= XFS_ATTR_DMI; | ||
669 | |||
670 | error = mnt_want_write_file(filp); | 668 | error = mnt_want_write_file(filp); |
671 | if (error) | 669 | if (error) |
672 | return error; | 670 | return error; |
671 | |||
673 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 672 | xfs_ilock(ip, XFS_IOLOCK_EXCL); |
674 | error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); | 673 | |
674 | switch (bf->l_whence) { | ||
675 | case 0: /*SEEK_SET*/ | ||
676 | break; | ||
677 | case 1: /*SEEK_CUR*/ | ||
678 | bf->l_start += filp->f_pos; | ||
679 | break; | ||
680 | case 2: /*SEEK_END*/ | ||
681 | bf->l_start += XFS_ISIZE(ip); | ||
682 | break; | ||
683 | default: | ||
684 | error = XFS_ERROR(EINVAL); | ||
685 | goto out_unlock; | ||
686 | } | ||
687 | |||
688 | /* | ||
689 | * length of <= 0 for resv/unresv/zero is invalid. length for | ||
690 | * alloc/free is ignored completely and we have no idea what userspace | ||
691 | * might have set it to, so set it to zero to allow range | ||
692 | * checks to pass. | ||
693 | */ | ||
694 | switch (cmd) { | ||
695 | case XFS_IOC_ZERO_RANGE: | ||
696 | case XFS_IOC_RESVSP: | ||
697 | case XFS_IOC_RESVSP64: | ||
698 | case XFS_IOC_UNRESVSP: | ||
699 | case XFS_IOC_UNRESVSP64: | ||
700 | if (bf->l_len <= 0) { | ||
701 | error = XFS_ERROR(EINVAL); | ||
702 | goto out_unlock; | ||
703 | } | ||
704 | break; | ||
705 | default: | ||
706 | bf->l_len = 0; | ||
707 | break; | ||
708 | } | ||
709 | |||
710 | if (bf->l_start < 0 || | ||
711 | bf->l_start > mp->m_super->s_maxbytes || | ||
712 | bf->l_start + bf->l_len < 0 || | ||
713 | bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) { | ||
714 | error = XFS_ERROR(EINVAL); | ||
715 | goto out_unlock; | ||
716 | } | ||
717 | |||
718 | switch (cmd) { | ||
719 | case XFS_IOC_ZERO_RANGE: | ||
720 | error = xfs_zero_file_space(ip, bf->l_start, bf->l_len); | ||
721 | if (!error) | ||
722 | setprealloc = true; | ||
723 | break; | ||
724 | case XFS_IOC_RESVSP: | ||
725 | case XFS_IOC_RESVSP64: | ||
726 | error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len, | ||
727 | XFS_BMAPI_PREALLOC); | ||
728 | if (!error) | ||
729 | setprealloc = true; | ||
730 | break; | ||
731 | case XFS_IOC_UNRESVSP: | ||
732 | case XFS_IOC_UNRESVSP64: | ||
733 | error = xfs_free_file_space(ip, bf->l_start, bf->l_len); | ||
734 | break; | ||
735 | case XFS_IOC_ALLOCSP: | ||
736 | case XFS_IOC_ALLOCSP64: | ||
737 | case XFS_IOC_FREESP: | ||
738 | case XFS_IOC_FREESP64: | ||
739 | if (bf->l_start > XFS_ISIZE(ip)) { | ||
740 | error = xfs_alloc_file_space(ip, XFS_ISIZE(ip), | ||
741 | bf->l_start - XFS_ISIZE(ip), 0); | ||
742 | if (error) | ||
743 | goto out_unlock; | ||
744 | } | ||
745 | |||
746 | iattr.ia_valid = ATTR_SIZE; | ||
747 | iattr.ia_size = bf->l_start; | ||
748 | |||
749 | error = xfs_setattr_size(ip, &iattr); | ||
750 | if (!error) | ||
751 | clrprealloc = true; | ||
752 | break; | ||
753 | default: | ||
754 | ASSERT(0); | ||
755 | error = XFS_ERROR(EINVAL); | ||
756 | } | ||
757 | |||
758 | if (error) | ||
759 | goto out_unlock; | ||
760 | |||
761 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID); | ||
762 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0); | ||
763 | if (error) { | ||
764 | xfs_trans_cancel(tp, 0); | ||
765 | goto out_unlock; | ||
766 | } | ||
767 | |||
768 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
769 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
770 | |||
771 | if (!(ioflags & IO_INVIS)) { | ||
772 | ip->i_d.di_mode &= ~S_ISUID; | ||
773 | if (ip->i_d.di_mode & S_IXGRP) | ||
774 | ip->i_d.di_mode &= ~S_ISGID; | ||
775 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
776 | } | ||
777 | |||
778 | if (setprealloc) | ||
779 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | ||
780 | else if (clrprealloc) | ||
781 | ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; | ||
782 | |||
783 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
784 | if (filp->f_flags & O_DSYNC) | ||
785 | xfs_trans_set_sync(tp); | ||
786 | error = xfs_trans_commit(tp, 0); | ||
787 | |||
788 | out_unlock: | ||
675 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 789 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
676 | mnt_drop_write_file(filp); | 790 | mnt_drop_write_file(filp); |
677 | return -error; | 791 | return -error; |
diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index f3738253c69a..d2c5057b5cc4 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h | |||
@@ -30,9 +30,7 @@ extern void xfs_setup_inode(struct xfs_inode *); | |||
30 | /* | 30 | /* |
31 | * Internal setattr interfaces. | 31 | * Internal setattr interfaces. |
32 | */ | 32 | */ |
33 | #define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */ | 33 | #define XFS_ATTR_NOACL 0x01 /* Don't call xfs_acl_chmod */ |
34 | #define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */ | ||
35 | #define XFS_ATTR_SYNC 0x10 /* synchronous operation required */ | ||
36 | 34 | ||
37 | extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, | 35 | extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, |
38 | int flags); | 36 | int flags); |