]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/rdwr.c
fix various typos
[thirdparty/xfsprogs-dev.git] / libxfs / rdwr.c
1 /*
2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
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.
8 *
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.
13 *
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
17 */
18
19 #include <xfs/libxfs.h>
20 #include <xfs/xfs_log.h>
21 #include <xfs/xfs_log_priv.h>
22 #include "init.h"
23
24 #define BDSTRAT_SIZE (256 * 1024)
25 #define min(x, y) ((x) < (y) ? (x) : (y))
26
27 #define IO_BCOMPARE_CHECK
28
29 void
30 libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len)
31 {
32 xfs_off_t start_offset, end_offset, offset;
33 ssize_t zsize, bytes;
34 char *z;
35 int fd;
36
37 zsize = min(BDSTRAT_SIZE, BBTOB(len));
38 if ((z = memalign(libxfs_device_alignment(), zsize)) == NULL) {
39 fprintf(stderr,
40 _("%s: %s can't memalign %d bytes: %s\n"),
41 progname, __FUNCTION__, (int)zsize, strerror(errno));
42 exit(1);
43 }
44 memset(z, 0, zsize);
45
46 fd = libxfs_device_to_fd(dev);
47 start_offset = LIBXFS_BBTOOFF64(start);
48
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));
53 exit(1);
54 }
55
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));
62 exit(1);
63 } else if (bytes == 0) {
64 fprintf(stderr, _("%s: %s not progressing?\n"),
65 progname, __FUNCTION__);
66 exit(1);
67 }
68 offset += bytes;
69 }
70 free(z);
71 }
72
73 static void unmount_record(void *p)
74 {
75 xlog_op_header_t *op = (xlog_op_header_t *)p;
76 /* the data section must be 32 bit size aligned */
77 struct {
78 __uint16_t magic;
79 __uint16_t pad1;
80 __uint32_t pad2; /* may as well make it 64 bits */
81 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
82
83 memset(p, 0, BBSIZE);
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;
88 op->oh_res2 = 0;
89
90 /* and the data for this op */
91 memcpy((char *)p + sizeof(xlog_op_header_t), &magic, sizeof(magic));
92 }
93
94 static xfs_caddr_t next(xfs_caddr_t ptr, int offset, void *private)
95 {
96 xfs_buf_t *buf = (xfs_buf_t *)private;
97
98 if (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset)
99 abort();
100 return ptr + offset;
101 }
102
103 int
104 libxfs_log_clear(
105 dev_t device,
106 xfs_daddr_t start,
107 uint length,
108 uuid_t *fs_uuid,
109 int version,
110 int sunit,
111 int fmt)
112 {
113 xfs_buf_t *bp;
114 int len;
115
116 if (!device || !fs_uuid)
117 return -EINVAL;
118
119 /* first zero the log */
120 libxfs_device_zero(device, start, length);
121
122 /* then write a log record header */
123 len = ((version == 2) && sunit) ? BTOBB(sunit) : 2;
124 len = MAX(len, 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;
129 libxfs_putbufr(bp);
130 return 0;
131 }
132
133 int
134 libxfs_log_header(
135 xfs_caddr_t caddr,
136 uuid_t *fs_uuid,
137 int version,
138 int sunit,
139 int fmt,
140 libxfs_get_block_t *nextfunc,
141 void *private)
142 {
143 xlog_rec_header_t *head = (xlog_rec_header_t *)caddr;
144 xfs_caddr_t p = caddr;
145 __be32 cycle_lsn;
146 int i, len;
147
148 len = ((version == 2) && sunit) ? BTOBB(sunit) : 1;
149
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.
153 */
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);
158 if (len != 1)
159 head->h_len = cpu_to_be32(sunit - BBSIZE);
160 else
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);
168
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));
171
172 memcpy(&head->h_fs_uuid, fs_uuid, sizeof(uuid_t));
173
174 len = MAX(len, 2);
175 p = nextfunc(p, BBSIZE, private);
176 unmount_record(p);
177
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;
183 }
184
185 return BBTOB(len);
186 }
187
188 /*
189 * Simple I/O (buffer cache) interface
190 */
191
192
193 #ifdef XFS_BUF_TRACING
194
195 #undef libxfs_readbuf
196 #undef libxfs_writebuf
197 #undef libxfs_getbuf
198 #undef libxfs_putbuf
199
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 *);
204
205 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)
207 {
208 xfs_buf_t *bp = libxfs_readbuf(dev, blkno, len, flags);
209
210 bp->b_func = func;
211 bp->b_file = file;
212 bp->b_line = line;
213
214 return bp;
215 }
216
217 int
218 libxfs_trace_writebuf(const char *func, const char *file, int line, xfs_buf_t *bp, int flags)
219 {
220 bp->b_func = func;
221 bp->b_file = file;
222 bp->b_line = line;
223
224 return libxfs_writebuf(bp, flags);
225 }
226
227 xfs_buf_t *
228 libxfs_trace_getbuf(const char *func, const char *file, int line, dev_t device, xfs_daddr_t blkno, int len)
229 {
230 xfs_buf_t *bp = libxfs_getbuf(device, blkno, len);
231
232 bp->b_func = func;
233 bp->b_file = file;
234 bp->b_line = line;
235
236 return bp;
237 }
238
239 void
240 libxfs_trace_putbuf(const char *func, const char *file, int line, xfs_buf_t *bp)
241 {
242 bp->b_func = func;
243 bp->b_file = file;
244 bp->b_line = line;
245
246 libxfs_putbuf(bp);
247 }
248
249
250 #endif
251
252
253 xfs_buf_t *
254 libxfs_getsb(xfs_mount_t *mp, int flags)
255 {
256 return libxfs_readbuf(mp->m_dev, XFS_SB_DADDR,
257 XFS_FSS_TO_BB(mp, 1), flags);
258 }
259
260 kmem_zone_t *xfs_buf_zone;
261
262 static struct cache_mru xfs_buf_freelist =
263 {{&xfs_buf_freelist.cm_list, &xfs_buf_freelist.cm_list},
264 0, PTHREAD_MUTEX_INITIALIZER };
265
266 typedef struct {
267 dev_t device;
268 xfs_daddr_t blkno;
269 unsigned int bblen;
270 } xfs_bufkey_t;
271
272 static unsigned int
273 libxfs_bhash(cache_key_t key, unsigned int hashsize)
274 {
275 return (((unsigned int)((xfs_bufkey_t *)key)->blkno) >> 5) % hashsize;
276 }
277
278 static int
279 libxfs_bcompare(struct cache_node *node, cache_key_t key)
280 {
281 xfs_buf_t *bp = (xfs_buf_t *)node;
282 xfs_bufkey_t *bkey = (xfs_bufkey_t *)key;
283
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",
290 pthread_self(),
291 (unsigned long long)bp->b_blkno, (int)bp->b_bcount,
292 (unsigned long long)bkey->blkno, BBTOB(bkey->bblen));
293 #endif
294
295 return (bp->b_dev == bkey->device &&
296 bp->b_blkno == bkey->blkno &&
297 bp->b_bcount == BBTOB(bkey->bblen));
298 }
299
300 void
301 libxfs_bprint(xfs_buf_t *bp)
302 {
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);
306 }
307
308 static void
309 libxfs_initbuf(xfs_buf_t *bp, dev_t device, xfs_daddr_t bno, unsigned int bytes)
310 {
311 bp->b_flags = 0;
312 bp->b_blkno = bno;
313 bp->b_bcount = bytes;
314 bp->b_dev = device;
315 if (!bp->b_addr)
316 bp->b_addr = memalign(libxfs_device_alignment(), bytes);
317 if (!bp->b_addr) {
318 fprintf(stderr,
319 _("%s: %s can't memalign %u bytes: %s\n"),
320 progname, __FUNCTION__, bytes,
321 strerror(errno));
322 exit(1);
323 }
324 #ifdef XFS_BUF_TRACING
325 list_head_init(&bp->b_lock_list);
326 #endif
327 pthread_mutex_init(&bp->b_lock, NULL);
328 }
329
330 xfs_buf_t *
331 libxfs_getbufr(dev_t device, xfs_daddr_t blkno, int bblen)
332 {
333 xfs_buf_t *bp;
334 int blen = BBTOB(bblen);
335
336 /*
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.
341 */
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);
347 break;
348 }
349 }
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);
354 free(bp->b_addr);
355 bp->b_addr = NULL;
356 }
357 } else
358 bp = kmem_zone_zalloc(xfs_buf_zone, 0);
359 pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex);
360
361 if (bp != NULL)
362 libxfs_initbuf(bp, device, blkno, blen);
363 #ifdef IO_DEBUG
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);
367 #endif
368
369 return bp;
370 }
371
372
373 #ifdef XFS_BUF_TRACING
374 struct list_head lock_buf_list = {&lock_buf_list, &lock_buf_list};
375 int lock_buf_count = 0;
376 #endif
377
378 extern int use_xfs_buf_lock;
379
380 xfs_buf_t *
381 libxfs_getbuf(dev_t device, xfs_daddr_t blkno, int len)
382 {
383 xfs_buf_t *bp;
384 xfs_bufkey_t key;
385 int miss;
386
387 key.device = device;
388 key.blkno = blkno;
389 key.bblen = len;
390
391 miss = cache_node_get(libxfs_bcache, &key, (struct cache_node **)&bp);
392 if (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);
400 lock_buf_count++;
401 list_add(&bp->b_lock_list, &lock_buf_list);
402 pthread_mutex_unlock(&libxfs_bcache->c_mutex);
403 #endif
404 #ifdef IO_DEBUG
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));
408 #endif
409 }
410
411 return bp;
412 }
413
414 void
415 libxfs_putbuf(xfs_buf_t *bp)
416 {
417 #ifdef XFS_BUF_TRACING
418 pthread_mutex_lock(&libxfs_bcache->c_mutex);
419 lock_buf_count--;
420 ASSERT(lock_buf_count >= 0);
421 list_del_init(&bp->b_lock_list);
422 pthread_mutex_unlock(&libxfs_bcache->c_mutex);
423 #endif
424 if (use_xfs_buf_lock)
425 pthread_mutex_unlock(&bp->b_lock);
426 cache_node_put(libxfs_bcache, (struct cache_node *)bp);
427 }
428
429 void
430 libxfs_purgebuf(xfs_buf_t *bp)
431 {
432 xfs_bufkey_t key;
433
434 key.device = bp->b_dev;
435 key.blkno = bp->b_blkno;
436 key.bblen = bp->b_bcount >> BBSHIFT;
437
438 cache_node_purge(libxfs_bcache, &key, (struct cache_node *)bp);
439 }
440
441 static struct cache_node *
442 libxfs_balloc(cache_key_t key)
443 {
444 xfs_bufkey_t *bufkey = (xfs_bufkey_t *)key;
445
446 return (struct cache_node *)libxfs_getbufr(bufkey->device,
447 bufkey->blkno, bufkey->bblen);
448 }
449
450 int
451 libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *bp, int len, int flags)
452 {
453 int fd = libxfs_device_to_fd(dev);
454 int bytes = BBTOB(len);
455
456 ASSERT(BBTOB(len) <= bp->b_bcount);
457
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)
462 exit(1);
463 return errno;
464 }
465 #ifdef IO_DEBUG
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);
469 #endif
470 if (bp->b_dev == dev &&
471 bp->b_blkno == blkno &&
472 bp->b_bcount == bytes)
473 bp->b_flags |= LIBXFS_B_UPTODATE;
474 return 0;
475 }
476
477 xfs_buf_t *
478 libxfs_readbuf(dev_t dev, xfs_daddr_t blkno, int len, int flags)
479 {
480 xfs_buf_t *bp;
481 int error;
482
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);
486 if (error) {
487 libxfs_putbuf(bp);
488 return NULL;
489 }
490 }
491 return bp;
492 }
493
494 int
495 libxfs_writebufr(xfs_buf_t *bp)
496 {
497 int sts;
498 int fd = libxfs_device_to_fd(bp->b_dev);
499
500 sts = pwrite64(fd, bp->b_addr, bp->b_bcount, LIBXFS_BBTOOFF64(bp->b_blkno));
501 if (sts < 0) {
502 fprintf(stderr, _("%s: pwrite64 failed: %s\n"),
503 progname, strerror(errno));
504 if (bp->b_flags & LIBXFS_B_EXIT)
505 exit(1);
506 return errno;
507 }
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)
512 exit(1);
513 return EIO;
514 }
515 #ifdef IO_DEBUG
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);
520 #endif
521 bp->b_flags |= LIBXFS_B_UPTODATE;
522 bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_EXIT);
523 return 0;
524 }
525
526 int
527 libxfs_writebuf_int(xfs_buf_t *bp, int flags)
528 {
529 bp->b_flags |= (LIBXFS_B_DIRTY | flags);
530 return 0;
531 }
532
533 int
534 libxfs_writebuf(xfs_buf_t *bp, int flags)
535 {
536 bp->b_flags |= (LIBXFS_B_DIRTY | flags);
537 libxfs_putbuf(bp);
538 return 0;
539 }
540
541 void
542 libxfs_iomove(xfs_buf_t *bp, uint boff, int len, void *data, int flags)
543 {
544 #ifdef IO_DEBUG
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);
549 abort();
550 }
551 #endif
552 switch (flags) {
553 case LIBXFS_BZERO:
554 memset(bp->b_addr + boff, 0, len);
555 break;
556 case LIBXFS_BREAD:
557 memcpy(data, bp->b_addr + boff, len);
558 break;
559 case LIBXFS_BWRITE:
560 memcpy(bp->b_addr + boff, data, len);
561 break;
562 }
563 }
564
565 static void
566 libxfs_brelse(struct cache_node *node)
567 {
568 xfs_buf_t *bp = (xfs_buf_t *)node;
569
570 if (bp != NULL) {
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);
576 }
577 }
578
579 static unsigned int
580 libxfs_bulkrelse(
581 struct cache *cache,
582 struct list_head *list)
583 {
584 xfs_buf_t *bp;
585 int count = 0;
586
587 if (list_empty(list))
588 return 0 ;
589
590 list_for_each_entry(bp, list, b_node.cn_mru) {
591 if (bp->b_flags & LIBXFS_B_DIRTY)
592 libxfs_writebufr(bp);
593 count++;
594 }
595
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);
599
600 return count;
601 }
602
603 static void
604 libxfs_bflush(struct cache_node *node)
605 {
606 xfs_buf_t *bp = (xfs_buf_t *)node;
607
608 if ((bp != NULL) && (bp->b_flags & LIBXFS_B_DIRTY))
609 libxfs_writebufr(bp);
610 }
611
612 void
613 libxfs_putbufr(xfs_buf_t *bp)
614 {
615 libxfs_brelse((struct cache_node *)bp);
616 }
617
618
619 void
620 libxfs_bcache_purge(void)
621 {
622 cache_purge(libxfs_bcache);
623 }
624
625 void
626 libxfs_bcache_flush(void)
627 {
628 cache_flush(libxfs_bcache);
629 }
630
631 int
632 libxfs_bcache_overflowed(void)
633 {
634 return cache_overflowed(libxfs_bcache);
635 }
636
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
644 };
645
646
647 /*
648 * Inode cache interfaces
649 */
650
651 extern kmem_zone_t *xfs_ili_zone;
652 extern kmem_zone_t *xfs_inode_zone;
653
654 static unsigned int
655 libxfs_ihash(cache_key_t key, unsigned int hashsize)
656 {
657 return ((unsigned int)*(xfs_ino_t *)key) % hashsize;
658 }
659
660 static int
661 libxfs_icompare(struct cache_node *node, cache_key_t key)
662 {
663 xfs_inode_t *ip = (xfs_inode_t *)node;
664
665 return (ip->i_ino == *(xfs_ino_t *)key);
666 }
667
668 int
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)
671 {
672 xfs_inode_t *ip;
673 int error = 0;
674
675 if (cache_node_get(libxfs_icache, &ino, (struct cache_node **)&ip)) {
676 #ifdef INO_DEBUG
677 fprintf(stderr, "%s: allocated inode, ino=%llu(%llu), %p\n",
678 __FUNCTION__, (unsigned long long)ino, bno, ip);
679 #endif
680 if ((error = libxfs_iread(mp, tp, ino, ip, bno))) {
681 cache_node_purge(libxfs_icache, &ino,
682 (struct cache_node *)ip);
683 ip = NULL;
684 }
685 }
686 *ipp = ip;
687 return error;
688 }
689
690 void
691 libxfs_iput(xfs_inode_t *ip, uint lock_flags)
692 {
693 cache_node_put(libxfs_icache, (struct cache_node *)ip);
694 }
695
696 static struct cache_node *
697 libxfs_ialloc(cache_key_t key)
698 {
699 return kmem_zone_zalloc(xfs_inode_zone, 0);
700 }
701
702 static void
703 libxfs_idestroy(xfs_inode_t *ip)
704 {
705 switch (ip->i_d.di_mode & S_IFMT) {
706 case S_IFREG:
707 case S_IFDIR:
708 case S_IFLNK:
709 libxfs_idestroy_fork(ip, XFS_DATA_FORK);
710 break;
711 }
712 if (ip->i_afp)
713 libxfs_idestroy_fork(ip, XFS_ATTR_FORK);
714 }
715
716 static void
717 libxfs_irelse(struct cache_node *node)
718 {
719 xfs_inode_t *ip = (xfs_inode_t *)node;
720
721 if (ip != NULL) {
722 if (ip->i_itemp)
723 kmem_zone_free(xfs_ili_zone, ip->i_itemp);
724 ip->i_itemp = NULL;
725 libxfs_idestroy(ip);
726 kmem_zone_free(xfs_inode_zone, ip);
727 ip = NULL;
728 }
729 }
730
731 void
732 libxfs_icache_purge(void)
733 {
734 cache_purge(libxfs_icache);
735 }
736
737 struct cache_operations libxfs_icache_operations = {
738 /* .hash */ libxfs_ihash,
739 /* .alloc */ libxfs_ialloc,
740 /* .flush */ NULL,
741 /* .relse */ libxfs_irelse,
742 /* .compare */ libxfs_icompare,
743 /* .bulkrelse */ NULL
744 };