summaryrefslogtreecommitdiffstats
path: root/fs/ext2
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
commitc9c06167e7933d93a6e396174c68abf242294abb (patch)
treed9a8bb30663e9a3405a1ef37ffb62bc14b9f019f /fs/ext2
parentf79e8cc3c34e4192a3e5ef4cc9c6542fdef703c0 (diff)
Merge with Linux 2.4.0-test12.
Diffstat (limited to 'fs/ext2')
-rw-r--r--fs/ext2/fsync.c130
-rw-r--r--fs/ext2/ialloc.c60
-rw-r--r--fs/ext2/inode.c12
-rw-r--r--fs/ext2/namei.c34
4 files changed, 62 insertions, 174 deletions
diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c
index 42ce44c65..8b2ecab41 100644
--- a/fs/ext2/fsync.c
+++ b/fs/ext2/fsync.c
@@ -28,98 +28,6 @@
#include <linux/smp_lock.h>
-#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
-#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
-
-static int sync_indirect(struct inode * inode, u32 * block, int wait)
-{
- struct buffer_head * bh;
-
- if (!*block)
- return 0;
- bh = get_hash_table(inode->i_dev, le32_to_cpu(*block), blocksize);
- if (!bh)
- return 0;
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- /* There can be a parallell read(2) that started read-I/O
- on the buffer so we can't assume that there's been
- an I/O error without first waiting I/O completation. */
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- {
- brelse (bh);
- return -1;
- }
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
- if (wait)
- /* when we return from fsync all the blocks
- must be _just_ stored on disk */
- wait_on_buffer(bh);
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- atomic_dec(&bh->b_count);
- return 0;
-}
-
-static int sync_iblock(struct inode * inode, u32 * iblock,
- struct buffer_head ** bh, int wait)
-{
- int rc, tmp;
-
- *bh = NULL;
- tmp = le32_to_cpu(*iblock);
- if (!tmp)
- return 0;
- rc = sync_indirect(inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (!*bh)
- return -1;
- return 0;
-}
-
-static int sync_dindirect(struct inode * inode, u32 * diblock, int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = sync_iblock(inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait);
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait)
-{
- int i;
- struct buffer_head * tind_bh;
- int rc, err = 0;
-
- rc = sync_iblock(inode, tiblock, &tind_bh, wait);
- if (rc || !tind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait);
- if (rc)
- err = rc;
- }
- brelse(tind_bh);
- return err;
-}
-
/*
* File may be NULL when we are called. Perhaps we shouldn't
* even pass file to fsync ?
@@ -127,32 +35,20 @@ static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait)
int ext2_sync_file(struct file * file, struct dentry *dentry, int datasync)
{
- int wait, err = 0;
struct inode *inode = dentry->d_inode;
+ return ext2_fsync_inode(inode, datasync);
+}
- lock_kernel();
- if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
- /*
- * Don't sync fast links!
- */
- goto skip;
-
- err = generic_buffer_fdatasync(inode, 0, ~0UL);
-
- for (wait=0; wait<=1; wait++)
- {
- err |= sync_indirect(inode,
- inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
- wait);
- err |= sync_dindirect(inode,
- inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
- wait);
- err |= sync_tindirect(inode,
- inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
- wait);
- }
-skip:
- err |= ext2_sync_inode (inode);
- unlock_kernel();
+int ext2_fsync_inode(struct inode *inode, int datasync)
+{
+ int err;
+
+ err = fsync_inode_buffers(inode);
+ if (!(inode->i_state & I_DIRTY))
+ return err;
+ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+ return err;
+
+ err |= ext2_sync_inode(inode);
return err ? -EIO : 0;
}
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index cf8fa5154..9e4a9b6b0 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -256,7 +256,7 @@ error_return:
* For other inodes, search forward from the parent directory\'s block
* group to find a free inode.
*/
-struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
+struct inode * ext2_new_inode (const struct inode * dir, int mode)
{
struct super_block * sb;
struct buffer_head * bh;
@@ -267,26 +267,22 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
struct ext2_group_desc * gdp;
struct ext2_group_desc * tmp;
struct ext2_super_block * es;
+ int err;
/* Cannot create files in a deleted directory */
- if (!dir || !dir->i_nlink) {
- *err = -EPERM;
- return NULL;
- }
+ if (!dir || !dir->i_nlink)
+ return ERR_PTR(-EPERM);
sb = dir->i_sb;
inode = new_inode(sb);
- if (!inode) {
- *err = -ENOMEM;
- return NULL;
- }
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
lock_super (sb);
es = sb->u.ext2_sb.s_es;
repeat:
gdp = NULL; i=0;
- *err = -ENOSPC;
if (S_ISDIR(mode)) {
avefreei = le32_to_cpu(es->s_free_inodes_count) /
sb->u.ext2_sb.s_groups_count;
@@ -365,18 +361,14 @@ repeat:
}
}
- if (!gdp) {
- unlock_super (sb);
- iput(inode);
- return NULL;
- }
+ err = -ENOSPC;
+ if (!gdp)
+ goto fail;
+
+ err = -EIO;
bitmap_nr = load_inode_bitmap (sb, i);
- if (bitmap_nr < 0) {
- unlock_super (sb);
- iput(inode);
- *err = -EIO;
- return NULL;
- }
+ if (bitmap_nr < 0)
+ goto fail;
bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
@@ -397,11 +389,11 @@ repeat:
ext2_error (sb, "ext2_new_inode",
"Free inodes count corrupted in group %d",
i);
- if (sb->s_flags & MS_RDONLY) {
- unlock_super (sb);
- iput (inode);
- return NULL;
- }
+ /* Is it really ENOSPC? */
+ err = -ENOSPC;
+ if (sb->s_flags & MS_RDONLY)
+ goto fail;
+
gdp->bg_free_inodes_count = 0;
mark_buffer_dirty(bh2);
}
@@ -412,10 +404,8 @@ repeat:
ext2_error (sb, "ext2_new_inode",
"reserved inode or inode > inodes count - "
"block_group = %d,inode=%d", i, j);
- unlock_super (sb);
- iput (inode);
- *err = -EIO;
- return NULL;
+ err = -EIO;
+ goto fail;
}
gdp->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
@@ -464,13 +454,15 @@ repeat:
sb->dq_op->drop(inode);
inode->i_nlink = 0;
iput(inode);
- *err = -EDQUOT;
- return NULL;
+ return ERR_PTR(-EDQUOT);
}
ext2_debug ("allocating inode %lu\n", inode->i_ino);
-
- *err = 0;
return inode;
+
+fail:
+ unlock_super(sb);
+ iput(inode);
+ return ERR_PTR(err);
}
unsigned long ext2_count_free_inodes (struct super_block * sb)
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 5852cef4c..658a06416 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -404,7 +404,7 @@ static int ext2_alloc_branch(struct inode *inode,
branch[n].p = (u32*) bh->b_data + offsets[n];
*branch[n].p = branch[n].key;
mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, inode);
if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -469,7 +469,7 @@ static inline int ext2_splice_branch(struct inode *inode,
/* had we spliced it onto indirect block? */
if (where->bh) {
- mark_buffer_dirty(where->bh);
+ mark_buffer_dirty_inode(where->bh, inode);
if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
ll_rw_block (WRITE, 1, &where->bh);
wait_on_buffer(where->bh);
@@ -591,7 +591,7 @@ struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, i
wait_on_buffer(bh);
memset(bh->b_data, 0, inode->i_sb->s_blocksize);
mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, inode);
}
return bh;
}
@@ -650,7 +650,7 @@ struct buffer_head * ext2_bread (struct inode * inode, int block,
return NULL;
}
-static int ext2_writepage(struct file *file, struct page *page)
+static int ext2_writepage(struct page *page)
{
return block_write_full_page(page,ext2_get_block);
}
@@ -907,7 +907,7 @@ void ext2_truncate (struct inode * inode)
if (partial == chain)
mark_inode_dirty(inode);
else
- mark_buffer_dirty(partial->bh);
+ mark_buffer_dirty_inode(partial->bh, inode);
ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
}
/* Clear the ends of indirect blocks on the shared branch */
@@ -916,7 +916,7 @@ void ext2_truncate (struct inode * inode)
partial->p + 1,
(u32*)partial->bh->b_data + addr_per_block,
(chain+n-1) - partial);
- mark_buffer_dirty(partial->bh);
+ mark_buffer_dirty_inode(partial->bh, inode);
if (IS_SYNC(inode)) {
ll_rw_block (WRITE, 1, &partial->bh);
wait_on_buffer (partial->bh);
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 3c981f75c..59d3ef492 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -296,7 +296,7 @@ int ext2_add_entry (struct inode * dir, const char * name, int namelen,
dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(dir);
dir->i_version = ++event;
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, dir);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -337,7 +337,7 @@ static int ext2_delete_entry (struct inode * dir,
else
de->inode = 0;
dir->i_version = ++event;
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, dir);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -361,11 +361,9 @@ static int ext2_delete_entry (struct inode * dir,
*/
static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
{
- struct inode * inode;
- int err;
-
- inode = ext2_new_inode (dir, mode, &err);
- if (!inode)
+ struct inode * inode = ext2_new_inode (dir, mode);
+ int err = PTR_ERR(inode);
+ if (IS_ERR(inode))
return err;
inode->i_op = &ext2_file_inode_operations;
@@ -387,11 +385,10 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
{
- struct inode * inode;
- int err;
+ struct inode * inode = ext2_new_inode (dir, mode);
+ int err = PTR_ERR(inode);
- inode = ext2_new_inode (dir, mode, &err);
- if (!inode)
+ if (IS_ERR(inode))
return err;
inode->i_uid = current->fsuid;
@@ -421,8 +418,9 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
if (dir->i_nlink >= EXT2_LINK_MAX)
return -EMLINK;
- inode = ext2_new_inode (dir, S_IFDIR, &err);
- if (!inode)
+ inode = ext2_new_inode (dir, S_IFDIR);
+ err = PTR_ERR(inode);
+ if (IS_ERR(inode))
return err;
inode->i_op = &ext2_dir_inode_operations;
@@ -449,7 +447,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
strcpy (de->name, "..");
ext2_set_de_type(dir->i_sb, de, S_IFDIR);
inode->i_nlink = 2;
- mark_buffer_dirty(dir_block);
+ mark_buffer_dirty_inode(dir_block, dir);
brelse (dir_block);
inode->i_mode = S_IFDIR | mode;
if (dir->i_mode & S_ISGID)
@@ -628,7 +626,9 @@ static int ext2_symlink (struct inode * dir, struct dentry *dentry, const char *
if (l > dir->i_sb->s_blocksize)
return -ENAMETOOLONG;
- if (!(inode = ext2_new_inode (dir, S_IFLNK, &err)))
+ inode = ext2_new_inode (dir, S_IFLNK);
+ err = PTR_ERR(inode);
+ if (IS_ERR(inode))
return err;
inode->i_mode = S_IFLNK | S_IRWXUGO;
@@ -755,7 +755,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
EXT2_FEATURE_INCOMPAT_FILETYPE))
new_de->file_type = old_de->file_type;
new_dir->i_version = ++event;
- mark_buffer_dirty(new_bh);
+ mark_buffer_dirty_inode(new_bh, new_dir);
if (IS_SYNC(new_dir)) {
ll_rw_block (WRITE, 1, &new_bh);
wait_on_buffer (new_bh);
@@ -786,7 +786,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
mark_inode_dirty(old_dir);
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
- mark_buffer_dirty(dir_bh);
+ mark_buffer_dirty_inode(dir_bh, old_inode);
old_dir->i_nlink--;
mark_inode_dirty(old_dir);
if (new_inode) {