diff options
-rw-r--r-- | fs/ocfs2/file.c | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 004c2abbc732..5727cd18302a 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/splice.h> | 34 | #include <linux/splice.h> |
35 | #include <linux/mount.h> | 35 | #include <linux/mount.h> |
36 | #include <linux/writeback.h> | 36 | #include <linux/writeback.h> |
37 | #include <linux/falloc.h> | ||
37 | 38 | ||
38 | #define MLOG_MASK_PREFIX ML_INODE | 39 | #define MLOG_MASK_PREFIX ML_INODE |
39 | #include <cluster/masklog.h> | 40 | #include <cluster/masklog.h> |
@@ -1504,30 +1505,19 @@ out: | |||
1504 | /* | 1505 | /* |
1505 | * Parts of this function taken from xfs_change_file_space() | 1506 | * Parts of this function taken from xfs_change_file_space() |
1506 | */ | 1507 | */ |
1507 | int ocfs2_change_file_space(struct file *file, unsigned int cmd, | 1508 | static int __ocfs2_change_file_space(struct file *file, struct inode *inode, |
1508 | struct ocfs2_space_resv *sr) | 1509 | loff_t f_pos, unsigned int cmd, |
1510 | struct ocfs2_space_resv *sr, | ||
1511 | int change_size) | ||
1509 | { | 1512 | { |
1510 | int ret; | 1513 | int ret; |
1511 | s64 llen; | 1514 | s64 llen; |
1512 | struct inode *inode = file->f_path.dentry->d_inode; | 1515 | loff_t size; |
1513 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1516 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
1514 | struct buffer_head *di_bh = NULL; | 1517 | struct buffer_head *di_bh = NULL; |
1515 | handle_t *handle; | 1518 | handle_t *handle; |
1516 | unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits); | 1519 | unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits); |
1517 | 1520 | ||
1518 | if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && | ||
1519 | !ocfs2_writes_unwritten_extents(osb)) | ||
1520 | return -ENOTTY; | ||
1521 | else if ((cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) && | ||
1522 | !ocfs2_sparse_alloc(osb)) | ||
1523 | return -ENOTTY; | ||
1524 | |||
1525 | if (!S_ISREG(inode->i_mode)) | ||
1526 | return -EINVAL; | ||
1527 | |||
1528 | if (!(file->f_mode & FMODE_WRITE)) | ||
1529 | return -EBADF; | ||
1530 | |||
1531 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) | 1521 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) |
1532 | return -EROFS; | 1522 | return -EROFS; |
1533 | 1523 | ||
@@ -1557,7 +1547,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, | |||
1557 | case 0: /*SEEK_SET*/ | 1547 | case 0: /*SEEK_SET*/ |
1558 | break; | 1548 | break; |
1559 | case 1: /*SEEK_CUR*/ | 1549 | case 1: /*SEEK_CUR*/ |
1560 | sr->l_start += file->f_pos; | 1550 | sr->l_start += f_pos; |
1561 | break; | 1551 | break; |
1562 | case 2: /*SEEK_END*/ | 1552 | case 2: /*SEEK_END*/ |
1563 | sr->l_start += i_size_read(inode); | 1553 | sr->l_start += i_size_read(inode); |
@@ -1577,6 +1567,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, | |||
1577 | ret = -EINVAL; | 1567 | ret = -EINVAL; |
1578 | goto out_meta_unlock; | 1568 | goto out_meta_unlock; |
1579 | } | 1569 | } |
1570 | size = sr->l_start + sr->l_len; | ||
1580 | 1571 | ||
1581 | if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) { | 1572 | if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) { |
1582 | if (sr->l_len <= 0) { | 1573 | if (sr->l_len <= 0) { |
@@ -1585,7 +1576,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, | |||
1585 | } | 1576 | } |
1586 | } | 1577 | } |
1587 | 1578 | ||
1588 | if (should_remove_suid(file->f_path.dentry)) { | 1579 | if (file && should_remove_suid(file->f_path.dentry)) { |
1589 | ret = __ocfs2_write_remove_suid(inode, di_bh); | 1580 | ret = __ocfs2_write_remove_suid(inode, di_bh); |
1590 | if (ret) { | 1581 | if (ret) { |
1591 | mlog_errno(ret); | 1582 | mlog_errno(ret); |
@@ -1628,6 +1619,9 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, | |||
1628 | goto out_meta_unlock; | 1619 | goto out_meta_unlock; |
1629 | } | 1620 | } |
1630 | 1621 | ||
1622 | if (change_size && i_size_read(inode) < size) | ||
1623 | i_size_write(inode, size); | ||
1624 | |||
1631 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | 1625 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; |
1632 | ret = ocfs2_mark_inode_dirty(handle, inode, di_bh); | 1626 | ret = ocfs2_mark_inode_dirty(handle, inode, di_bh); |
1633 | if (ret < 0) | 1627 | if (ret < 0) |
@@ -1646,6 +1640,52 @@ out: | |||
1646 | return ret; | 1640 | return ret; |
1647 | } | 1641 | } |
1648 | 1642 | ||
1643 | int ocfs2_change_file_space(struct file *file, unsigned int cmd, | ||
1644 | struct ocfs2_space_resv *sr) | ||
1645 | { | ||
1646 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1647 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);; | ||
1648 | |||
1649 | if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && | ||
1650 | !ocfs2_writes_unwritten_extents(osb)) | ||
1651 | return -ENOTTY; | ||
1652 | else if ((cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) && | ||
1653 | !ocfs2_sparse_alloc(osb)) | ||
1654 | return -ENOTTY; | ||
1655 | |||
1656 | if (!S_ISREG(inode->i_mode)) | ||
1657 | return -EINVAL; | ||
1658 | |||
1659 | if (!(file->f_mode & FMODE_WRITE)) | ||
1660 | return -EBADF; | ||
1661 | |||
1662 | return __ocfs2_change_file_space(file, inode, file->f_pos, cmd, sr, 0); | ||
1663 | } | ||
1664 | |||
1665 | static long ocfs2_fallocate(struct inode *inode, int mode, loff_t offset, | ||
1666 | loff_t len) | ||
1667 | { | ||
1668 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1669 | struct ocfs2_space_resv sr; | ||
1670 | int change_size = 1; | ||
1671 | |||
1672 | if (!ocfs2_writes_unwritten_extents(osb)) | ||
1673 | return -EOPNOTSUPP; | ||
1674 | |||
1675 | if (S_ISDIR(inode->i_mode)) | ||
1676 | return -ENODEV; | ||
1677 | |||
1678 | if (mode & FALLOC_FL_KEEP_SIZE) | ||
1679 | change_size = 0; | ||
1680 | |||
1681 | sr.l_whence = 0; | ||
1682 | sr.l_start = (s64)offset; | ||
1683 | sr.l_len = (s64)len; | ||
1684 | |||
1685 | return __ocfs2_change_file_space(NULL, inode, offset, | ||
1686 | OCFS2_IOC_RESVSP64, &sr, change_size); | ||
1687 | } | ||
1688 | |||
1649 | static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | 1689 | static int ocfs2_prepare_inode_for_write(struct dentry *dentry, |
1650 | loff_t *ppos, | 1690 | loff_t *ppos, |
1651 | size_t count, | 1691 | size_t count, |
@@ -2312,6 +2352,7 @@ const struct inode_operations ocfs2_file_iops = { | |||
2312 | .setattr = ocfs2_setattr, | 2352 | .setattr = ocfs2_setattr, |
2313 | .getattr = ocfs2_getattr, | 2353 | .getattr = ocfs2_getattr, |
2314 | .permission = ocfs2_permission, | 2354 | .permission = ocfs2_permission, |
2355 | .fallocate = ocfs2_fallocate, | ||
2315 | }; | 2356 | }; |
2316 | 2357 | ||
2317 | const struct inode_operations ocfs2_special_file_iops = { | 2358 | const struct inode_operations ocfs2_special_file_iops = { |