summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/fs/ufs_trans.h
blob: cdaf55c87c8e942fe595f0c7940d1bef94381d48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
 *
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_FS_UFS_TRANS_H
#define	_SYS_FS_UFS_TRANS_H

#ifdef	__cplusplus
extern "C" {
#endif

#include	<sys/types.h>
#include	<sys/cred.h>
#include	<sys/fs/ufs_fs.h>

/*
 * Types of deltas
 */
typedef enum delta_type {
	DT_NONE,	/*  0 no assigned type */
	DT_SB,		/*  1 superblock */
	DT_CG,		/*  2 cylinder group */
	DT_SI,		/*  3 summary info */
	DT_AB,		/*  4 allocation block */
	DT_ABZERO,	/*  5 a zero'ed allocation block */
	DT_DIR,		/*  6 directory */
	DT_INODE,	/*  7 inode */
	DT_FBI,		/*  8 fbiwrite */
	DT_QR,		/*  9 quota record */
	DT_COMMIT,	/* 10 commit record */
	DT_CANCEL,	/* 11 cancel record */
	DT_BOT,		/* 12 begin transaction */
	DT_EOT,		/* 13 end   transaction */
	DT_UD,		/* 14 userdata */
	DT_SUD,		/* 15 userdata found during log scan */
	DT_SHAD,	/* 16 data for a shadow inode */
	DT_MAX		/* 17 maximum delta type */
} delta_t;

/*
 * transaction operation types
 */
typedef enum top_type {
	TOP_READ_SYNC,		/* 0 */
	TOP_WRITE,		/* 1 */
	TOP_WRITE_SYNC,		/* 2 */
	TOP_SETATTR,		/* 3 */
	TOP_CREATE,		/* 4 */
	TOP_REMOVE,		/* 5 */
	TOP_LINK,		/* 6 */
	TOP_RENAME,		/* 7 */
	TOP_MKDIR,		/* 8 */
	TOP_RMDIR,		/* 9 */
	TOP_SYMLINK,		/* 10 */
	TOP_FSYNC,		/* 11 */
	TOP_GETPAGE,		/* 12 */
	TOP_PUTPAGE,		/* 13 */
	TOP_SBUPDATE_FLUSH,	/* 14 */
	TOP_SBUPDATE_UPDATE,	/* 15 */
	TOP_SBUPDATE_UNMOUNT,	/* 16 */
	TOP_SYNCIP_CLOSEDQ,	/* 17 */
	TOP_SYNCIP_FLUSHI,	/* 18 */
	TOP_SYNCIP_HLOCK,	/* 19 */
	TOP_SYNCIP_SYNC,	/* 20 */
	TOP_SYNCIP_FREE,	/* 21 */
	TOP_SBWRITE_RECLAIM,	/* 22 */
	TOP_SBWRITE_STABLE,	/* 23 */
	TOP_IFREE,		/* 24 */
	TOP_IUPDAT,		/* 25 */
	TOP_MOUNT,		/* 26 */
	TOP_COMMIT_ASYNC,	/* 27 */
	TOP_COMMIT_FLUSH,	/* 28 */
	TOP_COMMIT_UPDATE,	/* 29 */
	TOP_COMMIT_UNMOUNT,	/* 30 */
	TOP_SETSECATTR,		/* 31 */
	TOP_QUOTA,		/* 32 */
	TOP_ITRUNC,		/* 33 */
	TOP_ALLOCSP,		/* 34 */
	TOP_MAX			/* 35 TOP_MAX MUST be the last entry */
} top_t;

struct inode;
struct ufsvfs;

/*
 * vfs_log == NULL means not logging
 */
#define	TRANS_ISTRANS(ufsvfsp)	(ufsvfsp->vfs_log)

/*
 * begin a synchronous transaction
 */
#define	TRANS_BEGIN_SYNC(ufsvfsp, vid, vsize, error)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) { \
		error = 0; \
		top_begin_sync(ufsvfsp, vid, vsize, &error); \
	} \
}

/*
 * begin a asynchronous transaction
 */
#define	TRANS_BEGIN_ASYNC(ufsvfsp, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		(void) top_begin_async(ufsvfsp, vid, vsize, 0); \
}

/*
 * try to begin a asynchronous transaction
 */
