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
);
220 libxfs_trace_writebuf(const char *func
, const char *file
, int line
, xfs_buf_t
*bp
, int flags
)
226 return libxfs_writebuf(bp
, flags
);
230 libxfs_trace_getbuf(const char *func
, const char *file
, int line
, dev_t device
, xfs_daddr_t blkno
, int len
)
232 xfs_buf_t
*bp
= libxfs_getbuf(device
, blkno
, len
);
242 libxfs_trace_putbuf(const char *func
, const char *file
, int line
, xfs_buf_t
*bp
)
256 libxfs_getsb(xfs_mount_t
*mp
, int flags
)
258 return libxfs_readbuf(mp
->m_dev
, XFS_SB_DADDR
,
259 XFS_FSS_TO_BB(mp
, 1), flags
);
262 kmem_zone_t
*xfs_buf_zone
;
264 static struct cache_mru xfs_buf_freelist
=
265 {{&xfs_buf_freelist
.cm_list
, &xfs_buf_freelist
.cm_list
},
266 0, PTHREAD_MUTEX_INITIALIZER
};
275 libxfs_bhash(cache_key_t key
, unsigned int hashsize
)
277 return (((unsigned int)((xfs_bufkey_t
*)key
)->blkno
) >> 5) % hashsize
;
281 libxfs_bcompare(struct cache_node
*node
, cache_key_t key
)
283 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
284 xfs_bufkey_t
*bkey
= (xfs_bufkey_t
*)key
;
286 #ifdef IO_BCOMPARE_CHECK
287 if (bp
->b_dev
== bkey
->device
&&
288 bp
->b_blkno
== bkey
->blkno
&&
289 bp
->b_bcount
!= BBTOB(bkey
->bblen
))
290 fprintf(stderr
, "%lx: Badness in key lookup (length)\n"
291 "bp=(bno %llu, len %u bytes) key=(bno %llu, len %u bytes)\n",
293 (unsigned long long)bp
->b_blkno
, (int)bp
->b_bcount
,
294 (unsigned long long)bkey
->blkno
, BBTOB(bkey
->bblen
));
297 return (bp
->b_dev
== bkey
->device
&&
298 bp
->b_blkno
== bkey
->blkno
&&
299 bp
->b_bcount
== BBTOB(bkey
->bblen
));
303 libxfs_bprint(xfs_buf_t
*bp
)
305 fprintf(stderr
, "Buffer 0x%p blkno=%llu bytes=%u flags=0x%x count=%u\n",
306 bp
, (unsigned long long)bp
->b_blkno
, (unsigned)bp
->b_bcount
,
307 bp
->b_flags
, bp
->b_node
.cn_count
);
311 libxfs_initbuf(xfs_buf_t
*bp
, dev_t device
, xfs_daddr_t bno
, unsigned int bytes
)
315 bp
->b_bcount
= bytes
;
319 bp
->b_addr
= memalign(libxfs_device_alignment(), bytes
);
322 _("%s: %s can't memalign %u bytes: %s\n"),
323 progname
, __FUNCTION__
, bytes
,
327 #ifdef XFS_BUF_TRACING
328 list_head_init(&bp
->b_lock_list
);
330 pthread_mutex_init(&bp
->b_lock
, NULL
);
334 libxfs_getbufr(dev_t device
, xfs_daddr_t blkno
, int bblen
)
337 int blen
= BBTOB(bblen
);
340 * first look for a buffer that can be used as-is,
341 * if one cannot be found, see if there is a buffer,
342 * and if so, free its buffer and set b_addr to NULL
343 * before calling libxfs_initbuf.
345 pthread_mutex_lock(&xfs_buf_freelist
.cm_mutex
);
346 if (!list_empty(&xfs_buf_freelist
.cm_list
)) {
347 list_for_each_entry(bp
, &xfs_buf_freelist
.cm_list
, b_node
.cn_mru
) {
348 if (bp
->b_bcount
== blen
) {
349 list_del_init(&bp
->b_node
.cn_mru
);
353 if (&bp
->b_node
.cn_mru
== &xfs_buf_freelist
.cm_list
) {
354 bp
= list_entry(xfs_buf_freelist
.cm_list
.next
,
355 xfs_buf_t
, b_node
.cn_mru
);
356 list_del_init(&bp
->b_node
.cn_mru
);
361 bp
= kmem_zone_zalloc(xfs_buf_zone
, 0);
362 pthread_mutex_unlock(&xfs_buf_freelist
.cm_mutex
);
365 libxfs_initbuf(bp
, device
, blkno
, blen
);
367 printf("%lx: %s: allocated %u bytes buffer, key=%llu(%llu), %p\n",
368 pthread_self(), __FUNCTION__
, BBTOB(len
),
369 (long long)LIBXFS_BBTOOFF64(blkno
), (long long)blkno
, bp
);
376 #ifdef XFS_BUF_TRACING
377 struct list_head lock_buf_list
= {&lock_buf_list
, &lock_buf_list
};
378 int lock_buf_count
= 0;
381 extern int use_xfs_buf_lock
;
384 libxfs_getbuf(dev_t device
, xfs_daddr_t blkno
, int len
)
394 miss
= cache_node_get(libxfs_bcache
, &key
, (struct cache_node
**)&bp
);
396 if (use_xfs_buf_lock
)
397 pthread_mutex_lock(&bp
->b_lock
);
398 cache_node_set_priority(libxfs_bcache
, (struct cache_node
*)bp
,
399 cache_node_get_priority((struct cache_node
*)bp
) -
400 CACHE_PREFETCH_PRIORITY
);
401 #ifdef XFS_BUF_TRACING
402 pthread_mutex_lock(&libxfs_bcache
->c_mutex
);
404 list_add(&bp
->b_lock_list
, &lock_buf_list
);
405 pthread_mutex_unlock(&libxfs_bcache
->c_mutex
);
408 printf("%lx %s: %s buffer %p for bno = %llu\n",
409 pthread_self(), __FUNCTION__
, miss
? "miss" : "hit",
410 bp
, (long long)LIBXFS_BBTOOFF64(blkno
));
418 libxfs_putbuf(xfs_buf_t
*bp
)
420 #ifdef XFS_BUF_TRACING
421 pthread_mutex_lock(&libxfs_bcache
->c_mutex
);
423 ASSERT(lock_buf_count
>= 0);
424 list_del_init(&bp
->b_lock_list
);
425 pthread_mutex_unlock(&libxfs_bcache
->c_mutex
);
427 if (use_xfs_buf_lock
)
428 pthread_mutex_unlock(&bp
->b_lock
);
429 cache_node_put(libxfs_bcache
, (struct cache_node
*)bp
);
433 libxfs_purgebuf(xfs_buf_t
*bp
)
437 key
.device
= bp
->b_dev
;
438 key
.blkno
= bp
->b_blkno
;
439 key
.bblen
= bp
->b_bcount
>> BBSHIFT
;
441 cache_node_purge(libxfs_bcache
, &key
, (struct cache_node
*)bp
);
444 static struct cache_node
*
445 libxfs_balloc(cache_key_t key
)
447 xfs_bufkey_t
*bufkey
= (xfs_bufkey_t
*)key
;
449 return (struct cache_node
*)libxfs_getbufr(bufkey
->device
,
450 bufkey
->blkno
, bufkey
->bblen
);
454 libxfs_readbufr(dev_t dev
, xfs_daddr_t blkno
, xfs_buf_t
*bp
, int len
, int flags
)
456 int fd
= libxfs_device_to_fd(dev
);
457 int bytes
= BBTOB(len
);
461 ASSERT(BBTOB(len
) <= bp
->b_bcount
);
463 sts
= pread64(fd
, bp
->b_addr
, bytes
, LIBXFS_BBTOOFF64(blkno
));
466 fprintf(stderr
, _("%s: read failed: %s\n"),
467 progname
, strerror(error
));
468 if (flags
& LIBXFS_EXIT_ON_FAILURE
)
471 } else if (sts
!= bytes
) {
472 fprintf(stderr
, _("%s: error - read only %d of %d bytes\n"),
473 progname
, sts
, bytes
);
474 if (flags
& LIBXFS_EXIT_ON_FAILURE
)
479 printf("%lx: %s: read %u bytes, blkno=%llu(%llu), %p\n",
480 pthread_self(), __FUNCTION__
, bytes
,
481 (long long)LIBXFS_BBTOOFF64(blkno
), (long long)blkno
, bp
);
483 if (bp
->b_dev
== dev
&&
484 bp
->b_blkno
== blkno
&&
485 bp
->b_bcount
== bytes
)
486 bp
->b_flags
|= LIBXFS_B_UPTODATE
;
491 libxfs_readbuf(dev_t dev
, xfs_daddr_t blkno
, int len
, int flags
)
496 bp
= libxfs_getbuf(dev
, blkno
, len
);
497 if (bp
&& !(bp
->b_flags
& (LIBXFS_B_UPTODATE
|LIBXFS_B_DIRTY
))) {
498 error
= libxfs_readbufr(dev
, blkno
, bp
, len
, flags
);
506 libxfs_writebufr(xfs_buf_t
*bp
)
509 int fd
= libxfs_device_to_fd(bp
->b_dev
);
512 sts
= pwrite64(fd
, bp
->b_addr
, bp
->b_bcount
, LIBXFS_BBTOOFF64(bp
->b_blkno
));
515 fprintf(stderr
, _("%s: pwrite64 failed: %s\n"),
516 progname
, strerror(error
));
517 if (bp
->b_flags
& LIBXFS_B_EXIT
)
520 } else if (sts
!= bp
->b_bcount
) {
521 fprintf(stderr
, _("%s: error - wrote only %d of %d bytes\n"),
522 progname
, sts
, bp
->b_bcount
);
523 if (bp
->b_flags
& LIBXFS_B_EXIT
)
528 printf("%lx: %s: wrote %u bytes, blkno=%llu(%llu), %p\n",
529 pthread_self(), __FUNCTION__
, bp
->b_bcount
,
530 (long long)LIBXFS_BBTOOFF64(bp
->b_blkno
),
531 (long long)bp
->b_blkno
, bp
);
533 bp
->b_flags
|= LIBXFS_B_UPTODATE
;
534 bp
->b_flags
&= ~(LIBXFS_B_DIRTY
| LIBXFS_B_EXIT
);
539 libxfs_writebuf_int(xfs_buf_t
*bp
, int flags
)
541 bp
->b_flags
|= (LIBXFS_B_DIRTY
| flags
);
546 libxfs_writebuf(xfs_buf_t
*bp
, int flags
)
548 bp
->b_flags
|= (LIBXFS_B_DIRTY
| flags
);
554 libxfs_iomove(xfs_buf_t
*bp
, uint boff
, int len
, void *data
, int flags
)
557 if (boff
+ len
> bp
->b_bcount
) {
558 printf("Badness, iomove out of range!\n"
559 "bp=(bno %llu, bytes %u) range=(boff %u, bytes %u)\n",
560 (long long)bp
->b_blkno
, bp
->b_bcount
, boff
, len
);
566 memset(bp
->b_addr
+ boff
, 0, len
);
569 memcpy(data
, bp
->b_addr
+ boff
, len
);
572 memcpy(bp
->b_addr
+ boff
, data
, len
);
578 libxfs_brelse(struct cache_node
*node
)
580 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
583 if (bp
->b_flags
& LIBXFS_B_DIRTY
)
584 libxfs_writebufr(bp
);
585 pthread_mutex_lock(&xfs_buf_freelist
.cm_mutex
);
586 list_add(&bp
->b_node
.cn_mru
, &xfs_buf_freelist
.cm_list
);
587 pthread_mutex_unlock(&xfs_buf_freelist
.cm_mutex
);
594 struct list_head
*list
)
599 if (list_empty(list
))
602 list_for_each_entry(bp
, list
, b_node
.cn_mru
) {
603 if (bp
->b_flags
& LIBXFS_B_DIRTY
)
604 libxfs_writebufr(bp
);
608 pthread_mutex_lock(&xfs_buf_freelist
.cm_mutex
);
609 __list_splice(list
, &xfs_buf_freelist
.cm_list
);
610 pthread_mutex_unlock(&xfs_buf_freelist
.cm_mutex
);
616 libxfs_bflush(struct cache_node
*node
)
618 xfs_buf_t
*bp
= (xfs_buf_t
*)node
;
620 if ((bp
!= NULL
) && (bp
->b_flags
& LIBXFS_B_DIRTY
))
621 libxfs_writebufr(bp
);
625 libxfs_putbufr(xfs_buf_t
*bp
)
627 libxfs_brelse((struct cache_node
*)bp
);
632 libxfs_bcache_purge(void)
634 cache_purge(libxfs_bcache
);
638 libxfs_bcache_flush(void)
640 cache_flush(libxfs_bcache
);
644 libxfs_bcache_overflowed(void)
646 return cache_overflowed(libxfs_bcache
);
649 struct cache_operations libxfs_bcache_operations
= {
650 /* .hash */ libxfs_bhash
,
651 /* .alloc */ libxfs_balloc
,
652 /* .flush */ libxfs_bflush
,
653 /* .relse */ libxfs_brelse
,
654 /* .compare */ libxfs_bcompare
,
655 /* .bulkrelse */libxfs_bulkrelse
660 * Inode cache interfaces
663 extern kmem_zone_t
*xfs_ili_zone
;
664 extern kmem_zone_t
*xfs_inode_zone
;
667 libxfs_ihash(cache_key_t key
, unsigned int hashsize
)
669 return ((unsigned int)*(xfs_ino_t
*)key
) % hashsize
;
673 libxfs_icompare(struct cache_node
*node
, cache_key_t key
)
675 xfs_inode_t
*ip
= (xfs_inode_t
*)node
;
677 return (ip
->i_ino
== *(xfs_ino_t
*)key
);
681 libxfs_iget(xfs_mount_t
*mp
, xfs_trans_t
*tp
, xfs_ino_t ino
, uint lock_flags
,
682 xfs_inode_t
**ipp
, xfs_daddr_t bno
)
687 if (cache_node_get(libxfs_icache
, &ino
, (struct cache_node
**)&ip
)) {
689 fprintf(stderr
, "%s: allocated inode, ino=%llu(%llu), %p\n",
690 __FUNCTION__
, (unsigned long long)ino
, bno
, ip
);
692 if ((error
= libxfs_iread(mp
, tp
, ino
, ip
, bno
))) {
693 cache_node_purge(libxfs_icache
, &ino
,
694 (struct cache_node
*)ip
);
703 libxfs_iput(xfs_inode_t
*ip
, uint lock_flags
)
705 cache_node_put(libxfs_icache
, (struct cache_node
*)ip
);
708 static struct cache_node
*
709 libxfs_ialloc(cache_key_t key
)
711 return kmem_zone_zalloc(xfs_inode_zone
, 0);
715 libxfs_idestroy(xfs_inode_t
*ip
)
717 switch (ip
->i_d
.di_mode
& S_IFMT
) {
721 libxfs_idestroy_fork(ip
, XFS_DATA_FORK
);
725 libxfs_idestroy_fork(ip
, XFS_ATTR_FORK
);
729 libxfs_irelse(struct cache_node
*node
)
731 xfs_inode_t
*ip
= (xfs_inode_t
*)node
;
735 kmem_zone_free(xfs_ili_zone
, ip
->i_itemp
);
738 kmem_zone_free(xfs_inode_zone
, ip
);
744 libxfs_icache_purge(void)
746 cache_purge(libxfs_icache
);
749 struct cache_operations libxfs_icache_operations
= {
750 /* .hash */ libxfs_ihash
,
751 /* .alloc */ libxfs_ialloc
,
753 /* .relse */ libxfs_irelse
,
754 /* .compare */ libxfs_icompare
,
755 /* .bulkrelse */ NULL