]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/util.c
libxfs: validate metadata LSNs against log on v5 superblocks
[thirdparty/xfsprogs-dev.git] / libxfs / util.c
1 /*
2 * Copyright (c) 2000-2005 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 "libxfs_priv.h"
20 #include "init.h"
21 #include "xfs_fs.h"
22 #include "xfs_shared.h"
23 #include "xfs_format.h"
24 #include "xfs_log_format.h"
25 #include "xfs_trans_resv.h"
26 #include "xfs_mount.h"
27 #include "xfs_inode_buf.h"
28 #include "xfs_inode_fork.h"
29 #include "xfs_inode.h"
30 #include "xfs_trans.h"
31 #include "xfs_bmap.h"
32 #include "xfs_bmap_btree.h"
33 #include "xfs_trans_space.h"
34 #include "xfs_ialloc.h"
35 #include "xfs_alloc.h"
36
37 /*
38 * Calculate the worst case log unit reservation for a given superblock
39 * configuration. Copied and munged from the kernel code, and assumes a
40 * worse case header usage (maximum log buffer sizes)
41 */
42 int
43 xfs_log_calc_unit_res(
44 struct xfs_mount *mp,
45 int unit_bytes)
46 {
47 int iclog_space;
48 int iclog_header_size;
49 int iclog_size;
50 uint num_headers;
51
52 if (xfs_sb_version_haslogv2(&mp->m_sb)) {
53 iclog_size = XLOG_MAX_RECORD_BSIZE;
54 iclog_header_size = BBTOB(iclog_size / XLOG_HEADER_CYCLE_SIZE);
55 } else {
56 iclog_size = XLOG_BIG_RECORD_BSIZE;
57 iclog_header_size = BBSIZE;
58 }
59
60 /*
61 * Permanent reservations have up to 'cnt'-1 active log operations
62 * in the log. A unit in this case is the amount of space for one
63 * of these log operations. Normal reservations have a cnt of 1
64 * and their unit amount is the total amount of space required.
65 *
66 * The following lines of code account for non-transaction data
67 * which occupy space in the on-disk log.
68 *
69 * Normal form of a transaction is:
70 * <oph><trans-hdr><start-oph><reg1-oph><reg1><reg2-oph>...<commit-oph>
71 * and then there are LR hdrs, split-recs and roundoff at end of syncs.
72 *
73 * We need to account for all the leadup data and trailer data
74 * around the transaction data.
75 * And then we need to account for the worst case in terms of using
76 * more space.
77 * The worst case will happen if:
78 * - the placement of the transaction happens to be such that the
79 * roundoff is at its maximum
80 * - the transaction data is synced before the commit record is synced
81 * i.e. <transaction-data><roundoff> | <commit-rec><roundoff>
82 * Therefore the commit record is in its own Log Record.
83 * This can happen as the commit record is called with its
84 * own region to xlog_write().
85 * This then means that in the worst case, roundoff can happen for
86 * the commit-rec as well.
87 * The commit-rec is smaller than padding in this scenario and so it is
88 * not added separately.
89 */
90
91 /* for trans header */
92 unit_bytes += sizeof(xlog_op_header_t);
93 unit_bytes += sizeof(xfs_trans_header_t);
94
95 /* for start-rec */
96 unit_bytes += sizeof(xlog_op_header_t);
97
98 /*
99 * for LR headers - the space for data in an iclog is the size minus
100 * the space used for the headers. If we use the iclog size, then we
101 * undercalculate the number of headers required.
102 *
103 * Furthermore - the addition of op headers for split-recs might
104 * increase the space required enough to require more log and op
105 * headers, so take that into account too.
106 *
107 * IMPORTANT: This reservation makes the assumption that if this
108 * transaction is the first in an iclog and hence has the LR headers
109 * accounted to it, then the remaining space in the iclog is
110 * exclusively for this transaction. i.e. if the transaction is larger
111 * than the iclog, it will be the only thing in that iclog.
112 * Fundamentally, this means we must pass the entire log vector to
113 * xlog_write to guarantee this.
114 */
115 iclog_space = iclog_size - iclog_header_size;
116 num_headers = howmany(unit_bytes, iclog_space);
117
118 /* for split-recs - ophdrs added when data split over LRs */
119 unit_bytes += sizeof(xlog_op_header_t) * num_headers;
120
121 /* add extra header reservations if we overrun */
122 while (!num_headers ||
123 howmany(unit_bytes, iclog_space) > num_headers) {
124 unit_bytes += sizeof(xlog_op_header_t);
125 num_headers++;
126 }
127 unit_bytes += iclog_header_size * num_headers;
128
129 /* for commit-rec LR header - note: padding will subsume the ophdr */
130 unit_bytes += iclog_header_size;
131
132 /* for roundoff padding for transaction data and one for commit record */
133 if (xfs_sb_version_haslogv2(&mp->m_sb) && mp->m_sb.sb_logsunit > 1) {
134 /* log su roundoff */
135 unit_bytes += 2 * mp->m_sb.sb_logsunit;
136 } else {
137 /* BB roundoff */
138 unit_bytes += 2 * BBSIZE;
139 }
140
141 return unit_bytes;
142 }
143
144 /*
145 * Change the requested timestamp in the given inode.
146 *
147 * This was once shared with the kernel, but has diverged to the point
148 * where it's no longer worth the hassle of maintaining common code.
149 */
150 void
151 libxfs_trans_ichgtime(
152 struct xfs_trans *tp,
153 struct xfs_inode *ip,
154 int flags)
155 {
156 struct timespec tv;
157 struct timeval stv;
158
159 gettimeofday(&stv, (struct timezone *)0);
160 tv.tv_sec = stv.tv_sec;
161 tv.tv_nsec = stv.tv_usec * 1000;
162 if (flags & XFS_ICHGTIME_MOD) {
163 ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
164 ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
165 }
166 if (flags & XFS_ICHGTIME_CHG) {
167 ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
168 ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
169 }
170 if (flags & XFS_ICHGTIME_CREATE) {
171 ip->i_d.di_crtime.t_sec = (__int32_t)tv.tv_sec;
172 ip->i_d.di_crtime.t_nsec = (__int32_t)tv.tv_nsec;
173 }
174 }
175
176 /*
177 * Allocate an inode on disk and return a copy of its in-core version.
178 * Set mode, nlink, and rdev appropriately within the inode.
179 * The uid and gid for the inode are set according to the contents of
180 * the given cred structure.
181 *
182 * This was once shared with the kernel, but has diverged to the point
183 * where it's no longer worth the hassle of maintaining common code.
184 */
185 int
186 libxfs_ialloc(
187 xfs_trans_t *tp,
188 xfs_inode_t *pip,
189 mode_t mode,
190 nlink_t nlink,
191 xfs_dev_t rdev,
192 struct cred *cr,
193 struct fsxattr *fsx,
194 int okalloc,
195 xfs_buf_t **ialloc_context,
196 xfs_inode_t **ipp)
197 {
198 xfs_ino_t ino;
199 xfs_inode_t *ip;
200 uint flags;
201 int error;
202
203 /*
204 * Call the space management code to pick
205 * the on-disk inode to be allocated.
206 */
207 error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc,
208 ialloc_context, &ino);
209 if (error != 0)
210 return error;
211 if (*ialloc_context || ino == NULLFSINO) {
212 *ipp = NULL;
213 return 0;
214 }
215 ASSERT(*ialloc_context == NULL);
216
217 error = xfs_trans_iget(tp->t_mountp, tp, ino, 0, 0, &ip);
218 if (error != 0)
219 return error;
220 ASSERT(ip != NULL);
221
222 ip->i_d.di_mode = (__uint16_t)mode;
223 ip->i_d.di_onlink = 0;
224 ip->i_d.di_nlink = nlink;
225 ASSERT(ip->i_d.di_nlink == nlink);
226 ip->i_d.di_uid = cr->cr_uid;
227 ip->i_d.di_gid = cr->cr_gid;
228 xfs_set_projid(&ip->i_d, pip ? 0 : fsx->fsx_projid);
229 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
230 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD);
231
232 /*
233 * We only support filesystems that understand v2 format inodes. So if
234 * this is currently an old format inode, then change the inode version
235 * number now. This way we only do the conversion here rather than here
236 * and in the flush/logging code.
237 */
238 if (ip->i_d.di_version == 1) {
239 ip->i_d.di_version = 2;
240 /*
241 * old link count, projid_lo/hi field, pad field
242 * already zeroed
243 */
244 }
245
246 if (pip && (pip->i_d.di_mode & S_ISGID)) {
247 ip->i_d.di_gid = pip->i_d.di_gid;
248 if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR)
249 ip->i_d.di_mode |= S_ISGID;
250 }
251
252 ip->i_d.di_size = 0;
253 ip->i_d.di_nextents = 0;
254 ASSERT(ip->i_d.di_nblocks == 0);
255 /*
256 * di_gen will have been taken care of in xfs_iread.
257 */
258 ip->i_d.di_extsize = pip ? 0 : fsx->fsx_extsize;
259 ip->i_d.di_dmevmask = 0;
260 ip->i_d.di_dmstate = 0;
261 ip->i_d.di_flags = pip ? 0 : fsx->fsx_xflags;
262
263 if (ip->i_d.di_version == 3) {
264 ASSERT(ip->i_d.di_ino == ino);
265 ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid));
266 ip->i_d.di_crc = 0;
267 ip->i_d.di_changecount = 1;
268 ip->i_d.di_lsn = 0;
269 ip->i_d.di_flags2 = 0;
270 memset(&(ip->i_d.di_pad2[0]), 0, sizeof(ip->i_d.di_pad2));
271 ip->i_d.di_crtime = ip->i_d.di_mtime;
272 }
273
274 flags = XFS_ILOG_CORE;
275 switch (mode & S_IFMT) {
276 case S_IFIFO:
277 case S_IFSOCK:
278 /* doesn't make sense to set an rdev for these */
279 rdev = 0;
280 /* FALLTHROUGH */
281 case S_IFCHR:
282 case S_IFBLK:
283 ip->i_d.di_format = XFS_DINODE_FMT_DEV;
284 ip->i_df.if_u2.if_rdev = rdev;
285 flags |= XFS_ILOG_DEV;
286 break;
287 case S_IFREG:
288 case S_IFDIR:
289 if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
290 uint di_flags = 0;
291
292 if ((mode & S_IFMT) == S_IFDIR) {
293 if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
294 di_flags |= XFS_DIFLAG_RTINHERIT;
295 if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
296 di_flags |= XFS_DIFLAG_EXTSZINHERIT;
297 ip->i_d.di_extsize = pip->i_d.di_extsize;
298 }
299 } else {
300 if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
301 di_flags |= XFS_DIFLAG_REALTIME;
302 }
303 if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
304 di_flags |= XFS_DIFLAG_EXTSIZE;
305 ip->i_d.di_extsize = pip->i_d.di_extsize;
306 }
307 }
308 if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
309 di_flags |= XFS_DIFLAG_PROJINHERIT;
310 ip->i_d.di_flags |= di_flags;
311 }
312 /* FALLTHROUGH */
313 case S_IFLNK:
314 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
315 ip->i_df.if_flags = XFS_IFEXTENTS;
316 ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
317 ip->i_df.if_u1.if_extents = NULL;
318 break;
319 default:
320 ASSERT(0);
321 }
322 /* Attribute fork settings for new inode. */
323 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
324 ip->i_d.di_anextents = 0;
325
326 /*
327 * set up the inode ops structure that the libxfs code relies on
328 */
329 if (S_ISDIR(ip->i_d.di_mode))
330 ip->d_ops = ip->i_mount->m_dir_inode_ops;
331 else
332 ip->d_ops = ip->i_mount->m_nondir_inode_ops;
333
334 /*
335 * Log the new values stuffed into the inode.
336 */
337 xfs_trans_log_inode(tp, ip, flags);
338 *ipp = ip;
339 return 0;
340 }
341
342 void
343 libxfs_iprint(
344 xfs_inode_t *ip)
345 {
346 xfs_icdinode_t *dip;
347 xfs_bmbt_rec_host_t *ep;
348 xfs_extnum_t i;
349 xfs_extnum_t nextents;
350
351 printf("Inode %lx\n", (unsigned long)ip);
352 printf(" i_ino %llx\n", (unsigned long long)ip->i_ino);
353
354 if (ip->i_df.if_flags & XFS_IFEXTENTS)
355 printf("EXTENTS ");
356 printf("\n");
357 printf(" i_df.if_bytes %d\n", ip->i_df.if_bytes);
358 printf(" i_df.if_u1.if_extents/if_data %lx\n",
359 (unsigned long)ip->i_df.if_u1.if_extents);
360 if (ip->i_df.if_flags & XFS_IFEXTENTS) {
361 nextents = ip->i_df.if_bytes / (uint)sizeof(*ep);
362 for (ep = ip->i_df.if_u1.if_extents, i = 0; i < nextents;
363 i++, ep++) {
364 xfs_bmbt_irec_t rec;
365
366 xfs_bmbt_get_all(ep, &rec);
367 printf("\t%d: startoff %llu, startblock 0x%llx,"
368 " blockcount %llu, state %d\n",
369 i, (unsigned long long)rec.br_startoff,
370 (unsigned long long)rec.br_startblock,
371 (unsigned long long)rec.br_blockcount,
372 (int)rec.br_state);
373 }
374 }
375 printf(" i_df.if_broot %lx\n", (unsigned long)ip->i_df.if_broot);
376 printf(" i_df.if_broot_bytes %x\n", ip->i_df.if_broot_bytes);
377
378 dip = &ip->i_d;
379 printf("\nOn disk portion\n");
380 printf(" di_magic %x\n", dip->di_magic);
381 printf(" di_mode %o\n", dip->di_mode);
382 printf(" di_version %x\n", (uint)dip->di_version);
383 switch (ip->i_d.di_format) {
384 case XFS_DINODE_FMT_LOCAL:
385 printf(" Inline inode\n");
386 break;
387 case XFS_DINODE_FMT_EXTENTS:
388 printf(" Extents inode\n");
389 break;
390 case XFS_DINODE_FMT_BTREE:
391 printf(" B-tree inode\n");
392 break;
393 default:
394 printf(" Other inode\n");
395 break;
396 }
397 printf(" di_nlink %x\n", dip->di_nlink);
398 printf(" di_uid %d\n", dip->di_uid);
399 printf(" di_gid %d\n", dip->di_gid);
400 printf(" di_nextents %d\n", dip->di_nextents);
401 printf(" di_size %llu\n", (unsigned long long)dip->di_size);
402 printf(" di_gen %x\n", dip->di_gen);
403 printf(" di_extsize %d\n", dip->di_extsize);
404 printf(" di_flags %x\n", dip->di_flags);
405 printf(" di_nblocks %llu\n", (unsigned long long)dip->di_nblocks);
406 }
407
408 /*
409 * Writes a modified inode's changes out to the inode's on disk home.
410 * Originally based on xfs_iflush_int() from xfs_inode.c in the kernel.
411 */
412 int
413 libxfs_iflush_int(xfs_inode_t *ip, xfs_buf_t *bp)
414 {
415 xfs_inode_log_item_t *iip;
416 xfs_dinode_t *dip;
417 xfs_mount_t *mp;
418
419 ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
420 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
421 ip->i_d.di_nextents > ip->i_df.if_ext_max);
422 ASSERT(ip->i_d.di_version > 1);
423
424 iip = ip->i_itemp;
425 mp = ip->i_mount;
426
427 /* set *dip = inode's place in the buffer */
428 dip = xfs_buf_offset(bp, ip->i_imap.im_boffset);
429
430 ASSERT(ip->i_d.di_magic == XFS_DINODE_MAGIC);
431 if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
432 ASSERT( (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS) ||
433 (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) );
434 }
435 else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
436 ASSERT( (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS) ||
437 (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) ||
438 (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) );
439 }
440 ASSERT(ip->i_d.di_nextents+ip->i_d.di_anextents <= ip->i_d.di_nblocks);
441 ASSERT(ip->i_d.di_forkoff <= mp->m_sb.sb_inodesize);
442
443 /* bump the change count on v3 inodes */
444 if (ip->i_d.di_version == 3)
445 ip->i_d.di_changecount++;
446
447 /*
448 * Copy the dirty parts of the inode into the on-disk
449 * inode. We always copy out the core of the inode,
450 * because if the inode is dirty at all the core must
451 * be.
452 */
453 xfs_dinode_to_disk(dip, &ip->i_d);
454
455 xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK);
456 if (XFS_IFORK_Q(ip))
457 xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK);
458
459 /* update the lsn in the on disk inode if required */
460 if (ip->i_d.di_version == 3)
461 dip->di_lsn = cpu_to_be64(iip->ili_item.li_lsn);
462
463 /* generate the checksum. */
464 xfs_dinode_calc_crc(mp, dip);
465
466 return 0;
467 }
468
469 int
470 libxfs_mod_incore_sb(
471 struct xfs_mount *mp,
472 int field,
473 int64_t delta,
474 int rsvd)
475 {
476 long long lcounter; /* long counter for 64 bit fields */
477
478 switch (field) {
479 case XFS_TRANS_SB_FDBLOCKS:
480 lcounter = (long long)mp->m_sb.sb_fdblocks;
481 lcounter += delta;
482 if (lcounter < 0)
483 return -ENOSPC;
484 mp->m_sb.sb_fdblocks = lcounter;
485 return 0;
486 default:
487 ASSERT(0);
488 return -EINVAL;
489 }
490 }
491
492 int
493 libxfs_bmap_finish(
494 xfs_trans_t **tp,
495 xfs_bmap_free_t *flist,
496 int *committed)
497 {
498 xfs_bmap_free_item_t *free; /* free extent list item */
499 xfs_bmap_free_item_t *next; /* next item on free list */
500 int error;
501
502 if (flist->xbf_count == 0) {
503 *committed = 0;
504 return 0;
505 }
506
507 for (free = flist->xbf_first; free != NULL; free = next) {
508 next = free->xbfi_next;
509 if ((error = xfs_free_extent(*tp, free->xbfi_startblock,
510 free->xbfi_blockcount)))
511 return error;
512 xfs_bmap_del_free(flist, NULL, free);
513 }
514 *committed = 0;
515 return 0;
516 }
517
518 /*
519 * This routine allocates disk space for the given file.
520 * Originally derived from xfs_alloc_file_space().
521 */
522 int
523 libxfs_alloc_file_space(
524 xfs_inode_t *ip,
525 xfs_off_t offset,
526 xfs_off_t len,
527 int alloc_type,
528 int attr_flags)
529 {
530 xfs_mount_t *mp;
531 xfs_off_t count;
532 xfs_filblks_t datablocks;
533 xfs_filblks_t allocated_fsb;
534 xfs_filblks_t allocatesize_fsb;
535 xfs_fsblock_t firstfsb;
536 xfs_bmap_free_t free_list;
537 xfs_bmbt_irec_t *imapp;
538 xfs_bmbt_irec_t imaps[1];
539 int reccount;
540 uint resblks;
541 xfs_fileoff_t startoffset_fsb;
542 xfs_trans_t *tp;
543 int xfs_bmapi_flags;
544 int committed;
545 int error;
546
547 if (len <= 0)
548 return -EINVAL;
549
550 count = len;
551 error = 0;
552 imapp = &imaps[0];
553 reccount = 1;
554 xfs_bmapi_flags = alloc_type ? XFS_BMAPI_PREALLOC : 0;
555 mp = ip->i_mount;
556 startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
557 allocatesize_fsb = XFS_B_TO_FSB(mp, count);
558
559 /* allocate file space until done or until there is an error */
560 while (allocatesize_fsb && !error) {
561 datablocks = allocatesize_fsb;
562
563 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
564 resblks = (uint)XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
565 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write,
566 resblks, 0);
567 /*
568 * Check for running out of space
569 */
570 if (error) {
571 /*
572 * Free the transaction structure.
573 */
574 ASSERT(error == -ENOSPC);
575 xfs_trans_cancel(tp);
576 break;
577 }
578 xfs_trans_ijoin(tp, ip, 0);
579
580 xfs_bmap_init(&free_list, &firstfsb);
581 error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb,
582 xfs_bmapi_flags, &firstfsb, 0, imapp,
583 &reccount, &free_list);
584
585 if (error)
586 goto error0;
587
588 /* complete the transaction */
589 error = xfs_bmap_finish(&tp, &free_list, &committed);
590 if (error)
591 goto error0;
592
593 error = xfs_trans_commit(tp);
594 if (error)
595 break;
596
597 allocated_fsb = imapp->br_blockcount;
598 if (reccount == 0)
599 return -ENOSPC;
600
601 startoffset_fsb += allocated_fsb;
602 allocatesize_fsb -= allocated_fsb;
603 }
604 return error;
605
606 error0: /* Cancel bmap, cancel trans */
607 xfs_bmap_cancel(&free_list);
608 xfs_trans_cancel(tp);
609 return error;
610 }
611
612 unsigned int
613 libxfs_log2_roundup(unsigned int i)
614 {
615 unsigned int rval;
616
617 for (rval = 0; rval < NBBY * sizeof(i); rval++) {
618 if ((1 << rval) >= i)
619 break;
620 }
621 return rval;
622 }
623
624 /*
625 * Wrapper around call to libxfs_ialloc. Takes care of committing and
626 * allocating a new transaction as needed.
627 *
628 * Originally there were two copies of this code - one in mkfs, the
629 * other in repair - now there is just the one.
630 */
631 int
632 libxfs_inode_alloc(
633 xfs_trans_t **tp,
634 xfs_inode_t *pip,
635 mode_t mode,
636 nlink_t nlink,
637 xfs_dev_t rdev,
638 struct cred *cr,
639 struct fsxattr *fsx,
640 xfs_inode_t **ipp)
641 {
642 xfs_buf_t *ialloc_context;
643 xfs_inode_t *ip;
644 int error;
645
646 ialloc_context = (xfs_buf_t *)0;
647 error = libxfs_ialloc(*tp, pip, mode, nlink, rdev, cr, fsx,
648 1, &ialloc_context, &ip);
649 if (error) {
650 *ipp = NULL;
651 return error;
652 }
653 if (!ialloc_context && !ip) {
654 *ipp = NULL;
655 return -ENOSPC;
656 }
657
658 if (ialloc_context) {
659
660 xfs_trans_bhold(*tp, ialloc_context);
661
662 error = xfs_trans_roll(tp, NULL);
663 if (error) {
664 fprintf(stderr, _("%s: cannot duplicate transaction: %s\n"),
665 progname, strerror(error));
666 exit(1);
667 }
668 xfs_trans_bjoin(*tp, ialloc_context);
669 error = libxfs_ialloc(*tp, pip, mode, nlink, rdev, cr,
670 fsx, 1, &ialloc_context, &ip);
671 if (!ip)
672 error = -ENOSPC;
673 if (error)
674 return error;
675 }
676
677 *ipp = ip;
678 return error;
679 }
680
681 /*
682 * Userspace versions of common diagnostic routines (varargs fun).
683 */
684 void
685 libxfs_fs_repair_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
686 {
687 va_list ap;
688
689 va_start(ap, fmt);
690 vfprintf(stderr, fmt, ap);
691 fprintf(stderr, " This is a bug.\n");
692 fprintf(stderr, "%s version %s\n", progname, VERSION);
693 fprintf(stderr, "Please capture the filesystem metadata with "
694 "xfs_metadump and\nreport it to xfs@oss.sgi.com.\n");
695 va_end(ap);
696 }
697
698 void
699 libxfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
700 {
701 va_list ap;
702
703 va_start(ap, fmt);
704 vfprintf(stderr, fmt, ap);
705 fputs("\n", stderr);
706 va_end(ap);
707 }
708
709 void
710 cmn_err(int level, char *fmt, ...)
711 {
712 va_list ap;
713
714 va_start(ap, fmt);
715 vfprintf(stderr, fmt, ap);
716 fputs("\n", stderr);
717 va_end(ap);
718 }
719
720 /*
721 * Warnings specifically for verifier errors. Differentiate CRC vs. invalid
722 * values, and omit the stack trace unless the error level is tuned high.
723 */
724 void
725 xfs_verifier_error(
726 struct xfs_buf *bp)
727 {
728 xfs_alert(NULL, "Metadata %s detected at block 0x%llx/0x%x",
729 bp->b_error == -EFSBADCRC ? "CRC error" : "corruption",
730 bp->b_bn, BBTOB(bp->b_length));
731 }
732
733 bool
734 xfs_log_check_lsn(
735 struct xfs_mount *mp,
736 xfs_lsn_t lsn)
737 {
738 return true;
739 }