Commit f745bb1c73e2395e6b9961d4d915a8f8e2cd32cd
Exists in
master
and in
20 other branches
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
fs/ocfs2/file.c
... | ... | @@ -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 = { |