2 * linux/fs/sysv/fsync.c
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
9 * Copyright (C) 1993 Pascal Haible, Bruno Haible
12 * Copyright (C) 1993 Bruno Haible
14 * SystemV/Coherent fsync primitive
17 #include <linux/errno.h>
18 #include <linux/stat.h>
21 #include <linux/sysv_fs.h>
24 /* return values: 0 means OK/done, 1 means redo, -1 means I/O error. */
26 /* Sync one block. The block number is
27 * from_coh_ulong(*blockp) if convert=1, *blockp if convert=0.
29 static int sync_block (struct inode
* inode
, u32
*blockp
, int convert
, int wait
)
31 struct buffer_head
* bh
;
33 struct super_block
* sb
;
35 block
= tmp
= *blockp
;
37 block
= from_coh_ulong(block
);
41 bh
= sv_get_hash_table(sb
, inode
->i_dev
, block
);
48 if (wait
&& buffer_req(bh
) && !buffer_uptodate(bh
)) {
52 if (wait
|| !buffer_uptodate(bh
) || !buffer_dirty(bh
)) {
56 ll_rw_block(WRITE
, 1, &bh
);
57 atomic_dec(&bh
->b_count
);
61 /* Sync one block full of indirect pointers and read it because we'll need it. */
62 static int sync_iblock (struct inode
* inode
, u32
* iblockp
, int convert
,
63 struct buffer_head
* *bh
, int wait
)
69 block
= tmp
= *iblockp
;
71 block
= from_coh_ulong(block
);
74 rc
= sync_block (inode
, iblockp
, convert
, wait
);
77 *bh
= sv_bread(inode
->i_sb
, inode
->i_dev
, block
);
78 if (tmp
!= *iblockp
) {
89 static int sync_direct(struct inode
*inode
, int wait
)
94 for (i
= 0; i
< 10; i
++) {
95 rc
= sync_block (inode
, inode
->u
.sysv_i
.i_data
+ i
, 0, wait
);
104 static int sync_indirect(struct inode
*inode
, u32
*iblockp
, int convert
, int wait
)
107 struct buffer_head
* ind_bh
;
109 struct super_block
* sb
;
111 rc
= sync_iblock (inode
, iblockp
, convert
, &ind_bh
, wait
);
116 for (i
= 0; i
< sb
->sv_ind_per_block
; i
++) {
117 rc
= sync_block (inode
,
118 ((u32
*) ind_bh
->b_data
) + i
, sb
->sv_convert
,
129 static int sync_dindirect(struct inode
*inode
, u32
*diblockp
, int convert
,
133 struct buffer_head
* dind_bh
;
135 struct super_block
* sb
;
137 rc
= sync_iblock (inode
, diblockp
, convert
, &dind_bh
, wait
);
142 for (i
= 0; i
< sb
->sv_ind_per_block
; i
++) {
143 rc
= sync_indirect (inode
,
144 ((u32
*) dind_bh
->b_data
) + i
, sb
->sv_convert
,
155 static int sync_tindirect(struct inode
*inode
, u32
*tiblockp
, int convert
,
159 struct buffer_head
* tind_bh
;
161 struct super_block
* sb
;
163 rc
= sync_iblock (inode
, tiblockp
, convert
, &tind_bh
, wait
);
168 for (i
= 0; i
< sb
->sv_ind_per_block
; i
++) {
169 rc
= sync_dindirect (inode
,
170 ((u32
*) tind_bh
->b_data
) + i
, sb
->sv_convert
,
181 int sysv_sync_file(struct file
* file
, struct dentry
*dentry
)
184 struct inode
*inode
= dentry
->d_inode
;
186 if (!(S_ISREG(inode
->i_mode
) || S_ISDIR(inode
->i_mode
) ||
187 S_ISLNK(inode
->i_mode
)))
190 for (wait
=0; wait
<=1; wait
++) {
191 err
|= sync_direct(inode
, wait
);
192 err
|= sync_indirect(inode
, inode
->u
.sysv_i
.i_data
+10, 0, wait
);
193 err
|= sync_dindirect(inode
, inode
->u
.sysv_i
.i_data
+11, 0, wait
);
194 err
|= sync_tindirect(inode
, inode
->u
.sysv_i
.i_data
+12, 0, wait
);
196 err
|= sysv_sync_inode (inode
);
197 return (err
< 0) ? -EIO
: 0;