]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/rdwr.c
libxfs: contiguous buffers are not discontigous
[thirdparty/xfsprogs-dev.git] / libxfs / rdwr.c
CommitLineData
2bd0ea18 1/*
f1b058f9 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
da23017d 3 * All Rights Reserved.
2bd0ea18 4 *
da23017d
NS
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
2bd0ea18
NS
7 * published by the Free Software Foundation.
8 *
da23017d
NS
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.
2bd0ea18 13 *
da23017d
NS
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
2bd0ea18
NS
17 */
18
1d7e80ee 19#include <xfs/libxfs.h>
1aef52f8 20#include "init.h"
2bd0ea18 21
5000d01d 22#define BDSTRAT_SIZE (256 * 1024)
2bd0ea18 23
2556c98b
BN
24#define IO_BCOMPARE_CHECK
25
2bd0ea18 26void
75c8b434 27libxfs_device_zero(struct xfs_buftarg *btp, xfs_daddr_t start, uint len)
2bd0ea18 28{
3cc4d0db
NS
29 xfs_off_t start_offset, end_offset, offset;
30 ssize_t zsize, bytes;
2bd0ea18 31 char *z;
3cc4d0db 32 int fd;
2bd0ea18 33
3cc4d0db 34 zsize = min(BDSTRAT_SIZE, BBTOB(len));
b74a1f6a 35 if ((z = memalign(libxfs_device_alignment(), zsize)) == NULL) {
9440d84d
NS
36 fprintf(stderr,
37 _("%s: %s can't memalign %d bytes: %s\n"),
7dfd8291 38 progname, __FUNCTION__, (int)zsize, strerror(errno));
2bd0ea18
NS
39 exit(1);
40 }
3cc4d0db
NS
41 memset(z, 0, zsize);
42
75c8b434 43 fd = libxfs_device_to_fd(btp->dev);
cb5b3ef4 44 start_offset = LIBXFS_BBTOOFF64(start);
3cc4d0db
NS
45
46 if ((lseek64(fd, start_offset, SEEK_SET)) < 0) {
47 fprintf(stderr, _("%s: %s seek to offset %llu failed: %s\n"),
7dfd8291
NS
48 progname, __FUNCTION__,
49 (unsigned long long)start_offset, strerror(errno));
3cc4d0db
NS
50 exit(1);
51 }
52
cb5b3ef4 53 end_offset = LIBXFS_BBTOOFF64(start + len) - start_offset;
3cc4d0db
NS
54 for (offset = 0; offset < end_offset; ) {
55 bytes = min((ssize_t)(end_offset - offset), zsize);
56 if ((bytes = write(fd, z, bytes)) < 0) {
57 fprintf(stderr, _("%s: %s write failed: %s\n"),
9440d84d 58 progname, __FUNCTION__, strerror(errno));
2bd0ea18 59 exit(1);
3cc4d0db
NS
60 } else if (bytes == 0) {
61 fprintf(stderr, _("%s: %s not progressing?\n"),
62 progname, __FUNCTION__);
63 exit(1);
2bd0ea18 64 }
3cc4d0db 65 offset += bytes;
2bd0ea18
NS
66 }
67 free(z);
68}
69
989b74bc 70static void unmount_record(void *p)
2bd0ea18 71{
989b74bc 72 xlog_op_header_t *op = (xlog_op_header_t *)p;
5000d01d
SL
73 /* the data section must be 32 bit size aligned */
74 struct {
75 __uint16_t magic;
76 __uint16_t pad1;
77 __uint32_t pad2; /* may as well make it 64 bits */
78 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
79
989b74bc 80 memset(p, 0, BBSIZE);
5e656dbb
BN
81 op->oh_tid = cpu_to_be32(1);
82 op->oh_len = cpu_to_be32(sizeof(magic));
83 op->oh_clientid = XFS_LOG;
84 op->oh_flags = XLOG_UNMOUNT_TRANS;
85 op->oh_res2 = 0;
989b74bc
NS
86
87 /* and the data for this op */
1552a820 88 memcpy((char *)p + sizeof(xlog_op_header_t), &magic, sizeof(magic));
989b74bc
NS
89}
90
91static xfs_caddr_t next(xfs_caddr_t ptr, int offset, void *private)
92{
93 xfs_buf_t *buf = (xfs_buf_t *)private;
94
95 if (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset)
96 abort();
97 return ptr + offset;
98}
99
100int
101libxfs_log_clear(
75c8b434 102 struct xfs_buftarg *btp,
989b74bc
NS
103 xfs_daddr_t start,
104 uint length,
105 uuid_t *fs_uuid,
106 int version,
107 int sunit,
108 int fmt)
109{
e6b359b3 110 xfs_buf_t *bp;
989b74bc
NS
111 int len;
112
75c8b434 113 if (!btp->dev || !fs_uuid)
2bd0ea18 114 return -EINVAL;
5000d01d
SL
115
116 /* first zero the log */
75c8b434 117 libxfs_device_zero(btp, start, length);
5000d01d
SL
118
119 /* then write a log record header */
989b74bc
NS
120 len = ((version == 2) && sunit) ? BTOBB(sunit) : 2;
121 len = MAX(len, 2);
75c8b434 122 bp = libxfs_getbufr(btp, start, len);
e6b359b3
NS
123 libxfs_log_header(XFS_BUF_PTR(bp),
124 fs_uuid, version, sunit, fmt, next, bp);
125 bp->b_flags |= LIBXFS_B_DIRTY;
126 libxfs_putbufr(bp);
989b74bc
NS
127 return 0;
128}
5000d01d 129
989b74bc
NS
130int
131libxfs_log_header(
132 xfs_caddr_t caddr,
133 uuid_t *fs_uuid,
134 int version,
135 int sunit,
136 int fmt,
137 libxfs_get_block_t *nextfunc,
138 void *private)
139{
140 xlog_rec_header_t *head = (xlog_rec_header_t *)caddr;
141 xfs_caddr_t p = caddr;
5e656dbb 142 __be32 cycle_lsn;
989b74bc
NS
143 int i, len;
144
145 len = ((version == 2) && sunit) ? BTOBB(sunit) : 1;
5000d01d
SL
146
147 /* note that oh_tid actually contains the cycle number
148 * and the tid is stored in h_cycle_data[0] - that's the
149 * way things end up on disk.
150 */
989b74bc 151 memset(p, 0, BBSIZE);
5e656dbb
BN
152 head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
153 head->h_cycle = cpu_to_be32(1);
154 head->h_version = cpu_to_be32(version);
73bf5988 155 if (len != 1)
5e656dbb 156 head->h_len = cpu_to_be32(sunit - BBSIZE);
73bf5988 157 else
5e656dbb 158 head->h_len = cpu_to_be32(20);
a2ceac1f 159 head->h_crc = cpu_to_be32(0);
5e656dbb
BN
160 head->h_prev_block = cpu_to_be32(-1);
161 head->h_num_logops = cpu_to_be32(1);
162 head->h_cycle_data[0] = cpu_to_be32(0xb0c0d0d0);
163 head->h_fmt = cpu_to_be32(fmt);
164 head->h_size = cpu_to_be32(XLOG_HEADER_CYCLE_SIZE);
5000d01d 165
5e656dbb
BN
166 head->h_lsn = cpu_to_be64(xlog_assign_lsn(1, 0));
167 head->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(1, 0));
5000d01d 168
6699422d 169 memcpy(&head->h_fs_uuid, fs_uuid, sizeof(uuid_t));
73bf5988 170
989b74bc
NS
171 len = MAX(len, 2);
172 p = nextfunc(p, BBSIZE, private);
173 unmount_record(p);
73bf5988 174
46eca962 175 cycle_lsn = CYCLE_LSN_DISK(head->h_lsn);
989b74bc
NS
176 for (i = 2; i < len; i++) {
177 p = nextfunc(p, BBSIZE, private);
178 memset(p, 0, BBSIZE);
5e656dbb 179 *(__be32 *)p = cycle_lsn;
73bf5988 180 }
5000d01d 181
989b74bc 182 return BBTOB(len);
2bd0ea18
NS
183}
184
2556c98b
BN
185/*
186 * Simple I/O (buffer cache) interface
187 */
188
189
190#ifdef XFS_BUF_TRACING
191
192#undef libxfs_readbuf
a2ceac1f 193#undef libxfs_readbuf_map
2556c98b
BN
194#undef libxfs_writebuf
195#undef libxfs_getbuf
a2ceac1f 196#undef libxfs_getbuf_map
2ae22647 197#undef libxfs_getbuf_flags
2556c98b
BN
198#undef libxfs_putbuf
199
75c8b434 200xfs_buf_t *libxfs_readbuf(struct xfs_buftarg *, xfs_daddr_t, int, int,
f756f80c 201 const struct xfs_buf_ops *);
75c8b434 202xfs_buf_t *libxfs_readbuf_map(struct xfs_buftarg *, struct xfs_buf_map *,
f756f80c 203 int, int, const struct xfs_buf_ops *);
2556c98b 204int libxfs_writebuf(xfs_buf_t *, int);
75c8b434 205xfs_buf_t *libxfs_getbuf(struct xfs_buftarg *, xfs_daddr_t, int);
7e3ab890
DC
206xfs_buf_t *libxfs_getbuf_map(struct xfs_buftarg *, struct xfs_buf_map *,
207 int, int);
75c8b434
DC
208xfs_buf_t *libxfs_getbuf_flags(struct xfs_buftarg *, xfs_daddr_t, int,
209 unsigned int);
2556c98b
BN
210void libxfs_putbuf (xfs_buf_t *);
211
a2ceac1f
DC
212#define __add_trace(bp, func, file, line) \
213do { \
214 if (bp) { \
215 (bp)->b_func = (func); \
216 (bp)->b_file = (file); \
217 (bp)->b_line = (line); \
218 } \
219} while (0)
220
2556c98b 221xfs_buf_t *
a2ceac1f 222libxfs_trace_readbuf(const char *func, const char *file, int line,
75c8b434
DC
223 struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, int flags,
224 const struct xfs_buf_ops *ops)
2556c98b 225{
75c8b434 226 xfs_buf_t *bp = libxfs_readbuf(btp, blkno, len, flags, ops);
a2ceac1f
DC
227 __add_trace(bp, func, file, line);
228 return bp;
229}
2556c98b 230
a2ceac1f
DC
231xfs_buf_t *
232libxfs_trace_readbuf_map(const char *func, const char *file, int line,
75c8b434
DC
233 struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, int flags,
234 const struct xfs_buf_ops *ops)
a2ceac1f 235{
75c8b434 236 xfs_buf_t *bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops);
a2ceac1f 237 __add_trace(bp, func, file, line);
2556c98b
BN
238 return bp;
239}
240
241int
242libxfs_trace_writebuf(const char *func, const char *file, int line, xfs_buf_t *bp, int flags)
243{
a2ceac1f 244 __add_trace(bp, func, file, line);
2556c98b
BN
245 return libxfs_writebuf(bp, flags);
246}
247
248xfs_buf_t *
a2ceac1f 249libxfs_trace_getbuf(const char *func, const char *file, int line,
75c8b434 250 struct xfs_buftarg *btp, xfs_daddr_t blkno, int len)
2556c98b 251{
75c8b434 252 xfs_buf_t *bp = libxfs_getbuf(btp, blkno, len);
a2ceac1f
DC
253 __add_trace(bp, func, file, line);
254 return bp;
255}
2556c98b 256
a2ceac1f
DC
257xfs_buf_t *
258libxfs_trace_getbuf_map(const char *func, const char *file, int line,
7e3ab890
DC
259 struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
260 int flags)
a2ceac1f 261{
7e3ab890 262 xfs_buf_t *bp = libxfs_getbuf_map(btp, map, nmaps, flags);
a2ceac1f 263 __add_trace(bp, func, file, line);
2556c98b
BN
264 return bp;
265}
266
2ae22647
CH
267xfs_buf_t *
268libxfs_trace_getbuf_flags(const char *func, const char *file, int line,
75c8b434 269 struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, unsigned int flags)
2ae22647 270{
75c8b434 271 xfs_buf_t *bp = libxfs_getbuf_flags(btp, blkno, len, flags);
a2ceac1f 272 __add_trace(bp, func, file, line);
2ae22647
CH
273 return bp;
274}
275
2556c98b
BN
276void
277libxfs_trace_putbuf(const char *func, const char *file, int line, xfs_buf_t *bp)
278{
a2ceac1f 279 __add_trace(bp, func, file, line);
2556c98b
BN
280 libxfs_putbuf(bp);
281}
282
283
284#endif
285
286
f1b058f9
NS
287xfs_buf_t *
288libxfs_getsb(xfs_mount_t *mp, int flags)
289{
75c8b434
DC
290 return libxfs_readbuf(mp->m_ddev_targp, XFS_SB_DADDR,
291 XFS_FSS_TO_BB(mp, 1), flags, &xfs_sb_buf_ops);
f1b058f9
NS
292}
293
5e656dbb 294kmem_zone_t *xfs_buf_zone;
69ec88b5
BN
295
296static struct cache_mru xfs_buf_freelist =
297 {{&xfs_buf_freelist.cm_list, &xfs_buf_freelist.cm_list},
298 0, PTHREAD_MUTEX_INITIALIZER };
f1b058f9 299
a2ceac1f
DC
300/*
301 * The bufkey is used to pass the new buffer information to the cache object
302 * allocation routine. Because discontiguous buffers need to pass different
303 * information, we need fields to pass that information. However, because the
304 * blkno and bblen is needed for the initial cache entry lookup (i.e. for
305 * bcompare) the fact that the map/nmaps is non-null to switch to discontiguous
306 * buffer initialisation instead of a contiguous buffer.
307 */
308struct xfs_bufkey {
75c8b434 309 struct xfs_buftarg *buftarg;
a2ceac1f
DC
310 xfs_daddr_t blkno;
311 unsigned int bblen;
312 struct xfs_buf_map *map;
313 int nmaps;
314};
f1b058f9
NS
315
316static unsigned int
317libxfs_bhash(cache_key_t key, unsigned int hashsize)
318{
a2ceac1f 319 return (((unsigned int)((struct xfs_bufkey *)key)->blkno) >> 5) % hashsize;
f1b058f9
NS
320}
321
322static int
323libxfs_bcompare(struct cache_node *node, cache_key_t key)
324{
a2ceac1f
DC
325 struct xfs_buf *bp = (struct xfs_buf *)node;
326 struct xfs_bufkey *bkey = (struct xfs_bufkey *)key;
f1b058f9 327
75c8b434 328 if (bp->b_target->dev == bkey->buftarg->dev &&
ba9ecd40
DC
329 bp->b_bn == bkey->blkno) {
330 if (bp->b_bcount == BBTOB(bkey->bblen))
331 return CACHE_HIT;
332#ifdef IO_BCOMPARE_CHECK
333 if (!(libxfs_bcache->c_flags & CACHE_MISCOMPARE_PURGE)) {
334 fprintf(stderr,
335 "%lx: Badness in key lookup (length)\n"
336 "bp=(bno 0x%llx, len %u bytes) key=(bno 0x%llx, len %u bytes)\n",
337 pthread_self(),
338 (unsigned long long)bp->b_bn, (int)bp->b_bcount,
339 (unsigned long long)bkey->blkno,
340 BBTOB(bkey->bblen));
341 }
f1b058f9 342#endif
ba9ecd40
DC
343 return CACHE_PURGE;
344 }
345 return CACHE_MISS;
f1b058f9
NS
346}
347
348void
349libxfs_bprint(xfs_buf_t *bp)
350{
351 fprintf(stderr, "Buffer 0x%p blkno=%llu bytes=%u flags=0x%x count=%u\n",
5dfa5cd2 352 bp, (unsigned long long)bp->b_bn, (unsigned)bp->b_bcount,
f1b058f9
NS
353 bp->b_flags, bp->b_node.cn_count);
354}
355
e6b359b3 356static void
75c8b434
DC
357__initbuf(xfs_buf_t *bp, struct xfs_buftarg *btp, xfs_daddr_t bno,
358 unsigned int bytes)
e6b359b3
NS
359{
360 bp->b_flags = 0;
5dfa5cd2 361 bp->b_bn = bno;
e6b359b3 362 bp->b_bcount = bytes;
a2ceac1f 363 bp->b_length = BTOBB(bytes);
75c8b434 364 bp->b_target = btp;
a6a7776a 365 bp->b_error = 0;
69ec88b5
BN
366 if (!bp->b_addr)
367 bp->b_addr = memalign(libxfs_device_alignment(), bytes);
e6b359b3
NS
368 if (!bp->b_addr) {
369 fprintf(stderr,
370 _("%s: %s can't memalign %u bytes: %s\n"),
371 progname, __FUNCTION__, bytes,
372 strerror(errno));
373 exit(1);
374 }
2556c98b
BN
375#ifdef XFS_BUF_TRACING
376 list_head_init(&bp->b_lock_list);
377#endif
378 pthread_mutex_init(&bp->b_lock, NULL);
50722af1
CH
379 bp->b_holder = 0;
380 bp->b_recur = 0;
75c8b434 381 bp->b_ops = NULL;
e6b359b3
NS
382}
383
a2ceac1f 384static void
75c8b434
DC
385libxfs_initbuf(xfs_buf_t *bp, struct xfs_buftarg *btp, xfs_daddr_t bno,
386 unsigned int bytes)
a2ceac1f 387{
75c8b434 388 __initbuf(bp, btp, bno, bytes);
a2ceac1f
DC
389}
390
391static void
75c8b434
DC
392libxfs_initbuf_map(xfs_buf_t *bp, struct xfs_buftarg *btp,
393 struct xfs_buf_map *map, int nmaps)
a2ceac1f
DC
394{
395 unsigned int bytes = 0;
396 int i;
397
398 bytes = sizeof(struct xfs_buf_map) * nmaps;
399 bp->b_map = malloc(bytes);
400 if (!bp->b_map) {
401 fprintf(stderr,
402 _("%s: %s can't malloc %u bytes: %s\n"),
403 progname, __FUNCTION__, bytes,
404 strerror(errno));
405 exit(1);
406 }
407 bp->b_nmaps = nmaps;
408
409 bytes = 0;
410 for ( i = 0; i < nmaps; i++) {
411 bp->b_map[i].bm_bn = map[i].bm_bn;
412 bp->b_map[i].bm_len = map[i].bm_len;
413 bytes += BBTOB(map[i].bm_len);
414 }
415
75c8b434 416 __initbuf(bp, btp, map[0].bm_bn, bytes);
a2ceac1f
DC
417 bp->b_flags |= LIBXFS_B_DISCONTIG;
418}
419
e6b359b3 420xfs_buf_t *
a2ceac1f 421__libxfs_getbufr(int blen)
e6b359b3
NS
422{
423 xfs_buf_t *bp;
69ec88b5
BN
424
425 /*
426 * first look for a buffer that can be used as-is,
427 * if one cannot be found, see if there is a buffer,
ff1f79a7 428 * and if so, free its buffer and set b_addr to NULL
69ec88b5
BN
429 * before calling libxfs_initbuf.
430 */
431 pthread_mutex_lock(&xfs_buf_freelist.cm_mutex);
432 if (!list_empty(&xfs_buf_freelist.cm_list)) {
433 list_for_each_entry(bp, &xfs_buf_freelist.cm_list, b_node.cn_mru) {
434 if (bp->b_bcount == blen) {
435 list_del_init(&bp->b_node.cn_mru);
436 break;
437 }
438 }
439 if (&bp->b_node.cn_mru == &xfs_buf_freelist.cm_list) {
440 bp = list_entry(xfs_buf_freelist.cm_list.next,
441 xfs_buf_t, b_node.cn_mru);
442 list_del_init(&bp->b_node.cn_mru);
443 free(bp->b_addr);
444 bp->b_addr = NULL;
a2ceac1f
DC
445 free(bp->b_map);
446 bp->b_map = NULL;
69ec88b5
BN
447 }
448 } else
5e656dbb 449 bp = kmem_zone_zalloc(xfs_buf_zone, 0);
69ec88b5 450 pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex);
e0607266 451 bp->b_ops = NULL;
e6b359b3 452
a2ceac1f
DC
453 return bp;
454}
455
456xfs_buf_t *
75c8b434 457libxfs_getbufr(struct xfs_buftarg *btp, xfs_daddr_t blkno, int bblen)
a2ceac1f
DC
458{
459 xfs_buf_t *bp;
460 int blen = BBTOB(bblen);
461
462 bp =__libxfs_getbufr(blen);
463 if (bp)
75c8b434 464 libxfs_initbuf(bp, btp, blkno, blen);
2556c98b 465#ifdef IO_DEBUG
a2ceac1f 466 printf("%lx: %s: allocated %u bytes buffer, key=0x%llx(0x%llx), %p\n",
f63fd268 467 pthread_self(), __FUNCTION__, blen,
2556c98b
BN
468 (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp);
469#endif
69ec88b5 470
e6b359b3
NS
471 return bp;
472}
473
a2ceac1f 474xfs_buf_t *
75c8b434 475libxfs_getbufr_map(struct xfs_buftarg *btp, xfs_daddr_t blkno, int bblen,
a2ceac1f
DC
476 struct xfs_buf_map *map, int nmaps)
477{
478 xfs_buf_t *bp;
479 int blen = BBTOB(bblen);
480
481 if (!map || !nmaps) {
482 fprintf(stderr,
483 _("%s: %s invalid map %p or nmaps %d\n"),
484 progname, __FUNCTION__, map, nmaps);
485 exit(1);
486 }
487
488 if (blkno != map[0].bm_bn) {
489 fprintf(stderr,
490 _("%s: %s map blkno %lx doesn't match key %lx\n"),
491 progname, __FUNCTION__, map[0].bm_bn, blkno);
492 exit(1);
493 }
494
495 bp =__libxfs_getbufr(blen);
496 if (bp)
75c8b434 497 libxfs_initbuf_map(bp, btp, map, nmaps);
a2ceac1f
DC
498#ifdef IO_DEBUG
499 printf("%lx: %s: allocated %u bytes buffer, key=0x%llx(0x%llx), %p\n",
500 pthread_self(), __FUNCTION__, blen,
501 (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp);
502#endif
503
504 return bp;
505}
2556c98b
BN
506
507#ifdef XFS_BUF_TRACING
508struct list_head lock_buf_list = {&lock_buf_list, &lock_buf_list};
509int lock_buf_count = 0;
510#endif
e6b359b3 511
d0572de5
BN
512extern int use_xfs_buf_lock;
513
a2ceac1f
DC
514static struct xfs_buf *
515__cache_lookup(struct xfs_bufkey *key, unsigned int flags)
2bd0ea18 516{
a2ceac1f 517 struct xfs_buf *bp;
2556c98b 518
a2ceac1f 519 cache_node_get(libxfs_bcache, key, (struct cache_node **)&bp);
2ae22647
CH
520 if (!bp)
521 return NULL;
522
523 if (use_xfs_buf_lock) {
50722af1
CH
524 int ret;
525
526 ret = pthread_mutex_trylock(&bp->b_lock);
527 if (ret) {
528 ASSERT(ret == EAGAIN);
529 if (flags & LIBXFS_GETBUF_TRYLOCK)
530 goto out_put;
531
532 if (pthread_equal(bp->b_holder, pthread_self())) {
533 fprintf(stderr,
534 _("Warning: recursive buffer locking at block %" PRIu64 " detected\n"),
a2ceac1f 535 key->blkno);
50722af1
CH
536 bp->b_recur++;
537 return bp;
538 } else {
539 pthread_mutex_lock(&bp->b_lock);
2ae22647 540 }
2ae22647 541 }
50722af1
CH
542
543 bp->b_holder = pthread_self();
2ae22647
CH
544 }
545
546 cache_node_set_priority(libxfs_bcache, (struct cache_node *)bp,
547 cache_node_get_priority((struct cache_node *)bp) -
a040d7c9 548 CACHE_PREFETCH_PRIORITY);
2556c98b 549#ifdef XFS_BUF_TRACING
2ae22647
CH
550 pthread_mutex_lock(&libxfs_bcache->c_mutex);
551 lock_buf_count++;
552 list_add(&bp->b_lock_list, &lock_buf_list);
553 pthread_mutex_unlock(&libxfs_bcache->c_mutex);
2556c98b 554#endif
2bd0ea18 555#ifdef IO_DEBUG
a2ceac1f
DC
556 printf("%lx %s: hit buffer %p for bno = 0x%llx/0x%llx\n",
557 pthread_self(), __FUNCTION__,
558 bp, bp->b_bn, (long long)LIBXFS_BBTOOFF64(key->blkno));
2bd0ea18 559#endif
2556c98b 560
f1b058f9 561 return bp;
50722af1
CH
562out_put:
563 cache_node_put(libxfs_bcache, (struct cache_node *)bp);
564 return NULL;
f1b058f9
NS
565}
566
a2ceac1f 567struct xfs_buf *
75c8b434
DC
568libxfs_getbuf_flags(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len,
569 unsigned int flags)
a2ceac1f
DC
570{
571 struct xfs_bufkey key = {0};
572
75c8b434 573 key.buftarg = btp;
a2ceac1f
DC
574 key.blkno = blkno;
575 key.bblen = len;
576
577 return __cache_lookup(&key, flags);
578}
579
2ae22647 580struct xfs_buf *
75c8b434 581libxfs_getbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len)
2ae22647 582{
75c8b434 583 return libxfs_getbuf_flags(btp, blkno, len, 0);
2ae22647
CH
584}
585
a2ceac1f 586struct xfs_buf *
7e3ab890
DC
587libxfs_getbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map,
588 int nmaps, int flags)
a2ceac1f
DC
589{
590 struct xfs_bufkey key = {0};
591 int i;
592
f388124d
DC
593 if (nmaps == 1)
594 return libxfs_getbuf_flags(btp, map[0].bm_bn, map[0].bm_len,
595 flags);
596
75c8b434 597 key.buftarg = btp;
a2ceac1f
DC
598 key.blkno = map[0].bm_bn;
599 for (i = 0; i < nmaps; i++) {
600 key.bblen += map[i].bm_len;
601 }
602 key.map = map;
603 key.nmaps = nmaps;
604
7e3ab890 605 return __cache_lookup(&key, flags);
a2ceac1f
DC
606}
607
f1b058f9
NS
608void
609libxfs_putbuf(xfs_buf_t *bp)
610{
2556c98b
BN
611#ifdef XFS_BUF_TRACING
612 pthread_mutex_lock(&libxfs_bcache->c_mutex);
613 lock_buf_count--;
614 ASSERT(lock_buf_count >= 0);
615 list_del_init(&bp->b_lock_list);
616 pthread_mutex_unlock(&libxfs_bcache->c_mutex);
617#endif
50722af1
CH
618 if (use_xfs_buf_lock) {
619 if (bp->b_recur) {
620 bp->b_recur--;
621 } else {
622 bp->b_holder = 0;
623 pthread_mutex_unlock(&bp->b_lock);
624 }
625 }
a040d7c9 626 cache_node_put(libxfs_bcache, (struct cache_node *)bp);
f1b058f9
NS
627}
628
629void
630libxfs_purgebuf(xfs_buf_t *bp)
631{
a2ceac1f 632 struct xfs_bufkey key = {0};
f1b058f9 633
75c8b434 634 key.buftarg = bp->b_target;
5dfa5cd2 635 key.blkno = bp->b_bn;
75c8b434 636 key.bblen = bp->b_length;
f1b058f9
NS
637
638 cache_node_purge(libxfs_bcache, &key, (struct cache_node *)bp);
639}
2bd0ea18 640
f1b058f9 641static struct cache_node *
2556c98b 642libxfs_balloc(cache_key_t key)
f1b058f9 643{
a2ceac1f 644 struct xfs_bufkey *bufkey = (struct xfs_bufkey *)key;
2556c98b 645
a2ceac1f
DC
646 if (bufkey->map)
647 return (struct cache_node *)
75c8b434 648 libxfs_getbufr_map(bufkey->buftarg,
a2ceac1f
DC
649 bufkey->blkno, bufkey->bblen,
650 bufkey->map, bufkey->nmaps);
75c8b434 651 return (struct cache_node *)libxfs_getbufr(bufkey->buftarg,
a2ceac1f 652 bufkey->blkno, bufkey->bblen);
2bd0ea18
NS
653}
654
a2ceac1f
DC
655
656static int
657__read_buf(int fd, void *buf, int len, off64_t offset, int flags)
2bd0ea18 658{
bcea58c7 659 int sts;
2bd0ea18 660
a2ceac1f 661 sts = pread64(fd, buf, len, offset);
bcea58c7 662 if (sts < 0) {
a2ceac1f 663 int error = errno;
9440d84d 664 fprintf(stderr, _("%s: read failed: %s\n"),
c3928e39 665 progname, strerror(error));
9440d84d 666 if (flags & LIBXFS_EXIT_ON_FAILURE)
2bd0ea18 667 exit(1);
c3928e39 668 return error;
a2ceac1f 669 } else if (sts != len) {
bcea58c7 670 fprintf(stderr, _("%s: error - read only %d of %d bytes\n"),
a2ceac1f 671 progname, sts, len);
bcea58c7
CH
672 if (flags & LIBXFS_EXIT_ON_FAILURE)
673 exit(1);
674 return EIO;
2bd0ea18 675 }
a2ceac1f
DC
676 return 0;
677}
678
679int
75c8b434
DC
680libxfs_readbufr(struct xfs_buftarg *btp, xfs_daddr_t blkno, xfs_buf_t *bp,
681 int len, int flags)
a2ceac1f 682{
75c8b434 683 int fd = libxfs_device_to_fd(btp->dev);
a2ceac1f
DC
684 int bytes = BBTOB(len);
685 int error;
686
687 ASSERT(BBTOB(len) <= bp->b_bcount);
688
689 error = __read_buf(fd, bp->b_addr, bytes, LIBXFS_BBTOOFF64(blkno), flags);
690 if (!error &&
75c8b434 691 bp->b_target->dev == btp->dev &&
5dfa5cd2 692 bp->b_bn == blkno &&
f1b058f9
NS
693 bp->b_bcount == bytes)
694 bp->b_flags |= LIBXFS_B_UPTODATE;
a2ceac1f
DC
695#ifdef IO_DEBUG
696 printf("%lx: %s: read %u bytes, error %d, blkno=0x%llx(0x%llx), %p\n",
697 pthread_self(), __FUNCTION__, bytes, error,
698 (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp);
699#endif
700 return error;
2bd0ea18
NS
701}
702
703xfs_buf_t *
75c8b434
DC
704libxfs_readbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, int flags,
705 const struct xfs_buf_ops *ops)
2bd0ea18 706{
f1b058f9 707 xfs_buf_t *bp;
2bd0ea18
NS
708 int error;
709
75c8b434
DC
710 bp = libxfs_getbuf(btp, blkno, len);
711 if (!bp)
712 return NULL;
713 if ((bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY)))
714 return bp;
715
716 /*
717 * only set the ops on a cache miss (i.e. first physical read) as the
718 * verifier may change the ops to match the typ eof buffer it contains.
719 * A cache hit might reset the verifier to the original type if we set
720 * it again, but it won't get called again and set to match the buffer
721 * contents. *cough* xfs_da_node_buf_ops *cough*.
722 */
723 bp->b_error = 0;
724 bp->b_ops = ops;
725 error = libxfs_readbufr(btp, blkno, bp, len, flags);
726 if (error)
727 bp->b_error = error;
728 else if (bp->b_ops)
729 bp->b_ops->verify_read(bp);
f1b058f9 730 return bp;
2bd0ea18
NS
731}
732
800db1c1 733int
6d5e5ee0 734libxfs_readbufr_map(struct xfs_buftarg *btp, struct xfs_buf *bp, int flags)
a2ceac1f 735{
800db1c1
DC
736 int fd = libxfs_device_to_fd(btp->dev);
737 int error = 0;
738 char *buf;
739 int i;
75c8b434 740
75c8b434 741 fd = libxfs_device_to_fd(btp->dev);
a2ceac1f
DC
742 buf = bp->b_addr;
743 for (i = 0; i < bp->b_nmaps; i++) {
744 off64_t offset = LIBXFS_BBTOOFF64(bp->b_map[i].bm_bn);
745 int len = BBTOB(bp->b_map[i].bm_len);
746
a2ceac1f
DC
747 error = __read_buf(fd, buf, len, offset, flags);
748 if (error) {
749 bp->b_error = error;
750 break;
751 }
752 buf += len;
753 offset += len;
754 }
755
64eb960f 756 if (!error)
800db1c1
DC
757 bp->b_flags |= LIBXFS_B_UPTODATE;
758#ifdef IO_DEBUG
759 printf("%lx: %s: read %u bytes, error %d, blkno=0x%llx(0x%llx), %p\n",
760 pthread_self(), __FUNCTION__, , error,
761 (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp);
762#endif
763 return error;
764}
765
766struct xfs_buf *
767libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
768 int flags, const struct xfs_buf_ops *ops)
769{
770 struct xfs_buf *bp;
771 int error = 0;
772
773 if (nmaps == 1)
774 return libxfs_readbuf(btp, map[0].bm_bn, map[0].bm_len,
775 flags, ops);
776
7e3ab890 777 bp = libxfs_getbuf_map(btp, map, nmaps, 0);
800db1c1
DC
778 if (!bp)
779 return NULL;
780
781 bp->b_error = 0;
782 bp->b_ops = ops;
783 if ((bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY)))
784 return bp;
785
6d5e5ee0 786 error = libxfs_readbufr_map(btp, bp, flags);
75c8b434 787 if (!error) {
a2ceac1f 788 bp->b_flags |= LIBXFS_B_UPTODATE;
75c8b434
DC
789 if (bp->b_ops)
790 bp->b_ops->verify_read(bp);
791 }
a2ceac1f
DC
792#ifdef IO_DEBUG
793 printf("%lx: %s: read %lu bytes, error %d, blkno=%llu(%llu), %p\n",
794 pthread_self(), __FUNCTION__, buf - (char *)bp->b_addr, error,
5dfa5cd2 795 (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn, bp);
a2ceac1f
DC
796#endif
797 return bp;
798}
799
800static int
801__write_buf(int fd, void *buf, int len, off64_t offset, int flags)
2bd0ea18
NS
802{
803 int sts;
2bd0ea18 804
a2ceac1f 805 sts = pwrite64(fd, buf, len, offset);
2bd0ea18 806 if (sts < 0) {
a2ceac1f 807 int error = errno;
9440d84d 808 fprintf(stderr, _("%s: pwrite64 failed: %s\n"),
c3928e39 809 progname, strerror(error));
a2ceac1f 810 if (flags & LIBXFS_B_EXIT)
2bd0ea18 811 exit(1);
c3928e39 812 return error;
a2ceac1f
DC
813 } else if (sts != len) {
814 fprintf(stderr, _("%s: error - pwrite64 only %d of %d bytes\n"),
815 progname, sts, len);
816 if (flags & LIBXFS_B_EXIT)
2bd0ea18
NS
817 exit(1);
818 return EIO;
819 }
a2ceac1f
DC
820 return 0;
821}
822
823int
824libxfs_writebufr(xfs_buf_t *bp)
825{
75c8b434 826 int fd = libxfs_device_to_fd(bp->b_target->dev);
a2ceac1f
DC
827 int error = 0;
828
75c8b434
DC
829 /*
830 * we never write buffers that are marked stale. This indicates they
831 * contain data that has been invalidated, and even if the buffer is
832 * dirty it must *never* be written. Verifiers are wonderful for finding
833 * bugs like this. Make sure the error is obvious as to the cause.
834 */
835 if (bp->b_flags & LIBXFS_B_STALE) {
836 bp->b_error = ESTALE;
837 return bp->b_error;
838 }
839
840 /*
841 * clear any pre-existing error status on the buffer. This can occur if
842 * the buffer is corrupt on disk and the repair process doesn't clear
843 * the error before fixing and writing it back.
844 */
845 bp->b_error = 0;
846 if (bp->b_ops) {
847 bp->b_ops->verify_write(bp);
848 if (bp->b_error) {
849 fprintf(stderr,
850 _("%s: write verifer failed on bno 0x%llx/0x%x\n"),
851 __func__, (long long)bp->b_bn, bp->b_bcount);
852 return bp->b_error;
853 }
854 }
855
a2ceac1f
DC
856 if (!(bp->b_flags & LIBXFS_B_DISCONTIG)) {
857 error = __write_buf(fd, bp->b_addr, bp->b_bcount,
5dfa5cd2 858 LIBXFS_BBTOOFF64(bp->b_bn), bp->b_flags);
a2ceac1f
DC
859 } else {
860 int i;
861 char *buf = bp->b_addr;
862
863 for (i = 0; i < bp->b_nmaps; i++) {
864 off64_t offset = LIBXFS_BBTOOFF64(bp->b_map[i].bm_bn);
865 int len = BBTOB(bp->b_map[i].bm_len);
866
867 error = __write_buf(fd, buf, len, offset, bp->b_flags);
868 if (error) {
869 bp->b_error = error;
870 break;
871 }
872 buf += len;
873 offset += len;
874 }
875 }
876
f1b058f9 877#ifdef IO_DEBUG
2556c98b
BN
878 printf("%lx: %s: wrote %u bytes, blkno=%llu(%llu), %p\n",
879 pthread_self(), __FUNCTION__, bp->b_bcount,
5dfa5cd2
DC
880 (long long)LIBXFS_BBTOOFF64(bp->b_bn),
881 (long long)bp->b_bn, bp);
f1b058f9 882#endif
a2ceac1f
DC
883 if (!error) {
884 bp->b_flags |= LIBXFS_B_UPTODATE;
885 bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_EXIT);
886 }
887 return error;
2bd0ea18
NS
888}
889
890int
f1b058f9 891libxfs_writebuf_int(xfs_buf_t *bp, int flags)
2bd0ea18 892{
f1b058f9
NS
893 bp->b_flags |= (LIBXFS_B_DIRTY | flags);
894 return 0;
895}
896
897int
898libxfs_writebuf(xfs_buf_t *bp, int flags)
899{
e0607266
DC
900#ifdef IO_DEBUG
901 printf("%lx: %s: dirty blkno=%llu(%llu)\n",
902 pthread_self(), __FUNCTION__,
903 (long long)LIBXFS_BBTOOFF64(bp->b_bn),
904 (long long)bp->b_bn);
905#endif
f1b058f9
NS
906 bp->b_flags |= (LIBXFS_B_DIRTY | flags);
907 libxfs_putbuf(bp);
908 return 0;
2bd0ea18
NS
909}
910
57c9fccb 911void
f1b058f9 912libxfs_iomove(xfs_buf_t *bp, uint boff, int len, void *data, int flags)
57c9fccb 913{
f1b058f9
NS
914#ifdef IO_DEBUG
915 if (boff + len > bp->b_bcount) {
2556c98b 916 printf("Badness, iomove out of range!\n"
a2ceac1f 917 "bp=(bno 0x%llx, bytes %u) range=(boff %u, bytes %u)\n",
5dfa5cd2 918 (long long)bp->b_bn, bp->b_bcount, boff, len);
57c9fccb 919 abort();
f1b058f9
NS
920 }
921#endif
57c9fccb
NS
922 switch (flags) {
923 case LIBXFS_BZERO:
f1b058f9 924 memset(bp->b_addr + boff, 0, len);
57c9fccb
NS
925 break;
926 case LIBXFS_BREAD:
f1b058f9 927 memcpy(data, bp->b_addr + boff, len);
57c9fccb
NS
928 break;
929 case LIBXFS_BWRITE:
f1b058f9 930 memcpy(bp->b_addr + boff, data, len);
57c9fccb
NS
931 break;
932 }
933}
934
33165ec3 935static void
69ec88b5 936libxfs_brelse(struct cache_node *node)
33165ec3
BN
937{
938 xfs_buf_t *bp = (xfs_buf_t *)node;
939
69ec88b5
BN
940 if (bp != NULL) {
941 if (bp->b_flags & LIBXFS_B_DIRTY)
942 libxfs_writebufr(bp);
943 pthread_mutex_lock(&xfs_buf_freelist.cm_mutex);
944 list_add(&bp->b_node.cn_mru, &xfs_buf_freelist.cm_list);
945 pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex);
946 }
33165ec3
BN
947}
948
e08f5594 949static unsigned int
69ec88b5
BN
950libxfs_bulkrelse(
951 struct cache *cache,
952 struct list_head *list)
2556c98b 953{
69ec88b5 954 xfs_buf_t *bp;
e08f5594 955 int count = 0;
2556c98b 956
69ec88b5 957 if (list_empty(list))
e08f5594 958 return 0 ;
69ec88b5
BN
959
960 list_for_each_entry(bp, list, b_node.cn_mru) {
2556c98b
BN
961 if (bp->b_flags & LIBXFS_B_DIRTY)
962 libxfs_writebufr(bp);
e08f5594 963 count++;
2556c98b 964 }
69ec88b5
BN
965
966 pthread_mutex_lock(&xfs_buf_freelist.cm_mutex);
967 __list_splice(list, &xfs_buf_freelist.cm_list);
968 pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex);
e08f5594
BN
969
970 return count;
69ec88b5
BN
971}
972
973static void
974libxfs_bflush(struct cache_node *node)
975{
976 xfs_buf_t *bp = (xfs_buf_t *)node;
977
978 if ((bp != NULL) && (bp->b_flags & LIBXFS_B_DIRTY))
979 libxfs_writebufr(bp);
2556c98b
BN
980}
981
982void
983libxfs_putbufr(xfs_buf_t *bp)
984{
985 libxfs_brelse((struct cache_node *)bp);
986}
987
988
f1b058f9
NS
989void
990libxfs_bcache_purge(void)
991{
992 cache_purge(libxfs_bcache);
993}
994
e8cb94ee 995void
33165ec3
BN
996libxfs_bcache_flush(void)
997{
998 cache_flush(libxfs_bcache);
999}
1000
2556c98b
BN
1001int
1002libxfs_bcache_overflowed(void)
1003{
1004 return cache_overflowed(libxfs_bcache);
1005}
1006
f1b058f9
NS
1007struct cache_operations libxfs_bcache_operations = {
1008 /* .hash */ libxfs_bhash,
1009 /* .alloc */ libxfs_balloc,
33165ec3 1010 /* .flush */ libxfs_bflush,
f1b058f9
NS
1011 /* .relse */ libxfs_brelse,
1012 /* .compare */ libxfs_bcompare,
69ec88b5 1013 /* .bulkrelse */libxfs_bulkrelse
f1b058f9
NS
1014};
1015
2bd0ea18 1016
f1b058f9 1017/*
3a19fb7d 1018 * Inode cache stubs.
f1b058f9
NS
1019 */
1020
5e656dbb
BN
1021extern kmem_zone_t *xfs_ili_zone;
1022extern kmem_zone_t *xfs_inode_zone;
f1b058f9 1023
2bd0ea18
NS
1024int
1025libxfs_iget(xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint lock_flags,
1026 xfs_inode_t **ipp, xfs_daddr_t bno)
1027{
1028 xfs_inode_t *ip;
f1b058f9 1029 int error = 0;
2bd0ea18 1030
3a19fb7d
CH
1031 ip = kmem_zone_zalloc(xfs_inode_zone, 0);
1032 if (!ip)
1033 return ENOMEM;
2bd0ea18 1034
3a19fb7d
CH
1035 ip->i_ino = ino;
1036 ip->i_mount = mp;
1037 error = xfs_iread(mp, tp, ip, bno);
1038 if (error) {
1039 kmem_zone_free(xfs_inode_zone, ip);
1040 *ipp = NULL;
1041 return error;
1042 }
f1b058f9 1043
3a19fb7d
CH
1044 *ipp = ip;
1045 return 0;
f1b058f9
NS
1046}
1047
1048static void
014e5f6d
ES
1049libxfs_idestroy(xfs_inode_t *ip)
1050{
1051 switch (ip->i_d.di_mode & S_IFMT) {
1052 case S_IFREG:
1053 case S_IFDIR:
1054 case S_IFLNK:
1055 libxfs_idestroy_fork(ip, XFS_DATA_FORK);
1056 break;
1057 }
1058 if (ip->i_afp)
1059 libxfs_idestroy_fork(ip, XFS_ATTR_FORK);
1060}
1061
2bd0ea18 1062void
3a19fb7d 1063libxfs_iput(xfs_inode_t *ip, uint lock_flags)
2bd0ea18 1064{
3a19fb7d
CH
1065 if (ip->i_itemp)
1066 kmem_zone_free(xfs_ili_zone, ip->i_itemp);
1067 ip->i_itemp = NULL;
1068 libxfs_idestroy(ip);
1069 kmem_zone_free(xfs_inode_zone, ip);
2bd0ea18 1070}