aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-07-13 16:22:22 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-07-13 16:22:22 -0400
commitffacfa7a79d6c00624196b2d13b0a7f72f2b8227 (patch)
tree201920b755aff4c8a196006c0ec5538235b7ee32 /fs/ext4
parentf91d1d04171026e56c7e343ee3cdcc801dd85cfb (diff)
ext4: Fix truncation of symlinks after failed write
Contents of long symlinks is written via standard write methods. So when the write fails, we add inode to orphan list. But symlinks don't have .truncate method defined so nobody properly removes them from the on disk orphan list. Fix this by calling ext4_truncate() directly instead of calling vmtruncate() (which is saner anyway since we don't need anything vmtruncate() does except from calling .truncate in these paths). We also add inode to orphan list only if ext4_can_truncate() is true (currently, it can be false for symlinks when there are no blocks allocated) - otherwise orphan list processing will complain and ext4_truncate() will not remove inode from on-disk orphan list. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/inode.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 9760ba09275e..ff2afc1909b3 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1513,14 +1513,14 @@ retry:
1513 * Add inode to orphan list in case we crash before 1513 * Add inode to orphan list in case we crash before
1514 * truncate finishes 1514 * truncate finishes
1515 */ 1515 */
1516 if (pos + len > inode->i_size) 1516 if (pos + len > inode->i_size && ext4_can_truncate(inode))
1517 ext4_orphan_add(handle, inode); 1517 ext4_orphan_add(handle, inode);
1518 1518
1519 ext4_journal_stop(handle); 1519 ext4_journal_stop(handle);
1520 if (pos + len > inode->i_size) { 1520 if (pos + len > inode->i_size) {
1521 vmtruncate(inode, inode->i_size); 1521 ext4_truncate(inode);
1522 /* 1522 /*
1523 * If vmtruncate failed early the inode might 1523 * If truncate failed early the inode might
1524 * still be on the orphan list; we need to 1524 * still be on the orphan list; we need to
1525 * make sure the inode is removed from the 1525 * make sure the inode is removed from the
1526 * orphan list in that case. 1526 * orphan list in that case.
@@ -1614,7 +1614,7 @@ static int ext4_ordered_write_end(struct file *file,
1614 ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, 1614 ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
1615 page, fsdata); 1615 page, fsdata);
1616 copied = ret2; 1616 copied = ret2;
1617 if (pos + len > inode->i_size) 1617 if (pos + len > inode->i_size && ext4_can_truncate(inode))
1618 /* if we have allocated more blocks and copied 1618 /* if we have allocated more blocks and copied
1619 * less. We will have blocks allocated outside 1619 * less. We will have blocks allocated outside
1620 * inode->i_size. So truncate them 1620 * inode->i_size. So truncate them
@@ -1628,9 +1628,9 @@ static int ext4_ordered_write_end(struct file *file,
1628 ret = ret2; 1628 ret = ret2;
1629 1629
1630 if (pos + len > inode->i_size) { 1630 if (pos + len > inode->i_size) {
1631 vmtruncate(inode, inode->i_size); 1631 ext4_truncate(inode);
1632 /* 1632 /*
1633 * If vmtruncate failed early the inode might still be 1633 * If truncate failed early the inode might still be
1634 * on the orphan list; we need to make sure the inode 1634 * on the orphan list; we need to make sure the inode
1635 * is removed from the orphan list in that case. 1635 * is removed from the orphan list in that case.
1636 */ 1636 */
@@ -1655,7 +1655,7 @@ static int ext4_writeback_write_end(struct file *file,
1655 ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, 1655 ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
1656 page, fsdata); 1656 page, fsdata);
1657 copied = ret2; 1657 copied = ret2;
1658 if (pos + len > inode->i_size) 1658 if (pos + len > inode->i_size && ext4_can_truncate(inode))
1659 /* if we have allocated more blocks and copied 1659 /* if we have allocated more blocks and copied
1660 * less. We will have blocks allocated outside 1660 * less. We will have blocks allocated outside
1661 * inode->i_size. So truncate them 1661 * inode->i_size. So truncate them
@@ -1670,9 +1670,9 @@ static int ext4_writeback_write_end(struct file *file,
1670 ret = ret2; 1670 ret = ret2;
1671 1671
1672 if (pos + len > inode->i_size) { 1672 if (pos + len > inode->i_size) {
1673 vmtruncate(inode, inode->i_size); 1673 ext4_truncate(inode);
1674 /* 1674 /*
1675 * If vmtruncate failed early the inode might still be 1675 * If truncate failed early the inode might still be
1676 * on the orphan list; we need to make sure the inode 1676 * on the orphan list; we need to make sure the inode
1677 * is removed from the orphan list in that case. 1677 * is removed from the orphan list in that case.
1678 */ 1678 */
@@ -1722,7 +1722,7 @@ static int ext4_journalled_write_end(struct file *file,
1722 1722
1723 unlock_page(page); 1723 unlock_page(page);
1724 page_cache_release(page); 1724 page_cache_release(page);
1725 if (pos + len > inode->i_size) 1725 if (pos + len > inode->i_size && ext4_can_truncate(inode))
1726 /* if we have allocated more blocks and copied 1726 /* if we have allocated more blocks and copied
1727 * less. We will have blocks allocated outside 1727 * less. We will have blocks allocated outside
1728 * inode->i_size. So truncate them 1728 * inode->i_size. So truncate them
@@ -1733,9 +1733,9 @@ static int ext4_journalled_write_end(struct file *file,
1733 if (!ret) 1733 if (!ret)
1734 ret = ret2; 1734 ret = ret2;
1735 if (pos + len > inode->i_size) { 1735 if (pos + len > inode->i_size) {
1736 vmtruncate(inode, inode->i_size); 1736 ext4_truncate(inode);
1737 /* 1737 /*
1738 * If vmtruncate failed early the inode might still be 1738 * If truncate failed early the inode might still be
1739 * on the orphan list; we need to make sure the inode 1739 * on the orphan list; we need to make sure the inode
1740 * is removed from the orphan list in that case. 1740 * is removed from the orphan list in that case.
1741 */ 1741 */
@@ -2907,7 +2907,7 @@ retry:
2907 * i_size_read because we hold i_mutex. 2907 * i_size_read because we hold i_mutex.
2908 */ 2908 */
2909 if (pos + len > inode->i_size) 2909 if (pos + len > inode->i_size)
2910 vmtruncate(inode, inode->i_size); 2910 ext4_truncate(inode);
2911 } 2911 }
2912 2912
2913 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 2913 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))