#define	TRANS_TRY_BEGIN_ASYNC(ufsvfsp, vid, vsize, err)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		err = top_begin_async(ufsvfsp, vid, vsize, 1); \
	else\
		err = 0; \
}

/*
 * Begin a synchronous or asynchronous transaction.
 * The lint case is needed because vsize can be a constant.
 */
#ifndef __lint

#define	TRANS_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) {\
		if (ufsvfsp->vfs_syncdir) {\
			int error = 0; \
			ASSERT(vsize); \
			top_begin_sync(ufsvfsp, vid, vsize, &error); \
			ASSERT(error == 0); \
			issync = 1; \
		} else {\
			(void) top_begin_async(ufsvfsp, vid, vsize, 0); \
			issync = 0; \
		}\
	}\
}

#else /* __lint */

#define	TRANS_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) {\
		if (ufsvfsp->vfs_syncdir) {\
			int error = 0; \
			top_begin_sync(ufsvfsp, vid, vsize, &error); \
			issync = 1; \
		} else {\
			(void) top_begin_async(ufsvfsp, vid, vsize, 0); \
			issync = 0; \
		}\
	}\
}
#endif /* __lint */

/*
 * try to begin a synchronous or asynchronous transaction
 */

#define	TRANS_TRY_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize, error)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) {\
		if (ufsvfsp->vfs_syncdir) {\
			ASSERT(vsize); \
			top_begin_sync(ufsvfsp, vid, vsize, &error); \
			ASSERT(error == 0); \
			issync = 1; \
		} else {\
			error = top_begin_async(ufsvfsp, vid, vsize, 1); \
			issync = 0; \
		}\
	}\
}\


/*
 * end a asynchronous transaction
 */
#define	TRANS_END_ASYNC(ufsvfsp, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		top_end_async(ufsvfsp, vid, vsize); \
}

/*
 * end a synchronous transaction
 */
#define	TRANS_END_SYNC(ufsvfsp, error, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		top_end_sync(ufsvfsp, &error, vid, vsize); \
}

/*
 * end a synchronous or asynchronous transaction
 */
#define	TRANS_END_CSYNC(ufsvfsp, error, issync, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		if (issync)\
			top_end_sync(ufsvfsp, &error, vid, vsize); \
		else\
			top_end_async(ufsvfsp, vid, vsize); \
}
/*
 * record a delta
 */
#define	TRANS_DELTA(ufsvfsp, mof, nb, dtyp, func, arg) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_delta(ufsvfsp, (offset_t)(mof), nb, dtyp, func, arg)

/*
 * cancel a delta
 */
#define	TRANS_CANCEL(ufsvfsp, mof, nb, flags) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_cancel(ufsvfsp, (offset_t)(mof), nb, flags)
/*
 * log a delta
 */
#define	TRANS_LOG(ufsvfsp, va, mof, nb, buf, bufsz) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_log(ufsvfsp, va, (offset_t)(mof), nb, buf, bufsz)
/*
 * check if a range is being canceled (converting from metadata into userdata)
 */
#define	TRANS_ISCANCEL(ufsvfsp, mof, nb) \
	((TRANS_ISTRANS(ufsvfsp)) ? \
		top_iscancel(ufsvfsp, (offset_t)(mof), nb) : 0)
/*
 * put the log into error state
 */
#define	TRANS_SETERROR(ufsvfsp) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_seterror(ufsvfsp)
/*
 * check if device has had an error
 */
#define	TRANS_ISERROR(ufsvfsp) \
	((TRANS_ISTRANS(ufsvfsp)) ? \
		ufsvfsp->vfs_log->un_flags & LDL_ERROR : 0)

/*
 * The following macros provide a more readable interface to TRANS_DELTA
 */
#define	TRANS_BUF(ufsvfsp, vof, nb, bp, type) \
	TRANS_DELTA(ufsvfsp, \
		ldbtob(bp->b_blkno) + (offset_t)(vof), nb, type, \
		ufs_trans_push_buf, bp->b_blkno)

#define	TRANS_BUF_ITEM_128(ufsvfsp, item, base, bp, type) \
	TRANS_BUF(ufsvfsp, \
	(((uintptr_t)&(item)) & ~(128 - 1)) - (uintptr_t)(base), 128, bp, type)

