Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+59 -18
+59 -18
fs/ocfs2/file.c
··· 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> ··· 1505 1504 /* 1506 1505 * Parts of this function taken from xfs_change_file_space() 1507 1506 */ 1508 - int ocfs2_change_file_space(struct file *file, unsigned int cmd, 1509 - struct ocfs2_space_resv *sr) 1507 + static int __ocfs2_change_file_space(struct file *file, struct inode *inode, 1508 + loff_t f_pos, unsigned int cmd, 1509 + struct ocfs2_space_resv *sr, 1510 + int change_size) 1510 1511 { 1511 1512 int ret; 1512 1513 s64 llen; 1513 - struct inode *inode = file->f_path.dentry->d_inode; 1514 + loff_t size; 1514 1515 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 1515 1516 struct buffer_head *di_bh = NULL; 1516 1517 handle_t *handle; 1517 1518 unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits); 1518 - 1519 - if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && 1520 - !ocfs2_writes_unwritten_extents(osb)) 1521 - return -ENOTTY; 1522 - else if ((cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) && 1523 - !ocfs2_sparse_alloc(osb)) 1524 - return -ENOTTY; 1525 - 1526 - if (!S_ISREG(inode->i_mode)) 1527 - return -EINVAL; 1528 - 1529 - if (!(file->f_mode & FMODE_WRITE)) 1530 - return -EBADF; 1531 1519 1532 1520 if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) 1533 1521 return -EROFS; ··· 1547 1557 case 0: /*SEEK_SET*/ 1548 1558 break; 1549 1559 case 1: /*SEEK_CUR*/ 1550 - sr->l_start += file->f_pos; 1560 + sr->l_start += f_pos; 1551 1561 break; 1552 1562 case 2: /*SEEK_END*/ 1553 1563 sr->l_start += i_size_read(inode); ··· 1567 1577 ret = -EINVAL; 1568 1578 goto out_meta_unlock; 1569 1579 } 1580 + size = sr->l_start + sr->l_len; 1570 1581 1571 1582 if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) { 1572 1583 if (sr->l_len <= 0) { ··· 1576 1585 } 1577 1586 } 1578 1587 1579 - if (should_remove_suid(file->f_path.dentry)) { 1588 + if (file && should_remove_suid(file->f_path.dentry)) { 1580 1589 ret = __ocfs2_write_remove_suid(inode, di_bh); 1581 1590 if (ret) { 1582 1591 mlog_errno(ret); ··· 1619 1628 goto out_meta_unlock; 1620 1629 } 1621 1630 1631 + if (change_size && i_size_read(inode) < size) 1632 + i_size_write(inode, size); 1633 + 1622 1634 inode->i_ctime = inode->i_mtime = CURRENT_TIME; 1623 1635 ret = ocfs2_mark_inode_dirty(handle, inode, di_bh); 1624 1636 if (ret < 0) ··· 1638 1644 mutex_unlock(&inode->i_mutex); 1639 1645 out: 1640 1646 return ret; 1647 + } 1648 + 1649 + int ocfs2_change_file_space(struct file *file, unsigned int cmd, 1650 + struct ocfs2_space_resv *sr) 1651 + { 1652 + struct inode *inode = file->f_path.dentry->d_inode; 1653 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);; 1654 + 1655 + if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && 1656 + !ocfs2_writes_unwritten_extents(osb)) 1657 + return -ENOTTY; 1658 + else if ((cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) && 1659 + !ocfs2_sparse_alloc(osb)) 1660 + return -ENOTTY; 1661 + 1662 + if (!S_ISREG(inode->i_mode)) 1663 + return -EINVAL; 1664 + 1665 + if (!(file->f_mode & FMODE_WRITE)) 1666 + return -EBADF; 1667 + 1668 + return __ocfs2_change_file_space(file, inode, file->f_pos, cmd, sr, 0); 1669 + } 1670 + 1671 + static long ocfs2_fallocate(struct inode *inode, int mode, loff_t offset, 1672 + loff_t len) 1673 + { 1674 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 1675 + struct ocfs2_space_resv sr; 1676 + int change_size = 1; 1677 + 1678 + if (!ocfs2_writes_unwritten_extents(osb)) 1679 + return -EOPNOTSUPP; 1680 + 1681 + if (S_ISDIR(inode->i_mode)) 1682 + return -ENODEV; 1683 + 1684 + if (mode & FALLOC_FL_KEEP_SIZE) 1685 + change_size = 0; 1686 + 1687 + sr.l_whence = 0; 1688 + sr.l_start = (s64)offset; 1689 + sr.l_len = (s64)len; 1690 + 1691 + return __ocfs2_change_file_space(NULL, inode, offset, 1692 + OCFS2_IOC_RESVSP64, &sr, change_size); 1641 1693 } 1642 1694 1643 1695 static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ··· 2352 2312 .setattr = ocfs2_setattr, 2353 2313 .getattr = ocfs2_getattr, 2354 2314 .permission = ocfs2_permission, 2315 + .fallocate = ocfs2_fallocate, 2355 2316 }; 2356 2317 2357 2318 const struct inode_operations ocfs2_special_file_iops = {