aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/file.c77
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 */
1507int ocfs2_change_file_space(struct file *file, unsigned int cmd, 1508static 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
1643int 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
1665static 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
1649static int ocfs2_prepare_inode_for_write(struct dentry *dentry, 1689static 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
2317const struct inode_operations ocfs2_special_file_iops = { 2358const struct inode_operations ocfs2_special_file_iops = {