#define	TRANS_INODE(ufsvfsp, ip) \
	TRANS_DELTA(ufsvfsp, ip->i_doff, sizeof (struct dinode), \
			DT_INODE, ufs_trans_push_inode, ip->i_number)

/*
 * If ever parts of an inode except the timestamps are logged using
 * this macro (or any other technique), bootloader logging support must
 * be made aware of these changes.
 */
#define	TRANS_INODE_DELTA(ufsvfsp, vof, nb, ip) \
	TRANS_DELTA(ufsvfsp, (ip->i_doff + (offset_t)(vof)), \
		nb, DT_INODE, ufs_trans_push_inode, ip->i_number)

#define	TRANS_INODE_TIMES(ufsvfsp, ip) \
	TRANS_INODE_DELTA(ufsvfsp, (caddr_t)&ip->i_atime - (caddr_t)&ip->i_ic, \
		sizeof (struct timeval32) * 3, ip)

/*
 * Check if we need to log cylinder group summary info.
 */
#define	TRANS_SI(ufsvfsp, fs, cg) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		if (ufsvfsp->vfs_nolog_si) \
			fs->fs_si = FS_SI_BAD; \
		else \
			TRANS_DELTA(ufsvfsp, \
				ldbtob(fsbtodb(fs, fs->fs_csaddr)) + \
				((caddr_t)&fs->fs_cs(fs, cg) - \
				(caddr_t)fs->fs_u.fs_csp), \
				sizeof (struct csum), DT_SI, \
				ufs_trans_push_si, cg)

#define	TRANS_DIR(ip, offset) \
	(TRANS_ISTRANS(ip->i_ufsvfs) ? ufs_trans_dir(ip, offset) : 0)

#define	TRANS_QUOTA(dqp)	\
	if (TRANS_ISTRANS(dqp->dq_ufsvfsp))	\
		ufs_trans_quota(dqp);

#define	TRANS_DQRELE(ufsvfsp, dqp) \
	if (TRANS_ISTRANS(ufsvfsp) && \
	    ((curthread->t_flag & T_DONTBLOCK) == 0)) { \
		ufs_trans_dqrele(dqp); \
	} else { \
		rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER); \
		dqrele(dqp); \
		rw_exit(&ufsvfsp->vfs_dqrwlock); \
	}

#define	TRANS_ITRUNC(ip, length, flags, cr)	\
	ufs_trans_itrunc(ip, length, flags, cr);

#define	TRANS_WRITE_RESV(ip, uiop, ulp, resvp, residp)	\
	if ((TRANS_ISTRANS(ip->i_ufsvfs) != NULL) && (ulp != NULL)) \
		ufs_trans_write_resv(ip, uiop, resvp, residp);

#define	TRANS_WRITE(ip, uiop, ioflag, err, ulp, cr, resv, resid)	\
	if ((TRANS_ISTRANS(ip->i_ufsvfs) != NULL) && (ulp != NULL)) \
		err = ufs_trans_write(ip, uiop, ioflag, cr, resv, resid); \
	else \
		err = wrip(ip, uiop, ioflag, cr);

/*
 * These functions "wrap" functions that are not VOP or VFS
 * entry points but must still use the TRANS_BEGIN/TRANS_END
 * protocol
 */
#define	TRANS_SBUPDATE(ufsvfsp, vfsp, topid) \
	ufs_trans_sbupdate(ufsvfsp, vfsp, topid)
#define	TRANS_SYNCIP(ip, bflags, iflag, topid) \
	ufs_syncip(ip, bflags, iflag, topid)
#define	TRANS_SBWRITE(ufsvfsp, topid)	ufs_trans_sbwrite(ufsvfsp, topid)
#define	TRANS_IUPDAT(ip, waitfor)	ufs_trans_iupdat(ip, waitfor)

#ifdef	DEBUG
/*
 * Test/Debug ops
 *	The following ops maintain the metadata map.
 *	The metadata map is a debug/test feature.
 *	These ops are *not* used in the production product.
 */

/*
 * Set a flag if meta data checking.
 */
#define	TRANS_DOMATAMAP(ufsvfsp) \
	ufsvfsp->vfs_domatamap = \
		(TRANS_ISTRANS(ufsvfsp) && \
		(ufsvfsp->vfs_log->un_debug & MT_MATAMAP))

#define	TRANS_MATA_IGET(ufsvfsp, ip) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_iget(ip)

