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

truncate: use new helpers

Update some fs code to make use of new helper functions introduced
in the previous patch. Should be no significant change in behaviour
(except CIFS now calls send_sig under i_lock, via inode_newsize_ok).

Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Miklos Szeredi <miklos@szeredi.hu>
Cc: linux-nfs@vger.kernel.org
Cc: Trond.Myklebust@netapp.com
Cc: linux-cifs-client@lists.samba.org
Cc: sfrench@samba.org
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

npiggin@suse.de and committed by
al
c08d3b0e 25d9e2d1

+33 -125
+2 -8
fs/buffer.c
··· 2239 2239 struct address_space *mapping = inode->i_mapping; 2240 2240 struct page *page; 2241 2241 void *fsdata; 2242 - unsigned long limit; 2243 2242 int err; 2244 2243 2245 - err = -EFBIG; 2246 - limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; 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) 2244 + err = inode_newsize_ok(inode, size); 2245 + if (err) 2252 2246 goto out; 2253 2247 2254 2248 err = pagecache_write_begin(NULL, mapping, size, 0,
+9 -42
fs/cifs/inode.c
··· 1557 1557 1558 1558 static int cifs_vmtruncate(struct inode *inode, loff_t offset) 1559 1559 { 1560 - struct address_space *mapping = inode->i_mapping; 1561 - unsigned long limit; 1560 + loff_t oldsize; 1561 + int err; 1562 1562 1563 1563 spin_lock(&inode->i_lock); 1564 - if (inode->i_size < offset) 1565 - goto do_expand; 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)) { 1564 + err = inode_newsize_ok(inode, offset); 1565 + if (err) { 1571 1566 spin_unlock(&inode->i_lock); 1572 - goto out_busy; 1567 + goto out; 1573 1568 } 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 1569 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); 1593 - goto out_sig; 1594 - } 1595 - if (offset > inode->i_sb->s_maxbytes) { 1596 - spin_unlock(&inode->i_lock); 1597 - goto out_big; 1598 - } 1570 + oldsize = inode->i_size; 1599 1571 i_size_write(inode, offset); 1600 1572 spin_unlock(&inode->i_lock); 1601 - out_truncate: 1573 + truncate_pagecache(inode, oldsize, offset); 1602 1574 if (inode->i_op->truncate) 1603 1575 inode->i_op->truncate(inode); 1604 - return 0; 1605 - out_sig: 1606 - send_sig(SIGXFSZ, current, 0); 1607 - out_big: 1608 - return -EFBIG; 1609 - out_busy: 1610 - return -ETXTBSY; 1576 + out: 1577 + return err; 1611 1578 } 1612 1579 1613 1580 static int
+4 -10
fs/fuse/dir.c
··· 1276 1276 return 0; 1277 1277 1278 1278 if (attr->ia_valid & ATTR_SIZE) { 1279 - unsigned long limit; 1280 - if (IS_SWAPFILE(inode)) 1281 - return -ETXTBSY; 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 - } 1279 + err = inode_newsize_ok(inode, attr->ia_size); 1280 + if (err) 1281 + return err; 1287 1282 is_truncate = true; 1288 1283 } 1289 1284 ··· 1345 1350 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 1346 1351 */ 1347 1352 if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 1348 - if (outarg.attr.size < oldsize) 1349 - fuse_truncate(inode->i_mapping, outarg.attr.size); 1353 + truncate_pagecache(inode, oldsize, outarg.attr.size); 1350 1354 invalidate_inode_pages2(inode->i_mapping); 1351 1355 } 1352 1356
-2
fs/fuse/fuse_i.h
··· 606 606 void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 607 607 u64 attr_valid); 608 608 609 - void fuse_truncate(struct address_space *mapping, loff_t offset); 610 - 611 609 /** 612 610 * Initialize the client device 613 611 */
+1 -10
fs/fuse/inode.c
··· 140 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 143 void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 152 144 u64 attr_valid) 153 145 { ··· 197 205 spin_unlock(&fc->lock); 198 206 199 207 if (S_ISREG(inode->i_mode) && oldsize != attr->size) { 200 - if (attr->size < oldsize) 201 - fuse_truncate(inode->i_mapping, attr->size); 208 + truncate_pagecache(inode, oldsize, attr->size); 202 209 invalidate_inode_pages2(inode->i_mapping); 203 210 } 204 211 }
+12 -40
fs/nfs/inode.c
··· 458 458 */ 459 459 static int nfs_vmtruncate(struct inode * inode, loff_t offset) 460 460 { 461 - if (i_size_read(inode) < offset) { 462 - unsigned long limit; 461 + loff_t oldsize; 462 + int err; 463 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; 464 + err = inode_newsize_ok(inode, offset); 465 + if (err) 466 + goto out; 474 467 475 - /* 476 - * truncation of in-use swapfiles is disallowed - it would 477 - * cause subsequent swapout to scribble on the now-freed 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); 468 + spin_lock(&inode->i_lock); 469 + oldsize = inode->i_size; 470 + i_size_write(inode, offset); 471 + spin_unlock(&inode->i_lock); 485 472 486 - /* 487 - * unmap_mapping_range is called twice, first simply for 488 - * efficiency so that truncate_inode_pages does fewer 489 - * single-page unmaps. However after this first call, and 490 - * before truncate_inode_pages finishes, it is possible for 491 - * private pages to be COWed, which remain after 492 - * truncate_inode_pages finishes, hence the second 493 - * unmap_mapping_range call must be made for correctness. 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; 473 + truncate_pagecache(inode, oldsize, offset); 474 + out: 475 + return err; 504 476 } 505 477 506 478 /**
+5 -13
fs/ramfs/file-nommu.c
··· 69 69 /* make various checks */ 70 70 order = get_order(newsize); 71 71 if (unlikely(order >= MAX_ORDER)) 72 - goto too_big; 72 + return -EFBIG; 73 73 74 - limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; 75 - if (limit != RLIM_INFINITY && newsize > limit) 76 - goto fsize_exceeded; 77 - 78 - if (newsize > inode->i_sb->s_maxbytes) 79 - goto too_big; 74 + ret = inode_newsize_ok(inode, newsize); 75 + if (ret) 76 + return ret; 80 77 81 78 i_size_write(inode, newsize); 82 79 ··· 115 118 116 119 return 0; 117 120 118 - fsize_exceeded: 119 - send_sig(SIGXFSZ, current, 0); 120 - too_big: 121 - return -EFBIG; 122 - 123 - add_error: 121 + add_error: 124 122 while (loop < npages) 125 123 __free_page(pages + loop++); 126 124 return ret;