diff options
Diffstat (limited to 'fs/ufs')
-rw-r--r-- | fs/ufs/dir.c | 13 | ||||
-rw-r--r-- | fs/ufs/ialloc.c | 2 | ||||
-rw-r--r-- | fs/ufs/inode.c | 63 | ||||
-rw-r--r-- | fs/ufs/super.c | 2 | ||||
-rw-r--r-- | fs/ufs/truncate.c | 16 | ||||
-rw-r--r-- | fs/ufs/ufs.h | 2 | ||||
-rw-r--r-- | fs/ufs/util.h | 4 |
7 files changed, 53 insertions, 49 deletions
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index ec784756dc6..dbc90994715 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -95,8 +95,7 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, int err; lock_page(page); - err = __ufs_write_begin(NULL, page->mapping, pos, len, - AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); + err = ufs_prepare_chunk(page, pos, len); BUG_ON(err); de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); @@ -381,8 +380,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) got_it: pos = page_offset(page) + (char*)de - (char*)page_address(page); - err = __ufs_write_begin(NULL, page->mapping, pos, rec_len, - AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); + err = ufs_prepare_chunk(page, pos, rec_len); if (err) goto out_unlock; if (de->d_ino) { @@ -518,7 +516,6 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, struct page * page) { struct super_block *sb = inode->i_sb; - struct address_space *mapping = page->mapping; char *kaddr = page_address(page); unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); @@ -549,8 +546,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, pos = page_offset(page) + from; lock_page(page); - err = __ufs_write_begin(NULL, mapping, pos, to - from, - AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); + err = ufs_prepare_chunk(page, pos, to - from); BUG_ON(err); if (pde) pde->d_reclen = cpu_to_fs16(sb, to - from); @@ -577,8 +573,7 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) if (!page) return -ENOMEM; - err = __ufs_write_begin(NULL, mapping, 0, chunk_size, - AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); + err = ufs_prepare_chunk(page, 0, chunk_size); if (err) { unlock_page(page); goto fail; diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 594480e537d..428017e018f 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -94,8 +94,6 @@ void ufs_free_inode (struct inode * inode) is_directory = S_ISDIR(inode->i_mode); - clear_inode (inode); - if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit)) ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino); else { diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 73fe773aa03..2b251f2093a 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -558,20 +558,26 @@ static int ufs_readpage(struct file *file, struct page *page) return block_read_full_page(page,ufs_getfrag_block); } -int __ufs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) +int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len) { - return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, - ufs_getfrag_block); + return __block_write_begin(page, pos, len, ufs_getfrag_block); } static int ufs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - *pagep = NULL; - return __ufs_write_begin(file, mapping, pos, len, flags, pagep, fsdata); + int ret; + + ret = block_write_begin(mapping, pos, len, flags, pagep, + ufs_getfrag_block); + if (unlikely(ret)) { + loff_t isize = mapping->host->i_size; + if (pos + len > isize) + vmtruncate(mapping->host, isize); + } + + return ret; } static sector_t ufs_bmap(struct address_space *mapping, sector_t block) @@ -905,24 +911,33 @@ int ufs_sync_inode (struct inode *inode) return ufs_update_inode (inode, 1); } -void ufs_delete_inode (struct inode * inode) +void ufs_evict_inode(struct inode * inode) { - loff_t old_i_size; + int want_delete = 0; + + if (!inode->i_nlink && !is_bad_inode(inode)) + want_delete = 1; truncate_inode_pages(&inode->i_data, 0); - if (is_bad_inode(inode)) - goto no_delete; - /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ - lock_kernel(); - mark_inode_dirty(inode); - ufs_update_inode(inode, IS_SYNC(inode)); - old_i_size = inode->i_size; - inode->i_size = 0; - if (inode->i_blocks && ufs_truncate(inode, old_i_size)) - ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n"); - ufs_free_inode (inode); - unlock_kernel(); - return; -no_delete: - clear_inode(inode); /* We must guarantee clearing of inode... */ + if (want_delete) { + loff_t old_i_size; + /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ + lock_kernel(); + mark_inode_dirty(inode); + ufs_update_inode(inode, IS_SYNC(inode)); + old_i_size = inode->i_size; + inode->i_size = 0; + if (inode->i_blocks && ufs_truncate(inode, old_i_size)) + ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n"); + unlock_kernel(); + } + + invalidate_inode_buffers(inode); + end_writeback(inode); + + if (want_delete) { + lock_kernel(); + ufs_free_inode (inode); + unlock_kernel(); + } } diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 3ec5a9eb6ef..d510c1b9181 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1440,7 +1440,7 @@ static const struct super_operations ufs_super_ops = { .alloc_inode = ufs_alloc_inode, .destroy_inode = ufs_destroy_inode, .write_inode = ufs_write_inode, - .delete_inode = ufs_delete_inode, + .evict_inode = ufs_evict_inode, .put_super = ufs_put_super, .write_super = ufs_write_super, .sync_fs = ufs_sync_fs, diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 589e01a465b..34d5cb13532 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -500,11 +500,6 @@ out: return err; } -/* - * TODO: - * - truncate case should use proper ordering instead of using - * simple_setsize - */ int ufs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; @@ -518,14 +513,17 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr) if (ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) { loff_t old_i_size = inode->i_size; - error = simple_setsize(inode, attr->ia_size); - if (error) - return error; + /* XXX(truncate): truncate_setsize should be called last */ + truncate_setsize(inode, attr->ia_size); + error = ufs_truncate(inode, old_i_size); if (error) return error; } - return inode_setattr(inode, attr); + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + return 0; } const struct inode_operations ufs_file_inode_operations = { diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 179ae6b3180..c08782e1b48 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -108,7 +108,7 @@ extern struct inode * ufs_new_inode (struct inode *, int); extern struct inode *ufs_iget(struct super_block *, unsigned long); extern int ufs_write_inode (struct inode *, struct writeback_control *); extern int ufs_sync_inode (struct inode *); -extern void ufs_delete_inode (struct inode *); +extern void ufs_evict_inode (struct inode *); extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 23ceed8c8fb..0466036912f 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -257,9 +257,7 @@ ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value) extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *); extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t); -extern int __ufs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata); +extern int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len); /* * These functions manipulate ufs buffers |