#define	TRANS_MATA_FREE(ufsvfsp, mof, nb) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_free(ufsvfsp, (offset_t)(mof), nb)

#define	TRANS_MATA_ALLOC(ufsvfsp, ip, bno, size, zero) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_alloc(ufsvfsp, ip, bno, size, zero)

#define	TRANS_MATA_MOUNT(ufsvfsp) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_mount(ufsvfsp)

#define	TRANS_MATA_UMOUNT(ufsvfsp) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_umount(ufsvfsp)

#define	TRANS_MATA_SI(ufsvfsp, fs) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_si(ufsvfsp, fs)

#define	TRANS_MATAADD(ufsvfsp, mof, nb) \
	top_mataadd(ufsvfsp, (offset_t)(mof), nb)

#else /* !DEBUG */

#define	TRANS_DOMATAMAP(ufsvfsp)
#define	TRANS_MATA_IGET(ufsvfsp, ip)
#define	TRANS_MATA_FREE(ufsvfsp, mof, nb)
#define	TRANS_MATA_ALLOC(ufsvfsp, ip, bno, size, zero)
#define	TRANS_MATA_MOUNT(ufsvfsp)
#define	TRANS_MATA_UMOUNT(ufsvfsp)
#define	TRANS_MATA_SI(ufsvfsp, fs)
#define	TRANS_MATAADD(ufsvfsp, mof, nb)

#endif  /* !DEBUG */

#include	<sys/fs/ufs_quota.h>
#include	<sys/fs/ufs_lockfs.h>
/*
 * identifies the type of operation passed into TRANS_BEGIN/END
 */
#define	TOP_SYNC		(0x00000001)
#define	TOP_ASYNC		(0x00000002)
#define	TOP_SYNC_FORCED		(0x00000004)	/* forced sync transaction */
/*
 *  estimated values
 */
#define	HEADERSIZE		(128)
#define	ALLOCSIZE		(160)
#define	INODESIZE		(sizeof (struct dinode) + HEADERSIZE)
#define	SIZESB			((sizeof (struct fs)) + HEADERSIZE)
#define	SIZEDIR			(DIRBLKSIZ + HEADERSIZE)
/*
 * calculated values
 */
#define	SIZECG(IP)		((IP)->i_fs->fs_cgsize + HEADERSIZE)
#define	FRAGSIZE(IP)		((IP)->i_fs->fs_fsize + HEADERSIZE)
#define	ACLSIZE(IP)		(((IP)->i_ufsvfs->vfs_maxacl + HEADERSIZE) + \
					INODESIZE)
#define	MAXACLSIZE		((MAX_ACL_ENTRIES << 1) * sizeof (aclent_t))
#define	DIRSIZE(IP)		(INODESIZE + (4 * ALLOCSIZE) + \
				    (IP)->i_fs->fs_fsize + HEADERSIZE)
#define	QUOTASIZE		sizeof (struct dquot) + HEADERSIZE
/*
 * size calculations
 */
#define	TOP_CREATE_SIZE(IP)	\
	(ACLSIZE(IP) + SIZECG(IP) + DIRSIZE(IP) + INODESIZE)
#define	TOP_REMOVE_SIZE(IP)	\
	DIRSIZE(IP)  + SIZECG(IP) + INODESIZE + SIZESB
#define	TOP_LINK_SIZE(IP)	\
	DIRSIZE(IP) + INODESIZE
#define	TOP_RENAME_SIZE(IP)	\
	DIRSIZE(IP) + DIRSIZE(IP) + SIZECG(IP)
#define	TOP_MKDIR_SIZE(IP)	\
	DIRSIZE(IP) + INODESIZE + DIRSIZE(IP) + INODESIZE + FRAGSIZE(IP) + \
	    SIZECG(IP) + ACLSIZE(IP)
#define	TOP_SYMLINK_SIZE(IP)	\
	DIRSIZE((IP)) + INODESIZE + INODESIZE + SIZECG(IP)
#define	TOP_GETPAGE_SIZE(IP)	\
	ALLOCSIZE + ALLOCSIZE + ALLOCSIZE + INODESIZE + SIZECG(IP)
