aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/bfs/file.c14
-rw-r--r--fs/block_dev.c5
-rw-r--r--fs/buffer.c61
-rw-r--r--fs/ext2/inode.c5
-rw-r--r--fs/minix/inode.c12
-rw-r--r--fs/nilfs2/inode.c12
-rw-r--r--fs/nilfs2/recovery.c11
-rw-r--r--fs/omfs/file.c14
-rw-r--r--fs/sysv/itree.c13
-rw-r--r--fs/udf/inode.c13
-rw-r--r--fs/ufs/inode.c12
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c14
-rw-r--r--include/linux/buffer_head.h8
13 files changed, 103 insertions, 91 deletions
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 88b9a3ff44e4..8fc2e9c9739d 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -168,9 +168,17 @@ static int bfs_write_begin(struct file *file, struct address_space *mapping,
168 loff_t pos, unsigned len, unsigned flags, 168 loff_t pos, unsigned len, unsigned flags,
169 struct page **pagep, void **fsdata) 169 struct page **pagep, void **fsdata)
170{ 170{
171 *pagep = NULL; 171 int ret;
172 return block_write_begin(file, mapping, pos, len, flags, 172
173 pagep, fsdata, bfs_get_block); 173 ret = block_write_begin(mapping, pos, len, flags, pagep,
174 bfs_get_block);
175 if (unlikely(ret)) {
176 loff_t isize = mapping->host->i_size;
177 if (pos + len > isize)
178 vmtruncate(mapping->host, isize);
179 }
180
181 return ret;
174} 182}
175 183
176static sector_t bfs_bmap(struct address_space *mapping, sector_t block) 184static sector_t bfs_bmap(struct address_space *mapping, sector_t block)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 65a0c26508e5..63c9d6076205 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -308,9 +308,8 @@ static int blkdev_write_begin(struct file *file, struct address_space *mapping,
308 loff_t pos, unsigned len, unsigned flags, 308 loff_t pos, unsigned len, unsigned flags,
309 struct page **pagep, void **fsdata) 309 struct page **pagep, void **fsdata)
310{ 310{
311 *pagep = NULL; 311 return block_write_begin(mapping, pos, len, flags, pagep,
312 return block_write_begin_newtrunc(file, mapping, pos, len, flags, 312 blkdev_get_block);
313 pagep, fsdata, blkdev_get_block);
314} 313}
315 314
316static int blkdev_write_end(struct file *file, struct address_space *mapping, 315static int blkdev_write_end(struct file *file, struct address_space *mapping,
diff --git a/fs/buffer.c b/fs/buffer.c
index c319c49da511..50efa339e051 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1962,14 +1962,13 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len,
1962EXPORT_SYMBOL(__block_write_begin); 1962EXPORT_SYMBOL(__block_write_begin);
1963 1963
1964/* 1964/*
1965 * Filesystems implementing the new truncate sequence should use the 1965 * block_write_begin takes care of the basic task of block allocation and
1966 * _newtrunc postfix variant which won't incorrectly call vmtruncate. 1966 * bringing partial write blocks uptodate first.
1967 *
1967 * The filesystem needs to handle block truncation upon failure. 1968 * The filesystem needs to handle block truncation upon failure.
1968 */ 1969 */
1969int block_write_begin_newtrunc(struct file *file, struct address_space *mapping, 1970int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
1970 loff_t pos, unsigned len, unsigned flags, 1971 unsigned flags, struct page **pagep, get_block_t *get_block)
1971 struct page **pagep, void **fsdata,
1972 get_block_t *get_block)
1973{ 1972{
1974 pgoff_t index = pos >> PAGE_CACHE_SHIFT; 1973 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1975 struct page *page; 1974 struct page *page;
@@ -1989,44 +1988,6 @@ int block_write_begin_newtrunc(struct file *file, struct address_space *mapping,
1989 *pagep = page; 1988 *pagep = page;
1990 return status; 1989 return status;
1991} 1990}
1992EXPORT_SYMBOL(block_write_begin_newtrunc);
1993
1994/*
1995 * block_write_begin takes care of the basic task of block allocation and
1996 * bringing partial write blocks uptodate first.
1997 *
1998 * If *pagep is not NULL, then block_write_begin uses the locked page
1999 * at *pagep rather than allocating its own. In this case, the page will
2000 * not be unlocked or deallocated on failure.
2001 */
2002int block_write_begin(struct file *file, struct address_space *mapping,
2003 loff_t pos, unsigned len, unsigned flags,
2004 struct page **pagep, void **fsdata,
2005 get_block_t *get_block)
2006{
2007 int ret;
2008
2009 ret = block_write_begin_newtrunc(file, mapping, pos, len, flags,
2010 pagep, fsdata, get_block);
2011
2012 /*
2013 * prepare_write() may have instantiated a few blocks
2014 * outside i_size. Trim these off again. Don't need
2015 * i_size_read because we hold i_mutex.
2016 *
2017 * Filesystems which pass down their own page also cannot
2018 * call into vmtruncate here because it would lead to lock
2019 * inversion problems (*pagep is locked). This is a further
2020 * example of where the old truncate sequence is inadequate.
2021 */
2022 if (unlikely(ret) && *pagep == NULL) {
2023 loff_t isize = mapping->host->i_size;
2024 if (pos + len > isize)
2025 vmtruncate(mapping->host, isize);
2026 }
2027
2028 return ret;
2029}
2030EXPORT_SYMBOL(block_write_begin); 1991EXPORT_SYMBOL(block_write_begin);
2031 1992
2032int block_write_end(struct file *file, struct address_space *mapping, 1993int block_write_end(struct file *file, struct address_space *mapping,
@@ -2357,7 +2318,7 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
2357 2318
2358 err = cont_expand_zero(file, mapping, pos, bytes); 2319 err = cont_expand_zero(file, mapping, pos, bytes);
2359 if (err) 2320 if (err)
2360 goto out; 2321 return err;
2361 2322
2362 zerofrom = *bytes & ~PAGE_CACHE_MASK; 2323 zerofrom = *bytes & ~PAGE_CACHE_MASK;
2363 if (pos+len > *bytes && zerofrom & (blocksize-1)) { 2324 if (pos+len > *bytes && zerofrom & (blocksize-1)) {
@@ -2365,11 +2326,7 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
2365 (*bytes)++; 2326 (*bytes)++;
2366 } 2327 }
2367 2328
2368 *pagep = NULL; 2329 return block_write_begin(mapping, pos, len, flags, pagep, get_block);
2369 err = block_write_begin_newtrunc(file, mapping, pos, len,
2370 flags, pagep, fsdata, get_block);
2371out:
2372 return err;
2373} 2330}
2374EXPORT_SYMBOL(cont_write_begin); 2331EXPORT_SYMBOL(cont_write_begin);
2375 2332
@@ -2511,8 +2468,8 @@ int nobh_write_begin(struct address_space *mapping,
2511 unlock_page(page); 2468 unlock_page(page);
2512 page_cache_release(page); 2469 page_cache_release(page);
2513 *pagep = NULL; 2470 *pagep = NULL;
2514 return block_write_begin_newtrunc(NULL, mapping, pos, len, 2471 return block_write_begin(mapping, pos, len, flags, pagep,
2515 flags, pagep, fsdata, get_block); 2472 get_block);
2516 } 2473 }
2517 2474
2518 if (PageMappedToDisk(page)) 2475 if (PageMappedToDisk(page))
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 2f4dfbcd7696..74dfe5f73330 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -772,9 +772,8 @@ ext2_write_begin(struct file *file, struct address_space *mapping,
772{ 772{
773 int ret; 773 int ret;
774 774
775 *pagep = NULL; 775 ret = block_write_begin(mapping, pos, len, flags, pagep,
776 ret = block_write_begin_newtrunc(file, mapping, pos, len, flags, 776 ext2_get_block);
777 pagep, fsdata, ext2_get_block);
778 if (ret < 0) 777 if (ret < 0)
779 ext2_write_failed(mapping, pos + len); 778 ext2_write_failed(mapping, pos + len);
780 return ret; 779 return ret;
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 6b29e73f0ca6..125062f55ef2 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -366,9 +366,17 @@ static int minix_write_begin(struct file *file, struct address_space *mapping,
366 loff_t pos, unsigned len, unsigned flags, 366 loff_t pos, unsigned len, unsigned flags,
367 struct page **pagep, void **fsdata) 367 struct page **pagep, void **fsdata)
368{ 368{
369 *pagep = NULL; 369 int ret;
370 return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 370
371 ret = block_write_begin(mapping, pos, len, flags, pagep,
371 minix_get_block); 372 minix_get_block);
373 if (unlikely(ret)) {
374 loff_t isize = mapping->host->i_size;
375 if (pos + len > isize)
376 vmtruncate(mapping->host, isize);
377 }
378
379 return ret;
372} 380}
373 381
374static sector_t minix_bmap(struct address_space *mapping, sector_t block) 382static sector_t minix_bmap(struct address_space *mapping, sector_t block)
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 1dd9e6a7d787..5c694ece172e 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -197,11 +197,15 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping,
197 if (unlikely(err)) 197 if (unlikely(err))
198 return err; 198 return err;
199 199
200 *pagep = NULL; 200 err = block_write_begin(mapping, pos, len, flags, pagep,
201 err = block_write_begin(file, mapping, pos, len, flags, pagep, 201 nilfs_get_block);
202 fsdata, nilfs_get_block); 202 if (unlikely(err)) {
203 if (unlikely(err)) 203 loff_t isize = mapping->host->i_size;
204 if (pos + len > isize)
205 vmtruncate(mapping->host, isize);
206
204 nilfs_transaction_abort(inode->i_sb); 207 nilfs_transaction_abort(inode->i_sb);
208 }
205 return err; 209 return err;
206} 210}
207 211
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index bae2a516b4ee..2f11f0868d87 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -505,11 +505,14 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi,
505 } 505 }
506 506
507 pos = rb->blkoff << inode->i_blkbits; 507 pos = rb->blkoff << inode->i_blkbits;
508 page = NULL; 508 err = block_write_begin(inode->i_mapping, pos, blocksize,
509 err = block_write_begin(NULL, inode->i_mapping, pos, blocksize, 509 0, &page, nilfs_get_block);
510 0, &page, NULL, nilfs_get_block); 510 if (unlikely(err)) {
511 if (unlikely(err)) 511 loff_t isize = inode->i_size;
512 if (pos + blocksize > isize)
513 vmtruncate(inode, isize);
512 goto failed_inode; 514 goto failed_inode;
515 }
513 516
514 err = nilfs_recovery_copy_block(sbi, rb, page); 517 err = nilfs_recovery_copy_block(sbi, rb, page);
515 if (unlikely(err)) 518 if (unlikely(err))
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index 6e7a3291bbe8..810cff346468 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -312,9 +312,17 @@ static int omfs_write_begin(struct file *file, struct address_space *mapping,
312 loff_t pos, unsigned len, unsigned flags, 312 loff_t pos, unsigned len, unsigned flags,
313 struct page **pagep, void **fsdata) 313 struct page **pagep, void **fsdata)
314{ 314{
315 *pagep = NULL; 315 int ret;
316 return block_write_begin(file, mapping, pos, len, flags, 316
317 pagep, fsdata, omfs_get_block); 317 ret = block_write_begin(mapping, pos, len, flags, pagep,
318 omfs_get_block);
319 if (unlikely(ret)) {
320 loff_t isize = mapping->host->i_size;
321 if (pos + len > isize)
322 vmtruncate(mapping->host, isize);
323 }
324
325 return ret;
318} 326}
319 327
320static sector_t omfs_bmap(struct address_space *mapping, sector_t block) 328static sector_t omfs_bmap(struct address_space *mapping, sector_t block)
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 82a005c3d7eb..9ca66276315e 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -468,9 +468,16 @@ static int sysv_write_begin(struct file *file, struct address_space *mapping,
468 loff_t pos, unsigned len, unsigned flags, 468 loff_t pos, unsigned len, unsigned flags,
469 struct page **pagep, void **fsdata) 469 struct page **pagep, void **fsdata)
470{ 470{
471 *pagep = NULL; 471 int ret;
472 return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 472
473 get_block); 473 ret = block_write_begin(mapping, pos, len, flags, pagep, get_block);
474 if (unlikely(ret)) {
475 loff_t isize = mapping->host->i_size;
476 if (pos + len > isize)
477 vmtruncate(mapping->host, isize);
478 }
479
480 return ret;
474} 481}
475 482
476static sector_t sysv_bmap(struct address_space *mapping, sector_t block) 483static sector_t sysv_bmap(struct address_space *mapping, sector_t block)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 124852bcf6fe..ecddcc2ed746 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -127,9 +127,16 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
127 loff_t pos, unsigned len, unsigned flags, 127 loff_t pos, unsigned len, unsigned flags,
128 struct page **pagep, void **fsdata) 128 struct page **pagep, void **fsdata)
129{ 129{
130 *pagep = NULL; 130 int ret;
131 return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 131
132 udf_get_block); 132 ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block);
133 if (unlikely(ret)) {
134 loff_t isize = mapping->host->i_size;
135 if (pos + len > isize)
136 vmtruncate(mapping->host, isize);
137 }
138
139 return ret;
133} 140}
134 141
135static sector_t udf_bmap(struct address_space *mapping, sector_t block) 142static sector_t udf_bmap(struct address_space *mapping, sector_t block)
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 45ce32391f8f..45cafa937a4b 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -567,9 +567,17 @@ static int ufs_write_begin(struct file *file, struct address_space *mapping,
567 loff_t pos, unsigned len, unsigned flags, 567 loff_t pos, unsigned len, unsigned flags,
568 struct page **pagep, void **fsdata) 568 struct page **pagep, void **fsdata)
569{ 569{
570 *pagep = NULL; 570 int ret;
571 return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 571
572 ret = block_write_begin(mapping, pos, len, flags, pagep,
572 ufs_getfrag_block); 573 ufs_getfrag_block);
574 if (unlikely(ret)) {
575 loff_t isize = mapping->host->i_size;
576 if (pos + len > isize)
577 vmtruncate(mapping->host, isize);
578 }
579
580 return ret;
573} 581}
574 582
575static sector_t ufs_bmap(struct address_space *mapping, sector_t block) 583static sector_t ufs_bmap(struct address_space *mapping, sector_t block)
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 7968d41e27ad..bf7aad0d78b8 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1504,9 +1504,17 @@ xfs_vm_write_begin(
1504 struct page **pagep, 1504 struct page **pagep,
1505 void **fsdata) 1505 void **fsdata)
1506{ 1506{
1507 *pagep = NULL; 1507 int ret;
1508 return block_write_begin(file, mapping, pos, len, flags | AOP_FLAG_NOFS, 1508
1509 pagep, fsdata, xfs_get_blocks); 1509 ret = block_write_begin(mapping, pos, len, flags | AOP_FLAG_NOFS,
1510 pagep, xfs_get_blocks);
1511 if (unlikely(ret)) {
1512 loff_t isize = mapping->host->i_size;
1513 if (pos + len > isize)
1514 vmtruncate(mapping->host, isize);
1515 }
1516
1517 return ret;
1510} 1518}
1511 1519
1512STATIC sector_t 1520STATIC sector_t
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index accc9f81bb63..3f69054f86d9 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -203,12 +203,8 @@ int block_write_full_page_endio(struct page *page, get_block_t *get_block,
203int block_read_full_page(struct page*, get_block_t*); 203int block_read_full_page(struct page*, get_block_t*);
204int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, 204int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
205 unsigned long from); 205 unsigned long from);
206int block_write_begin_newtrunc(struct file *, struct address_space *, 206int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
207 loff_t, unsigned, unsigned, 207 unsigned flags, struct page **pagep, get_block_t *get_block);
208 struct page **, void **, get_block_t*);
209int block_write_begin(struct file *, struct address_space *,
210 loff_t, unsigned, unsigned,
211 struct page **, void **, get_block_t*);
212int __block_write_begin(struct page *page, loff_t pos, unsigned len, 208int __block_write_begin(struct page *page, loff_t pos, unsigned len,
213 get_block_t *get_block); 209 get_block_t *get_block);
214int block_write_end(struct file *, struct address_space *, 210int block_write_end(struct file *, struct address_space *,