--- drivers/acorn/block/fd1772.c~ Thu Jan 7 16:46:58 1999 +++ drivers/acorn/block/fd1772.c Wed May 5 23:46:42 1999 @@ -1569,7 +1569,7 @@ if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT))) /* if the file is mounted OR (writable now AND writable at open time) Linus: Does this cover all cases? */ - block_fsync(inode, filp); + block_fsync(inode, filp, 0); if (fd_ref[drive] < 0) fd_ref[drive] = 0; --- drivers/block/ataflop.c~ Tue Dec 29 19:23:59 1998 +++ drivers/block/ataflop.c Wed May 5 23:46:13 1999 @@ -1986,7 +1986,7 @@ * sync is required. Otherwise, sync if filp is writable. */ if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT))) - block_fsync (filp, filp->f_dentry); + block_fsync (filp, filp->f_dentry, 0); if (fd_ref[drive] < 0) fd_ref[drive] = 0; --- drivers/block/floppy.c~ Tue Apr 20 22:33:21 1999 +++ drivers/block/floppy.c Wed May 5 23:45:40 1999 @@ -3677,7 +3677,7 @@ * sync is required. Otherwise, sync if filp is writable. */ if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT))) - block_fsync(filp, filp->f_dentry); + block_fsync(filp, filp->f_dentry, 0); if (UDRS->fd_ref < 0) UDRS->fd_ref=0; --- drivers/block/swim3.c~ Tue Apr 20 22:33:02 1999 +++ drivers/block/swim3.c Wed May 5 23:46:26 1999 @@ -941,7 +941,7 @@ * sync is required. Otherwise, sync if filp is writable. */ if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT))) - block_fsync (filp, filp->f_dentry); + block_fsync (filp, filp->f_dentry, 0); fs = &floppy_states[devnum]; sw = fs->swim3; --- fs/block_dev.c~ Fri Nov 13 18:07:26 1998 +++ fs/block_dev.c Wed May 5 23:16:42 1999 @@ -292,7 +292,7 @@ * since the vma has no handle. */ -int block_fsync(struct file *filp, struct dentry *dentry) +int block_fsync(struct file *filp, struct dentry *dentry, int datasync) { return fsync_dev(dentry->d_inode->i_rdev); } --- fs/buffer.c~ Thu May 6 00:54:43 1999 +++ fs/buffer.c Thu May 6 11:14:26 1999 @@ -627,13 +627,14 @@ while (!list_empty(&inode->i_dirty_buffers)) { bh = BH_ENTRY(inode->i_dirty_buffers.next); list_del(&bh->b_inode_buffers); - if (!buffer_dirty(bh)) + if (!buffer_dirty(bh) && !buffer_locked(bh)) bh->b_inode = NULL; else { bh->b_inode = &tmp; list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers); bh->b_count++; - ll_rw_block(WRITE, 1, &bh); + if (buffer_dirty(bh)) + ll_rw_block(WRITE, 1, &bh); } } --- fs/coda/dir.c~ Tue Apr 20 22:33:35 1999 +++ fs/coda/dir.c Wed May 5 23:32:39 1999 @@ -50,7 +50,7 @@ /* support routines */ static int coda_venus_readdir(struct file *filp, void *dirent, filldir_t filldir); -int coda_fsync(struct file *, struct dentry *dentry); +int coda_fsync(struct file *, struct dentry *dentry, int); int coda_crossvol_rename = 0; int coda_hasmknod = 0; --- fs/coda/file.c~ Mon Aug 31 23:46:10 1998 +++ fs/coda/file.c Wed May 5 23:49:58 1999 @@ -32,7 +32,7 @@ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma); /* also exported from this file (used for dirs) */ -int coda_fsync(struct file *, struct dentry *dentry); +int coda_fsync(struct file *, struct dentry *dentry, int); struct inode_operations coda_file_inode_operations = { &coda_file_operations, /* default file operations */ @@ -205,7 +205,7 @@ return result; } -int coda_fsync(struct file *coda_file, struct dentry *coda_dentry) +int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) { struct coda_inode_info *cnp; struct inode *coda_inode = coda_dentry->d_inode; @@ -234,7 +234,7 @@ down(&cont_inode->i_sem); - result = file_fsync(&cont_file ,&cont_dentry); + result = file_fsync(&cont_file ,&cont_dentry, 0); if ( result == 0 ) { result = venus_fsync(coda_inode->i_sb, &(cnp->c_fid)); } --- fs/ext2/file.c~ Mon Dec 21 23:22:54 1998 +++ fs/ext2/file.c Wed May 5 23:55:53 1999 @@ -270,7 +270,10 @@ buf += c; count -= c; mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 0); + /* Even if the file is open for O_SYNC write, we need to + * attach the dirty buffer to the inode to avoid a + * concurrent fsync() returning early. */ + mark_buffer_dirty_inode(bh, 0, inode); if (filp->f_flags & O_SYNC) bufferlist[buffercount++] = bh; @@ -307,7 +310,9 @@ inode->u.ext2_i.i_osync--; inode->i_ctime = inode->i_mtime = CURRENT_TIME; *ppos = pos; - mark_inode_dirty(inode); + mark_inode_dirty_sync(inode); + if (filp->f_flags & O_SYNC) + ext2_sync_file(filp, filp->f_dentry, 0); return written; } --- fs/ext2/fsync.c~ Wed May 20 21:09:12 1998 +++ fs/ext2/fsync.c Wed May 5 23:57:14 1999 @@ -32,254 +32,23 @@ #include -#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) -{ - struct buffer_head * bh; - - if (!*block) - return 0; - bh = get_hash_table (inode->i_dev, *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; -} - -#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, - 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); - if (rc) - return rc; - *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) -{ - 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_swab32 (inode, - ((u32 *) dind_bh->b_data) + i, - wait); - if (rc) - err = rc; - } - 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) -{ - 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_swab32 (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 ? */ -int ext2_sync_file(struct file * file, struct dentry *dentry) +int ext2_sync_file(struct file * file, struct dentry *dentry, int datasync) { - int wait, err = 0; + int err; struct inode *inode = dentry->d_inode; - - if (S_ISLNK(inode->i_mode) && !(inode->i_blocks)) - /* - * Don't sync fast links! - */ - goto skip; - - for (wait=0; wait<=1; wait++) - { - err |= sync_direct (inode, 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); + + 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; } --- fs/ext2/inode.c~ Tue Apr 20 22:33:09 1999 +++ fs/ext2/inode.c Wed May 5 22:22:53 1999 @@ -123,7 +123,7 @@ } memset(bh->b_data, 0, inode->i_sb->s_blocksize); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, inode); brelse (bh); } else { ext2_discard_prealloc (inode); @@ -340,7 +340,7 @@ goto repeat; } *p = le32_to_cpu(tmp); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, inode); if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); --- fs/ext2/namei.c~ Tue Apr 20 22:33:36 1999 +++ fs/ext2/namei.c Wed May 5 22:22:52 1999 @@ -304,7 +304,7 @@ dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); *res_dir = de; *err = 0; return bh; @@ -386,7 +386,7 @@ EXT2_FEATURE_INCOMPAT_FILETYPE)) de->file_type = EXT2_FT_REG_FILE; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -439,7 +439,7 @@ if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = to_kdev_t(rdev); mark_inode_dirty(inode); - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -500,7 +500,7 @@ EXT2_FEATURE_INCOMPAT_FILETYPE)) de->file_type = EXT2_FT_DIR; inode->i_nlink = 2; - mark_buffer_dirty(dir_block, 1); + mark_buffer_dirty_inode(dir_block, 1, dir); brelse (dir_block); inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask); if (dir->i_mode & S_ISGID) @@ -514,7 +514,7 @@ EXT2_FEATURE_INCOMPAT_FILETYPE)) de->file_type = EXT2_FT_DIR; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -624,7 +624,7 @@ dir->i_version = ++event; if (retval) goto end_rmdir; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -677,7 +677,7 @@ if (retval) goto end_unlink; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -736,7 +736,7 @@ link[i++] = c; link[i] = 0; if (name_block) { - mark_buffer_dirty(name_block, 1); + mark_buffer_dirty_inode(name_block, 1, inode); brelse (name_block); } inode->i_size = i; @@ -750,7 +750,7 @@ EXT2_FEATURE_INCOMPAT_FILETYPE)) de->file_type = EXT2_FT_SYMLINK; dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -803,7 +803,7 @@ de->file_type = EXT2_FT_FIFO; } dir->i_version = ++event; - mark_buffer_dirty(bh, 1); + mark_buffer_dirty_inode(bh, 1, dir); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); @@ -904,7 +904,7 @@ 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, 1); + mark_buffer_dirty_inode(dir_bh, 1, old_inode); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { @@ -916,12 +916,12 @@ mark_inode_dirty(new_dir); } } - mark_buffer_dirty(old_bh, 1); + mark_buffer_dirty_inode(old_bh, 1, old_dir); if (IS_SYNC(old_dir)) { ll_rw_block (WRITE, 1, &old_bh); wait_on_buffer (old_bh); } - mark_buffer_dirty(new_bh, 1); + mark_buffer_dirty_inode(new_bh, 1, new_dir); if (IS_SYNC(new_dir)) { ll_rw_block (WRITE, 1, &new_bh); wait_on_buffer (new_bh); --- fs/ext2/truncate.c~ Mon Oct 5 18:04:34 1998 +++ fs/ext2/truncate.c Wed May 5 22:22:45 1999 @@ -143,7 +143,7 @@ */ bforget(bh); if (ind_bh) - mark_buffer_dirty(ind_bh, 1); + mark_buffer_dirty_inode(ind_bh, 1, inode); ext2_free_blocks (inode, tmp, 1); goto out; } @@ -230,7 +230,7 @@ inode->i_ino, tmp); *p = 0; if (dind_bh) - mark_buffer_dirty(dind_bh, 1); + mark_buffer_dirty_inode(dind_bh, 1, inode); else mark_inode_dirty(inode); return 0; @@ -266,7 +266,7 @@ inode->i_blocks -= blocks; mark_inode_dirty(inode); bforget(bh); - mark_buffer_dirty(ind_bh, 1); + mark_buffer_dirty_inode(ind_bh, 1, inode); /* accumulate blocks to free if they're contiguous */ if (free_count == 0) @@ -312,7 +312,7 @@ inode->i_ino, tmp); *p = 0; if (tind_bh) - mark_buffer_dirty(tind_bh, 1); + mark_buffer_dirty_inode(tind_bh, 1, inode); else mark_inode_dirty(inode); return 0; @@ -425,7 +425,7 @@ if (bh) { memset (bh->b_data + offset, 0, inode->i_sb->s_blocksize - offset); - mark_buffer_dirty (bh, 0); + mark_buffer_dirty_inode (bh, 0, inode); brelse (bh); } } --- fs/inode.c~ Tue Apr 20 22:33:36 1999 +++ fs/inode.c Thu May 6 01:07:34 1999 @@ -79,14 +79,14 @@ * In short, make sure you hash any inodes _before_ * you start marking them dirty.. */ -void __mark_inode_dirty(struct inode *inode) +void __mark_inode_dirty(struct inode *inode, int flags) { struct super_block * sb = inode->i_sb; if (sb) { spin_lock(&inode_lock); - if (!(inode->i_state & I_DIRTY)) { - inode->i_state |= I_DIRTY; + if ((inode->i_state & flags) != flags) { + inode->i_state |= flags; /* Only add valid (ie hashed) inodes to the dirty list */ if (!list_empty(&inode->i_hash)) { list_del(&inode->i_list); @@ -129,6 +129,7 @@ init_waitqueue(&inode->i_wait); INIT_LIST_HEAD(&inode->i_hash); INIT_LIST_HEAD(&inode->i_dentry); + INIT_LIST_HEAD(&inode->i_dirty_buffers); sema_init(&inode->i_sem, 1); sema_init(&inode->i_atomic_write, 1); } @@ -149,7 +150,8 @@ list_del(&inode->i_list); list_add(&inode->i_list, &inode_in_use); /* Set I_LOCK, reset I_DIRTY */ - inode->i_state ^= I_DIRTY | I_LOCK; + inode->i_state |= I_LOCK; + inode->i_state &= ~I_DIRTY; spin_unlock(&inode_lock); write_inode(inode); @@ -194,6 +196,7 @@ spin_unlock(&inode_lock); } + /* * Called with the spinlock already held.. */ @@ -291,7 +294,7 @@ inode = list_entry(tmp, struct inode, i_list); if (inode->i_sb != sb) continue; - if (!inode->i_count) { + if (!inode->i_count && list_empty(&inode->i_dirty_buffers)) { list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); list_del(&inode->i_list); @@ -336,7 +339,8 @@ * dispose_list. */ #define CAN_UNUSE(inode) \ - (((inode)->i_count | (inode)->i_state) == 0) + (((inode)->i_count | (inode)->i_state) == 0 && \ + list_empty(&(inode)->i_dirty_buffers)) #define INODE(entry) (list_entry(entry, struct inode, i_list)) static int free_inodes(void) @@ -802,5 +806,5 @@ if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return; if ( IS_RDONLY (inode) ) return; inode->i_atime = CURRENT_TIME; - mark_inode_dirty (inode); + mark_inode_dirty_sync (inode); } /* End Function update_atime */ --- fs/minix/fsync.c~ Thu Nov 12 19:44:09 1998 +++ fs/minix/fsync.c Wed May 5 23:24:36 1999 @@ -332,7 +332,7 @@ * NULL */ -int minix_sync_file(struct file * file, struct dentry *dentry) +int minix_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; --- fs/ncpfs/file.c~ Mon Aug 24 21:02:44 1998 +++ fs/ncpfs/file.c Wed May 5 23:30:08 1999 @@ -26,7 +26,7 @@ return a < b ? a : b; } -static int ncp_fsync(struct file *file, struct dentry *dentry) +static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync) { return 0; } --- fs/nfs/file.c~ Tue Apr 20 22:33:09 1999 +++ fs/nfs/file.c Wed May 5 23:27:13 1999 @@ -36,7 +36,7 @@ static ssize_t nfs_file_read(struct file *, char *, size_t, loff_t *); static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); static int nfs_file_flush(struct file *); -static int nfs_fsync(struct file *, struct dentry *dentry); +static int nfs_fsync(struct file *, struct dentry *dentry, int); static struct file_operations nfs_file_operations = { NULL, /* lseek - default */ @@ -141,7 +141,7 @@ * whether any write errors occurred for this process. */ static int -nfs_fsync(struct file *file, struct dentry *dentry) +nfs_fsync(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int status; --- fs/nfsd/vfs.c~ Tue Apr 20 22:33:36 1999 +++ fs/nfsd/vfs.c Wed May 5 23:49:38 1999 @@ -398,7 +398,7 @@ void nfsd_sync(struct inode *inode, struct file *filp) { - filp->f_op->fsync(filp, filp->f_dentry); + filp->f_op->fsync(filp, filp->f_dentry, 0); } /* --- fs/qnx4/fsync.c~ Tue Sep 1 18:43:13 1998 +++ fs/qnx4/fsync.c Wed May 5 23:30:54 1999 @@ -146,7 +146,7 @@ return err; } -int qnx4_sync_file(struct file *file, struct dentry *dentry) +int qnx4_sync_file(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int wait, err = 0; --- fs/smbfs/file.c~ Wed Mar 17 16:12:22 1999 +++ fs/smbfs/file.c Wed May 5 23:29:22 1999 @@ -39,7 +39,7 @@ } static int -smb_fsync(struct file *file, struct dentry * dentry) +smb_fsync(struct file *file, struct dentry * dentry, int datasync) { #ifdef SMBFS_DEBUG_VERBOSE printk("smb_fsync: sync file %s/%s\n", --- fs/sysv/fsync.c~ Sun Sep 13 20:12:34 1998 +++ fs/sysv/fsync.c Wed May 5 23:28:41 1999 @@ -178,7 +178,7 @@ return err; } -int sysv_sync_file(struct file * file, struct dentry *dentry) +int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync) { int wait, err = 0; struct inode *inode = dentry->d_inode; --- include/linux/ext2_fs.h~ Mon Dec 28 06:18:28 1998 +++ include/linux/ext2_fs.h Wed May 5 23:27:47 1999 @@ -544,7 +544,7 @@ extern int ext2_write (struct inode *, struct file *, char *, int); /* fsync.c */ -extern int ext2_sync_file (struct file *, struct dentry *); +extern int ext2_sync_file (struct file *, struct dentry *, int); /* ialloc.c */ extern struct inode * ext2_new_inode (const struct inode *, int, int *); --- include/linux/fs.h~ Wed May 5 23:43:38 1999 +++ include/linux/fs.h Wed May 5 23:45:33 1999 @@ -402,10 +402,10 @@ }; /* Inode state bits.. */ -#define I_DIRTY_SYNC 1 -#define I_LOCK 2 -#define I_FREEING 4 -#define I_DIRTY_DATASYNC 8 +#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ +#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ +#define I_LOCK 4 +#define I_FREEING 8 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC) --- include/linux/minix_fs.h~ Sun Nov 22 17:34:01 1998 +++ include/linux/minix_fs.h Wed May 5 23:24:45 1999 @@ -115,7 +115,7 @@ extern void minix_truncate(struct inode *); extern int init_minix_fs(void); extern int minix_sync_inode(struct inode *); -extern int minix_sync_file(struct file *, struct dentry *); +extern int minix_sync_file(struct file *, struct dentry *, int); extern struct inode_operations minix_file_inode_operations; extern struct inode_operations minix_dir_inode_operations; --- include/linux/qnx4_fs.h~ Mon Aug 31 21:01:35 1998 +++ include/linux/qnx4_fs.h Wed May 5 23:31:14 1999 @@ -114,7 +114,7 @@ extern void qnx4_free_inode(struct inode *inode); extern int qnx4_unlink(struct inode *dir, struct dentry *dentry); extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry); -extern int qnx4_sync_file(struct file *file, struct dentry *dentry); +extern int qnx4_sync_file(struct file *file, struct dentry *dentry, int); extern int qnx4_sync_inode(struct inode *inode); extern int qnx4_bmap(struct inode *inode, int block); --- include/linux/sysv_fs.h~ Wed May 5 22:58:41 1999 +++ include/linux/sysv_fs.h Wed May 5 23:59:15 1999 @@ -400,7 +400,7 @@ extern void sysv_write_inode(struct inode *); extern int sysv_statfs(struct super_block *, struct statfs *, int); extern int sysv_sync_inode(struct inode *); -extern int sysv_sync_file(struct file *, struct dentry *); +extern int sysv_sync_file(struct file *, struct dentry *, int); extern int sysv_mmap(struct file *, struct vm_area_struct *); extern struct inode_operations sysv_file_inode_operations; --- mm/filemap.c~ Tue Apr 20 22:33:14 1999 +++ mm/filemap.c Wed May 5 23:52:28 1999 @@ -1356,7 +1356,10 @@ struct dentry * dentry = file->f_dentry; struct inode * inode = dentry->d_inode; down(&inode->i_sem); - error = file_fsync(file, dentry); + /* According to SingleUnix, we are only + * required to implement fdatasync, not + * fsync, consistency here. */ + error = file_fsync(file, dentry, 1); up(&inode->i_sem); } } .