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 = { |
