2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <xfs/libxfs.h>
20 #include <xfs/xfs_log.h>
21 #include <xfs/xfs_log_priv.h>
24 #define BDSTRAT_SIZE (256 * 1024)
25 #define min(x, y) ((x) < (y) ? (x) : (y))
28 libxfs_memalign(size_t size
)
30 static size_t memalignment
;
33 memalignment
= platform_memalignment();
34 return memalign(memalignment
, size
);
38 libxfs_device_zero(dev_t dev
, xfs_daddr_t start
, uint len
)
40 xfs_off_t start_offset
, end_offset
, offset
;
45 zsize
= min(BDSTRAT_SIZE
, BBTOB(len
));
46 if ((z
= libxfs_memalign(zsize
)) == NULL
) {
48 _("%s: %s can't memalign %d bytes: %s\n"),
49 progname
, __FUNCTION__
, (int)zsize
, strerror(errno
));
54 fd
= libxfs_device_to_fd(dev
);
55 start_offset
= LIBXFS_BBTOOFF64(start
);
57 if ((lseek64(fd
, start_offset
, SEEK_SET
)) < 0) {
58 fprintf(stderr
, _("%s: %s seek to offset %llu failed: %s\n"),
59 progname
, __FUNCTION__
,
60 (unsigned long long)start_offset
, strerror(errno
));
64 end_offset
= LIBXFS_BBTOOFF64(start
+ len
) - start_offset
;
65 for (offset
= 0; offset
< end_offset
; ) {
66 bytes
= min((ssize_t
)(end_offset
- offset
), zsize
);
67 if ((bytes
= write(fd
, z
, bytes
)) < 0) {
68 fprintf(stderr
, _("%s: %s write failed: %s\n"),
69 progname
, __FUNCTION__
, strerror(errno
));
71 } else if (bytes
== 0) {
72 fprintf(stderr
, _("%s: %s not progressing?\n"),
73 progname
, __FUNCTION__
);
81 static void unmount_record(void *p
)
83 xlog_op_header_t
*op
= (xlog_op_header_t
*)p
;
84 /* the data section must be 32 bit size aligned */
88 __uint32_t pad2
; /* may as well make it 64 bits */
89 } magic
= { XLOG_UNMOUNT_TYPE
, 0, 0 };
92 INT_SET(op
->oh_tid
, ARCH_CONVERT
, 1);
93 INT_SET(op
->oh_len
, ARCH_CONVERT
, sizeof(magic
));
94 INT_SET(op
->oh_clientid
, ARCH_CONVERT
, XFS_LOG
);
95 INT_SET(op
->oh_flags
, ARCH_CONVERT
, XLOG_UNMOUNT_TRANS
);
96 INT_SET(op
->oh_res2
, ARCH_CONVERT
, 0);
98 /* and the data for this op */
99 memcpy((char *)p
+ sizeof(xlog_op_header_t
), &magic
, sizeof(magic
));
102 static xfs_caddr_t
next(xfs_caddr_t ptr
, int offset
, void *private)
104 xfs_buf_t
*buf
= (xfs_buf_t
*)private;
106 if (XFS_BUF_COUNT(buf
) < (int)(ptr
- XFS_BUF_PTR(buf
)) + offset
)
124 if (!device
|| !fs_uuid
)
127 /* first zero the log */
128 libxfs_device_zero(device
, start
, length
);
130 /* then write a log record header */
131 len
= ((version
== 2) && sunit
) ? BTOBB(sunit
) : 2;
133 buf
= libxfs_getbuf(device
, start
, len
);
134 libxfs_log_header(XFS_BUF_PTR(buf
),
135 fs_uuid
, version
, sunit
, fmt
, next
, buf
);
136 libxfs_writebufr(buf
);
148 libxfs_get_block_t
*nextfunc
,
151 xlog_rec_header_t
*head
= (xlog_rec_header_t
*)caddr
;
152 xfs_caddr_t p
= caddr
;
156 len
= ((version
== 2) && sunit
) ? BTOBB(sunit
) : 1;
158 /* note that oh_tid actually contains the cycle number
159 * and the tid is stored in h_cycle_data[0] - that's the
160 * way things end up on disk.
162 memset(p
, 0, BBSIZE
);
163 INT_SET(head
->h_magicno
, ARCH_CONVERT
, XLOG_HEADER_MAGIC_NUM
);
164 INT_SET(head
->h_cycle
, ARCH_CONVERT
, 1);
165 INT_SET(head
->h_version
, ARCH_CONVERT
, version
);
167 INT_SET(head
->h_len
, ARCH_CONVERT
, sunit
- BBSIZE
);
169 INT_SET(head
->h_len
, ARCH_CONVERT
, 20);
170 INT_SET(head
->h_chksum
, ARCH_CONVERT
, 0);
171 INT_SET(head
->h_prev_block
, ARCH_CONVERT
, -1);
172 INT_SET(head
->h_num_logops
, ARCH_CONVERT
, 1);
173 INT_SET(head
->h_cycle_data
[0], ARCH_CONVERT
, 0xb0c0d0d0);
174 INT_SET(head
->h_fmt
, ARCH_CONVERT
, fmt
);
175 INT_SET(head
->h_size
, ARCH_CONVERT
, XLOG_HEADER_CYCLE_SIZE
);
177 ASSIGN_ANY_LSN_DISK(head
->h_lsn
, 1, 0);
178 ASSIGN_ANY_LSN_DISK(head
->h_tail_lsn
, 1, 0);
180 memcpy(&head
->h_fs_uuid
, fs_uuid
, sizeof(uuid_t
));
183 p
= nextfunc(p
, BBSIZE
, private);
186 cycle_lsn
= CYCLE_LSN_DISK(head
->h_lsn
);
187 for (i
= 2; i
< len
; i
++) {
188 p
= nextfunc(p
, BBSIZE
, private);
189 memset(p
, 0, BBSIZE
);
190 *(uint
*)p
= cycle_lsn
;
197 libxfs_getsb(xfs_mount_t
*mp
, int flags
)
199 return libxfs_readbuf(mp
->m_dev
, XFS_SB_DADDR
,
200 XFS_FSS_TO_BB(mp
, 1), flags
);
205 * Simple I/O (buffer cache) interface
208 xfs_zone_t
*xfs_buf_zone
;
217 libxfs_bhash(cache_key_t key
, unsigned int hashsize
)
219 return ((unsigned int)((xfs_bufkey_t
*)key
)->blkno
) % hashsize
;
223 libxfs_bcompare(struct cache_node
*node
, cache_key_t key
)
225 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
226 xfs_bufkey_t
*bkey
= (xfs_bufkey_t
*)key
;
228 #ifdef IO_BCOMPARE_CHECK
229 if (bp
->b_dev
== bkey
->device
&&
230 bp
->b_blkno
== bkey
->blkno
&&
231 bp
->b_bcount
!= bkey
->count
)
232 fprintf(stderr
, "Badness in key lookup (length)\n"
233 "bp=(bno %llu, len %u bb) key=(bno %llu, len %u bbs)\n",
234 (unsigned long long)bp
->b_blkno
, (int)bp
->b_bcount
,
235 (unsigned long long)bkey
->blkno
, (int)bkey
->count
);
238 return (bp
->b_dev
== bkey
->device
&&
239 bp
->b_blkno
== bkey
->blkno
&&
240 bp
->b_bcount
== bkey
->count
);
244 libxfs_bprint(xfs_buf_t
*bp
)
246 fprintf(stderr
, "Buffer 0x%p blkno=%llu bytes=%u flags=0x%x count=%u\n",
247 bp
, (unsigned long long)bp
->b_blkno
, (unsigned)bp
->b_bcount
,
248 bp
->b_flags
, bp
->b_node
.cn_count
);
252 libxfs_getbuf(dev_t device
, xfs_daddr_t blkno
, int len
)
256 unsigned int bytes
= BBTOB(len
);
262 if (cache_node_get(libxfs_bcache
, &key
, (struct cache_node
**)&bp
)) {
264 fprintf(stderr
, "%s: allocated buffer, key=%llu(%llu), %p\n",
265 __FUNCTION__
, BBTOB(len
), LIBXFS_BBTOOFF64(blkno
), blkno
, buf
);
269 bp
->b_bcount
= bytes
;
271 if (!(bp
->b_addr
= libxfs_memalign(bytes
))) {
273 _("%s: %s can't memalign %d bytes: %s\n"),
274 progname
, __FUNCTION__
, (int)bytes
,
283 libxfs_putbuf(xfs_buf_t
*bp
)
285 cache_node_put((struct cache_node
*)bp
);
289 libxfs_purgebuf(xfs_buf_t
*bp
)
293 key
.device
= bp
->b_dev
;
294 key
.blkno
= bp
->b_blkno
;
295 key
.count
= bp
->b_bcount
;
297 cache_node_purge(libxfs_bcache
, &key
, (struct cache_node
*)bp
);
300 static struct cache_node
*
303 return libxfs_zone_zalloc(xfs_buf_zone
);
307 libxfs_readbufr(dev_t dev
, xfs_daddr_t blkno
, xfs_buf_t
*bp
, int len
, int flags
)
309 int fd
= libxfs_device_to_fd(dev
);
310 int bytes
= BBTOB(len
);
312 ASSERT(BBTOB(len
) <= bp
->b_bcount
);
314 if (pread64(fd
, bp
->b_addr
, bytes
, LIBXFS_BBTOOFF64(blkno
)) < 0) {
315 fprintf(stderr
, _("%s: read failed: %s\n"),
316 progname
, strerror(errno
));
317 if (flags
& LIBXFS_EXIT_ON_FAILURE
)
322 fprintf(stderr
, "readbufr read %ubytes, blkno=%llu(%llu), %p\n",
323 bytes
, LIBXFS_BBTOOFF64(blkno
), blkno
, bp
);
325 if (bp
->b_dev
== dev
&&
326 bp
->b_blkno
== blkno
&&
327 bp
->b_bcount
== bytes
)
328 bp
->b_flags
|= LIBXFS_B_UPTODATE
;
333 libxfs_readbuf(dev_t dev
, xfs_daddr_t blkno
, int len
, int flags
)
338 bp
= libxfs_getbuf(dev
, blkno
, len
);
339 if (!(bp
->b_flags
& (LIBXFS_B_UPTODATE
|LIBXFS_B_DIRTY
))) {
340 error
= libxfs_readbufr(dev
, blkno
, bp
, len
, flags
);
350 libxfs_writebufr(xfs_buf_t
*bp
)
353 int fd
= libxfs_device_to_fd(bp
->b_dev
);
355 sts
= pwrite64(fd
, bp
->b_addr
, bp
->b_bcount
, LIBXFS_BBTOOFF64(bp
->b_blkno
));
357 fprintf(stderr
, _("%s: pwrite64 failed: %s\n"),
358 progname
, strerror(errno
));
359 if (bp
->b_flags
& LIBXFS_B_EXIT
)
363 else if (sts
!= bp
->b_bcount
) {
364 fprintf(stderr
, _("%s: error - wrote only %d of %d bytes\n"),
365 progname
, sts
, bp
->b_bcount
);
366 if (bp
->b_flags
& LIBXFS_B_EXIT
)
371 fprintf(stderr
, "writebufr wrote %ubytes, blkno=%llu(%llu), %p\n",
372 bp
->b_bcount
, LIBXFS_BBTOOFF64(bp
->b_blkno
), bp
->b_blkno
, bp
);
374 bp
->b_flags
|= LIBXFS_B_UPTODATE
;
375 bp
->b_flags
&= ~(LIBXFS_B_DIRTY
| LIBXFS_B_EXIT
);
380 libxfs_writebuf_int(xfs_buf_t
*bp
, int flags
)
382 bp
->b_flags
|= (LIBXFS_B_DIRTY
| flags
);
387 libxfs_writebuf(xfs_buf_t
*bp
, int flags
)
389 bp
->b_flags
|= (LIBXFS_B_DIRTY
| flags
);
395 libxfs_iomove(xfs_buf_t
*bp
, uint boff
, int len
, void *data
, int flags
)
398 if (boff
+ len
> bp
->b_bcount
) {
399 fprintf(stderr
, "Badness, iomove out of range!\n"
400 "bp=(bno %llu, bytes %u) range=(boff %u, bytes %u)\n",
401 bp
->b_blkno
, bp
->b_bcount
, boff
, len
);
407 memset(bp
->b_addr
+ boff
, 0, len
);
410 memcpy(data
, bp
->b_addr
+ boff
, len
);
413 memcpy(bp
->b_addr
+ boff
, data
, len
);
419 libxfs_bflush(struct cache_node
*node
)
421 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
423 if ((bp
!= NULL
) && (bp
->b_flags
& LIBXFS_B_DIRTY
))
424 libxfs_writebufr(bp
);
428 libxfs_brelse(struct cache_node
*node
)
430 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
431 xfs_buf_log_item_t
*bip
;
432 extern xfs_zone_t
*xfs_buf_item_zone
;
435 if (bp
->b_flags
& LIBXFS_B_DIRTY
)
436 libxfs_writebufr(bp
);
437 bip
= XFS_BUF_FSPRIVATE(bp
, xfs_buf_log_item_t
*);
439 libxfs_zone_free(xfs_buf_item_zone
, bip
);
449 libxfs_bcache_purge(void)
451 cache_purge(libxfs_bcache
);
455 libxfs_bcache_flush(void)
457 cache_flush(libxfs_bcache
);
460 struct cache_operations libxfs_bcache_operations
= {
461 /* .hash */ libxfs_bhash
,
462 /* .alloc */ libxfs_balloc
,
463 /* .flush */ libxfs_bflush
,
464 /* .relse */ libxfs_brelse
,
465 /* .compare */ libxfs_bcompare
,
466 /* .bulkrelse */ NULL
/* TODO: lio_listio64 interface? */
471 * Simple memory interface
475 libxfs_zone_init(int size
, char *name
)
479 if ((ptr
= malloc(sizeof(xfs_zone_t
))) == NULL
) {
480 fprintf(stderr
, _("%s: zone init failed (%s, %d bytes): %s\n"),
481 progname
, name
, (int)sizeof(xfs_zone_t
), strerror(errno
));
484 ptr
->zone_unitsize
= size
;
485 ptr
->zone_name
= name
;
488 fprintf(stderr
, "new zone %p for \"%s\", size=%d\n", ptr
, name
, size
);
494 libxfs_zone_zalloc(xfs_zone_t
*z
)
498 if ((ptr
= calloc(z
->zone_unitsize
, 1)) == NULL
) {
499 fprintf(stderr
, _("%s: zone calloc failed (%s, %d bytes): %s\n"),
500 progname
, z
->zone_name
, z
->zone_unitsize
,
506 fprintf(stderr
, "## zone alloc'd item %p from %s (%d bytes) (%d active)\n",
507 ptr
, z
->zone_name
, z
->zone_unitsize
,
514 libxfs_zone_free(xfs_zone_t
*z
, void *ptr
)
518 fprintf(stderr
, "## zone freed item %p from %s (%d bytes) (%d active)\n",
519 ptr
, z
->zone_name
, z
->zone_unitsize
,
529 libxfs_malloc(size_t size
)
533 if ((ptr
= calloc(1, size
)) == NULL
) {
534 fprintf(stderr
, _("%s: calloc failed (%d bytes): %s\n"),
535 progname
, (int)size
, strerror(errno
));
539 fprintf(stderr
, "## calloc'd item %p size %d bytes\n", ptr
, size
);
545 libxfs_free(void *ptr
)
548 fprintf(stderr
, "## freed item %p\n", ptr
);
557 libxfs_realloc(void *ptr
, size_t size
)
562 if ((ptr
= realloc(ptr
, size
)) == NULL
) {
563 fprintf(stderr
, _("%s: realloc failed (%d bytes): %s\n"),
564 progname
, (int)size
, strerror(errno
));
568 fprintf(stderr
, "## realloc'd item %p now %p size %d bytes\n",
576 * Inode cache interfaces
579 extern xfs_zone_t
*xfs_ili_zone
;
580 extern xfs_zone_t
*xfs_inode_zone
;
583 libxfs_ihash(cache_key_t key
, unsigned int hashsize
)
585 return ((unsigned int)*(xfs_ino_t
*)key
) % hashsize
;
589 libxfs_icompare(struct cache_node
*node
, cache_key_t key
)
591 xfs_inode_t
*ip
= (xfs_inode_t
*)node
;
593 return (ip
->i_ino
== *(xfs_ino_t
*)key
);
597 libxfs_iget(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_ino_t ino
, uint lock_flags
,
598 xfs_inode_t
**ipp
, xfs_daddr_t bno
)
603 if (cache_node_get(libxfs_icache
, &ino
, (struct cache_node
**)&ip
)) {
605 fprintf(stderr
, "%s: allocated inode, ino=%llu(%llu), %p\n",
606 __FUNCTION__
, (unsigned long long)ino
, bno
, ip
);
608 if ((error
= libxfs_iread(mp
, tp
, ino
, ip
, bno
))) {
609 cache_node_purge(libxfs_icache
, &ino
,
610 (struct cache_node
*)ip
);
619 libxfs_iput(xfs_inode_t
*ip
, uint lock_flags
)
621 cache_node_put((struct cache_node
*)ip
);
624 static struct cache_node
*
627 return libxfs_zone_zalloc(xfs_inode_zone
);
631 libxfs_idestroy(xfs_inode_t
*ip
)
633 switch (ip
->i_d
.di_mode
& S_IFMT
) {
637 libxfs_idestroy_fork(ip
, XFS_DATA_FORK
);
641 libxfs_idestroy_fork(ip
, XFS_ATTR_FORK
);
645 libxfs_irelse(struct cache_node
*node
)
647 xfs_inode_t
*ip
= (xfs_inode_t
*)node
;
651 libxfs_zone_free(xfs_ili_zone
, ip
->i_itemp
);
654 libxfs_zone_free(xfs_inode_zone
, ip
);
660 libxfs_icache_purge(void)
662 cache_purge(libxfs_icache
);
665 struct cache_operations libxfs_icache_operations
= {
666 /* .hash */ libxfs_ihash
,
667 /* .alloc */ libxfs_ialloc
,
669 /* .relse */ libxfs_irelse
,
670 /* .compare */ libxfs_icompare
,
671 /* .bulkrelse */ NULL