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