diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 53 |
1 files changed, 10 insertions, 43 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 1f09c7619319..5e2492535daa 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1557,57 +1557,24 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) | |||
1557 | 1557 | ||
1558 | static int cifs_vmtruncate(struct inode *inode, loff_t offset) | 1558 | static int cifs_vmtruncate(struct inode *inode, loff_t offset) |
1559 | { | 1559 | { |
1560 | struct address_space *mapping = inode->i_mapping; | 1560 | loff_t oldsize; |
1561 | unsigned long limit; | 1561 | int err; |
1562 | 1562 | ||
1563 | spin_lock(&inode->i_lock); | 1563 | spin_lock(&inode->i_lock); |
1564 | if (inode->i_size < offset) | 1564 | err = inode_newsize_ok(inode, offset); |
1565 | goto do_expand; | 1565 | if (err) { |
1566 | /* | ||
1567 | * truncation of in-use swapfiles is disallowed - it would cause | ||
1568 | * subsequent swapout to scribble on the now-freed blocks. | ||
1569 | */ | ||
1570 | if (IS_SWAPFILE(inode)) { | ||
1571 | spin_unlock(&inode->i_lock); | ||
1572 | goto out_busy; | ||
1573 | } | ||
1574 | i_size_write(inode, offset); | ||
1575 | spin_unlock(&inode->i_lock); | ||
1576 | /* | ||
1577 | * unmap_mapping_range is called twice, first simply for efficiency | ||
1578 | * so that truncate_inode_pages does fewer single-page unmaps. However | ||
1579 | * after this first call, and before truncate_inode_pages finishes, | ||
1580 | * it is possible for private pages to be COWed, which remain after | ||
1581 | * truncate_inode_pages finishes, hence the second unmap_mapping_range | ||
1582 | * call must be made for correctness. | ||
1583 | */ | ||
1584 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1585 | truncate_inode_pages(mapping, offset); | ||
1586 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1587 | goto out_truncate; | ||
1588 | |||
1589 | do_expand: | ||
1590 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | ||
1591 | if (limit != RLIM_INFINITY && offset > limit) { | ||
1592 | spin_unlock(&inode->i_lock); | 1566 | spin_unlock(&inode->i_lock); |
1593 | goto out_sig; | 1567 | goto out; |
1594 | } | ||
1595 | if (offset > inode->i_sb->s_maxbytes) { | ||
1596 | spin_unlock(&inode->i_lock); | ||
1597 | goto out_big; | ||
1598 | } | 1568 | } |
1569 | |||
1570 | oldsize = inode->i_size; | ||
1599 | i_size_write(inode, offset); | 1571 | i_size_write(inode, offset); |
1600 | spin_unlock(&inode->i_lock); | 1572 | spin_unlock(&inode->i_lock); |
1601 | out_truncate: | 1573 | truncate_pagecache(inode, oldsize, offset); |
1602 | if (inode->i_op->truncate) | 1574 | if (inode->i_op->truncate) |
1603 | inode->i_op->truncate(inode); | 1575 | inode->i_op->truncate(inode); |
1604 | return 0; | 1576 | out: |
1605 | out_sig: | 1577 | return err; |
1606 | send_sig(SIGXFSZ, current, 0); | ||
1607 | out_big: | ||
1608 | return -EFBIG; | ||
1609 | out_busy: | ||
1610 | return -ETXTBSY; | ||
1611 | } | 1578 | } |
1612 | 1579 | ||
1613 | static int | 1580 | static int |