diff options
Diffstat (limited to 'fs/ext2/dir.c')
-rw-r--r-- | fs/ext2/dir.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 2bf49d7ef84..05d9342bb64 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -22,7 +22,9 @@ */ #include "ext2.h" +#include <linux/buffer_head.h> #include <linux/pagemap.h> +#include <linux/swap.h> typedef struct ext2_dir_entry_2 ext2_dirent; @@ -61,16 +63,25 @@ ext2_last_byte(struct inode *inode, unsigned long page_nr) return last_byte; } -static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to) +static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len) { - struct inode *dir = page->mapping->host; + struct address_space *mapping = page->mapping; + struct inode *dir = mapping->host; int err = 0; + dir->i_version++; - page->mapping->a_ops->commit_write(NULL, page, from, to); + block_write_end(NULL, mapping, pos, len, len, page, NULL); + + if (pos+len > dir->i_size) { + i_size_write(dir, pos+len); + mark_inode_dirty(dir); + } + if (IS_DIRSYNC(dir)) err = write_one_page(page, 1); else unlock_page(page); + return err; } @@ -412,16 +423,18 @@ ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry) void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, struct page *page, struct inode *inode) { - unsigned from = (char *) de - (char *) page_address(page); - unsigned to = from + le16_to_cpu(de->rec_len); + loff_t pos = page_offset(page) + + (char *) de - (char *) page_address(page); + unsigned len = le16_to_cpu(de->rec_len); int err; lock_page(page); - err = page->mapping->a_ops->prepare_write(NULL, page, from, to); + err = __ext2_write_begin(NULL, page->mapping, pos, len, + AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); BUG_ON(err); de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type (de, inode); - err = ext2_commit_chunk(page, from, to); + ext2_set_de_type(de, inode); + err = ext2_commit_chunk(page, pos, len); ext2_put_page(page); dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; @@ -444,7 +457,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) unsigned long npages = dir_pages(dir); unsigned long n; char *kaddr; - unsigned from, to; + loff_t pos; int err; /* @@ -497,9 +510,10 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) return -EINVAL; got_it: - from = (char*)de - (char*)page_address(page); - to = from + rec_len; - err = page->mapping->a_ops->prepare_write(NULL, page, from, to); + pos = page_offset(page) + + (char*)de - (char*)page_address(page); + err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, + &page, NULL); if (err) goto out_unlock; if (de->inode) { @@ -509,10 +523,10 @@ got_it: de = de1; } de->name_len = namelen; - memcpy (de->name, name, namelen); + memcpy(de->name, name, namelen); de->inode = cpu_to_le32(inode->i_ino); ext2_set_de_type (de, inode); - err = ext2_commit_chunk(page, from, to); + err = ext2_commit_chunk(page, pos, rec_len); dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); @@ -537,6 +551,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) char *kaddr = page_address(page); unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len); + loff_t pos; ext2_dirent * pde = NULL; ext2_dirent * de = (ext2_dirent *) (kaddr + from); int err; @@ -553,13 +568,15 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) } if (pde) from = (char*)pde - (char*)page_address(page); + pos = page_offset(page) + from; lock_page(page); - err = mapping->a_ops->prepare_write(NULL, page, from, to); + err = __ext2_write_begin(NULL, page->mapping, pos, to - from, 0, + &page, NULL); BUG_ON(err); if (pde) - pde->rec_len = cpu_to_le16(to-from); + pde->rec_len = cpu_to_le16(to - from); dir->inode = 0; - err = ext2_commit_chunk(page, from, to); + err = ext2_commit_chunk(page, pos, to - from); inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(inode); @@ -582,7 +599,9 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) if (!page) return -ENOMEM; - err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size); + + err = __ext2_write_begin(NULL, page->mapping, 0, chunk_size, 0, + &page, NULL); if (err) { unlock_page(page); goto fail; |