Commit f745bb1c73e2395e6b9961d4d915a8f8e2cd32cd

Authored by Linus Torvalds

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2:
  ocfs2: ->fallocate() support

Showing 1 changed file Side-by-side Diff

... ... @@ -34,6 +34,7 @@
34 34 #include <linux/splice.h>
35 35 #include <linux/mount.h>
36 36 #include <linux/writeback.h>
  37 +#include <linux/falloc.h>
37 38  
38 39 #define MLOG_MASK_PREFIX ML_INODE
39 40 #include <cluster/masklog.h>
40 41  
41 42  
... ... @@ -1504,30 +1505,19 @@
1504 1505 /*
1505 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   - struct ocfs2_space_resv *sr)
  1508 +static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
  1509 + loff_t f_pos, unsigned int cmd,
  1510 + struct ocfs2_space_resv *sr,
  1511 + int change_size)
1509 1512 {
1510 1513 int ret;
1511 1514 s64 llen;
1512   - struct inode *inode = file->f_path.dentry->d_inode;
  1515 + loff_t size;
1513 1516 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1514 1517 struct buffer_head *di_bh = NULL;
1515 1518 handle_t *handle;
1516 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 1521 if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
1532 1522 return -EROFS;
1533 1523  
... ... @@ -1557,7 +1547,7 @@
1557 1547 case 0: /*SEEK_SET*/
1558 1548 break;
1559 1549 case 1: /*SEEK_CUR*/
1560   - sr->l_start += file->f_pos;
  1550 + sr->l_start += f_pos;
1561 1551 break;
1562 1552 case 2: /*SEEK_END*/
1563 1553 sr->l_start += i_size_read(inode);
... ... @@ -1577,6 +1567,7 @@
1577 1567 ret = -EINVAL;
1578 1568 goto out_meta_unlock;
1579 1569 }
  1570 + size = sr->l_start + sr->l_len;
1580 1571  
1581 1572 if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) {
1582 1573 if (sr->l_len <= 0) {
... ... @@ -1585,7 +1576,7 @@
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 1580 ret = __ocfs2_write_remove_suid(inode, di_bh);
1590 1581 if (ret) {
1591 1582 mlog_errno(ret);
... ... @@ -1628,6 +1619,9 @@
1628 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 1625 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
1632 1626 ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
1633 1627 if (ret < 0)
... ... @@ -1646,6 +1640,52 @@
1646 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 1689 static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
1650 1690 loff_t *ppos,
1651 1691 size_t count,
... ... @@ -2312,6 +2352,7 @@
2312 2352 .setattr = ocfs2_setattr,
2313 2353 .getattr = ocfs2_getattr,
2314 2354 .permission = ocfs2_permission,
  2355 + .fallocate = ocfs2_fallocate,
2315 2356 };
2316 2357  
2317 2358 const struct inode_operations ocfs2_special_file_iops = {