diff options
| -rw-r--r-- | fs/buffer.c | 10 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 53 | ||||
| -rw-r--r-- | fs/fuse/dir.c | 14 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 2 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 11 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 54 | ||||
| -rw-r--r-- | fs/ramfs/file-nommu.c | 18 |
7 files changed, 35 insertions, 127 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 209f7f15f5f8..24afd7422ae8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -2239,16 +2239,10 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size) | |||
| 2239 | struct address_space *mapping = inode->i_mapping; | 2239 | struct address_space *mapping = inode->i_mapping; |
| 2240 | struct page *page; | 2240 | struct page *page; |
| 2241 | void *fsdata; | 2241 | void *fsdata; |
| 2242 | unsigned long limit; | ||
| 2243 | int err; | 2242 | int err; |
| 2244 | 2243 | ||
| 2245 | err = -EFBIG; | 2244 | err = inode_newsize_ok(inode, size); |
| 2246 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | 2245 | if (err) |
| 2247 | if (limit != RLIM_INFINITY && size > (loff_t)limit) { | ||
| 2248 | send_sig(SIGXFSZ, current, 0); | ||
| 2249 | goto out; | ||
| 2250 | } | ||
| 2251 | if (size > inode->i_sb->s_maxbytes) | ||
| 2252 | goto out; | 2246 | goto out; |
| 2253 | 2247 | ||
| 2254 | err = pagecache_write_begin(NULL, mapping, size, 0, | 2248 | err = pagecache_write_begin(NULL, mapping, size, 0, |
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 |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e703654e7f40..992f6c9410bb 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -1276,14 +1276,9 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | |||
| 1276 | return 0; | 1276 | return 0; |
| 1277 | 1277 | ||
| 1278 | if (attr->ia_valid & ATTR_SIZE) { | 1278 | if (attr->ia_valid & ATTR_SIZE) { |
| 1279 | unsigned long limit; | 1279 | err = inode_newsize_ok(inode, attr->ia_size); |
| 1280 | if (IS_SWAPFILE(inode)) | 1280 | if (err) |
| 1281 | return -ETXTBSY; | 1281 | return err; |
| 1282 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | ||
| 1283 | if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) { | ||
| 1284 | send_sig(SIGXFSZ, current, 0); | ||
| 1285 | return -EFBIG; | ||
| 1286 | } | ||
| 1287 | is_truncate = true; | 1282 | is_truncate = true; |
| 1288 | } | 1283 | } |
| 1289 | 1284 | ||
| @@ -1350,8 +1345,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | |||
| 1350 | * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. | 1345 | * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. |
| 1351 | */ | 1346 | */ |
| 1352 | if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { | 1347 | if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { |
| 1353 | if (outarg.attr.size < oldsize) | 1348 | truncate_pagecache(inode, oldsize, outarg.attr.size); |
| 1354 | fuse_truncate(inode->i_mapping, outarg.attr.size); | ||
| 1355 | invalidate_inode_pages2(inode->i_mapping); | 1349 | invalidate_inode_pages2(inode->i_mapping); |
| 1356 | } | 1350 | } |
| 1357 | 1351 | ||
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index fc9c79feb5f7..01cc462ff45d 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -606,8 +606,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
| 606 | void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | 606 | void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, |
| 607 | u64 attr_valid); | 607 | u64 attr_valid); |
| 608 | 608 | ||
| 609 | void fuse_truncate(struct address_space *mapping, loff_t offset); | ||
| 610 | |||
| 611 | /** | 609 | /** |
| 612 | * Initialize the client device | 610 | * Initialize the client device |
| 613 | */ | 611 | */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 6da947daabda..1a822ce2b24b 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -140,14 +140,6 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) | |||
| 140 | return 0; | 140 | return 0; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | void fuse_truncate(struct address_space *mapping, loff_t offset) | ||
| 144 | { | ||
| 145 | /* See vmtruncate() */ | ||
| 146 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
| 147 | truncate_inode_pages(mapping, offset); | ||
| 148 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
| 149 | } | ||
| 150 | |||
| 151 | void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | 143 | void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, |
| 152 | u64 attr_valid) | 144 | u64 attr_valid) |
| 153 | { | 145 | { |
| @@ -205,8 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
| 205 | spin_unlock(&fc->lock); | 197 | spin_unlock(&fc->lock); |
| 206 | 198 | ||
| 207 | if (S_ISREG(inode->i_mode) && oldsize != attr->size) { | 199 | if (S_ISREG(inode->i_mode) && oldsize != attr->size) { |
| 208 | if (attr->size < oldsize) | 200 | truncate_pagecache(inode, oldsize, attr->size); |
| 209 | fuse_truncate(inode->i_mapping, attr->size); | ||
| 210 | invalidate_inode_pages2(inode->i_mapping); | 201 | invalidate_inode_pages2(inode->i_mapping); |
| 211 | } | 202 | } |
| 212 | } | 203 | } |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 060022b4651c..faa091865ad0 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -458,49 +458,21 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 458 | */ | 458 | */ |
| 459 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) | 459 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) |
| 460 | { | 460 | { |
| 461 | if (i_size_read(inode) < offset) { | 461 | loff_t oldsize; |
| 462 | unsigned long limit; | 462 | int err; |
| 463 | |||
| 464 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | ||
| 465 | if (limit != RLIM_INFINITY && offset > limit) | ||
| 466 | goto out_sig; | ||
| 467 | if (offset > inode->i_sb->s_maxbytes) | ||
| 468 | goto out_big; | ||
| 469 | spin_lock(&inode->i_lock); | ||
| 470 | i_size_write(inode, offset); | ||
| 471 | spin_unlock(&inode->i_lock); | ||
| 472 | } else { | ||
| 473 | struct address_space *mapping = inode->i_mapping; | ||
| 474 | 463 | ||
| 475 | /* | 464 | err = inode_newsize_ok(inode, offset); |
| 476 | * truncation of in-use swapfiles is disallowed - it would | 465 | if (err) |
| 477 | * cause subsequent swapout to scribble on the now-freed | 466 | goto out; |
| 478 | * blocks. | ||
| 479 | */ | ||
| 480 | if (IS_SWAPFILE(inode)) | ||
| 481 | return -ETXTBSY; | ||
| 482 | spin_lock(&inode->i_lock); | ||
| 483 | i_size_write(inode, offset); | ||
| 484 | spin_unlock(&inode->i_lock); | ||
| 485 | 467 | ||
| 486 | /* | 468 | spin_lock(&inode->i_lock); |
| 487 | * unmap_mapping_range is called twice, first simply for | 469 | oldsize = inode->i_size; |
| 488 | * efficiency so that truncate_inode_pages does fewer | 470 | i_size_write(inode, offset); |
| 489 | * single-page unmaps. However after this first call, and | 471 | spin_unlock(&inode->i_lock); |
| 490 | * before truncate_inode_pages finishes, it is possible for | 472 | |
| 491 | * private pages to be COWed, which remain after | 473 | truncate_pagecache(inode, oldsize, offset); |
| 492 | * truncate_inode_pages finishes, hence the second | 474 | out: |
| 493 | * unmap_mapping_range call must be made for correctness. | 475 | return err; |
| 494 | */ | ||
| 495 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
| 496 | truncate_inode_pages(mapping, offset); | ||
| 497 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
| 498 | } | ||
| 499 | return 0; | ||
| 500 | out_sig: | ||
| 501 | send_sig(SIGXFSZ, current, 0); | ||
| 502 | out_big: | ||
| 503 | return -EFBIG; | ||
| 504 | } | 476 | } |
| 505 | 477 | ||
| 506 | /** | 478 | /** |
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 11f0c06316de..32fae4040ebf 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
| @@ -69,14 +69,11 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) | |||
| 69 | /* make various checks */ | 69 | /* make various checks */ |
| 70 | order = get_order(newsize); | 70 | order = get_order(newsize); |
| 71 | if (unlikely(order >= MAX_ORDER)) | 71 | if (unlikely(order >= MAX_ORDER)) |
| 72 | goto too_big; | 72 | return -EFBIG; |
| 73 | 73 | ||
| 74 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | 74 | ret = inode_newsize_ok(inode, newsize); |
| 75 | if (limit != RLIM_INFINITY && newsize > limit) | 75 | if (ret) |
| 76 | goto fsize_exceeded; | 76 | return ret; |
| 77 | |||
| 78 | if (newsize > inode->i_sb->s_maxbytes) | ||
| 79 | goto too_big; | ||
| 80 | 77 | ||
| 81 | i_size_write(inode, newsize); | 78 | i_size_write(inode, newsize); |
| 82 | 79 | ||
| @@ -118,12 +115,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) | |||
| 118 | 115 | ||
| 119 | return 0; | 116 | return 0; |
| 120 | 117 | ||
| 121 | fsize_exceeded: | 118 | add_error: |
| 122 | send_sig(SIGXFSZ, current, 0); | ||
| 123 | too_big: | ||
| 124 | return -EFBIG; | ||
| 125 | |||
| 126 | add_error: | ||
| 127 | while (loop < npages) | 119 | while (loop < npages) |
| 128 | __free_page(pages + loop++); | 120 | __free_page(pages + loop++); |
| 129 | return ret; | 121 | return ret; |
