]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/rdwr.c
Fix buffer sizing issue for large pagesize systems, affecting mkfs auto-device-type...
[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
NS
19#include <xfs/libxfs.h>
20#include <xfs/xfs_log.h>
21#include <xfs/xfs_log_priv.h>
1aef52f8 22#include "init.h"
2bd0ea18 23
5000d01d 24#define BDSTRAT_SIZE (256 * 1024)
3cc4d0db 25#define min(x, y) ((x) < (y) ? (x) : (y))
2bd0ea18 26
f1b058f9
NS
27static inline void *
28libxfs_memalign(size_t size)
29{
1aef52f8 30 static size_t memalignment;
f1b058f9 31
1aef52f8
MV
32 if (!memalignment)
33 memalignment = platform_memalignment();
34 return memalign(memalignment, size);
f1b058f9
NS
35}
36
2bd0ea18
NS
37void
38libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len)
39{
3cc4d0db
NS
40 xfs_off_t start_offset, end_offset, offset;
41 ssize_t zsize, bytes;
2bd0ea18 42 char *z;
3cc4d0db 43 int fd;
2bd0ea18 44
3cc4d0db 45 zsize = min(BDSTRAT_SIZE, BBTOB(len));
f1b058f9 46 if ((z = libxfs_memalign(zsize)) == NULL) {
9440d84d
NS
47 fprintf(stderr,
48 _("%s: %s can't memalign %d bytes: %s\n"),
7dfd8291 49 progname, __FUNCTION__, (int)zsize, strerror(errno));
2bd0ea18
NS
50 exit(1);
51 }
3cc4d0db
NS
52 memset(z, 0, zsize);
53
2bd0ea18 54 fd = libxfs_device_to_fd(dev);
cb5b3ef4 55 start_offset = LIBXFS_BBTOOFF64(start);
3cc4d0db
NS
56
57 if ((lseek64(fd, start_offset, SEEK_SET)) < 0) {
58 fprintf(stderr, _("%s: %s seek to offset %llu failed: %s\n"),
7dfd8291
NS
59 progname, __FUNCTION__,
60 (unsigned long long)start_offset, strerror(errno));
3cc4d0db
NS
61 exit(1);
62 }
63
cb5b3ef4 64 end_offset = LIBXFS_BBTOOFF64(start + len) - start_offset;
3cc4d0db
NS
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"),
9440d84d 69 progname, __FUNCTION__, strerror(errno));
2bd0ea18 70 exit(1);
3cc4d0db
NS
71 } else if (bytes == 0) {
72 fprintf(stderr, _("%s: %s not progressing?\n"),
73 progname, __FUNCTION__);
74 exit(1);
2bd0ea18 75 }
3cc4d0db 76 offset += bytes;
2bd0ea18
NS
77 }
78 free(z);
79}
80
989b74bc 81static void unmount_record(void *p)
2bd0ea18 82{
989b74bc 83 xlog_op_header_t *op = (xlog_op_header_t *)p;
5000d01d
SL
84 /* the data section must be 32 bit size aligned */
85 struct {
86 __uint16_t magic;
87 __uint16_t pad1;
88 __uint32_t pad2; /* may as well make it 64 bits */
89 } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
90
989b74bc
NS
91 memset(p, 0, BBSIZE);
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);
97
98 /* and the data for this op */
1552a820 99 memcpy((char *)p + sizeof(xlog_op_header_t), &magic, sizeof(magic));
989b74bc
NS
100}
101
102static xfs_caddr_t next(xfs_caddr_t ptr, int offset, void *private)
103{
104 xfs_buf_t *buf = (xfs_buf_t *)private;
105
106 if (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset)
107 abort();
108 return ptr + offset;
109}
110
111int
112libxfs_log_clear(
113 dev_t device,
114 xfs_daddr_t start,
115 uint length,
116 uuid_t *fs_uuid,
117 int version,
118 int sunit,
119 int fmt)
120{
121 xfs_buf_t *buf;
122 int len;
123
2bd0ea18
NS
124 if (!device || !fs_uuid)
125 return -EINVAL;
5000d01d
SL
126
127 /* first zero the log */
128 libxfs_device_zero(device, start, length);
129
130 /* then write a log record header */
989b74bc
NS
131 len = ((version == 2) && sunit) ? BTOBB(sunit) : 2;
132 len = MAX(len, 2);
5000d01d 133 buf = libxfs_getbuf(device, start, len);
989b74bc
NS
134 libxfs_log_header(XFS_BUF_PTR(buf),
135 fs_uuid, version, sunit, fmt, next, buf);
f1b058f9
NS
136 libxfs_writebufr(buf);
137 libxfs_putbuf(buf);
989b74bc
NS
138 return 0;
139}
5000d01d 140
989b74bc
NS
141int
142libxfs_log_header(
143 xfs_caddr_t caddr,
144 uuid_t *fs_uuid,
145 int version,
146 int sunit,
147 int fmt,
148 libxfs_get_block_t *nextfunc,
149 void *private)
150{
151 xlog_rec_header_t *head = (xlog_rec_header_t *)caddr;
152 xfs_caddr_t p = caddr;
153 uint cycle_lsn;
154 int i, len;
155
156 len = ((version == 2) && sunit) ? BTOBB(sunit) : 1;
5000d01d
SL
157
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.
161 */
989b74bc 162 memset(p, 0, BBSIZE);
5000d01d
SL
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);
73bf5988 166 if (len != 1)
5000d01d 167 INT_SET(head->h_len, ARCH_CONVERT, sunit - BBSIZE);
73bf5988 168 else
5000d01d
SL
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);
73bf5988 175 INT_SET(head->h_size, ARCH_CONVERT, XLOG_HEADER_CYCLE_SIZE);
5000d01d 176
46eca962
NS
177 ASSIGN_ANY_LSN_DISK(head->h_lsn, 1, 0);
178 ASSIGN_ANY_LSN_DISK(head->h_tail_lsn, 1, 0);
5000d01d 179
6699422d 180 memcpy(&head->h_fs_uuid, fs_uuid, sizeof(uuid_t));
73bf5988 181
989b74bc
NS
182 len = MAX(len, 2);
183 p = nextfunc(p, BBSIZE, private);
184 unmount_record(p);
73bf5988 185
46eca962 186 cycle_lsn = CYCLE_LSN_DISK(head->h_lsn);
989b74bc
NS
187 for (i = 2; i < len; i++) {
188 p = nextfunc(p, BBSIZE, private);
189 memset(p, 0, BBSIZE);
190 *(uint *)p = cycle_lsn;
73bf5988 191 }
5000d01d 192
989b74bc 193 return BBTOB(len);
2bd0ea18
NS
194}
195
f1b058f9
NS
196xfs_buf_t *
197libxfs_getsb(xfs_mount_t *mp, int flags)
198{
199 return libxfs_readbuf(mp->m_dev, XFS_SB_DADDR,
200 XFS_FSS_TO_BB(mp, 1), flags);
201}
202
989b74bc 203
2bd0ea18 204/*
f1b058f9 205 * Simple I/O (buffer cache) interface
2bd0ea18
NS
206 */
207
f1b058f9
NS
208xfs_zone_t *xfs_buf_zone;
209
210typedef struct {
211 dev_t device;
212 xfs_daddr_t blkno;
213 unsigned int count;
214} xfs_bufkey_t;
215
216static unsigned int
217libxfs_bhash(cache_key_t key, unsigned int hashsize)
218{
219 return ((unsigned int)((xfs_bufkey_t *)key)->blkno) % hashsize;
220}
221
222static int
223libxfs_bcompare(struct cache_node *node, cache_key_t key)
224{
225 xfs_buf_t *bp = (xfs_buf_t *)node;
226 xfs_bufkey_t *bkey = (xfs_bufkey_t *)key;
227
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);
236#endif
237
238 return (bp->b_dev == bkey->device &&
239 bp->b_blkno == bkey->blkno &&
240 bp->b_bcount == bkey->count);
241}
242
243void
244libxfs_bprint(xfs_buf_t *bp)
245{
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);
249}
250
2bd0ea18
NS
251xfs_buf_t *
252libxfs_getbuf(dev_t device, xfs_daddr_t blkno, int len)
253{
f1b058f9
NS
254 xfs_buf_t *bp;
255 xfs_bufkey_t key;
256 unsigned int bytes = BBTOB(len);
2bd0ea18 257
f1b058f9
NS
258 key.device = device;
259 key.blkno = blkno;
260 key.count = bytes;
261
262 if (cache_node_get(libxfs_bcache, &key, (struct cache_node **)&bp)) {
2bd0ea18 263#ifdef IO_DEBUG
f1b058f9 264 fprintf(stderr, "%s: allocated buffer, key=%llu(%llu), %p\n",
cb5b3ef4 265 __FUNCTION__, BBTOB(len), LIBXFS_BBTOOFF64(blkno), blkno, buf);
2bd0ea18 266#endif
f1b058f9
NS
267 bp->b_flags = 0;
268 bp->b_blkno = blkno;
269 bp->b_bcount = bytes;
270 bp->b_dev = device;
271 if (!(bp->b_addr = libxfs_memalign(bytes))) {
272 fprintf(stderr,
273 _("%s: %s can't memalign %d bytes: %s\n"),
274 progname, __FUNCTION__, (int)bytes,
275 strerror(errno));
276 exit(1);
277 }
278 }
279 return bp;
280}
281
282void
283libxfs_putbuf(xfs_buf_t *bp)
284{
285 cache_node_put((struct cache_node *)bp);
286}
287
288void
289libxfs_purgebuf(xfs_buf_t *bp)
290{
291 xfs_bufkey_t key;
292
293 key.device = bp->b_dev;
294 key.blkno = bp->b_blkno;
295 key.count = bp->b_bcount;
296
297 cache_node_purge(libxfs_bcache, &key, (struct cache_node *)bp);
298}
2bd0ea18 299
f1b058f9
NS
300static struct cache_node *
301libxfs_balloc(void)
302{
303 return libxfs_zone_zalloc(xfs_buf_zone);
2bd0ea18
NS
304}
305
306int
f1b058f9 307libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *bp, int len, int flags)
2bd0ea18
NS
308{
309 int fd = libxfs_device_to_fd(dev);
f1b058f9 310 int bytes = BBTOB(len);
2bd0ea18 311
f1b058f9 312 ASSERT(BBTOB(len) <= bp->b_bcount);
2bd0ea18 313
cb5b3ef4 314 if (pread64(fd, bp->b_addr, bytes, LIBXFS_BBTOOFF64(blkno)) < 0) {
9440d84d 315 fprintf(stderr, _("%s: read failed: %s\n"),
2bd0ea18 316 progname, strerror(errno));
9440d84d 317 if (flags & LIBXFS_EXIT_ON_FAILURE)
2bd0ea18
NS
318 exit(1);
319 return errno;
320 }
321#ifdef IO_DEBUG
322 fprintf(stderr, "readbufr read %ubytes, blkno=%llu(%llu), %p\n",
cb5b3ef4 323 bytes, LIBXFS_BBTOOFF64(blkno), blkno, bp);
2bd0ea18 324#endif
f1b058f9
NS
325 if (bp->b_dev == dev &&
326 bp->b_blkno == blkno &&
327 bp->b_bcount == bytes)
328 bp->b_flags |= LIBXFS_B_UPTODATE;
2bd0ea18
NS
329 return 0;
330}
331
332xfs_buf_t *
9440d84d 333libxfs_readbuf(dev_t dev, xfs_daddr_t blkno, int len, int flags)
2bd0ea18 334{
f1b058f9 335 xfs_buf_t *bp;
2bd0ea18
NS
336 int error;
337
f1b058f9
NS
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);
341 if (error) {
342 libxfs_putbuf(bp);
343 return NULL;
344 }
2bd0ea18 345 }
f1b058f9 346 return bp;
2bd0ea18
NS
347}
348
349int
f1b058f9 350libxfs_writebufr(xfs_buf_t *bp)
2bd0ea18
NS
351{
352 int sts;
f1b058f9 353 int fd = libxfs_device_to_fd(bp->b_dev);
2bd0ea18 354
cb5b3ef4 355 sts = pwrite64(fd, bp->b_addr, bp->b_bcount, LIBXFS_BBTOOFF64(bp->b_blkno));
2bd0ea18 356 if (sts < 0) {
9440d84d 357 fprintf(stderr, _("%s: pwrite64 failed: %s\n"),
2bd0ea18 358 progname, strerror(errno));
f1b058f9 359 if (bp->b_flags & LIBXFS_B_EXIT)
2bd0ea18
NS
360 exit(1);
361 return errno;
362 }
f1b058f9 363 else if (sts != bp->b_bcount) {
9440d84d 364 fprintf(stderr, _("%s: error - wrote only %d of %d bytes\n"),
f1b058f9
NS
365 progname, sts, bp->b_bcount);
366 if (bp->b_flags & LIBXFS_B_EXIT)
2bd0ea18
NS
367 exit(1);
368 return EIO;
369 }
f1b058f9
NS
370#ifdef IO_DEBUG
371 fprintf(stderr, "writebufr wrote %ubytes, blkno=%llu(%llu), %p\n",
cb5b3ef4 372 bp->b_bcount, LIBXFS_BBTOOFF64(bp->b_blkno), bp->b_blkno, bp);
f1b058f9
NS
373#endif
374 bp->b_flags |= LIBXFS_B_UPTODATE;
375 bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_EXIT);
2bd0ea18
NS
376 return 0;
377}
378
379int
f1b058f9 380libxfs_writebuf_int(xfs_buf_t *bp, int flags)
2bd0ea18 381{
f1b058f9
NS
382 bp->b_flags |= (LIBXFS_B_DIRTY | flags);
383 return 0;
384}
385
386int
387libxfs_writebuf(xfs_buf_t *bp, int flags)
388{
389 bp->b_flags |= (LIBXFS_B_DIRTY | flags);
390 libxfs_putbuf(bp);
391 return 0;
2bd0ea18
NS
392}
393
57c9fccb 394void
f1b058f9 395libxfs_iomove(xfs_buf_t *bp, uint boff, int len, void *data, int flags)
57c9fccb 396{
f1b058f9
NS
397#ifdef IO_DEBUG
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);
57c9fccb 402 abort();
f1b058f9
NS
403 }
404#endif
57c9fccb
NS
405 switch (flags) {
406 case LIBXFS_BZERO:
f1b058f9 407 memset(bp->b_addr + boff, 0, len);
57c9fccb
NS
408 break;
409 case LIBXFS_BREAD:
f1b058f9 410 memcpy(data, bp->b_addr + boff, len);
57c9fccb
NS
411 break;
412 case LIBXFS_BWRITE:
f1b058f9 413 memcpy(bp->b_addr + boff, data, len);
57c9fccb
NS
414 break;
415 }
416}
417
f1b058f9
NS
418static void
419libxfs_brelse(struct cache_node *node)
2bd0ea18 420{
f1b058f9
NS
421 xfs_buf_t *bp = (xfs_buf_t *)node;
422 xfs_buf_log_item_t *bip;
423 extern xfs_zone_t *xfs_buf_item_zone;
424
425 if (bp != NULL) {
426 if (bp->b_flags & LIBXFS_B_DIRTY)
427 libxfs_writebufr(bp);
428 bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
5000d01d
SL
429 if (bip)
430 libxfs_zone_free(xfs_buf_item_zone, bip);
f1b058f9
NS
431 free(bp->b_addr);
432 bp->b_addr = NULL;
433 bp->b_flags = 0;
434 free(bp);
435 bp = NULL;
2bd0ea18
NS
436 }
437}
438
f1b058f9
NS
439void
440libxfs_bcache_purge(void)
441{
442 cache_purge(libxfs_bcache);
443}
444
445struct cache_operations libxfs_bcache_operations = {
446 /* .hash */ libxfs_bhash,
447 /* .alloc */ libxfs_balloc,
448 /* .relse */ libxfs_brelse,
449 /* .compare */ libxfs_bcompare,
1c4110bd 450 /* .bulkrelse */ NULL /* TODO: lio_listio64 interface? */
f1b058f9
NS
451};
452
2bd0ea18
NS
453
454/*
455 * Simple memory interface
456 */
457
458xfs_zone_t *
459libxfs_zone_init(int size, char *name)
460{
461 xfs_zone_t *ptr;
462
463 if ((ptr = malloc(sizeof(xfs_zone_t))) == NULL) {
9440d84d 464 fprintf(stderr, _("%s: zone init failed (%s, %d bytes): %s\n"),
5b64e00a 465 progname, name, (int)sizeof(xfs_zone_t), strerror(errno));
2bd0ea18
NS
466 exit(1);
467 }
468 ptr->zone_unitsize = size;
469 ptr->zone_name = name;
470#ifdef MEM_DEBUG
5000d01d 471 ptr->allocated = 0;
2bd0ea18
NS
472 fprintf(stderr, "new zone %p for \"%s\", size=%d\n", ptr, name, size);
473#endif
474 return ptr;
475}
476
477void *
478libxfs_zone_zalloc(xfs_zone_t *z)
479{
480 void *ptr;
481
2bd0ea18 482 if ((ptr = calloc(z->zone_unitsize, 1)) == NULL) {
9440d84d 483 fprintf(stderr, _("%s: zone calloc failed (%s, %d bytes): %s\n"),
2bd0ea18
NS
484 progname, z->zone_name, z->zone_unitsize,
485 strerror(errno));
486 exit(1);
487 }
488#ifdef MEM_DEBUG
5000d01d
SL
489 z->allocated++;
490 fprintf(stderr, "## zone alloc'd item %p from %s (%d bytes) (%d active)\n",
491 ptr, z->zone_name, z->zone_unitsize,
492 z->allocated);
2bd0ea18
NS
493#endif
494 return ptr;
495}
496
497void
498libxfs_zone_free(xfs_zone_t *z, void *ptr)
499{
500#ifdef MEM_DEBUG
5000d01d
SL
501 z->allocated--;
502 fprintf(stderr, "## zone freed item %p from %s (%d bytes) (%d active)\n",
503 ptr, z->zone_name, z->zone_unitsize,
504 z->allocated);
2bd0ea18
NS
505#endif
506 if (ptr != NULL) {
507 free(ptr);
508 ptr = NULL;
509 }
510}
511
512void *
513libxfs_malloc(size_t size)
514{
515 void *ptr;
516
044fe078 517 if ((ptr = calloc(1, size)) == NULL) {
9440d84d 518 fprintf(stderr, _("%s: calloc failed (%d bytes): %s\n"),
5b64e00a 519 progname, (int)size, strerror(errno));
2bd0ea18
NS
520 exit(1);
521 }
522#ifdef MEM_DEBUG
f1b058f9 523 fprintf(stderr, "## calloc'd item %p size %d bytes\n", ptr, size);
2bd0ea18
NS
524#endif
525 return ptr;
526}
527
528void
529libxfs_free(void *ptr)
530{
531#ifdef MEM_DEBUG
f1b058f9 532 fprintf(stderr, "## freed item %p\n", ptr);
2bd0ea18
NS
533#endif
534 if (ptr != NULL) {
535 free(ptr);
536 ptr = NULL;
537 }
538}
539
540void *
541libxfs_realloc(void *ptr, size_t size)
542{
543#ifdef MEM_DEBUG
5000d01d 544 void *optr=ptr;
2bd0ea18
NS
545#endif
546 if ((ptr = realloc(ptr, size)) == NULL) {
9440d84d 547 fprintf(stderr, _("%s: realloc failed (%d bytes): %s\n"),
5b64e00a 548 progname, (int)size, strerror(errno));
2bd0ea18
NS
549 exit(1);
550 }
551#ifdef MEM_DEBUG
5000d01d
SL
552 fprintf(stderr, "## realloc'd item %p now %p size %d bytes\n",
553 optr, ptr, size);
2bd0ea18
NS
554#endif
555 return ptr;
556}
557
558
f1b058f9
NS
559/*
560 * Inode cache interfaces
561 */
562
563extern xfs_zone_t *xfs_ili_zone;
564extern xfs_zone_t *xfs_inode_zone;
565
566static unsigned int
567libxfs_ihash(cache_key_t key, unsigned int hashsize)
568{
569 return ((unsigned int)*(xfs_ino_t *)key) % hashsize;
570}
571
572static int
573libxfs_icompare(struct cache_node *node, cache_key_t key)
574{
575 xfs_inode_t *ip = (xfs_inode_t *)node;
576
577 return (ip->i_ino == *(xfs_ino_t *)key);
578}
579
2bd0ea18
NS
580int
581libxfs_iget(xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint lock_flags,
582 xfs_inode_t **ipp, xfs_daddr_t bno)
583{
584 xfs_inode_t *ip;
f1b058f9 585 int error = 0;
2bd0ea18 586
f1b058f9
NS
587 if (cache_node_get(libxfs_icache, &ino, (struct cache_node **)&ip)) {
588#ifdef INO_DEBUG
589 fprintf(stderr, "%s: allocated inode, ino=%llu(%llu), %p\n",
590 __FUNCTION__, (unsigned long long)ino, bno, ip);
591#endif
592 if ((error = libxfs_iread(mp, tp, ino, ip, bno))) {
593 cache_node_purge(libxfs_icache, &ino,
594 (struct cache_node *)ip);
595 ip = NULL;
596 }
597 }
2bd0ea18 598 *ipp = ip;
f1b058f9 599 return error;
2bd0ea18
NS
600}
601
014e5f6d 602void
f1b058f9
NS
603libxfs_iput(xfs_inode_t *ip, uint lock_flags)
604{
605 cache_node_put((struct cache_node *)ip);
606}
607
608static struct cache_node *
609libxfs_ialloc(void)
610{
611 return libxfs_zone_zalloc(xfs_inode_zone);
612}
613
614static void
014e5f6d
ES
615libxfs_idestroy(xfs_inode_t *ip)
616{
617 switch (ip->i_d.di_mode & S_IFMT) {
618 case S_IFREG:
619 case S_IFDIR:
620 case S_IFLNK:
621 libxfs_idestroy_fork(ip, XFS_DATA_FORK);
622 break;
623 }
624 if (ip->i_afp)
625 libxfs_idestroy_fork(ip, XFS_ATTR_FORK);
626}
627
f1b058f9
NS
628static void
629libxfs_irelse(struct cache_node *node)
2bd0ea18 630{
f1b058f9 631 xfs_inode_t *ip = (xfs_inode_t *)node;
2bd0ea18
NS
632
633 if (ip != NULL) {
5000d01d
SL
634 if (ip->i_itemp)
635 libxfs_zone_free(xfs_ili_zone, ip->i_itemp);
636 ip->i_itemp = NULL;
014e5f6d 637 libxfs_idestroy(ip);
2bd0ea18
NS
638 libxfs_zone_free(xfs_inode_zone, ip);
639 ip = NULL;
640 }
641}
642
2bd0ea18 643void
f1b058f9 644libxfs_icache_purge(void)
2bd0ea18 645{
f1b058f9 646 cache_purge(libxfs_icache);
2bd0ea18 647}
f1b058f9
NS
648
649struct cache_operations libxfs_icache_operations = {
650 /* .hash */ libxfs_ihash,
651 /* .alloc */ libxfs_ialloc,
652 /* .relse */ libxfs_irelse,
653 /* .compare */ libxfs_icompare,
1c4110bd 654 /* .bulkrelse */ NULL
f1b058f9 655};