]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/util.c
libxfs: print name of verifier if it fails
[thirdparty/xfsprogs-dev.git] / libxfs / util.c
CommitLineData
2bd0ea18 1/*
da23017d
NS
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
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
9c799827 19#include "libxfs_priv.h"
b626fb59
DC
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"
2bd0ea18 36
88cd79be
DC
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 */
42int
43xfs_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
2bd0ea18
NS
144/*
145 * Change the requested timestamp in the given inode.
5000d01d 146 *
2bd0ea18 147 * This was once shared with the kernel, but has diverged to the point
ff1f79a7 148 * where it's no longer worth the hassle of maintaining common code.
2bd0ea18
NS
149 */
150void
56b2de80
DC
151libxfs_trans_ichgtime(
152 struct xfs_trans *tp,
153 struct xfs_inode *ip,
154 int flags)
2bd0ea18 155{
5000d01d 156 struct timespec tv;
2bd0ea18
NS
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 }
2bd0ea18
NS
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 }
41ce5f36
DC
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 }
2bd0ea18
NS
174}
175
176/*
ff1f79a7 177 * Allocate an inode on disk and return a copy of its in-core version.
2bd0ea18
NS
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
ff1f79a7 183 * where it's no longer worth the hassle of maintaining common code.
2bd0ea18 184 */
5e656dbb 185int
2bd0ea18
NS
186libxfs_ialloc(
187 xfs_trans_t *tp,
188 xfs_inode_t *pip,
189 mode_t mode,
190 nlink_t nlink,
63899e27 191 xfs_dev_t rdev,
9f064b7e
NS
192 struct cred *cr,
193 struct fsxattr *fsx,
2bd0ea18
NS
194 int okalloc,
195 xfs_buf_t **ialloc_context,
2bd0ea18
NS
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,
a2ceac1f 208 ialloc_context, &ino);
2bd0ea18
NS
209 if (error != 0)
210 return error;
a2ceac1f 211 if (*ialloc_context || ino == NULLFSINO) {
2bd0ea18
NS
212 *ipp = NULL;
213 return 0;
214 }
215 ASSERT(*ialloc_context == NULL);
216
46eca962 217 error = xfs_trans_iget(tp->t_mountp, tp, ino, 0, 0, &ip);
2bd0ea18
NS
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;
22bc10ed 228 xfs_set_projid(&ip->i_d, pip ? 0 : fsx->fsx_projid);
32181a02 229 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
41ce5f36 230 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD);
2bd0ea18
NS
231
232 /*
ff105f75
DC
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.
2bd0ea18 237 */
ff105f75 238 if (ip->i_d.di_version == 1) {
56b2de80 239 ip->i_d.di_version = 2;
22bc10ed
AM
240 /*
241 * old link count, projid_lo/hi field, pad field
242 * already zeroed
243 */
5000d01d 244 }
2bd0ea18 245
9f064b7e
NS
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
2bd0ea18
NS
252 ip->i_d.di_size = 0;
253 ip->i_d.di_nextents = 0;
254 ASSERT(ip->i_d.di_nblocks == 0);
2bd0ea18
NS
255 /*
256 * di_gen will have been taken care of in xfs_iread.
257 */
9f064b7e 258 ip->i_d.di_extsize = pip ? 0 : fsx->fsx_extsize;
2bd0ea18
NS
259 ip->i_d.di_dmevmask = 0;
260 ip->i_d.di_dmstate = 0;
9f064b7e 261 ip->i_d.di_flags = pip ? 0 : fsx->fsx_xflags;
41ce5f36
DC
262
263 if (ip->i_d.di_version == 3) {
264 ASSERT(ip->i_d.di_ino == ino);
299c0388 265 ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid));
41ce5f36
DC
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
2bd0ea18 274 flags = XFS_ILOG_CORE;
322f2a29
SL
275 switch (mode & S_IFMT) {
276 case S_IFIFO:
63899e27
NS
277 case S_IFSOCK:
278 /* doesn't make sense to set an rdev for these */
279 rdev = 0;
90ec25ed 280 /* FALLTHROUGH */
322f2a29
SL
281 case S_IFCHR:
282 case S_IFBLK:
2bd0ea18 283 ip->i_d.di_format = XFS_DINODE_FMT_DEV;
63899e27 284 ip->i_df.if_u2.if_rdev = rdev;
2bd0ea18
NS
285 flags |= XFS_ILOG_DEV;
286 break;
322f2a29
SL
287 case S_IFREG:
288 case S_IFDIR:
9f064b7e
NS
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 */
322f2a29 313 case S_IFLNK:
2bd0ea18
NS
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
ff105f75
DC
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
2bd0ea18
NS
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
342void
5e656dbb
BN
343libxfs_iprint(
344 xfs_inode_t *ip)
2bd0ea18 345{
5e656dbb
BN
346 xfs_icdinode_t *dip;
347 xfs_bmbt_rec_host_t *ep;
db15fab1
NS
348 xfs_extnum_t i;
349 xfs_extnum_t nextents;
2bd0ea18 350
5b64e00a 351 printf("Inode %lx\n", (unsigned long)ip);
5b64e00a 352 printf(" i_ino %llx\n", (unsigned long long)ip->i_ino);
2bd0ea18
NS
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);
5b64e00a
NS
358 printf(" i_df.if_u1.if_extents/if_data %lx\n",
359 (unsigned long)ip->i_df.if_u1.if_extents);
2bd0ea18
NS
360 if (ip->i_df.if_flags & XFS_IFEXTENTS) {
361 nextents = ip->i_df.if_bytes / (uint)sizeof(*ep);
5e656dbb
BN
362 for (ep = ip->i_df.if_u1.if_extents, i = 0; i < nextents;
363 i++, ep++) {
5000d01d 364 xfs_bmbt_irec_t rec;
2bd0ea18
NS
365
366 xfs_bmbt_get_all(ep, &rec);
5b64e00a
NS
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,
2bd0ea18
NS
372 (int)rec.br_state);
373 }
374 }
5b64e00a 375 printf(" i_df.if_broot %lx\n", (unsigned long)ip->i_df.if_broot);
2bd0ea18
NS
376 printf(" i_df.if_broot_bytes %x\n", ip->i_df.if_broot_bytes);
377
5e656dbb 378 dip = &ip->i_d;
2bd0ea18
NS
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);
5b64e00a 401 printf(" di_size %llu\n", (unsigned long long)dip->di_size);
2bd0ea18
NS
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);
5b64e00a 405 printf(" di_nblocks %llu\n", (unsigned long long)dip->di_nblocks);
2bd0ea18
NS
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 */
412int
413libxfs_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);
ff105f75 422 ASSERT(ip->i_d.di_version > 1);
2bd0ea18
NS
423
424 iip = ip->i_itemp;
425 mp = ip->i_mount;
426
427 /* set *dip = inode's place in the buffer */
92acb899 428 dip = xfs_buf_offset(bp, ip->i_imap.im_boffset);
2bd0ea18 429
2bd0ea18 430 ASSERT(ip->i_d.di_magic == XFS_DINODE_MAGIC);
322f2a29 431 if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
2bd0ea18
NS
432 ASSERT( (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS) ||
433 (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) );
434 }
322f2a29 435 else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
2bd0ea18
NS
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);
2bd0ea18 442
41ce5f36
DC
443 /* bump the change count on v3 inodes */
444 if (ip->i_d.di_version == 3)
445 ip->i_d.di_changecount++;
446
2bd0ea18
NS
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 */
56b2de80 453 xfs_dinode_to_disk(dip, &ip->i_d);
46eca962 454
ff105f75 455 xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK);
5e656dbb 456 if (XFS_IFORK_Q(ip))
ff105f75 457 xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK);
2bd0ea18 458
41ce5f36
DC
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
2bd0ea18
NS
466 return 0;
467}
468
2bd0ea18 469int
5e656dbb 470libxfs_mod_incore_sb(
19ebedcf
DC
471 struct xfs_mount *mp,
472 int field,
5e656dbb
BN
473 int64_t delta,
474 int rsvd)
2bd0ea18
NS
475{
476 long long lcounter; /* long counter for 64 bit fields */
477
478 switch (field) {
19ebedcf 479 case XFS_TRANS_SB_FDBLOCKS:
2bd0ea18
NS
480 lcounter = (long long)mp->m_sb.sb_fdblocks;
481 lcounter += delta;
482 if (lcounter < 0)
12b53197 483 return -ENOSPC;
2bd0ea18 484 mp->m_sb.sb_fdblocks = lcounter;
5e656dbb 485 return 0;
2bd0ea18
NS
486 default:
487 ASSERT(0);
12b53197 488 return -EINVAL;
2bd0ea18 489 }
2bd0ea18
NS
490}
491
492int
493libxfs_bmap_finish(
494 xfs_trans_t **tp,
5000d01d 495 xfs_bmap_free_t *flist,
2bd0ea18
NS
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;
2bd0ea18
NS
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;
0e266570
NS
509 if ((error = xfs_free_extent(*tp, free->xbfi_startblock,
510 free->xbfi_blockcount)))
2bd0ea18
NS
511 return error;
512 xfs_bmap_del_free(flist, NULL, free);
513 }
57c9fccb 514 *committed = 0;
2bd0ea18
NS
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 */
522int
523libxfs_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;
5000d01d
SL
536 xfs_bmap_free_t free_list;
537 xfs_bmbt_irec_t *imapp;
538 xfs_bmbt_irec_t imaps[1];
2bd0ea18
NS
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)
12b53197 548 return -EINVAL;
2bd0ea18
NS
549
550 count = len;
551 error = 0;
552 imapp = &imaps[0];
553 reccount = 1;
a2ceac1f 554 xfs_bmapi_flags = alloc_type ? XFS_BMAPI_PREALLOC : 0;
2bd0ea18
NS
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);
48ea6cb9
DC
565 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write,
566 resblks, 0);
682fa9e0
ES
567 /*
568 * Check for running out of space
569 */
570 if (error) {
571 /*
572 * Free the transaction structure.
573 */
12b53197 574 ASSERT(error == -ENOSPC);
3d7434fe 575 xfs_trans_cancel(tp);
2bd0ea18 576 break;
682fa9e0 577 }
2bd0ea18 578 xfs_trans_ijoin(tp, ip, 0);
2bd0ea18 579
56b2de80 580 xfs_bmap_init(&free_list, &firstfsb);
a2ceac1f 581 error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb,
2bd0ea18 582 xfs_bmapi_flags, &firstfsb, 0, imapp,
56b2de80
DC
583 &reccount, &free_list);
584
2bd0ea18 585 if (error)
682fa9e0 586 goto error0;
2bd0ea18
NS
587
588 /* complete the transaction */
5e656dbb 589 error = xfs_bmap_finish(&tp, &free_list, &committed);
2bd0ea18 590 if (error)
682fa9e0 591 goto error0;
2bd0ea18 592
de5a3f46 593 error = xfs_trans_commit(tp);
2bd0ea18
NS
594 if (error)
595 break;
596
597 allocated_fsb = imapp->br_blockcount;
598 if (reccount == 0)
12b53197 599 return -ENOSPC;
2bd0ea18
NS
600
601 startoffset_fsb += allocated_fsb;
602 allocatesize_fsb -= allocated_fsb;
603 }
604 return error;
682fa9e0
ES
605
606error0: /* Cancel bmap, cancel trans */
607 xfs_bmap_cancel(&free_list);
3d7434fe 608 xfs_trans_cancel(tp);
682fa9e0 609 return error;
2bd0ea18
NS
610}
611
612unsigned int
613libxfs_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
9f064b7e
NS
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 */
631int
632libxfs_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{
9f064b7e
NS
642 xfs_buf_t *ialloc_context;
643 xfs_inode_t *ip;
9f064b7e
NS
644 int error;
645
9f064b7e
NS
646 ialloc_context = (xfs_buf_t *)0;
647 error = libxfs_ialloc(*tp, pip, mode, nlink, rdev, cr, fsx,
a2ceac1f
DC
648 1, &ialloc_context, &ip);
649 if (error) {
650 *ipp = NULL;
9f064b7e 651 return error;
a2ceac1f
DC
652 }
653 if (!ialloc_context && !ip) {
654 *ipp = NULL;
12b53197 655 return -ENOSPC;
a2ceac1f 656 }
9f064b7e 657
a2ceac1f 658 if (ialloc_context) {
48ea6cb9 659
9f064b7e 660 xfs_trans_bhold(*tp, ialloc_context);
d262295d
CH
661
662 error = xfs_trans_roll(tp, NULL);
48ea6cb9 663 if (error) {
d262295d 664 fprintf(stderr, _("%s: cannot duplicate transaction: %s\n"),
48ea6cb9 665 progname, strerror(error));
9f064b7e
NS
666 exit(1);
667 }
668 xfs_trans_bjoin(*tp, ialloc_context);
669 error = libxfs_ialloc(*tp, pip, mode, nlink, rdev, cr,
a2ceac1f 670 fsx, 1, &ialloc_context, &ip);
9f064b7e 671 if (!ip)
12b53197 672 error = -ENOSPC;
9f064b7e
NS
673 if (error)
674 return error;
675 }
9f064b7e
NS
676
677 *ipp = ip;
678 return error;
679}
1552a820
NS
680
681/*
682 * Userspace versions of common diagnostic routines (varargs fun).
683 */
684void
5e656dbb 685libxfs_fs_repair_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
1552a820
NS
686{
687 va_list ap;
688
689 va_start(ap, fmt);
690 vfprintf(stderr, fmt, ap);
691 fprintf(stderr, " This is a bug.\n");
89c4bb8e 692 fprintf(stderr, "%s version %s\n", progname, VERSION);
6c39a3cb
BN
693 fprintf(stderr, "Please capture the filesystem metadata with "
694 "xfs_metadump and\nreport it to xfs@oss.sgi.com.\n");
1552a820
NS
695 va_end(ap);
696}
697
698void
5e656dbb 699libxfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
1552a820
NS
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
709void
710cmn_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}
99c1ec96
DC
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 */
724void
725xfs_verifier_error(
726 struct xfs_buf *bp)
727{
a3fac935 728 xfs_alert(NULL, "Metadata %s detected at %s block 0x%llx/0x%x",
12b53197 729 bp->b_error == -EFSBADCRC ? "CRC error" : "corruption",
a3fac935 730 bp->b_ops->name, bp->b_bn, BBTOB(bp->b_length));
99c1ec96 731}
a65d8d29 732
7d77349c
BF
733/*
734 * This is called from I/O verifiers on v5 superblock filesystems. In the
735 * kernel, it validates the metadata LSN parameter against the current LSN of
736 * the active log. We don't have an active log in userspace so this kind of
737 * validation is not required. Therefore, this function always returns true in
738 * userspace.
739 *
740 * xfs_repair piggybacks off this mechanism to help track the largest metadata
741 * LSN in use on a filesystem. Keep a record of the largest LSN seen such that
742 * repair can validate it against the state of the log.
743 */
744xfs_lsn_t libxfs_max_lsn = 0;
745pthread_mutex_t libxfs_max_lsn_lock = PTHREAD_MUTEX_INITIALIZER;
746
a65d8d29
BF
747bool
748xfs_log_check_lsn(
749 struct xfs_mount *mp,
750 xfs_lsn_t lsn)
751{
7d77349c
BF
752 int cycle = CYCLE_LSN(lsn);
753 int block = BLOCK_LSN(lsn);
754 int max_cycle;
755 int max_block;
756
757 if (lsn == NULLCOMMITLSN)
758 return true;
759
760 pthread_mutex_lock(&libxfs_max_lsn_lock);
761
762 max_cycle = CYCLE_LSN(libxfs_max_lsn);
763 max_block = BLOCK_LSN(libxfs_max_lsn);
764
765 if ((cycle > max_cycle) ||
766 (cycle == max_cycle && block > max_block))
767 libxfs_max_lsn = lsn;
768
769 pthread_mutex_unlock(&libxfs_max_lsn_lock);
770
a65d8d29
BF
771 return true;
772}