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>
This commit is contained in:
parent
282dc17884
commit
f4e420dc42
13 changed files with 57 additions and 107 deletions
|
@ -218,8 +218,7 @@ got_it:
|
|||
pos = page_offset(page) +
|
||||
(char*)de - (char*)page_address(page);
|
||||
lock_page(page);
|
||||
err = __sysv_write_begin(NULL, page->mapping, pos, SYSV_DIRSIZE,
|
||||
AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
|
||||
err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
memcpy (de->name, name, namelen);
|
||||
|
@ -239,15 +238,13 @@ out_unlock:
|
|||
|
||||
int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
|
||||
{
|
||||
struct address_space *mapping = page->mapping;
|
||||
struct inode *inode = (struct inode*)mapping->host;
|
||||
struct inode *inode = page->mapping->host;
|
||||
char *kaddr = (char*)page_address(page);
|
||||
loff_t pos = page_offset(page) + (char *)de - kaddr;
|
||||
int err;
|
||||
|
||||
lock_page(page);
|
||||
err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE,
|
||||
AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
|
||||
err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
|
||||
BUG_ON(err);
|
||||
de->inode = 0;
|
||||
err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
|
||||
|
@ -259,16 +256,14 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
|
|||
|
||||
int sysv_make_empty(struct inode *inode, struct inode *dir)
|
||||
{
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
struct page *page = grab_cache_page(mapping, 0);
|
||||
struct page *page = grab_cache_page(inode->i_mapping, 0);
|
||||
struct sysv_dir_entry * de;
|
||||
char *base;
|
||||
int err;
|
||||
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
err = __sysv_write_begin(NULL, mapping, 0, 2 * SYSV_DIRSIZE,
|
||||
AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
|
||||
err = sysv_prepare_chunk(page, 0, 2 * SYSV_DIRSIZE);
|
||||
if (err) {
|
||||
unlock_page(page);
|
||||
goto fail;
|
||||
|
@ -341,15 +336,13 @@ not_empty:
|
|||
void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct address_space *mapping = page->mapping;
|
||||
struct inode *dir = mapping->host;
|
||||
struct inode *dir = page->mapping->host;
|
||||
loff_t pos = page_offset(page) +
|
||||
(char *)de-(char*)page_address(page);
|
||||
int err;
|
||||
|
||||
lock_page(page);
|
||||
err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE,
|
||||
AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
|
||||
err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
|
||||
BUG_ON(err);
|
||||
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
|
||||
err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
|
||||
|
|
|
@ -459,12 +459,10 @@ static int sysv_readpage(struct file *file, struct page *page)
|
|||
return block_read_full_page(page,get_block);
|
||||
}
|
||||
|
||||
int __sysv_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
struct page **pagep, void **fsdata)
|
||||
int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len)
|
||||
{
|
||||
return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
|
||||
get_block);
|
||||
return block_write_begin_newtrunc(NULL, page->mapping, pos, len, 0,
|
||||
&page, NULL, get_block);
|
||||
}
|
||||
|
||||
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,
|
|||
struct page **pagep, void **fsdata)
|
||||
{
|
||||
*pagep = NULL;
|
||||
return __sysv_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
|
||||
return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
|
||||
get_block);
|
||||
}
|
||||
|
||||
static sector_t sysv_bmap(struct address_space *mapping, sector_t block)
|
||||
|
|
|
@ -136,9 +136,7 @@ extern unsigned long sysv_count_free_blocks(struct super_block *);
|
|||
|
||||
/* itree.c */
|
||||
extern void sysv_truncate(struct inode *);
|
||||
extern int __sysv_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
struct page **pagep, void **fsdata);
|
||||
extern int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len);
|
||||
|
||||
/* inode.c */
|
||||
extern struct inode *sysv_iget(struct super_block *, unsigned int);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue