diff options
author | Christoph Hellwig <hch@lst.de> | 2010-06-04 05:29:56 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:47:31 -0400 |
commit | f4e420dc423148fba637af1ab618fa8896dfb2d6 (patch) | |
tree | df0e81f5f4b8448dd6b3929e5537dcc46e7d7dde /fs/sysv | |
parent | 282dc178849882289d30e58b54be6b2799b351aa (diff) |
clean up write_begin usage for directories in pagecache
For filesystem that implement directories in pagecache we call
block_write_begin with an already allocated page for this code, while the
normal regular file write path uses the default block_write_begin behaviour.
Get rid of the __foofs_write_begin helper and opencode the normal write_begin
call in foofs_write_begin, while adding a new foofs_prepare_chunk helper for
the directory code. The added benefit is that foofs_prepare_chunk has
a much saner calling convention.
Note that the interruptible flag passed into block_write_begin is always
ignored if we already pass in a page (see next patch for details), and
we never were doing truncations of exessive blocks for this case either so we
can switch directly to block_write_begin_newtrunc.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/sysv')
-rw-r--r-- | fs/sysv/dir.c | 21 | ||||
-rw-r--r-- | fs/sysv/itree.c | 11 | ||||
-rw-r--r-- | fs/sysv/sysv.h | 4 |
3 files changed, 13 insertions, 23 deletions
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index 79941e4964a4..a77c42157620 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -218,8 +218,7 @@ got_it: | |||
218 | pos = page_offset(page) + | 218 | pos = page_offset(page) + |
219 | (char*)de - (char*)page_address(page); | 219 | (char*)de - (char*)page_address(page); |
220 | lock_page(page); | 220 | lock_page(page); |
221 | err = __sysv_write_begin(NULL, page->mapping, pos, SYSV_DIRSIZE, | 221 | err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE); |
222 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
223 | if (err) | 222 | if (err) |
224 | goto out_unlock; | 223 | goto out_unlock; |
225 | memcpy (de->name, name, namelen); | 224 | memcpy (de->name, name, namelen); |
@@ -239,15 +238,13 @@ out_unlock: | |||
239 | 238 | ||
240 | int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) | 239 | int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) |
241 | { | 240 | { |
242 | struct address_space *mapping = page->mapping; | 241 | struct inode *inode = page->mapping->host; |
243 | struct inode *inode = (struct inode*)mapping->host; | ||
244 | char *kaddr = (char*)page_address(page); | 242 | char *kaddr = (char*)page_address(page); |
245 | loff_t pos = page_offset(page) + (char *)de - kaddr; | 243 | loff_t pos = page_offset(page) + (char *)de - kaddr; |
246 | int err; | 244 | int err; |
247 | 245 | ||
248 | lock_page(page); | 246 | lock_page(page); |
249 | err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE, | 247 | err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE); |
250 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
251 | BUG_ON(err); | 248 | BUG_ON(err); |
252 | de->inode = 0; | 249 | de->inode = 0; |
253 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); | 250 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
@@ -259,16 +256,14 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) | |||
259 | 256 | ||
260 | int sysv_make_empty(struct inode *inode, struct inode *dir) | 257 | int sysv_make_empty(struct inode *inode, struct inode *dir) |
261 | { | 258 | { |
262 | struct address_space *mapping = inode->i_mapping; | 259 | struct page *page = grab_cache_page(inode->i_mapping, 0); |
263 | struct page *page = grab_cache_page(mapping, 0); | ||
264 | struct sysv_dir_entry * de; | 260 | struct sysv_dir_entry * de; |
265 | char *base; | 261 | char *base; |
266 | int err; | 262 | int err; |
267 | 263 | ||
268 | if (!page) | 264 | if (!page) |
269 | return -ENOMEM; | 265 | return -ENOMEM; |
270 | err = __sysv_write_begin(NULL, mapping, 0, 2 * SYSV_DIRSIZE, | 266 | err = sysv_prepare_chunk(page, 0, 2 * SYSV_DIRSIZE); |
271 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
272 | if (err) { | 267 | if (err) { |
273 | unlock_page(page); | 268 | unlock_page(page); |
274 | goto fail; | 269 | goto fail; |
@@ -341,15 +336,13 @@ not_empty: | |||
341 | void sysv_set_link(struct sysv_dir_entry *de, struct page *page, | 336 | void sysv_set_link(struct sysv_dir_entry *de, struct page *page, |
342 | struct inode *inode) | 337 | struct inode *inode) |
343 | { | 338 | { |
344 | struct address_space *mapping = page->mapping; | 339 | struct inode *dir = page->mapping->host; |
345 | struct inode *dir = mapping->host; | ||
346 | loff_t pos = page_offset(page) + | 340 | loff_t pos = page_offset(page) + |
347 | (char *)de-(char*)page_address(page); | 341 | (char *)de-(char*)page_address(page); |
348 | int err; | 342 | int err; |
349 | 343 | ||
350 | lock_page(page); | 344 | lock_page(page); |
351 | err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE, | 345 | err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE); |
352 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
353 | BUG_ON(err); | 346 | BUG_ON(err); |
354 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); | 347 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); |
355 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); | 348 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index f042eec464c2..4068f485cfd6 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c | |||
@@ -459,12 +459,10 @@ static int sysv_readpage(struct file *file, struct page *page) | |||
459 | return block_read_full_page(page,get_block); | 459 | return block_read_full_page(page,get_block); |
460 | } | 460 | } |
461 | 461 | ||
462 | int __sysv_write_begin(struct file *file, struct address_space *mapping, | 462 | int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len) |
463 | loff_t pos, unsigned len, unsigned flags, | ||
464 | struct page **pagep, void **fsdata) | ||
465 | { | 463 | { |
466 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 464 | return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0, |
467 | get_block); | 465 | &page, NULL, get_block); |
468 | } | 466 | } |
469 | 467 | ||
470 | static int sysv_write_begin(struct file *file, struct address_space *mapping, | 468 | static int sysv_write_begin(struct file *file, struct address_space *mapping, |
@@ -472,7 +470,8 @@ static int sysv_write_begin(struct file *file, struct address_space *mapping, | |||
472 | struct page **pagep, void **fsdata) | 470 | struct page **pagep, void **fsdata) |
473 | { | 471 | { |
474 | *pagep = NULL; | 472 | *pagep = NULL; |
475 | return __sysv_write_begin(file, mapping, pos, len, flags, pagep, fsdata); | 473 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
474 | get_block); | ||
476 | } | 475 | } |
477 | 476 | ||
478 | static sector_t sysv_bmap(struct address_space *mapping, sector_t block) | 477 | static sector_t sysv_bmap(struct address_space *mapping, sector_t block) |
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index 94cb9b4d76c2..bb55cdb394bf 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h | |||
@@ -136,9 +136,7 @@ extern unsigned long sysv_count_free_blocks(struct super_block *); | |||
136 | 136 | ||
137 | /* itree.c */ | 137 | /* itree.c */ |
138 | extern void sysv_truncate(struct inode *); | 138 | extern void sysv_truncate(struct inode *); |
139 | extern int __sysv_write_begin(struct file *file, struct address_space *mapping, | 139 | extern int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len); |
140 | loff_t pos, unsigned len, unsigned flags, | ||
141 | struct page **pagep, void **fsdata); | ||
142 | 140 | ||
143 | /* inode.c */ | 141 | /* inode.c */ |
144 | extern struct inode *sysv_iget(struct super_block *, unsigned int); | 142 | extern struct inode *sysv_iget(struct super_block *, unsigned int); |