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))
27 #define IO_BCOMPARE_CHECK
30 libxfs_device_zero(dev_t dev
, xfs_daddr_t start
, uint len
)
32 xfs_off_t start_offset
, end_offset
, offset
;
37 zsize
= min(BDSTRAT_SIZE
, BBTOB(len
));
38 if ((z
= memalign(libxfs_device_alignment(), zsize
)) == NULL
) {
40 _("%s: %s can't memalign %d bytes: %s\n"),
41 progname
, __FUNCTION__
, (int)zsize
, strerror(errno
));
46 fd
= libxfs_device_to_fd(dev
);
47 start_offset
= LIBXFS_BBTOOFF64(start
);
49 if ((lseek64(fd
, start_offset
, SEEK_SET
)) < 0) {
50 fprintf(stderr
, _("%s: %s seek to offset %llu failed: %s\n"),
51 progname
, __FUNCTION__
,
52 (unsigned long long)start_offset
, strerror(errno
));
56 end_offset
= LIBXFS_BBTOOFF64(start
+ len
) - start_offset
;
57 for (offset
= 0; offset
< end_offset
; ) {
58 bytes
= min((ssize_t
)(end_offset
- offset
), zsize
);
59 if ((bytes
= write(fd
, z
, bytes
)) < 0) {
60 fprintf(stderr
, _("%s: %s write failed: %s\n"),
61 progname
, __FUNCTION__
, strerror(errno
));
63 } else if (bytes
== 0) {
64 fprintf(stderr
, _("%s: %s not progressing?\n"),
65 progname
, __FUNCTION__
);
73 static void unmount_record(void *p
)
75 xlog_op_header_t
*op
= (xlog_op_header_t
*)p
;
76 /* the data section must be 32 bit size aligned */
80 __uint32_t pad2
; /* may as well make it 64 bits */
81 } magic
= { XLOG_UNMOUNT_TYPE
, 0, 0 };
84 op
->oh_tid
= cpu_to_be32(1);
85 op
->oh_len
= cpu_to_be32(sizeof(magic
));
86 op
->oh_clientid
= XFS_LOG
;
87 op
->oh_flags
= XLOG_UNMOUNT_TRANS
;
90 /* and the data for this op */
91 memcpy((char *)p
+ sizeof(xlog_op_header_t
), &magic
, sizeof(magic
));
94 static xfs_caddr_t
next(xfs_caddr_t ptr
, int offset
, void *private)
96 xfs_buf_t
*buf
= (xfs_buf_t
*)private;
98 if (XFS_BUF_COUNT(buf
) < (int)(ptr
- XFS_BUF_PTR(buf
)) + offset
)
116 if (!device
|| !fs_uuid
)
119 /* first zero the log */
120 libxfs_device_zero(device
, start
, length
);
122 /* then write a log record header */
123 len
= ((version
== 2) && sunit
) ? BTOBB(sunit
) : 2;
125 bp
= libxfs_getbufr(device
, start
, len
);
126 libxfs_log_header(XFS_BUF_PTR(bp
),
127 fs_uuid
, version
, sunit
, fmt
, next
, bp
);
128 bp
->b_flags
|= LIBXFS_B_DIRTY
;
140 libxfs_get_block_t
*nextfunc
,
143 xlog_rec_header_t
*head
= (xlog_rec_header_t
*)caddr
;
144 xfs_caddr_t p
= caddr
;
148 len
= ((version
== 2) && sunit
) ? BTOBB(sunit
) : 1;
150 /* note that oh_tid actually contains the cycle number
151 * and the tid is stored in h_cycle_data[0] - that's the
152 * way things end up on disk.
154 memset(p
, 0, BBSIZE
);
155 head
->h_magicno
= cpu_to_be32(XLOG_HEADER_MAGIC_NUM
);
156 head
->h_cycle
= cpu_to_be32(1);
157 head
->h_version
= cpu_to_be32(version
);
159 head
->h_len
= cpu_to_be32(sunit
- BBSIZE
);
161 head
->h_len
= cpu_to_be32(20);
162 head
->h_chksum
= cpu_to_be32(0);
163 head
->h_prev_block
= cpu_to_be32(-1);
164 head
->h_num_logops
= cpu_to_be32(1);
165 head
->h_cycle_data
[0] = cpu_to_be32(0xb0c0d0d0);
166 head
->h_fmt
= cpu_to_be32(fmt
);
167 head
->h_size
= cpu_to_be32(XLOG_HEADER_CYCLE_SIZE
);
169 head
->h_lsn
= cpu_to_be64(xlog_assign_lsn(1, 0));
170 head
->h_tail_lsn
= cpu_to_be64(xlog_assign_lsn(1, 0));
172 memcpy(&head
->h_fs_uuid
, fs_uuid
, sizeof(uuid_t
));
175 p
= nextfunc(p
, BBSIZE
, private);
178 cycle_lsn
= CYCLE_LSN_DISK(head
->h_lsn
);
179 for (i
= 2; i
< len
; i
++) {
180 p
= nextfunc(p
, BBSIZE
, private);
181 memset(p
, 0, BBSIZE
);
182 *(__be32
*)p
= cycle_lsn
;
189 * Simple I/O (buffer cache) interface
193 #ifdef XFS_BUF_TRACING
195 #undef libxfs_readbuf
196 #undef libxfs_writebuf
200 xfs_buf_t
*libxfs_readbuf(dev_t
, xfs_daddr_t
, int, int);
201 int libxfs_writebuf(xfs_buf_t
*, int);
202 xfs_buf_t
*libxfs_getbuf(dev_t
, xfs_daddr_t
, int);
203 void libxfs_putbuf (xfs_buf_t
*);
206 libxfs_trace_readbuf(const char *func
, const char *file
, int line
, dev_t dev
, xfs_daddr_t blkno
, int len
, int flags
)
208 xfs_buf_t
*bp
= libxfs_readbuf(dev
, blkno
, len
, flags
);
218 libxfs_trace_writebuf(const char *func
, const char *file
, int line
, xfs_buf_t
*bp
, int flags
)
224 return libxfs_writebuf(bp
, flags
);
228 libxfs_trace_getbuf(const char *func
, const char *file
, int line
, dev_t device
, xfs_daddr_t blkno
, int len
)
230 xfs_buf_t
*bp
= libxfs_getbuf(device
, blkno
, len
);
240 libxfs_trace_putbuf(const char *func
, const char *file
, int line
, xfs_buf_t
*bp
)
254 libxfs_getsb(xfs_mount_t
*mp
, int flags
)
256 return libxfs_readbuf(mp
->m_dev
, XFS_SB_DADDR
,
257 XFS_FSS_TO_BB(mp
, 1), flags
);
260 kmem_zone_t
*xfs_buf_zone
;
262 static struct cache_mru xfs_buf_freelist
=
263 {{&xfs_buf_freelist
.cm_list
, &xfs_buf_freelist
.cm_list
},
264 0, PTHREAD_MUTEX_INITIALIZER
};
273 libxfs_bhash(cache_key_t key
, unsigned int hashsize
)
275 return (((unsigned int)((xfs_bufkey_t
*)key
)->blkno
) >> 5) % hashsize
;
279 libxfs_bcompare(struct cache_node
*node
, cache_key_t key
)
281 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
282 xfs_bufkey_t
*bkey
= (xfs_bufkey_t
*)key
;
284 #ifdef IO_BCOMPARE_CHECK
285 if (bp
->b_dev
== bkey
->device
&&
286 bp
->b_blkno
== bkey
->blkno
&&
287 bp
->b_bcount
!= BBTOB(bkey
->bblen
))
288 fprintf(stderr
, "%lx: Badness in key lookup (length)\n"
289 "bp=(bno %llu, len %u bytes) key=(bno %llu, len %u bytes)\n",
291 (unsigned long long)bp
->b_blkno
, (int)bp
->b_bcount
,
292 (unsigned long long)bkey
->blkno
, BBTOB(bkey
->bblen
));
295 return (bp
->b_dev
== bkey
->device
&&
296 bp
->b_blkno
== bkey
->blkno
&&
297 bp
->b_bcount
== BBTOB(bkey
->bblen
));
301 libxfs_bprint(xfs_buf_t
*bp
)
303 fprintf(stderr
, "Buffer 0x%p blkno=%llu bytes=%u flags=0x%x count=%u\n",
304 bp
, (unsigned long long)bp
->b_blkno
, (unsigned)bp
->b_bcount
,
305 bp
->b_flags
, bp
->b_node
.cn_count
);
309 libxfs_initbuf(xfs_buf_t
*bp
, dev_t device
, xfs_daddr_t bno
, unsigned int bytes
)
313 bp
->b_bcount
= bytes
;
316 bp
->b_addr
= memalign(libxfs_device_alignment(), bytes
);
319 _("%s: %s can't memalign %u bytes: %s\n"),
320 progname
, __FUNCTION__
, bytes
,
324 #ifdef XFS_BUF_TRACING
325 list_head_init(&bp
->b_lock_list
);
327 pthread_mutex_init(&bp
->b_lock
, NULL
);
331 libxfs_getbufr(dev_t device
, xfs_daddr_t blkno
, int bblen
)
334 int blen
= BBTOB(bblen
);
337 * first look for a buffer that can be used as-is,
338 * if one cannot be found, see if there is a buffer,
339 * and if so, free its buffer and set b_addr to NULL
340 * before calling libxfs_initbuf.
342 pthread_mutex_lock(&xfs_buf_freelist
.cm_mutex
);
343 if (!list_empty(&xfs_buf_freelist
.cm_list
)) {
344 list_for_each_entry(bp
, &xfs_buf_freelist
.cm_list
, b_node
.cn_mru
) {
345 if (bp
->b_bcount
== blen
) {
346 list_del_init(&bp
->b_node
.cn_mru
);
350 if (&bp
->b_node
.cn_mru
== &xfs_buf_freelist
.cm_list
) {
351 bp
= list_entry(xfs_buf_freelist
.cm_list
.next
,
352 xfs_buf_t
, b_node
.cn_mru
);
353 list_del_init(&bp
->b_node
.cn_mru
);
358 bp
= kmem_zone_zalloc(xfs_buf_zone
, 0);
359 pthread_mutex_unlock(&xfs_buf_freelist
.cm_mutex
);
362 libxfs_initbuf(bp
, device
, blkno
, blen
);
364 printf("%lx: %s: allocated %u bytes buffer, key=%llu(%llu), %p\n",
365 pthread_self(), __FUNCTION__
, BBTOB(len
),
366 (long long)LIBXFS_BBTOOFF64(blkno
), (long long)blkno
, bp
);
373 #ifdef XFS_BUF_TRACING
374 struct list_head lock_buf_list
= {&lock_buf_list
, &lock_buf_list
};
375 int lock_buf_count
= 0;
378 extern int use_xfs_buf_lock
;
381 libxfs_getbuf(dev_t device
, xfs_daddr_t blkno
, int len
)
391 miss
= cache_node_get(libxfs_bcache
, &key
, (struct cache_node
**)&bp
);
393 if (use_xfs_buf_lock
)
394 pthread_mutex_lock(&bp
->b_lock
);
395 cache_node_set_priority(libxfs_bcache
, (struct cache_node
*)bp
,
396 cache_node_get_priority((struct cache_node
*)bp
) -
397 CACHE_PREFETCH_PRIORITY
);
398 #ifdef XFS_BUF_TRACING
399 pthread_mutex_lock(&libxfs_bcache
->c_mutex
);
401 list_add(&bp
->b_lock_list
, &lock_buf_list
);
402 pthread_mutex_unlock(&libxfs_bcache
->c_mutex
);
405 printf("%lx %s: %s buffer %p for bno = %llu\n",
406 pthread_self(), __FUNCTION__
, miss
? "miss" : "hit",
407 bp
, (long long)LIBXFS_BBTOOFF64(blkno
));
415 libxfs_putbuf(xfs_buf_t
*bp
)
417 #ifdef XFS_BUF_TRACING
418 pthread_mutex_lock(&libxfs_bcache
->c_mutex
);
420 ASSERT(lock_buf_count
>= 0);
421 list_del_init(&bp
->b_lock_list
);
422 pthread_mutex_unlock(&libxfs_bcache
->c_mutex
);
424 if (use_xfs_buf_lock
)
425 pthread_mutex_unlock(&bp
->b_lock
);
426 cache_node_put(libxfs_bcache
, (struct cache_node
*)bp
);
430 libxfs_purgebuf(xfs_buf_t
*bp
)
434 key
.device
= bp
->b_dev
;
435 key
.blkno
= bp
->b_blkno
;
436 key
.bblen
= bp
->b_bcount
>> BBSHIFT
;
438 cache_node_purge(libxfs_bcache
, &key
, (struct cache_node
*)bp
);
441 static struct cache_node
*
442 libxfs_balloc(cache_key_t key
)
444 xfs_bufkey_t
*bufkey
= (xfs_bufkey_t
*)key
;
446 return (struct cache_node
*)libxfs_getbufr(bufkey
->device
,
447 bufkey
->blkno
, bufkey
->bblen
);
451 libxfs_readbufr(dev_t dev
, xfs_daddr_t blkno
, xfs_buf_t
*bp
, int len
, int flags
)
453 int fd
= libxfs_device_to_fd(dev
);
454 int bytes
= BBTOB(len
);
456 ASSERT(BBTOB(len
) <= bp
->b_bcount
);
458 if (pread64(fd
, bp
->b_addr
, bytes
, LIBXFS_BBTOOFF64(blkno
)) < 0) {
459 fprintf(stderr
, _("%s: read failed: %s\n"),
460 progname
, strerror(errno
));
461 if (flags
& LIBXFS_EXIT_ON_FAILURE
)
466 printf("%lx: %s: read %u bytes, blkno=%llu(%llu), %p\n",
467 pthread_self(), __FUNCTION__
, bytes
,
468 (long long)LIBXFS_BBTOOFF64(blkno
), (long long)blkno
, bp
);
470 if (bp
->b_dev
== dev
&&
471 bp
->b_blkno
== blkno
&&
472 bp
->b_bcount
== bytes
)
473 bp
->b_flags
|= LIBXFS_B_UPTODATE
;
478 libxfs_readbuf(dev_t dev
, xfs_daddr_t blkno
, int len
, int flags
)
483 bp
= libxfs_getbuf(dev
, blkno
, len
);
484 if (bp
&& !(bp
->b_flags
& (LIBXFS_B_UPTODATE
|LIBXFS_B_DIRTY
))) {
485 error
= libxfs_readbufr(dev
, blkno
, bp
, len
, flags
);
495 libxfs_writebufr(xfs_buf_t
*bp
)
498 int fd
= libxfs_device_to_fd(bp
->b_dev
);
500 sts
= pwrite64(fd
, bp
->b_addr
, bp
->b_bcount
, LIBXFS_BBTOOFF64(bp
->b_blkno
));
502 fprintf(stderr
, _("%s: pwrite64 failed: %s\n"),
503 progname
, strerror(errno
));
504 if (bp
->b_flags
& LIBXFS_B_EXIT
)
508 else if (sts
!= bp
->b_bcount
) {
509 fprintf(stderr
, _("%s: error - wrote only %d of %d bytes\n"),
510 progname
, sts
, bp
->b_bcount
);
511 if (bp
->b_flags
& LIBXFS_B_EXIT
)
516 printf("%lx: %s: wrote %u bytes, blkno=%llu(%llu), %p\n",
517 pthread_self(), __FUNCTION__
, bp
->b_bcount
,
518 (long long)LIBXFS_BBTOOFF64(bp
->b_blkno
),
519 (long long)bp
->b_blkno
, bp
);
521 bp
->b_flags
|= LIBXFS_B_UPTODATE
;
522 bp
->b_flags
&= ~(LIBXFS_B_DIRTY
| LIBXFS_B_EXIT
);
527 libxfs_writebuf_int(xfs_buf_t
*bp
, int flags
)
529 bp
->b_flags
|= (LIBXFS_B_DIRTY
| flags
);
534 libxfs_writebuf(xfs_buf_t
*bp
, int flags
)
536 bp
->b_flags
|= (LIBXFS_B_DIRTY
| flags
);
542 libxfs_iomove(xfs_buf_t
*bp
, uint boff
, int len
, void *data
, int flags
)
545 if (boff
+ len
> bp
->b_bcount
) {
546 printf("Badness, iomove out of range!\n"
547 "bp=(bno %llu, bytes %u) range=(boff %u, bytes %u)\n",
548 (long long)bp
->b_blkno
, bp
->b_bcount
, boff
, len
);
554 memset(bp
->b_addr
+ boff
, 0, len
);
557 memcpy(data
, bp
->b_addr
+ boff
, len
);
560 memcpy(bp
->b_addr
+ boff
, data
, len
);
566 libxfs_brelse(struct cache_node
*node
)
568 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
571 if (bp
->b_flags
& LIBXFS_B_DIRTY
)
572 libxfs_writebufr(bp
);
573 pthread_mutex_lock(&xfs_buf_freelist
.cm_mutex
);
574 list_add(&bp
->b_node
.cn_mru
, &xfs_buf_freelist
.cm_list
);
575 pthread_mutex_unlock(&xfs_buf_freelist
.cm_mutex
);
582 struct list_head
*list
)
587 if (list_empty(list
))
590 list_for_each_entry(bp
, list
, b_node
.cn_mru
) {
591 if (bp
->b_flags
& LIBXFS_B_DIRTY
)
592 libxfs_writebufr(bp
);
596 pthread_mutex_lock(&xfs_buf_freelist
.cm_mutex
);
597 __list_splice(list
, &xfs_buf_freelist
.cm_list
);
598 pthread_mutex_unlock(&xfs_buf_freelist
.cm_mutex
);
604 libxfs_bflush(struct cache_node
*node
)
606 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
608 if ((bp
!= NULL
) && (bp
->b_flags
& LIBXFS_B_DIRTY
))
609 libxfs_writebufr(bp
);
613 libxfs_putbufr(xfs_buf_t
*bp
)
615 libxfs_brelse((struct cache_node
*)bp
);
620 libxfs_bcache_purge(void)
622 cache_purge(libxfs_bcache
);
626 libxfs_bcache_flush(void)
628 cache_flush(libxfs_bcache
);
632 libxfs_bcache_overflowed(void)
634 return cache_overflowed(libxfs_bcache
);
637 struct cache_operations libxfs_bcache_operations
= {
638 /* .hash */ libxfs_bhash
,
639 /* .alloc */ libxfs_balloc
,
640 /* .flush */ libxfs_bflush
,
641 /* .relse */ libxfs_brelse
,
642 /* .compare */ libxfs_bcompare
,
643 /* .bulkrelse */libxfs_bulkrelse
648 * Inode cache interfaces
651 extern kmem_zone_t
*xfs_ili_zone
;
652 extern kmem_zone_t
*xfs_inode_zone
;
655 libxfs_ihash(cache_key_t key
, unsigned int hashsize
)
657 return ((unsigned int)*(xfs_ino_t
*)key
) % hashsize
;
661 libxfs_icompare(struct cache_node
*node
, cache_key_t key
)
663 xfs_inode_t
*ip
= (xfs_inode_t
*)node
;
665 return (ip
->i_ino
== *(xfs_ino_t
*)key
);
669 libxfs_iget(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_ino_t ino
, uint lock_flags
,
670 xfs_inode_t
**ipp
, xfs_daddr_t bno
)
675 if (cache_node_get(libxfs_icache
, &ino
, (struct cache_node
**)&ip
)) {
677 fprintf(stderr
, "%s: allocated inode, ino=%llu(%llu), %p\n",
678 __FUNCTION__
, (unsigned long long)ino
, bno
, ip
);
680 if ((error
= libxfs_iread(mp
, tp
, ino
, ip
, bno
))) {
681 cache_node_purge(libxfs_icache
, &ino
,
682 (struct cache_node
*)ip
);
691 libxfs_iput(xfs_inode_t
*ip
, uint lock_flags
)
693 cache_node_put(libxfs_icache
, (struct cache_node
*)ip
);
696 static struct cache_node
*
697 libxfs_ialloc(cache_key_t key
)
699 return kmem_zone_zalloc(xfs_inode_zone
, 0);
703 libxfs_idestroy(xfs_inode_t
*ip
)
705 switch (ip
->i_d
.di_mode
& S_IFMT
) {
709 libxfs_idestroy_fork(ip
, XFS_DATA_FORK
);
713 libxfs_idestroy_fork(ip
, XFS_ATTR_FORK
);
717 libxfs_irelse(struct cache_node
*node
)
719 xfs_inode_t
*ip
= (xfs_inode_t
*)node
;
723 kmem_zone_free(xfs_ili_zone
, ip
->i_itemp
);
726 kmem_zone_free(xfs_inode_zone
, ip
);
732 libxfs_icache_purge(void)
734 cache_purge(libxfs_icache
);
737 struct cache_operations libxfs_icache_operations
= {
738 /* .hash */ libxfs_ihash
,
739 /* .alloc */ libxfs_ialloc
,
741 /* .relse */ libxfs_irelse
,
742 /* .compare */ libxfs_icompare
,
743 /* .bulkrelse */ NULL