diff options
Diffstat (limited to 'fs/ext2/fsync.c')
-rw-r--r-- | fs/ext2/fsync.c | 195 |
1 files changed, 31 insertions, 164 deletions
diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c index 1a13c876b..8ae361e73 100644 --- a/fs/ext2/fsync.c +++ b/fs/ext2/fsync.c @@ -17,6 +17,9 @@ * Removed unnecessary code duplication for little endian machines * and excessive __inline__s. * Andi Kleen, 1997 + * + * Major simplications and cleanup - we only need to do the metadata, because + * we can depend on generic_block_fdatasync() to sync the data blocks. */ #include <asm/uaccess.h> @@ -32,221 +35,84 @@ #include <linux/locks.h> -#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb)) -#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb)) +#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb)) +#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb)) -static int sync_block (struct inode * inode, u32 * block, int wait) +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, *block, blocksize); + bh = get_hash_table(inode->i_dev, le32_to_cpu(*block), blocksize); if (!bh) return 0; if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - brelse (bh); + brelse(bh); return -1; } if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { - brelse (bh); + brelse(bh); return 0; } - ll_rw_block (WRITE, 1, &bh); + ll_rw_block(WRITE, 1, &bh); bh->b_count--; return 0; } -#ifndef __LITTLE_ENDIAN -static int sync_block_swab32 (struct inode * inode, u32 * block, int wait) -{ - struct buffer_head * bh; - - if (!le32_to_cpu(*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)) { - brelse (bh); - return -1; - } - if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { - brelse (bh); - return 0; - } - ll_rw_block (WRITE, 1, &bh); - bh->b_count--; - return 0; -} -#else -#define sync_block_swab32 sync_block -#endif - - -static int sync_iblock (struct inode * inode, u32 * iblock, +static int sync_iblock(struct inode * inode, u32 * iblock, struct buffer_head ** bh, int wait) { int rc, tmp; *bh = NULL; - tmp = *iblock; - if (!tmp) - return 0; - rc = sync_block (inode, iblock, wait); - if (rc) - return rc; - *bh = bread (inode->i_dev, tmp, blocksize); - if (!*bh) - return -1; - return 0; -} - -#ifndef __LITTLE_ENDIAN -static int sync_iblock_swab32 (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_block_swab32 (inode, iblock, wait); + rc = sync_indirect(inode, iblock, wait); if (rc) return rc; - *bh = bread (inode->i_dev, tmp, blocksize); + *bh = bread(inode->i_dev, tmp, blocksize); if (!*bh) return -1; return 0; } -#else -#define sync_iblock_swab32 sync_iblock -#endif - -static int sync_direct (struct inode * inode, int wait) -{ - int i; - int rc, err = 0; - - for (i = 0; i < EXT2_NDIR_BLOCKS; i++) { - rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait); - if (rc) - err = rc; - } - return err; -} - -static int sync_indirect (struct inode * inode, u32 * iblock, int wait) -{ - int i; - struct buffer_head * ind_bh; - int rc, err = 0; - - rc = sync_iblock (inode, iblock, &ind_bh, wait); - if (rc || !ind_bh) - return rc; - - for (i = 0; i < addr_per_block; i++) { - rc = sync_block_swab32 (inode, - ((u32 *) ind_bh->b_data) + i, - wait); - if (rc) - err = rc; - } - brelse (ind_bh); - return err; -} - -#ifndef __LITTLE_ENDIAN -static __inline__ int sync_indirect_swab32 (struct inode * inode, u32 * iblock, int wait) -{ - int i; - struct buffer_head * ind_bh; - int rc, err = 0; - - rc = sync_iblock_swab32 (inode, iblock, &ind_bh, wait); - if (rc || !ind_bh) - return rc; - - for (i = 0; i < addr_per_block; i++) { - rc = sync_block_swab32 (inode, - ((u32 *) ind_bh->b_data) + i, - wait); - if (rc) - err = rc; - } - brelse (ind_bh); - return err; -} -#else -#define sync_indirect_swab32 sync_indirect -#endif -static int sync_dindirect (struct inode * inode, u32 * diblock, int wait) +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); + 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_swab32 (inode, - ((u32 *) dind_bh->b_data) + i, - wait); + rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait); if (rc) err = rc; } - brelse (dind_bh); + brelse(dind_bh); return err; } -#ifndef __LITTLE_ENDIAN -static __inline__ int sync_dindirect_swab32 (struct inode * inode, u32 * diblock, int wait) -{ - int i; - struct buffer_head * dind_bh; - int rc, err = 0; - - rc = sync_iblock_swab32 (inode, diblock, &dind_bh, wait); - if (rc || !dind_bh) - return rc; - - for (i = 0; i < addr_per_block; i++) { - rc = sync_indirect_swab32 (inode, - ((u32 *) dind_bh->b_data) + i, - wait); - if (rc) - err = rc; - } - brelse (dind_bh); - return err; -} -#else -#define sync_dindirect_swab32 sync_dindirect -#endif - -static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait) +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); + 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_swab32 (inode, - ((u32 *) tind_bh->b_data) + i, - wait); + rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait); if (rc) err = rc; } - brelse (tind_bh); + brelse(tind_bh); return err; } @@ -266,18 +132,19 @@ int ext2_sync_file(struct file * file, struct dentry *dentry) */ goto skip; + err = generic_buffer_fdatasync(inode, 0, ~0UL); + for (wait=0; wait<=1; wait++) { - err |= sync_direct (inode, wait); - err |= sync_indirect (inode, - inode->u.ext2_i.i_data+EXT2_IND_BLOCK, + 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); - 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); |