aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-10-12 03:55:08 -0400
committerBen Myers <bpm@sgi.com>2013-10-21 17:57:03 -0400
commit865e9446b4c17f78be0b1387426394b6bfc278f3 (patch)
tree648e535bbeab231458a57d42bd8341afc53c492f
parent83aee9e4c2976143f35b3a42ad1faadf58c53ae7 (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.c178
-rw-r--r--fs/xfs/xfs_bmap_util.h5
-rw-r--r--fs/xfs/xfs_ioctl.c130
-rw-r--r--fs/xfs/xfs_iops.h4
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
1388STATIC int 1388int
1389xfs_zero_file_space( 1389xfs_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 */
1459int
1460xfs_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 */
96int xfs_change_file_space(struct xfs_inode *ip, int cmd,
97 xfs_flock64_t *bf, xfs_off_t offset,
98 int attr_flags);
99int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, 96int 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);
101int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, 98int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset,
102 xfs_off_t len); 99 xfs_off_t len);
100int 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 */
105bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); 104bool 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
788out_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
37extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, 35extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap,
38 int flags); 36 int flags);