#define	TOP_SYNCIP_SIZE		INODESIZE
#define	TOP_READ_SIZE		INODESIZE
#define	TOP_RMDIR_SIZE		(SIZESB + (INODESIZE * 2) + SIZEDIR)
#define	TOP_SETQUOTA_SIZE(FS)	((FS)->fs_bsize << 2)
#define	TOP_QUOTA_SIZE		(QUOTASIZE)
#define	TOP_SETSECATTR_SIZE(IP)	(MAXACLSIZE)
#define	TOP_IUPDAT_SIZE(IP)	INODESIZE + SIZECG(IP)
#define	TOP_SBUPDATE_SIZE	(SIZESB)
#define	TOP_SBWRITE_SIZE	(SIZESB)
#define	TOP_PUTPAGE_SIZE(IP)	(INODESIZE + SIZECG(IP))
#define	TOP_SETATTR_SIZE(IP)	(SIZECG(IP) + INODESIZE + QUOTASIZE + \
		ACLSIZE(IP))
#define	TOP_IFREE_SIZE(IP)	(SIZECG(IP) + INODESIZE + QUOTASIZE)
#define	TOP_MOUNT_SIZE		(SIZESB)
#define	TOP_COMMIT_SIZE		(0)

/*
 * The minimum log size is 1M.  So we will allow 1 fs operation to
 * reserve at most 512K of log space.
 */
#define	TOP_MAX_RESV	(512 * 1024)


/*
 * ufs trans function prototypes
 */
#if defined(_KERNEL)

extern int		ufs_trans_hlock();
extern void		ufs_trans_onerror();
extern int		ufs_trans_push_inode(struct ufsvfs *, delta_t, ino_t);
extern int		ufs_trans_push_buf(struct ufsvfs *, delta_t, daddr_t);
extern int		ufs_trans_push_si(struct ufsvfs *, delta_t, int);
extern void		ufs_trans_sbupdate(struct ufsvfs *, struct vfs *,
				top_t);
extern void		ufs_trans_sbwrite(struct ufsvfs *, top_t);
extern void		ufs_trans_iupdat(struct inode *, int);
extern void		ufs_trans_mata_mount(struct ufsvfs *);
extern void		ufs_trans_mata_umount(struct ufsvfs *);
extern void		ufs_trans_mata_si(struct ufsvfs *, struct fs *);
extern void		ufs_trans_mata_iget(struct inode *);
extern void		ufs_trans_mata_free(struct ufsvfs *, offset_t, off_t);
extern void		ufs_trans_mata_alloc(struct ufsvfs *, struct inode *,
				daddr_t, ulong_t, int);
extern int		ufs_trans_dir(struct inode *, off_t);
extern void		ufs_trans_quota(struct dquot *);
extern void		ufs_trans_dqrele(struct dquot *);
extern int		ufs_trans_itrunc(struct inode *, u_offset_t, int,
			    cred_t *);
extern int		ufs_trans_write(struct inode *, struct uio *, int,
			    cred_t *, int, long);
extern void		ufs_trans_write_resv(struct inode *, struct uio *,
				int *, int *);
extern int		ufs_trans_check(dev_t);
extern void		ufs_trans_redev(dev_t odev, dev_t ndev);
extern void		ufs_trans_trunc_resv(struct inode *, u_offset_t, int *,
				u_offset_t *);

/*
 * transaction prototypes
 */
void	lufs_unsnarf(struct ufsvfs *ufsvfsp);
int	lufs_snarf(struct ufsvfs *ufsvfsp, struct fs *fs, int ronly);
void	top_delta(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb, delta_t dtyp,
	    int (*func)(), ulong_t arg);
void	top_cancel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb, int flags);
int	top_iscancel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb);
void	top_seterror(struct ufsvfs *ufsvfsp);
int	top_iserror(struct ufsvfs *ufsvfsp);
void	top_begin_sync(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size,
	    int *error);
int	top_begin_async(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size,
	    int tryasync);
void	top_end_sync(struct ufsvfs *ufsvfsp, int *ep, top_t topid,
	    ulong_t size);
void	top_end_async(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size);
void	top_log(struct ufsvfs *ufsvfsp, char *va, offset_t vamof, off_t nb,
	    caddr_t buf, uint32_t bufsz);
void	top_mataadd(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb);
void	top_matadel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb);
void	top_mataclr(struct ufsvfs *ufsvfsp);


#endif	/* defined(_KERNEL) */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_TRANS_H */