]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/xfs_inode.c
cmd/xfs/bmap/Makefile 1.8 Renamed to cmd/xfsprogs/bmap/Makefile
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_inode.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <xfs.h>
34
35 xfs_zone_t *xfs_ifork_zone;
36 xfs_zone_t *xfs_inode_zone;
37
38 #ifdef DEBUG
39 void
40 xfs_inobp_check(
41 xfs_mount_t *mp,
42 xfs_buf_t *bp)
43 {
44 int i;
45 int j;
46 xfs_dinode_t *dip;
47
48 j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog;
49
50 for (i = 0; i < j; i++) {
51 dip = (xfs_dinode_t *)xfs_buf_offset(bp,
52 i * mp->m_sb.sb_inodesize);
53 if (INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT)) {
54 xfs_fs_cmn_err(CE_ALERT, mp,
55 "Detected a bogus zero next_unlinked field in incore inode buffer 0x%p. About to pop an ASSERT.",
56 bp);
57 ASSERT(!INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT));
58 }
59 }
60 }
61 #endif
62
63
64 /*
65 * This routine is called to map an inode to the buffer containing
66 * the on-disk version of the inode. It returns a pointer to the
67 * buffer containing the on-disk inode in the bpp parameter, and in
68 * the dip parameter it returns a pointer to the on-disk inode within
69 * that buffer.
70 *
71 * If a non-zero error is returned, then the contents of bpp and
72 * dipp are undefined.
73 *
74 * If the inode is new and has not yet been initialized, use xfs_imap()
75 * to determine the size and location of the buffer to read from disk.
76 * If the inode has already been mapped to its buffer and read in once,
77 * then use the mapping information stored in the inode rather than
78 * calling xfs_imap(). This allows us to avoid the overhead of looking
79 * at the inode btree for small block file systems (see xfs_dilocate()).
80 * We can tell whether the inode has been mapped in before by comparing
81 * its disk block address to 0. Only uninitialized inodes will have
82 * 0 for the disk block address.
83 */
84 int
85 xfs_itobp(
86 xfs_mount_t *mp,
87 xfs_trans_t *tp,
88 xfs_inode_t *ip,
89 xfs_dinode_t **dipp,
90 xfs_buf_t **bpp,
91 xfs_daddr_t bno)
92 {
93 xfs_buf_t *bp;
94 int error;
95 xfs_imap_t imap;
96 #ifdef __KERNEL__
97 int i;
98 int ni;
99 #endif
100
101 if (ip->i_blkno == (xfs_daddr_t)0) {
102 /*
103 * Call the space management code to find the location of the
104 * inode on disk.
105 */
106 imap.im_blkno = bno;
107 error = xfs_imap(mp, tp, ip->i_ino, &imap, XFS_IMAP_LOOKUP);
108 if (error != 0) {
109 return error;
110 }
111
112 /*
113 * If the inode number maps to a block outside the bounds
114 * of the file system then return NULL rather than calling
115 * read_buf and panicing when we get an error from the
116 * driver.
117 */
118 if ((imap.im_blkno + imap.im_len) >
119 XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
120 return XFS_ERROR(EINVAL);
121 }
122
123 /*
124 * Fill in the fields in the inode that will be used to
125 * map the inode to its buffer from now on.
126 */
127 ip->i_blkno = imap.im_blkno;
128 ip->i_len = imap.im_len;
129 ip->i_boffset = imap.im_boffset;
130 } else {
131 /*
132 * We've already mapped the inode once, so just use the
133 * mapping that we saved the first time.
134 */
135 imap.im_blkno = ip->i_blkno;
136 imap.im_len = ip->i_len;
137 imap.im_boffset = ip->i_boffset;
138 }
139 ASSERT(bno == 0 || bno == imap.im_blkno);
140
141 /*
142 * Read in the buffer. If tp is NULL, xfs_trans_read_buf() will
143 * default to just a read_buf() call.
144 */
145 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
146 (int)imap.im_len, XFS_BUF_LOCK, &bp);
147
148 if (error) {
149 return error;
150 }
151 #ifdef __KERNEL__
152 /*
153 * Validate the magic number and version of every inode in the buffer
154 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
155 */
156 #ifdef DEBUG
157 ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog;
158 #else
159 ni = 1;
160 #endif
161 for (i = 0; i < ni; i++) {
162 int di_ok;
163 xfs_dinode_t *dip;
164
165 dip = (xfs_dinode_t *)xfs_buf_offset(bp,
166 (i << mp->m_sb.sb_inodelog));
167 di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
168 XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
169 if (XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
170 XFS_RANDOM_ITOBP_INOTOBP)) {
171 #ifdef DEBUG
172 prdev("bad inode magic/vsn daddr 0x%Lx #%d (magic=%x)",
173 mp->m_dev, imap.im_blkno, i,
174 INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
175 #endif
176 xfs_trans_brelse(tp, bp);
177 return XFS_ERROR(EFSCORRUPTED);
178 }
179 }
180 #endif /* __KERNEL__ */
181
182 xfs_inobp_check(mp, bp);
183
184 /*
185 * Mark the buffer as an inode buffer now that it looks good
186 */
187 XFS_BUF_SET_VTYPE(bp, B_FS_INO);
188
189 /*
190 * Set *dipp to point to the on-disk inode in the buffer.
191 */
192 *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
193 *bpp = bp;
194 return 0;
195 }
196
197 /*
198 * Move inode type and inode format specific information from the
199 * on-disk inode to the in-core inode. For fifos, devs, and sockets
200 * this means set if_rdev to the proper value. For files, directories,
201 * and symlinks this means to bring in the in-line data or extent
202 * pointers. For a file in B-tree format, only the root is immediately
203 * brought in-core. The rest will be in-lined in if_extents when it
204 * is first referenced (see xfs_iread_extents()).
205 */
206 STATIC int
207 xfs_iformat(
208 xfs_inode_t *ip,
209 xfs_dinode_t *dip)
210 {
211 xfs_attr_shortform_t *atp;
212 int size;
213 int error;
214 xfs_fsize_t di_size;
215 ip->i_df.if_ext_max =
216 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
217 error = 0;
218
219 if (INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) +
220 INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) >
221 INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT)) {
222 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
223 "corrupt dinode %Lu, extent total = %d, nblocks = %Ld. Unmount and run xfs_repair.",
224 ip->i_ino,
225 (int)(INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)),
226 INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT));
227 return XFS_ERROR(EFSCORRUPTED);
228 }
229
230 if (INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize) {
231 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
232 "corrupt dinode %Lu, forkoff = 0x%x. Unmount and run xfs_repair.",
233 ip->i_ino, (int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT)));
234 return XFS_ERROR(EFSCORRUPTED);
235 }
236
237 switch (ip->i_d.di_mode & IFMT) {
238 case IFIFO:
239 case IFCHR:
240 case IFBLK:
241 case IFSOCK:
242 if (INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV)
243 return XFS_ERROR(EFSCORRUPTED);
244 ip->i_d.di_size = 0;
245 ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
246 break;
247
248 case IFREG:
249 case IFLNK:
250 case IFDIR:
251 switch (INT_GET(dip->di_core.di_format, ARCH_CONVERT)) {
252 case XFS_DINODE_FMT_LOCAL:
253 /*
254 * no local regular files yet
255 */
256 if ((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFREG) {
257 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
258 "corrupt inode (local format for regular file) %Lu. Unmount and run xfs_repair.",
259 ip->i_ino);
260 return XFS_ERROR(EFSCORRUPTED);
261 }
262
263 di_size=INT_GET(dip->di_core.di_size, ARCH_CONVERT);
264 if (di_size >
265 XFS_DFORK_DSIZE_ARCH(dip, ip->i_mount, ARCH_CONVERT)) {
266 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
267 "corrupt inode %Lu (bad size %Ld for local inode). Unmount and run xfs_repair.",
268 ip->i_ino, di_size);
269 return XFS_ERROR(EFSCORRUPTED);
270 }
271
272 size = (int)di_size;
273 error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, size);
274 break;
275 case XFS_DINODE_FMT_EXTENTS:
276 error = xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
277 break;
278 case XFS_DINODE_FMT_BTREE:
279 error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
280 break;
281 default:
282 return XFS_ERROR(EFSCORRUPTED);
283 }
284 break;
285
286 default:
287 return XFS_ERROR(EFSCORRUPTED);
288 }
289 if (error) {
290 return error;
291 }
292 if (!XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT))
293 return 0;
294 ASSERT(ip->i_afp == NULL);
295 ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
296 ip->i_afp->if_ext_max =
297 XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
298 switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) {
299 case XFS_DINODE_FMT_LOCAL:
300 atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT);
301 size = (int)INT_GET(atp->hdr.totsize, ARCH_CONVERT);
302 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
303 break;
304 case XFS_DINODE_FMT_EXTENTS:
305 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
306 break;
307 case XFS_DINODE_FMT_BTREE:
308 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
309 break;
310 default:
311 error = XFS_ERROR(EFSCORRUPTED);
312 break;
313 }
314 if (error) {
315 kmem_zone_free(xfs_ifork_zone, ip->i_afp);
316 ip->i_afp = NULL;
317 xfs_idestroy_fork(ip, XFS_DATA_FORK);
318 }
319 return error;
320 }
321
322 /*
323 * The file is in-lined in the on-disk inode.
324 * If it fits into if_inline_data, then copy
325 * it there, otherwise allocate a buffer for it
326 * and copy the data there. Either way, set
327 * if_data to point at the data.
328 * If we allocate a buffer for the data, make
329 * sure that its size is a multiple of 4 and
330 * record the real size in i_real_bytes.
331 */
332 STATIC int
333 xfs_iformat_local(
334 xfs_inode_t *ip,
335 xfs_dinode_t *dip,
336 int whichfork,
337 int size)
338 {
339 xfs_ifork_t *ifp;
340 int real_size;
341
342 /*
343 * If the size is unreasonable, then something
344 * is wrong and we just bail out rather than crash in
345 * kmem_alloc() or bcopy() below.
346 */
347 if (size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)) {
348 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
349 "corrupt inode %Lu (bad size %d for local fork, size = %d). Unmount and run xfs_repair.",
350 ip->i_ino, size,
351 XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT));
352 return XFS_ERROR(EFSCORRUPTED);
353 }
354 ifp = XFS_IFORK_PTR(ip, whichfork);
355 real_size = 0;
356 if (size == 0)
357 ifp->if_u1.if_data = NULL;
358 else if (size <= sizeof(ifp->if_u2.if_inline_data))
359 ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
360 else {
361 real_size = roundup(size, 4);
362 ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP);
363 }
364 ifp->if_bytes = size;
365 ifp->if_real_bytes = real_size;
366 if (size)
367 bcopy(XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT), ifp->if_u1.if_data, size);
368 ifp->if_flags &= ~XFS_IFEXTENTS;
369 ifp->if_flags |= XFS_IFINLINE;
370 return 0;
371 }
372
373 /*
374 * The file consists of a set of extents all
375 * of which fit into the on-disk inode.
376 * If there are few enough extents to fit into
377 * the if_inline_ext, then copy them there.
378 * Otherwise allocate a buffer for them and copy
379 * them into it. Either way, set if_extents
380 * to point at the extents.
381 */
382 STATIC int
383 xfs_iformat_extents(
384 xfs_inode_t *ip,
385 xfs_dinode_t *dip,
386 int whichfork)
387 {
388 xfs_ifork_t *ifp;
389 int nex;
390 int real_size;
391 int size;
392
393 ifp = XFS_IFORK_PTR(ip, whichfork);
394 nex = XFS_DFORK_NEXTENTS_ARCH(dip, whichfork, ARCH_CONVERT);
395 size = nex * (uint)sizeof(xfs_bmbt_rec_t);
396
397 /*
398 * If the number of extents is unreasonable, then something
399 * is wrong and we just bail out rather than crash in
400 * kmem_alloc() or bcopy() below.
401 */
402 if (size < 0 || size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)) {
403 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
404 "corrupt inode %Lu ((a)extents = %d). Unmount and run xfs_repair.",
405 ip->i_ino, nex);
406 return XFS_ERROR(EFSCORRUPTED);
407 }
408
409 real_size = 0;
410 if (nex == 0)
411 ifp->if_u1.if_extents = NULL;
412 else if (nex <= XFS_INLINE_EXTS)
413 ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
414 else {
415 ifp->if_u1.if_extents = kmem_alloc(size, KM_SLEEP);
416 ASSERT(ifp->if_u1.if_extents != NULL);
417 real_size = size;
418 }
419 ifp->if_bytes = size;
420 ifp->if_real_bytes = real_size;
421 if (size) {
422 xfs_validate_extents(
423 (xfs_bmbt_rec_32_t *)XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT),
424 nex, XFS_EXTFMT_INODE(ip));
425 bcopy(XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT), ifp->if_u1.if_extents,
426 size);
427 xfs_bmap_trace_exlist("xfs_iformat_extents", ip, nex,
428 whichfork);
429 if (whichfork != XFS_DATA_FORK ||
430 XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
431 if (xfs_check_nostate_extents(
432 ifp->if_u1.if_extents, nex))
433 return XFS_ERROR(EFSCORRUPTED);
434 }
435 ifp->if_flags |= XFS_IFEXTENTS;
436 return 0;
437 }
438
439 /*
440 * The file has too many extents to fit into
441 * the inode, so they are in B-tree format.
442 * Allocate a buffer for the root of the B-tree
443 * and copy the root into it. The i_extents
444 * field will remain NULL until all of the
445 * extents are read in (when they are needed).
446 */
447 STATIC int
448 xfs_iformat_btree(
449 xfs_inode_t *ip,
450 xfs_dinode_t *dip,
451 int whichfork)
452 {
453 xfs_bmdr_block_t *dfp;
454 xfs_ifork_t *ifp;
455 /* REFERENCED */
456 int nrecs;
457 int size;
458
459 ifp = XFS_IFORK_PTR(ip, whichfork);
460 dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
461 size = XFS_BMAP_BROOT_SPACE(dfp);
462 nrecs = XFS_BMAP_BROOT_NUMRECS(dfp);
463
464 /*
465 * blow out if -- fork has less extents than can fit in
466 * fork (fork shouldn't be a btree format), root btree
467 * block has more records than can fit into the fork,
468 * or the number of extents is greater than the number of
469 * blocks.
470 */
471 if (XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
472 || XFS_BMDR_SPACE_CALC(nrecs) >
473 XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)
474 || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) {
475 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
476 "corrupt inode %Lu (btree). Unmount and run xfs_repair.",
477 ip->i_ino);
478 return XFS_ERROR(EFSCORRUPTED);
479 }
480
481 ifp->if_broot_bytes = size;
482 ifp->if_broot = kmem_alloc(size, KM_SLEEP);
483 ASSERT(ifp->if_broot != NULL);
484 /*
485 * Copy and convert from the on-disk structure
486 * to the in-memory structure.
487 */
488 xfs_bmdr_to_bmbt(dfp, XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT),
489 ifp->if_broot, size);
490 ifp->if_flags &= ~XFS_IFEXTENTS;
491 ifp->if_flags |= XFS_IFBROOT;
492
493 return 0;
494 }
495
496 /*
497 * xfs_xlate_dinode_core - translate an xfs_inode_core_t between ondisk
498 * and native format
499 *
500 * buf = on-disk representation
501 * dip = native representation
502 * dir = direction - +ve -> disk to native
503 * -ve -> native to disk
504 * arch = on-disk architecture
505 */
506
507 void
508 xfs_xlate_dinode_core(xfs_caddr_t buf, xfs_dinode_core_t *dip,
509 int dir, xfs_arch_t arch)
510 {
511 xfs_dinode_core_t *buf_core;
512 xfs_dinode_core_t *mem_core;
513
514 ASSERT(dir);
515
516 buf_core=(xfs_dinode_core_t*)buf;
517 mem_core=(xfs_dinode_core_t*)dip;
518
519 if (arch == ARCH_NOCONVERT) {
520 if (dir>0) {
521 bcopy((xfs_caddr_t)buf_core, (xfs_caddr_t)mem_core, sizeof(xfs_dinode_core_t));
522 } else {
523 bcopy((xfs_caddr_t)mem_core, (xfs_caddr_t)buf_core, sizeof(xfs_dinode_core_t));
524 }
525 return;
526 }
527
528 INT_XLATE(buf_core->di_magic, mem_core->di_magic, dir, arch);
529 INT_XLATE(buf_core->di_mode, mem_core->di_mode, dir, arch);
530 INT_XLATE(buf_core->di_version, mem_core->di_version, dir, arch);
531 INT_XLATE(buf_core->di_format, mem_core->di_format, dir, arch);
532 INT_XLATE(buf_core->di_onlink, mem_core->di_onlink, dir, arch);
533 INT_XLATE(buf_core->di_uid, mem_core->di_uid, dir, arch);
534 INT_XLATE(buf_core->di_gid, mem_core->di_gid, dir, arch);
535 INT_XLATE(buf_core->di_nlink, mem_core->di_nlink, dir, arch);
536 INT_XLATE(buf_core->di_projid, mem_core->di_projid, dir, arch);
537
538 if (dir>0) {
539 bcopy(buf_core->di_pad, mem_core->di_pad, sizeof(buf_core->di_pad));
540 } else {
541 bcopy(mem_core->di_pad, buf_core->di_pad, sizeof(buf_core->di_pad));
542 }
543
544 INT_XLATE(buf_core->di_atime.t_sec, mem_core->di_atime.t_sec, dir, arch);
545 INT_XLATE(buf_core->di_atime.t_nsec,mem_core->di_atime.t_nsec, dir, arch);
546
547 INT_XLATE(buf_core->di_mtime.t_sec, mem_core->di_mtime.t_sec, dir, arch);
548 INT_XLATE(buf_core->di_mtime.t_nsec,mem_core->di_mtime.t_nsec, dir, arch);
549
550 INT_XLATE(buf_core->di_ctime.t_sec, mem_core->di_ctime.t_sec, dir, arch);
551 INT_XLATE(buf_core->di_ctime.t_nsec,mem_core->di_ctime.t_nsec, dir, arch);
552
553 INT_XLATE(buf_core->di_size, mem_core->di_size, dir, arch);
554 INT_XLATE(buf_core->di_nblocks, mem_core->di_nblocks, dir, arch);
555 INT_XLATE(buf_core->di_extsize, mem_core->di_extsize, dir, arch);
556
557 INT_XLATE(buf_core->di_nextents, mem_core->di_nextents, dir, arch);
558 INT_XLATE(buf_core->di_anextents, mem_core->di_anextents, dir, arch);
559 INT_XLATE(buf_core->di_forkoff, mem_core->di_forkoff, dir, arch);
560 INT_XLATE(buf_core->di_aformat, mem_core->di_aformat, dir, arch);
561 INT_XLATE(buf_core->di_dmevmask, mem_core->di_dmevmask, dir, arch);
562 INT_XLATE(buf_core->di_dmstate, mem_core->di_dmstate, dir, arch);
563 INT_XLATE(buf_core->di_flags, mem_core->di_flags, dir, arch);
564 INT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
565
566 }
567
568 /*
569 * Given a mount structure and an inode number, return a pointer
570 * to a newly allocated in-core inode coresponding to the given
571 * inode number.
572 *
573 * Initialize the inode's attributes and extent pointers if it
574 * already has them (it will not if the inode has no links).
575 */
576 int
577 xfs_iread(
578 xfs_mount_t *mp,
579 xfs_trans_t *tp,
580 xfs_ino_t ino,
581 xfs_inode_t **ipp,
582 xfs_daddr_t bno)
583 {
584 xfs_buf_t *bp;
585 xfs_dinode_t *dip;
586 xfs_inode_t *ip;
587 int error;
588
589 ASSERT(xfs_inode_zone != NULL);
590
591 ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
592 ip->i_ino = ino;
593 ip->i_dev = mp->m_dev;
594 ip->i_mount = mp;
595
596 /*
597 * Get pointer's to the on-disk inode and the buffer containing it.
598 * If the inode number refers to a block outside the file system
599 * then xfs_itobp() will return NULL. In this case we should
600 * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will
601 * know that this is a new incore inode.
602 */
603 error = xfs_itobp(mp, tp, ip, &dip, &bp, bno);
604
605 if (error != 0) {
606 kmem_zone_free(xfs_inode_zone, ip);
607 return error;
608 }
609
610 /*
611 * Initialize inode's trace buffers.
612 * Do this before xfs_iformat in case it adds entries.
613 */
614 #ifdef XFS_BMAP_TRACE
615 ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP);
616 #endif
617 #ifdef XFS_BMBT_TRACE
618 ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_SLEEP);
619 #endif
620 #ifdef XFS_RW_TRACE
621 ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_SLEEP);
622 #endif
623 #ifdef XFS_STRAT_TRACE
624 ip->i_strat_trace = ktrace_alloc(XFS_STRAT_KTRACE_SIZE, KM_SLEEP);
625 #endif
626 #ifdef XFS_ILOCK_TRACE
627 ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_SLEEP);
628 #endif
629 #ifdef XFS_DIR2_TRACE
630 ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_SLEEP);
631 #endif
632
633 /*
634 * If we got something that isn't an inode it means someone
635 * (nfs or dmi) has a stale handle.
636 */
637 if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
638 kmem_zone_free(xfs_inode_zone, ip);
639 xfs_trans_brelse(tp, bp);
640 return XFS_ERROR(EINVAL);
641 }
642
643 /*
644 * If the on-disk inode is already linked to a directory
645 * entry, copy all of the inode into the in-core inode.
646 * xfs_iformat() handles copying in the inode format
647 * specific information.
648 * Otherwise, just get the truly permanent information.
649 */
650 if (!INT_ISZERO(dip->di_core.di_mode, ARCH_CONVERT)) {
651 xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
652 &(ip->i_d), 1, ARCH_CONVERT);
653 error = xfs_iformat(ip, dip);
654 if (error) {
655 kmem_zone_free(xfs_inode_zone, ip);
656 xfs_trans_brelse(tp, bp);
657 return error;
658 }
659 } else {
660 ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
661 ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT);
662 ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT);
663 /*
664 * Make sure to pull in the mode here as well in
665 * case the inode is released without being used.
666 * This ensures that xfs_inactive() will see that
667 * the inode is already free and not try to mess
668 * with the uninitialized part of it.
669 */
670 ip->i_d.di_mode = 0;
671 /*
672 * Initialize the per-fork minima and maxima for a new
673 * inode here. xfs_iformat will do it for old inodes.
674 */
675 ip->i_df.if_ext_max =
676 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
677 }
678
679 /*
680 * The inode format changed when we moved the link count and
681 * made it 32 bits long. If this is an old format inode,
682 * convert it in memory to look like a new one. If it gets
683 * flushed to disk we will convert back before flushing or
684 * logging it. We zero out the new projid field and the old link
685 * count field. We'll handle clearing the pad field (the remains
686 * of the old uuid field) when we actually convert the inode to
687 * the new format. We don't change the version number so that we
688 * can distinguish this from a real new format inode.
689 */
690 if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
691 ip->i_d.di_nlink = ip->i_d.di_onlink;
692 ip->i_d.di_onlink = 0;
693 ip->i_d.di_projid = 0;
694 }
695
696 ip->i_delayed_blks = 0;
697
698 /*
699 * Mark the buffer containing the inode as something to keep
700 * around for a while. This helps to keep recently accessed
701 * meta-data in-core longer.
702 */
703 XFS_BUF_SET_REF(bp, XFS_INO_REF);
704
705 /*
706 * Use xfs_trans_brelse() to release the buffer containing the
707 * on-disk inode, because it was acquired with xfs_trans_read_buf()
708 * in xfs_itobp() above. If tp is NULL, this is just a normal
709 * brelse(). If we're within a transaction, then xfs_trans_brelse()
710 * will only release the buffer if it is not dirty within the
711 * transaction. It will be OK to release the buffer in this case,
712 * because inodes on disk are never destroyed and we will be
713 * locking the new in-core inode before putting it in the hash
714 * table where other processes can find it. Thus we don't have
715 * to worry about the inode being changed just because we released
716 * the buffer.
717 */
718 xfs_trans_brelse(tp, bp);
719 *ipp = ip;
720 return 0;
721 }
722
723 /*
724 * Read in extents from a btree-format inode.
725 * Allocate and fill in if_extents. Real work is done in xfs_bmap.c.
726 */
727 int
728 xfs_iread_extents(
729 xfs_trans_t *tp,
730 xfs_inode_t *ip,
731 int whichfork)
732 {
733 int error;
734 xfs_ifork_t *ifp;
735 size_t size;
736
737 if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
738 return XFS_ERROR(EFSCORRUPTED);
739 size = XFS_IFORK_NEXTENTS(ip, whichfork) * (uint)sizeof(xfs_bmbt_rec_t);
740 ifp = XFS_IFORK_PTR(ip, whichfork);
741 /*
742 * We know that the size is legal (it's checked in iformat_btree)
743 */
744 ifp->if_u1.if_extents = kmem_alloc(size, KM_SLEEP);
745 ASSERT(ifp->if_u1.if_extents != NULL);
746 ifp->if_lastex = NULLEXTNUM;
747 ifp->if_bytes = ifp->if_real_bytes = (int)size;
748 ifp->if_flags |= XFS_IFEXTENTS;
749 error = xfs_bmap_read_extents(tp, ip, whichfork);
750 if (error) {
751 kmem_free(ifp->if_u1.if_extents, size);
752 ifp->if_u1.if_extents = NULL;
753 ifp->if_bytes = ifp->if_real_bytes = 0;
754 ifp->if_flags &= ~XFS_IFEXTENTS;
755 return error;
756 }
757 xfs_validate_extents((xfs_bmbt_rec_32_t *)ifp->if_u1.if_extents,
758 XFS_IFORK_NEXTENTS(ip, whichfork), XFS_EXTFMT_INODE(ip));
759 return 0;
760 }
761
762 /*
763 * Reallocate the space for if_broot based on the number of records
764 * being added or deleted as indicated in rec_diff. Move the records
765 * and pointers in if_broot to fit the new size. When shrinking this
766 * will eliminate holes between the records and pointers created by
767 * the caller. When growing this will create holes to be filled in
768 * by the caller.
769 *
770 * The caller must not request to add more records than would fit in
771 * the on-disk inode root. If the if_broot is currently NULL, then
772 * if we adding records one will be allocated. The caller must also
773 * not request that the number of records go below zero, although
774 * it can go to zero.
775 *
776 * ip -- the inode whose if_broot area is changing
777 * ext_diff -- the change in the number of records, positive or negative,
778 * requested for the if_broot array.
779 */
780 void
781 xfs_iroot_realloc(
782 xfs_inode_t *ip,
783 int rec_diff,
784 int whichfork)
785 {
786 int cur_max;
787 xfs_ifork_t *ifp;
788 xfs_bmbt_block_t *new_broot;
789 int new_max;
790 size_t new_size;
791 char *np;
792 char *op;
793
794 /*
795 * Handle the degenerate case quietly.
796 */
797 if (rec_diff == 0) {
798 return;
799 }
800
801 ifp = XFS_IFORK_PTR(ip, whichfork);
802 if (rec_diff > 0) {
803 /*
804 * If there wasn't any memory allocated before, just
805 * allocate it now and get out.
806 */
807 if (ifp->if_broot_bytes == 0) {
808 new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff);
809 ifp->if_broot = (xfs_bmbt_block_t*)kmem_alloc(new_size,
810 KM_SLEEP);
811 ifp->if_broot_bytes = (int)new_size;
812 return;
813 }
814
815 /*
816 * If there is already an existing if_broot, then we need
817 * to realloc() it and shift the pointers to their new
818 * location. The records don't change location because
819 * they are kept butted up against the btree block header.
820 */
821 cur_max = XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes);
822 new_max = cur_max + rec_diff;
823 new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
824 ifp->if_broot = (xfs_bmbt_block_t *)
825 kmem_realloc(ifp->if_broot,
826 new_size,
827 (size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */
828 KM_SLEEP);
829 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1,
830 ifp->if_broot_bytes);
831 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1,
832 (int)new_size);
833 ifp->if_broot_bytes = (int)new_size;
834 ASSERT(ifp->if_broot_bytes <=
835 XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
836 ovbcopy(op, np, cur_max * (uint)sizeof(xfs_dfsbno_t));
837 return;
838 }
839
840 /*
841 * rec_diff is less than 0. In this case, we are shrinking the
842 * if_broot buffer. It must already exist. If we go to zero
843 * records, just get rid of the root and clear the status bit.
844 */
845 ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
846 cur_max = XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes);
847 new_max = cur_max + rec_diff;
848 ASSERT(new_max >= 0);
849 if (new_max > 0)
850 new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
851 else
852 new_size = 0;
853 if (new_size > 0) {
854 new_broot = (xfs_bmbt_block_t *)kmem_alloc(new_size, KM_SLEEP);
855 /*
856 * First copy over the btree block header.
857 */
858 bcopy(ifp->if_broot, new_broot, sizeof(xfs_bmbt_block_t));
859 } else {
860 new_broot = NULL;
861 ifp->if_flags &= ~XFS_IFBROOT;
862 }
863
864 /*
865 * Only copy the records and pointers if there are any.
866 */
867 if (new_max > 0) {
868 /*
869 * First copy the records.
870 */
871 op = (char *)XFS_BMAP_BROOT_REC_ADDR(ifp->if_broot, 1,
872 ifp->if_broot_bytes);
873 np = (char *)XFS_BMAP_BROOT_REC_ADDR(new_broot, 1,
874 (int)new_size);
875 bcopy(op, np, new_max * (uint)sizeof(xfs_bmbt_rec_t));
876
877 /*
878 * Then copy the pointers.
879 */
880 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1,
881 ifp->if_broot_bytes);
882 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(new_broot, 1,
883 (int)new_size);
884 bcopy(op, np, new_max * (uint)sizeof(xfs_dfsbno_t));
885 }
886 kmem_free(ifp->if_broot, ifp->if_broot_bytes);
887 ifp->if_broot = new_broot;
888 ifp->if_broot_bytes = (int)new_size;
889 ASSERT(ifp->if_broot_bytes <=
890 XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
891 return;
892 }
893
894 /*
895 * This is called when the amount of space needed for if_extents
896 * is increased or decreased. The change in size is indicated by
897 * the number of extents that need to be added or deleted in the
898 * ext_diff parameter.
899 *
900 * If the amount of space needed has decreased below the size of the
901 * inline buffer, then switch to using the inline buffer. Otherwise,
902 * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
903 * to what is needed.
904 *
905 * ip -- the inode whose if_extents area is changing
906 * ext_diff -- the change in the number of extents, positive or negative,
907 * requested for the if_extents array.
908 */
909 void
910 xfs_iext_realloc(
911 xfs_inode_t *ip,
912 int ext_diff,
913 int whichfork)
914 {
915 int byte_diff;
916 xfs_ifork_t *ifp;
917 int new_size;
918 uint rnew_size;
919
920 if (ext_diff == 0) {
921 return;
922 }
923
924 ifp = XFS_IFORK_PTR(ip, whichfork);
925 byte_diff = ext_diff * (uint)sizeof(xfs_bmbt_rec_t);
926 new_size = (int)ifp->if_bytes + byte_diff;
927 ASSERT(new_size >= 0);
928
929 if (new_size == 0) {
930 if (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext) {
931 ASSERT(ifp->if_real_bytes != 0);
932 kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes);
933 }
934 ifp->if_u1.if_extents = NULL;
935 rnew_size = 0;
936 } else if (new_size <= sizeof(ifp->if_u2.if_inline_ext)) {
937 /*
938 * If the valid extents can fit in if_inline_ext,
939 * copy them from the malloc'd vector and free it.
940 */
941 if (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext) {
942 /*
943 * For now, empty files are format EXTENTS,
944 * so the if_extents pointer is null.
945 */
946 if (ifp->if_u1.if_extents) {
947 bcopy(ifp->if_u1.if_extents,
948 ifp->if_u2.if_inline_ext, new_size);
949 kmem_free(ifp->if_u1.if_extents,
950 ifp->if_real_bytes);
951 }
952 ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
953 }
954 rnew_size = 0;
955 } else {
956 rnew_size = new_size;
957 if ((rnew_size & (rnew_size - 1)) != 0)
958 rnew_size = xfs_iroundup(rnew_size);
959 /*
960 * Stuck with malloc/realloc.
961 */
962 if (ifp->if_u1.if_extents == ifp->if_u2.if_inline_ext) {
963 ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
964 kmem_alloc(rnew_size, KM_SLEEP);
965 bcopy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents,
966 sizeof(ifp->if_u2.if_inline_ext));
967 } else if (rnew_size != ifp->if_real_bytes) {
968 ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
969 kmem_realloc(ifp->if_u1.if_extents,
970 rnew_size,
971 ifp->if_real_bytes,
972 KM_SLEEP);
973 }
974 }
975 ifp->if_real_bytes = rnew_size;
976 ifp->if_bytes = new_size;
977 }
978
979
980 /*
981 * This is called when the amount of space needed for if_data
982 * is increased or decreased. The change in size is indicated by
983 * the number of bytes that need to be added or deleted in the
984 * byte_diff parameter.
985 *
986 * If the amount of space needed has decreased below the size of the
987 * inline buffer, then switch to using the inline buffer. Otherwise,
988 * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
989 * to what is needed.
990 *
991 * ip -- the inode whose if_data area is changing
992 * byte_diff -- the change in the number of bytes, positive or negative,
993 * requested for the if_data array.
994 */
995 void
996 xfs_idata_realloc(
997 xfs_inode_t *ip,
998 int byte_diff,
999 int whichfork)
1000 {
1001 xfs_ifork_t *ifp;
1002 int new_size;
1003 int real_size;
1004
1005 if (byte_diff == 0) {
1006 return;
1007 }
1008
1009 ifp = XFS_IFORK_PTR(ip, whichfork);
1010 new_size = (int)ifp->if_bytes + byte_diff;
1011 ASSERT(new_size >= 0);
1012
1013 if (new_size == 0) {
1014 if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
1015 kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes);
1016 }
1017 ifp->if_u1.if_data = NULL;
1018 real_size = 0;
1019 } else if (new_size <= sizeof(ifp->if_u2.if_inline_data)) {
1020 /*
1021 * If the valid extents/data can fit in if_inline_ext/data,
1022 * copy them from the malloc'd vector and free it.
1023 */
1024 if (ifp->if_u1.if_data == NULL) {
1025 ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
1026 } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
1027 ASSERT(ifp->if_real_bytes != 0);
1028 bcopy(ifp->if_u1.if_data, ifp->if_u2.if_inline_data,
1029 new_size);
1030 kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes);
1031 ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
1032 }
1033 real_size = 0;
1034 } else {
1035 /*
1036 * Stuck with malloc/realloc.
1037 * For inline data, the underlying buffer must be
1038 * a multiple of 4 bytes in size so that it can be
1039 * logged and stay on word boundaries. We enforce
1040 * that here.
1041 */
1042 real_size = roundup(new_size, 4);
1043 if (ifp->if_u1.if_data == NULL) {
1044 ASSERT(ifp->if_real_bytes == 0);
1045 ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP);
1046 } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
1047 /*
1048 * Only do the realloc if the underlying size
1049 * is really changing.
1050 */
1051 if (ifp->if_real_bytes != real_size) {
1052 ifp->if_u1.if_data =
1053 kmem_realloc(ifp->if_u1.if_data,
1054 real_size,
1055 ifp->if_real_bytes,
1056 KM_SLEEP);
1057 }
1058 } else {
1059 ASSERT(ifp->if_real_bytes == 0);
1060 ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP);
1061 bcopy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data,
1062 ifp->if_bytes);
1063 }
1064 }
1065 ifp->if_real_bytes = real_size;
1066 ifp->if_bytes = new_size;
1067 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
1068 }
1069
1070
1071 /*
1072 * Map inode to disk block and offset.
1073 *
1074 * mp -- the mount point structure for the current file system
1075 * tp -- the current transaction
1076 * ino -- the inode number of the inode to be located
1077 * imap -- this structure is filled in with the information necessary
1078 * to retrieve the given inode from disk
1079 * flags -- flags to pass to xfs_dilocate indicating whether or not
1080 * lookups in the inode btree were OK or not
1081 */
1082 int
1083 xfs_imap(
1084 xfs_mount_t *mp,
1085 xfs_trans_t *tp,
1086 xfs_ino_t ino,
1087 xfs_imap_t *imap,
1088 uint flags)
1089 {
1090 xfs_fsblock_t fsbno;
1091 int len;
1092 int off;
1093 int error;
1094
1095 fsbno = imap->im_blkno ?
1096 XFS_DADDR_TO_FSB(mp, imap->im_blkno) : NULLFSBLOCK;
1097 error = xfs_dilocate(mp, tp, ino, &fsbno, &len, &off, flags);
1098 if (error != 0) {
1099 return error;
1100 }
1101 imap->im_blkno = XFS_FSB_TO_DADDR(mp, fsbno);
1102 imap->im_len = XFS_FSB_TO_BB(mp, len);
1103 imap->im_agblkno = XFS_FSB_TO_AGBNO(mp, fsbno);
1104 imap->im_ioffset = (ushort)off;
1105 imap->im_boffset = (ushort)(off << mp->m_sb.sb_inodelog);
1106 return 0;
1107 }
1108
1109 void
1110 xfs_idestroy_fork(
1111 xfs_inode_t *ip,
1112 int whichfork)
1113 {
1114 xfs_ifork_t *ifp;
1115
1116 ifp = XFS_IFORK_PTR(ip, whichfork);
1117 if (ifp->if_broot != NULL) {
1118 kmem_free(ifp->if_broot, ifp->if_broot_bytes);
1119 ifp->if_broot = NULL;
1120 }
1121
1122 /*
1123 * If the format is local, then we can't have an extents
1124 * array so just look for an inline data array. If we're
1125 * not local then we may or may not have an extents list,
1126 * so check and free it up if we do.
1127 */
1128 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
1129 if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) &&
1130 (ifp->if_u1.if_data != NULL)) {
1131 ASSERT(ifp->if_real_bytes != 0);
1132 kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes);
1133 ifp->if_u1.if_data = NULL;
1134 ifp->if_real_bytes = 0;
1135 }
1136 } else if ((ifp->if_flags & XFS_IFEXTENTS) &&
1137 (ifp->if_u1.if_extents != NULL) &&
1138 (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext)) {
1139 ASSERT(ifp->if_real_bytes != 0);
1140 kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes);
1141 ifp->if_u1.if_extents = NULL;
1142 ifp->if_real_bytes = 0;
1143 }
1144 ASSERT(ifp->if_u1.if_extents == NULL ||
1145 ifp->if_u1.if_extents == ifp->if_u2.if_inline_ext);
1146 ASSERT(ifp->if_real_bytes == 0);
1147 if (whichfork == XFS_ATTR_FORK) {
1148 kmem_zone_free(xfs_ifork_zone, ip->i_afp);
1149 ip->i_afp = NULL;
1150 }
1151 }
1152
1153 /*
1154 * xfs_iroundup: round up argument to next power of two
1155 */
1156 uint
1157 xfs_iroundup(
1158 uint v)
1159 {
1160 int i;
1161 uint m;
1162
1163 if ((v & (v - 1)) == 0)
1164 return v;
1165 ASSERT((v & 0x80000000) == 0);
1166 if ((v & (v + 1)) == 0)
1167 return v + 1;
1168 for (i = 0, m = 1; i < 31; i++, m <<= 1) {
1169 if (v & m)
1170 continue;
1171 v |= m;
1172 if ((v & (v + 1)) == 0)
1173 return v + 1;
1174 }
1175 ASSERT(0);
1176 return( 0 );
1177 }
1178
1179 /*
1180 * xfs_iextents_copy()
1181 *
1182 * This is called to copy the REAL extents (as opposed to the delayed
1183 * allocation extents) from the inode into the given buffer. It
1184 * returns the number of bytes copied into the buffer.
1185 *
1186 * If there are no delayed allocation extents, then we can just
1187 * bcopy() the extents into the buffer. Otherwise, we need to
1188 * examine each extent in turn and skip those which are delayed.
1189 */
1190 int
1191 xfs_iextents_copy(
1192 xfs_inode_t *ip,
1193 xfs_bmbt_rec_32_t *buffer,
1194 int whichfork)
1195 {
1196 int copied;
1197 xfs_bmbt_rec_32_t *dest_ep;
1198 xfs_bmbt_rec_t *ep;
1199 #ifdef DEBUG
1200 xfs_exntfmt_t fmt = XFS_EXTFMT_INODE(ip);
1201 #endif
1202 #ifdef XFS_BMAP_TRACE
1203 static char fname[] = "xfs_iextents_copy";
1204 #endif
1205 int i;
1206 xfs_ifork_t *ifp;
1207 int nrecs;
1208 xfs_fsblock_t start_block;
1209
1210 ifp = XFS_IFORK_PTR(ip, whichfork);
1211 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
1212 ASSERT(ifp->if_bytes > 0);
1213
1214 nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
1215 xfs_bmap_trace_exlist(fname, ip, nrecs, whichfork);
1216 ASSERT(nrecs > 0);
1217 if (nrecs == XFS_IFORK_NEXTENTS(ip, whichfork)) {
1218 /*
1219 * There are no delayed allocation extents,
1220 * so just copy everything.
1221 */
1222 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
1223 ASSERT(ifp->if_bytes ==
1224 (XFS_IFORK_NEXTENTS(ip, whichfork) *
1225 (uint)sizeof(xfs_bmbt_rec_t)));
1226 bcopy(ifp->if_u1.if_extents, buffer, ifp->if_bytes);
1227 xfs_validate_extents(buffer, nrecs, fmt);
1228 return ifp->if_bytes;
1229 }
1230
1231 ASSERT(whichfork == XFS_DATA_FORK);
1232 /*
1233 * There are some delayed allocation extents in the
1234 * inode, so copy the extents one at a time and skip
1235 * the delayed ones. There must be at least one
1236 * non-delayed extent.
1237 */
1238 ASSERT(nrecs > ip->i_d.di_nextents);
1239 ep = ifp->if_u1.if_extents;
1240 dest_ep = buffer;
1241 copied = 0;
1242 for (i = 0; i < nrecs; i++) {
1243 start_block = xfs_bmbt_get_startblock(ep);
1244 if (ISNULLSTARTBLOCK(start_block)) {
1245 /*
1246 * It's a delayed allocation extent, so skip it.
1247 */
1248 ep++;
1249 continue;
1250 }
1251
1252 *dest_ep = *(xfs_bmbt_rec_32_t *)ep;
1253 dest_ep++;
1254 ep++;
1255 copied++;
1256 }
1257 ASSERT(copied != 0);
1258 ASSERT(copied == ip->i_d.di_nextents);
1259 ASSERT((copied * (uint)sizeof(xfs_bmbt_rec_t)) <= XFS_IFORK_DSIZE(ip));
1260 xfs_validate_extents(buffer, copied, fmt);
1261
1262 return (copied * (uint)sizeof(xfs_bmbt_rec_t));
1263 }
1264
1265 /*
1266 * Each of the following cases stores data into the same region
1267 * of the on-disk inode, so only one of them can be valid at
1268 * any given time. While it is possible to have conflicting formats
1269 * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
1270 * in EXTENTS format, this can only happen when the fork has
1271 * changed formats after being modified but before being flushed.
1272 * In these cases, the format always takes precedence, because the
1273 * format indicates the current state of the fork.
1274 */
1275 STATIC int
1276 xfs_iflush_fork(
1277 xfs_inode_t *ip,
1278 xfs_dinode_t *dip,
1279 xfs_inode_log_item_t *iip,
1280 int whichfork,
1281 xfs_buf_t *bp)
1282 {
1283 char *cp;
1284 xfs_ifork_t *ifp;
1285 xfs_mount_t *mp;
1286 #ifdef XFS_TRANS_DEBUG
1287 int first;
1288 #endif
1289 static const short brootflag[2] =
1290 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
1291 static const short dataflag[2] =
1292 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
1293 static const short extflag[2] =
1294 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
1295
1296 if (iip == NULL)
1297 return 0;
1298 ifp = XFS_IFORK_PTR(ip, whichfork);
1299 /*
1300 * This can happen if we gave up in iformat in an error path,
1301 * for the attribute fork.
1302 */
1303 if (ifp == NULL) {
1304 ASSERT(whichfork == XFS_ATTR_FORK);
1305 return 0;
1306 }
1307 cp = XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
1308 mp = ip->i_mount;
1309 switch (XFS_IFORK_FORMAT(ip, whichfork)) {
1310 case XFS_DINODE_FMT_LOCAL:
1311 if ((iip->ili_format.ilf_fields & dataflag[whichfork]) &&
1312 (ifp->if_bytes > 0)) {
1313 ASSERT(ifp->if_u1.if_data != NULL);
1314 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
1315 bcopy(ifp->if_u1.if_data, cp, ifp->if_bytes);
1316 }
1317 if (whichfork == XFS_DATA_FORK) {
1318 if (XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip)) {
1319 return XFS_ERROR(EFSCORRUPTED);
1320 }
1321 }
1322 break;
1323
1324 case XFS_DINODE_FMT_EXTENTS:
1325 ASSERT((ifp->if_flags & XFS_IFEXTENTS) ||
1326 !(iip->ili_format.ilf_fields & extflag[whichfork]));
1327 ASSERT((ifp->if_u1.if_extents != NULL) || (ifp->if_bytes == 0));
1328 ASSERT((ifp->if_u1.if_extents == NULL) || (ifp->if_bytes > 0));
1329 if ((iip->ili_format.ilf_fields & extflag[whichfork]) &&
1330 (ifp->if_bytes > 0)) {
1331 ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
1332 (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_32_t *)cp,
1333 whichfork);
1334 }
1335 break;
1336
1337 case XFS_DINODE_FMT_BTREE:
1338 if ((iip->ili_format.ilf_fields & brootflag[whichfork]) &&
1339 (ifp->if_broot_bytes > 0)) {
1340 ASSERT(ifp->if_broot != NULL);
1341 ASSERT(ifp->if_broot_bytes <=
1342 (XFS_IFORK_SIZE(ip, whichfork) +
1343 XFS_BROOT_SIZE_ADJ));
1344 xfs_bmbt_to_bmdr(ifp->if_broot, ifp->if_broot_bytes,
1345 (xfs_bmdr_block_t *)cp,
1346 XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT));
1347 }
1348 break;
1349
1350 case XFS_DINODE_FMT_DEV:
1351 if (iip->ili_format.ilf_fields & XFS_ILOG_DEV) {
1352 ASSERT(whichfork == XFS_DATA_FORK);
1353 INT_SET(dip->di_u.di_dev, ARCH_CONVERT, ip->i_df.if_u2.if_rdev);
1354 }
1355 break;
1356
1357 case XFS_DINODE_FMT_UUID:
1358 if (iip->ili_format.ilf_fields & XFS_ILOG_UUID) {
1359 ASSERT(whichfork == XFS_DATA_FORK);
1360 bcopy(&ip->i_df.if_u2.if_uuid, &dip->di_u.di_muuid,
1361 sizeof(uuid_t));
1362 }
1363 break;
1364
1365 default:
1366 ASSERT(0);
1367 break;
1368 }
1369
1370 return 0;
1371 }