Loading...
1/*
2 * Copyright (c) 2000-2001,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#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_format.h"
21#include "xfs_log_format.h"
22#include "xfs_trans_resv.h"
23#include "xfs_mount.h"
24#include "xfs_defer.h"
25#include "xfs_da_format.h"
26#include "xfs_da_btree.h"
27#include "xfs_inode.h"
28#include "xfs_trans.h"
29#include "xfs_inode_item.h"
30#include "xfs_bmap.h"
31#include "xfs_dir2.h"
32#include "xfs_dir2_priv.h"
33#include "xfs_ialloc.h"
34#include "xfs_errortag.h"
35#include "xfs_error.h"
36#include "xfs_trace.h"
37
38struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
39
40/*
41 * Convert inode mode to directory entry filetype
42 */
43unsigned char
44xfs_mode_to_ftype(
45 int mode)
46{
47 switch (mode & S_IFMT) {
48 case S_IFREG:
49 return XFS_DIR3_FT_REG_FILE;
50 case S_IFDIR:
51 return XFS_DIR3_FT_DIR;
52 case S_IFCHR:
53 return XFS_DIR3_FT_CHRDEV;
54 case S_IFBLK:
55 return XFS_DIR3_FT_BLKDEV;
56 case S_IFIFO:
57 return XFS_DIR3_FT_FIFO;
58 case S_IFSOCK:
59 return XFS_DIR3_FT_SOCK;
60 case S_IFLNK:
61 return XFS_DIR3_FT_SYMLINK;
62 default:
63 return XFS_DIR3_FT_UNKNOWN;
64 }
65}
66
67/*
68 * ASCII case-insensitive (ie. A-Z) support for directories that was
69 * used in IRIX.
70 */
71STATIC xfs_dahash_t
72xfs_ascii_ci_hashname(
73 struct xfs_name *name)
74{
75 xfs_dahash_t hash;
76 int i;
77
78 for (i = 0, hash = 0; i < name->len; i++)
79 hash = tolower(name->name[i]) ^ rol32(hash, 7);
80
81 return hash;
82}
83
84STATIC enum xfs_dacmp
85xfs_ascii_ci_compname(
86 struct xfs_da_args *args,
87 const unsigned char *name,
88 int len)
89{
90 enum xfs_dacmp result;
91 int i;
92
93 if (args->namelen != len)
94 return XFS_CMP_DIFFERENT;
95
96 result = XFS_CMP_EXACT;
97 for (i = 0; i < len; i++) {
98 if (args->name[i] == name[i])
99 continue;
100 if (tolower(args->name[i]) != tolower(name[i]))
101 return XFS_CMP_DIFFERENT;
102 result = XFS_CMP_CASE;
103 }
104
105 return result;
106}
107
108static const struct xfs_nameops xfs_ascii_ci_nameops = {
109 .hashname = xfs_ascii_ci_hashname,
110 .compname = xfs_ascii_ci_compname,
111};
112
113int
114xfs_da_mount(
115 struct xfs_mount *mp)
116{
117 struct xfs_da_geometry *dageo;
118 int nodehdr_size;
119
120
121 ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
122 ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
123
124 mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
125 mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
126
127 nodehdr_size = mp->m_dir_inode_ops->node_hdr_size;
128 mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
129 KM_SLEEP | KM_MAYFAIL);
130 mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
131 KM_SLEEP | KM_MAYFAIL);
132 if (!mp->m_dir_geo || !mp->m_attr_geo) {
133 kmem_free(mp->m_dir_geo);
134 kmem_free(mp->m_attr_geo);
135 return -ENOMEM;
136 }
137
138 /* set up directory geometry */
139 dageo = mp->m_dir_geo;
140 dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
141 dageo->fsblog = mp->m_sb.sb_blocklog;
142 dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
143 dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
144
145 /*
146 * Now we've set up the block conversion variables, we can calculate the
147 * segment block constants using the geometry structure.
148 */
149 dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
150 dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
151 dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
152 dageo->node_ents = (dageo->blksize - nodehdr_size) /
153 (uint)sizeof(xfs_da_node_entry_t);
154 dageo->magicpct = (dageo->blksize * 37) / 100;
155
156 /* set up attribute geometry - single fsb only */
157 dageo = mp->m_attr_geo;
158 dageo->blklog = mp->m_sb.sb_blocklog;
159 dageo->fsblog = mp->m_sb.sb_blocklog;
160 dageo->blksize = 1 << dageo->blklog;
161 dageo->fsbcount = 1;
162 dageo->node_ents = (dageo->blksize - nodehdr_size) /
163 (uint)sizeof(xfs_da_node_entry_t);
164 dageo->magicpct = (dageo->blksize * 37) / 100;
165
166 if (xfs_sb_version_hasasciici(&mp->m_sb))
167 mp->m_dirnameops = &xfs_ascii_ci_nameops;
168 else
169 mp->m_dirnameops = &xfs_default_nameops;
170
171 return 0;
172}
173
174void
175xfs_da_unmount(
176 struct xfs_mount *mp)
177{
178 kmem_free(mp->m_dir_geo);
179 kmem_free(mp->m_attr_geo);
180}
181
182/*
183 * Return 1 if directory contains only "." and "..".
184 */
185int
186xfs_dir_isempty(
187 xfs_inode_t *dp)
188{
189 xfs_dir2_sf_hdr_t *sfp;
190
191 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
192 if (dp->i_d.di_size == 0) /* might happen during shutdown. */
193 return 1;
194 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
195 return 0;
196 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
197 return !sfp->count;
198}
199
200/*
201 * Validate a given inode number.
202 */
203int
204xfs_dir_ino_validate(
205 xfs_mount_t *mp,
206 xfs_ino_t ino)
207{
208 bool ino_ok = xfs_verify_dir_ino(mp, ino);
209
210 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE))) {
211 xfs_warn(mp, "Invalid inode number 0x%Lx",
212 (unsigned long long) ino);
213 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
214 return -EFSCORRUPTED;
215 }
216 return 0;
217}
218
219/*
220 * Initialize a directory with its "." and ".." entries.
221 */
222int
223xfs_dir_init(
224 xfs_trans_t *tp,
225 xfs_inode_t *dp,
226 xfs_inode_t *pdp)
227{
228 struct xfs_da_args *args;
229 int error;
230
231 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
232 error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
233 if (error)
234 return error;
235
236 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
237 if (!args)
238 return -ENOMEM;
239
240 args->geo = dp->i_mount->m_dir_geo;
241 args->dp = dp;
242 args->trans = tp;
243 error = xfs_dir2_sf_create(args, pdp->i_ino);
244 kmem_free(args);
245 return error;
246}
247
248/*
249 * Enter a name in a directory, or check for available space.
250 * If inum is 0, only the available space test is performed.
251 */
252int
253xfs_dir_createname(
254 xfs_trans_t *tp,
255 xfs_inode_t *dp,
256 struct xfs_name *name,
257 xfs_ino_t inum, /* new entry inode number */
258 xfs_fsblock_t *first, /* bmap's firstblock */
259 struct xfs_defer_ops *dfops, /* bmap's freeblock list */
260 xfs_extlen_t total) /* bmap's total block count */
261{
262 struct xfs_da_args *args;
263 int rval;
264 int v; /* type-checking value */
265
266 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
267 if (inum) {
268 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
269 if (rval)
270 return rval;
271 XFS_STATS_INC(dp->i_mount, xs_dir_create);
272 }
273
274 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
275 if (!args)
276 return -ENOMEM;
277
278 args->geo = dp->i_mount->m_dir_geo;
279 args->name = name->name;
280 args->namelen = name->len;
281 args->filetype = name->type;
282 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
283 args->inumber = inum;
284 args->dp = dp;
285 args->firstblock = first;
286 args->dfops = dfops;
287 args->total = total;
288 args->whichfork = XFS_DATA_FORK;
289 args->trans = tp;
290 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
291 if (!inum)
292 args->op_flags |= XFS_DA_OP_JUSTCHECK;
293
294 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
295 rval = xfs_dir2_sf_addname(args);
296 goto out_free;
297 }
298
299 rval = xfs_dir2_isblock(args, &v);
300 if (rval)
301 goto out_free;
302 if (v) {
303 rval = xfs_dir2_block_addname(args);
304 goto out_free;
305 }
306
307 rval = xfs_dir2_isleaf(args, &v);
308 if (rval)
309 goto out_free;
310 if (v)
311 rval = xfs_dir2_leaf_addname(args);
312 else
313 rval = xfs_dir2_node_addname(args);
314
315out_free:
316 kmem_free(args);
317 return rval;
318}
319
320/*
321 * If doing a CI lookup and case-insensitive match, dup actual name into
322 * args.value. Return EEXIST for success (ie. name found) or an error.
323 */
324int
325xfs_dir_cilookup_result(
326 struct xfs_da_args *args,
327 const unsigned char *name,
328 int len)
329{
330 if (args->cmpresult == XFS_CMP_DIFFERENT)
331 return -ENOENT;
332 if (args->cmpresult != XFS_CMP_CASE ||
333 !(args->op_flags & XFS_DA_OP_CILOOKUP))
334 return -EEXIST;
335
336 args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
337 if (!args->value)
338 return -ENOMEM;
339
340 memcpy(args->value, name, len);
341 args->valuelen = len;
342 return -EEXIST;
343}
344
345/*
346 * Lookup a name in a directory, give back the inode number.
347 * If ci_name is not NULL, returns the actual name in ci_name if it differs
348 * to name, or ci_name->name is set to NULL for an exact match.
349 */
350
351int
352xfs_dir_lookup(
353 xfs_trans_t *tp,
354 xfs_inode_t *dp,
355 struct xfs_name *name,
356 xfs_ino_t *inum, /* out: inode number */
357 struct xfs_name *ci_name) /* out: actual name if CI match */
358{
359 struct xfs_da_args *args;
360 int rval;
361 int v; /* type-checking value */
362 int lock_mode;
363
364 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
365 XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
366
367 /*
368 * We need to use KM_NOFS here so that lockdep will not throw false
369 * positive deadlock warnings on a non-transactional lookup path. It is
370 * safe to recurse into inode recalim in that case, but lockdep can't
371 * easily be taught about it. Hence KM_NOFS avoids having to add more
372 * lockdep Doing this avoids having to add a bunch of lockdep class
373 * annotations into the reclaim path for the ilock.
374 */
375 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
376 args->geo = dp->i_mount->m_dir_geo;
377 args->name = name->name;
378 args->namelen = name->len;
379 args->filetype = name->type;
380 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
381 args->dp = dp;
382 args->whichfork = XFS_DATA_FORK;
383 args->trans = tp;
384 args->op_flags = XFS_DA_OP_OKNOENT;
385 if (ci_name)
386 args->op_flags |= XFS_DA_OP_CILOOKUP;
387
388 lock_mode = xfs_ilock_data_map_shared(dp);
389 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
390 rval = xfs_dir2_sf_lookup(args);
391 goto out_check_rval;
392 }
393
394 rval = xfs_dir2_isblock(args, &v);
395 if (rval)
396 goto out_free;
397 if (v) {
398 rval = xfs_dir2_block_lookup(args);
399 goto out_check_rval;
400 }
401
402 rval = xfs_dir2_isleaf(args, &v);
403 if (rval)
404 goto out_free;
405 if (v)
406 rval = xfs_dir2_leaf_lookup(args);
407 else
408 rval = xfs_dir2_node_lookup(args);
409
410out_check_rval:
411 if (rval == -EEXIST)
412 rval = 0;
413 if (!rval) {
414 *inum = args->inumber;
415 if (ci_name) {
416 ci_name->name = args->value;
417 ci_name->len = args->valuelen;
418 }
419 }
420out_free:
421 xfs_iunlock(dp, lock_mode);
422 kmem_free(args);
423 return rval;
424}
425
426/*
427 * Remove an entry from a directory.
428 */
429int
430xfs_dir_removename(
431 xfs_trans_t *tp,
432 xfs_inode_t *dp,
433 struct xfs_name *name,
434 xfs_ino_t ino,
435 xfs_fsblock_t *first, /* bmap's firstblock */
436 struct xfs_defer_ops *dfops, /* bmap's freeblock list */
437 xfs_extlen_t total) /* bmap's total block count */
438{
439 struct xfs_da_args *args;
440 int rval;
441 int v; /* type-checking value */
442
443 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
444 XFS_STATS_INC(dp->i_mount, xs_dir_remove);
445
446 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
447 if (!args)
448 return -ENOMEM;
449
450 args->geo = dp->i_mount->m_dir_geo;
451 args->name = name->name;
452 args->namelen = name->len;
453 args->filetype = name->type;
454 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
455 args->inumber = ino;
456 args->dp = dp;
457 args->firstblock = first;
458 args->dfops = dfops;
459 args->total = total;
460 args->whichfork = XFS_DATA_FORK;
461 args->trans = tp;
462
463 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
464 rval = xfs_dir2_sf_removename(args);
465 goto out_free;
466 }
467
468 rval = xfs_dir2_isblock(args, &v);
469 if (rval)
470 goto out_free;
471 if (v) {
472 rval = xfs_dir2_block_removename(args);
473 goto out_free;
474 }
475
476 rval = xfs_dir2_isleaf(args, &v);
477 if (rval)
478 goto out_free;
479 if (v)
480 rval = xfs_dir2_leaf_removename(args);
481 else
482 rval = xfs_dir2_node_removename(args);
483out_free:
484 kmem_free(args);
485 return rval;
486}
487
488/*
489 * Replace the inode number of a directory entry.
490 */
491int
492xfs_dir_replace(
493 xfs_trans_t *tp,
494 xfs_inode_t *dp,
495 struct xfs_name *name, /* name of entry to replace */
496 xfs_ino_t inum, /* new inode number */
497 xfs_fsblock_t *first, /* bmap's firstblock */
498 struct xfs_defer_ops *dfops, /* bmap's freeblock list */
499 xfs_extlen_t total) /* bmap's total block count */
500{
501 struct xfs_da_args *args;
502 int rval;
503 int v; /* type-checking value */
504
505 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
506
507 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
508 if (rval)
509 return rval;
510
511 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
512 if (!args)
513 return -ENOMEM;
514
515 args->geo = dp->i_mount->m_dir_geo;
516 args->name = name->name;
517 args->namelen = name->len;
518 args->filetype = name->type;
519 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
520 args->inumber = inum;
521 args->dp = dp;
522 args->firstblock = first;
523 args->dfops = dfops;
524 args->total = total;
525 args->whichfork = XFS_DATA_FORK;
526 args->trans = tp;
527
528 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
529 rval = xfs_dir2_sf_replace(args);
530 goto out_free;
531 }
532
533 rval = xfs_dir2_isblock(args, &v);
534 if (rval)
535 goto out_free;
536 if (v) {
537 rval = xfs_dir2_block_replace(args);
538 goto out_free;
539 }
540
541 rval = xfs_dir2_isleaf(args, &v);
542 if (rval)
543 goto out_free;
544 if (v)
545 rval = xfs_dir2_leaf_replace(args);
546 else
547 rval = xfs_dir2_node_replace(args);
548out_free:
549 kmem_free(args);
550 return rval;
551}
552
553/*
554 * See if this entry can be added to the directory without allocating space.
555 */
556int
557xfs_dir_canenter(
558 xfs_trans_t *tp,
559 xfs_inode_t *dp,
560 struct xfs_name *name) /* name of entry to add */
561{
562 return xfs_dir_createname(tp, dp, name, 0, NULL, NULL, 0);
563}
564
565/*
566 * Utility routines.
567 */
568
569/*
570 * Add a block to the directory.
571 *
572 * This routine is for data and free blocks, not leaf/node blocks which are
573 * handled by xfs_da_grow_inode.
574 */
575int
576xfs_dir2_grow_inode(
577 struct xfs_da_args *args,
578 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
579 xfs_dir2_db_t *dbp) /* out: block number added */
580{
581 struct xfs_inode *dp = args->dp;
582 struct xfs_mount *mp = dp->i_mount;
583 xfs_fileoff_t bno; /* directory offset of new block */
584 int count; /* count of filesystem blocks */
585 int error;
586
587 trace_xfs_dir2_grow_inode(args, space);
588
589 /*
590 * Set lowest possible block in the space requested.
591 */
592 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
593 count = args->geo->fsbcount;
594
595 error = xfs_da_grow_inode_int(args, &bno, count);
596 if (error)
597 return error;
598
599 *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
600
601 /*
602 * Update file's size if this is the data space and it grew.
603 */
604 if (space == XFS_DIR2_DATA_SPACE) {
605 xfs_fsize_t size; /* directory file (data) size */
606
607 size = XFS_FSB_TO_B(mp, bno + count);
608 if (size > dp->i_d.di_size) {
609 dp->i_d.di_size = size;
610 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
611 }
612 }
613 return 0;
614}
615
616/*
617 * See if the directory is a single-block form directory.
618 */
619int
620xfs_dir2_isblock(
621 struct xfs_da_args *args,
622 int *vp) /* out: 1 is block, 0 is not block */
623{
624 xfs_fileoff_t last; /* last file offset */
625 int rval;
626
627 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
628 return rval;
629 rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
630 if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
631 return -EFSCORRUPTED;
632 *vp = rval;
633 return 0;
634}
635
636/*
637 * See if the directory is a single-leaf form directory.
638 */
639int
640xfs_dir2_isleaf(
641 struct xfs_da_args *args,
642 int *vp) /* out: 1 is block, 0 is not block */
643{
644 xfs_fileoff_t last; /* last file offset */
645 int rval;
646
647 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
648 return rval;
649 *vp = last == args->geo->leafblk + args->geo->fsbcount;
650 return 0;
651}
652
653/*
654 * Remove the given block from the directory.
655 * This routine is used for data and free blocks, leaf/node are done
656 * by xfs_da_shrink_inode.
657 */
658int
659xfs_dir2_shrink_inode(
660 xfs_da_args_t *args,
661 xfs_dir2_db_t db,
662 struct xfs_buf *bp)
663{
664 xfs_fileoff_t bno; /* directory file offset */
665 xfs_dablk_t da; /* directory file offset */
666 int done; /* bunmap is finished */
667 xfs_inode_t *dp;
668 int error;
669 xfs_mount_t *mp;
670 xfs_trans_t *tp;
671
672 trace_xfs_dir2_shrink_inode(args, db);
673
674 dp = args->dp;
675 mp = dp->i_mount;
676 tp = args->trans;
677 da = xfs_dir2_db_to_da(args->geo, db);
678
679 /* Unmap the fsblock(s). */
680 error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0,
681 args->firstblock, args->dfops, &done);
682 if (error) {
683 /*
684 * ENOSPC actually can happen if we're in a removename with no
685 * space reservation, and the resulting block removal would
686 * cause a bmap btree split or conversion from extents to btree.
687 * This can only happen for un-fragmented directory blocks,
688 * since you need to be punching out the middle of an extent.
689 * In this case we need to leave the block in the file, and not
690 * binval it. So the block has to be in a consistent empty
691 * state and appropriately logged. We don't free up the buffer,
692 * the caller can tell it hasn't happened since it got an error
693 * back.
694 */
695 return error;
696 }
697 ASSERT(done);
698 /*
699 * Invalidate the buffer from the transaction.
700 */
701 xfs_trans_binval(tp, bp);
702 /*
703 * If it's not a data block, we're done.
704 */
705 if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
706 return 0;
707 /*
708 * If the block isn't the last one in the directory, we're done.
709 */
710 if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
711 return 0;
712 bno = da;
713 if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
714 /*
715 * This can't really happen unless there's kernel corruption.
716 */
717 return error;
718 }
719 if (db == args->geo->datablk)
720 ASSERT(bno == 0);
721 else
722 ASSERT(bno > 0);
723 /*
724 * Set the size to the new last block.
725 */
726 dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
727 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
728 return 0;
729}
1/*
2 * Copyright (c) 2000-2001,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#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_format.h"
21#include "xfs_log_format.h"
22#include "xfs_trans_resv.h"
23#include "xfs_mount.h"
24#include "xfs_defer.h"
25#include "xfs_da_format.h"
26#include "xfs_da_btree.h"
27#include "xfs_inode.h"
28#include "xfs_trans.h"
29#include "xfs_inode_item.h"
30#include "xfs_bmap.h"
31#include "xfs_dir2.h"
32#include "xfs_dir2_priv.h"
33#include "xfs_error.h"
34#include "xfs_trace.h"
35
36struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
37
38/*
39 * Convert inode mode to directory entry filetype
40 */
41unsigned char xfs_mode_to_ftype(int mode)
42{
43 switch (mode & S_IFMT) {
44 case S_IFREG:
45 return XFS_DIR3_FT_REG_FILE;
46 case S_IFDIR:
47 return XFS_DIR3_FT_DIR;
48 case S_IFCHR:
49 return XFS_DIR3_FT_CHRDEV;
50 case S_IFBLK:
51 return XFS_DIR3_FT_BLKDEV;
52 case S_IFIFO:
53 return XFS_DIR3_FT_FIFO;
54 case S_IFSOCK:
55 return XFS_DIR3_FT_SOCK;
56 case S_IFLNK:
57 return XFS_DIR3_FT_SYMLINK;
58 default:
59 return XFS_DIR3_FT_UNKNOWN;
60 }
61}
62
63/*
64 * ASCII case-insensitive (ie. A-Z) support for directories that was
65 * used in IRIX.
66 */
67STATIC xfs_dahash_t
68xfs_ascii_ci_hashname(
69 struct xfs_name *name)
70{
71 xfs_dahash_t hash;
72 int i;
73
74 for (i = 0, hash = 0; i < name->len; i++)
75 hash = tolower(name->name[i]) ^ rol32(hash, 7);
76
77 return hash;
78}
79
80STATIC enum xfs_dacmp
81xfs_ascii_ci_compname(
82 struct xfs_da_args *args,
83 const unsigned char *name,
84 int len)
85{
86 enum xfs_dacmp result;
87 int i;
88
89 if (args->namelen != len)
90 return XFS_CMP_DIFFERENT;
91
92 result = XFS_CMP_EXACT;
93 for (i = 0; i < len; i++) {
94 if (args->name[i] == name[i])
95 continue;
96 if (tolower(args->name[i]) != tolower(name[i]))
97 return XFS_CMP_DIFFERENT;
98 result = XFS_CMP_CASE;
99 }
100
101 return result;
102}
103
104static const struct xfs_nameops xfs_ascii_ci_nameops = {
105 .hashname = xfs_ascii_ci_hashname,
106 .compname = xfs_ascii_ci_compname,
107};
108
109int
110xfs_da_mount(
111 struct xfs_mount *mp)
112{
113 struct xfs_da_geometry *dageo;
114 int nodehdr_size;
115
116
117 ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
118 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
119 XFS_MAX_BLOCKSIZE);
120
121 mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
122 mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
123
124 nodehdr_size = mp->m_dir_inode_ops->node_hdr_size;
125 mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
126 KM_SLEEP | KM_MAYFAIL);
127 mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
128 KM_SLEEP | KM_MAYFAIL);
129 if (!mp->m_dir_geo || !mp->m_attr_geo) {
130 kmem_free(mp->m_dir_geo);
131 kmem_free(mp->m_attr_geo);
132 return -ENOMEM;
133 }
134
135 /* set up directory geometry */
136 dageo = mp->m_dir_geo;
137 dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
138 dageo->fsblog = mp->m_sb.sb_blocklog;
139 dageo->blksize = 1 << dageo->blklog;
140 dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
141
142 /*
143 * Now we've set up the block conversion variables, we can calculate the
144 * segment block constants using the geometry structure.
145 */
146 dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
147 dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
148 dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
149 dageo->node_ents = (dageo->blksize - nodehdr_size) /
150 (uint)sizeof(xfs_da_node_entry_t);
151 dageo->magicpct = (dageo->blksize * 37) / 100;
152
153 /* set up attribute geometry - single fsb only */
154 dageo = mp->m_attr_geo;
155 dageo->blklog = mp->m_sb.sb_blocklog;
156 dageo->fsblog = mp->m_sb.sb_blocklog;
157 dageo->blksize = 1 << dageo->blklog;
158 dageo->fsbcount = 1;
159 dageo->node_ents = (dageo->blksize - nodehdr_size) /
160 (uint)sizeof(xfs_da_node_entry_t);
161 dageo->magicpct = (dageo->blksize * 37) / 100;
162
163 if (xfs_sb_version_hasasciici(&mp->m_sb))
164 mp->m_dirnameops = &xfs_ascii_ci_nameops;
165 else
166 mp->m_dirnameops = &xfs_default_nameops;
167
168 return 0;
169}
170
171void
172xfs_da_unmount(
173 struct xfs_mount *mp)
174{
175 kmem_free(mp->m_dir_geo);
176 kmem_free(mp->m_attr_geo);
177}
178
179/*
180 * Return 1 if directory contains only "." and "..".
181 */
182int
183xfs_dir_isempty(
184 xfs_inode_t *dp)
185{
186 xfs_dir2_sf_hdr_t *sfp;
187
188 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
189 if (dp->i_d.di_size == 0) /* might happen during shutdown. */
190 return 1;
191 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
192 return 0;
193 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
194 return !sfp->count;
195}
196
197/*
198 * Validate a given inode number.
199 */
200int
201xfs_dir_ino_validate(
202 xfs_mount_t *mp,
203 xfs_ino_t ino)
204{
205 xfs_agblock_t agblkno;
206 xfs_agino_t agino;
207 xfs_agnumber_t agno;
208 int ino_ok;
209 int ioff;
210
211 agno = XFS_INO_TO_AGNO(mp, ino);
212 agblkno = XFS_INO_TO_AGBNO(mp, ino);
213 ioff = XFS_INO_TO_OFFSET(mp, ino);
214 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
215 ino_ok =
216 agno < mp->m_sb.sb_agcount &&
217 agblkno < mp->m_sb.sb_agblocks &&
218 agblkno != 0 &&
219 ioff < (1 << mp->m_sb.sb_inopblog) &&
220 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
221 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
222 XFS_RANDOM_DIR_INO_VALIDATE))) {
223 xfs_warn(mp, "Invalid inode number 0x%Lx",
224 (unsigned long long) ino);
225 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
226 return -EFSCORRUPTED;
227 }
228 return 0;
229}
230
231/*
232 * Initialize a directory with its "." and ".." entries.
233 */
234int
235xfs_dir_init(
236 xfs_trans_t *tp,
237 xfs_inode_t *dp,
238 xfs_inode_t *pdp)
239{
240 struct xfs_da_args *args;
241 int error;
242
243 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
244 error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
245 if (error)
246 return error;
247
248 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
249 if (!args)
250 return -ENOMEM;
251
252 args->geo = dp->i_mount->m_dir_geo;
253 args->dp = dp;
254 args->trans = tp;
255 error = xfs_dir2_sf_create(args, pdp->i_ino);
256 kmem_free(args);
257 return error;
258}
259
260/*
261 * Enter a name in a directory, or check for available space.
262 * If inum is 0, only the available space test is performed.
263 */
264int
265xfs_dir_createname(
266 xfs_trans_t *tp,
267 xfs_inode_t *dp,
268 struct xfs_name *name,
269 xfs_ino_t inum, /* new entry inode number */
270 xfs_fsblock_t *first, /* bmap's firstblock */
271 struct xfs_defer_ops *dfops, /* bmap's freeblock list */
272 xfs_extlen_t total) /* bmap's total block count */
273{
274 struct xfs_da_args *args;
275 int rval;
276 int v; /* type-checking value */
277
278 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
279 if (inum) {
280 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
281 if (rval)
282 return rval;
283 XFS_STATS_INC(dp->i_mount, xs_dir_create);
284 }
285
286 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
287 if (!args)
288 return -ENOMEM;
289
290 args->geo = dp->i_mount->m_dir_geo;
291 args->name = name->name;
292 args->namelen = name->len;
293 args->filetype = name->type;
294 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
295 args->inumber = inum;
296 args->dp = dp;
297 args->firstblock = first;
298 args->dfops = dfops;
299 args->total = total;
300 args->whichfork = XFS_DATA_FORK;
301 args->trans = tp;
302 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
303 if (!inum)
304 args->op_flags |= XFS_DA_OP_JUSTCHECK;
305
306 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
307 rval = xfs_dir2_sf_addname(args);
308 goto out_free;
309 }
310
311 rval = xfs_dir2_isblock(args, &v);
312 if (rval)
313 goto out_free;
314 if (v) {
315 rval = xfs_dir2_block_addname(args);
316 goto out_free;
317 }
318
319 rval = xfs_dir2_isleaf(args, &v);
320 if (rval)
321 goto out_free;
322 if (v)
323 rval = xfs_dir2_leaf_addname(args);
324 else
325 rval = xfs_dir2_node_addname(args);
326
327out_free:
328 kmem_free(args);
329 return rval;
330}
331
332/*
333 * If doing a CI lookup and case-insensitive match, dup actual name into
334 * args.value. Return EEXIST for success (ie. name found) or an error.
335 */
336int
337xfs_dir_cilookup_result(
338 struct xfs_da_args *args,
339 const unsigned char *name,
340 int len)
341{
342 if (args->cmpresult == XFS_CMP_DIFFERENT)
343 return -ENOENT;
344 if (args->cmpresult != XFS_CMP_CASE ||
345 !(args->op_flags & XFS_DA_OP_CILOOKUP))
346 return -EEXIST;
347
348 args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
349 if (!args->value)
350 return -ENOMEM;
351
352 memcpy(args->value, name, len);
353 args->valuelen = len;
354 return -EEXIST;
355}
356
357/*
358 * Lookup a name in a directory, give back the inode number.
359 * If ci_name is not NULL, returns the actual name in ci_name if it differs
360 * to name, or ci_name->name is set to NULL for an exact match.
361 */
362
363int
364xfs_dir_lookup(
365 xfs_trans_t *tp,
366 xfs_inode_t *dp,
367 struct xfs_name *name,
368 xfs_ino_t *inum, /* out: inode number */
369 struct xfs_name *ci_name) /* out: actual name if CI match */
370{
371 struct xfs_da_args *args;
372 int rval;
373 int v; /* type-checking value */
374 int lock_mode;
375
376 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
377 XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
378
379 /*
380 * We need to use KM_NOFS here so that lockdep will not throw false
381 * positive deadlock warnings on a non-transactional lookup path. It is
382 * safe to recurse into inode recalim in that case, but lockdep can't
383 * easily be taught about it. Hence KM_NOFS avoids having to add more
384 * lockdep Doing this avoids having to add a bunch of lockdep class
385 * annotations into the reclaim path for the ilock.
386 */
387 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
388 args->geo = dp->i_mount->m_dir_geo;
389 args->name = name->name;
390 args->namelen = name->len;
391 args->filetype = name->type;
392 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
393 args->dp = dp;
394 args->whichfork = XFS_DATA_FORK;
395 args->trans = tp;
396 args->op_flags = XFS_DA_OP_OKNOENT;
397 if (ci_name)
398 args->op_flags |= XFS_DA_OP_CILOOKUP;
399
400 lock_mode = xfs_ilock_data_map_shared(dp);
401 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
402 rval = xfs_dir2_sf_lookup(args);
403 goto out_check_rval;
404 }
405
406 rval = xfs_dir2_isblock(args, &v);
407 if (rval)
408 goto out_free;
409 if (v) {
410 rval = xfs_dir2_block_lookup(args);
411 goto out_check_rval;
412 }
413
414 rval = xfs_dir2_isleaf(args, &v);
415 if (rval)
416 goto out_free;
417 if (v)
418 rval = xfs_dir2_leaf_lookup(args);
419 else
420 rval = xfs_dir2_node_lookup(args);
421
422out_check_rval:
423 if (rval == -EEXIST)
424 rval = 0;
425 if (!rval) {
426 *inum = args->inumber;
427 if (ci_name) {
428 ci_name->name = args->value;
429 ci_name->len = args->valuelen;
430 }
431 }
432out_free:
433 xfs_iunlock(dp, lock_mode);
434 kmem_free(args);
435 return rval;
436}
437
438/*
439 * Remove an entry from a directory.
440 */
441int
442xfs_dir_removename(
443 xfs_trans_t *tp,
444 xfs_inode_t *dp,
445 struct xfs_name *name,
446 xfs_ino_t ino,
447 xfs_fsblock_t *first, /* bmap's firstblock */
448 struct xfs_defer_ops *dfops, /* bmap's freeblock list */
449 xfs_extlen_t total) /* bmap's total block count */
450{
451 struct xfs_da_args *args;
452 int rval;
453 int v; /* type-checking value */
454
455 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
456 XFS_STATS_INC(dp->i_mount, xs_dir_remove);
457
458 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
459 if (!args)
460 return -ENOMEM;
461
462 args->geo = dp->i_mount->m_dir_geo;
463 args->name = name->name;
464 args->namelen = name->len;
465 args->filetype = name->type;
466 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
467 args->inumber = ino;
468 args->dp = dp;
469 args->firstblock = first;
470 args->dfops = dfops;
471 args->total = total;
472 args->whichfork = XFS_DATA_FORK;
473 args->trans = tp;
474
475 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
476 rval = xfs_dir2_sf_removename(args);
477 goto out_free;
478 }
479
480 rval = xfs_dir2_isblock(args, &v);
481 if (rval)
482 goto out_free;
483 if (v) {
484 rval = xfs_dir2_block_removename(args);
485 goto out_free;
486 }
487
488 rval = xfs_dir2_isleaf(args, &v);
489 if (rval)
490 goto out_free;
491 if (v)
492 rval = xfs_dir2_leaf_removename(args);
493 else
494 rval = xfs_dir2_node_removename(args);
495out_free:
496 kmem_free(args);
497 return rval;
498}
499
500/*
501 * Replace the inode number of a directory entry.
502 */
503int
504xfs_dir_replace(
505 xfs_trans_t *tp,
506 xfs_inode_t *dp,
507 struct xfs_name *name, /* name of entry to replace */
508 xfs_ino_t inum, /* new inode number */
509 xfs_fsblock_t *first, /* bmap's firstblock */
510 struct xfs_defer_ops *dfops, /* bmap's freeblock list */
511 xfs_extlen_t total) /* bmap's total block count */
512{
513 struct xfs_da_args *args;
514 int rval;
515 int v; /* type-checking value */
516
517 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
518
519 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
520 if (rval)
521 return rval;
522
523 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
524 if (!args)
525 return -ENOMEM;
526
527 args->geo = dp->i_mount->m_dir_geo;
528 args->name = name->name;
529 args->namelen = name->len;
530 args->filetype = name->type;
531 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
532 args->inumber = inum;
533 args->dp = dp;
534 args->firstblock = first;
535 args->dfops = dfops;
536 args->total = total;
537 args->whichfork = XFS_DATA_FORK;
538 args->trans = tp;
539
540 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
541 rval = xfs_dir2_sf_replace(args);
542 goto out_free;
543 }
544
545 rval = xfs_dir2_isblock(args, &v);
546 if (rval)
547 goto out_free;
548 if (v) {
549 rval = xfs_dir2_block_replace(args);
550 goto out_free;
551 }
552
553 rval = xfs_dir2_isleaf(args, &v);
554 if (rval)
555 goto out_free;
556 if (v)
557 rval = xfs_dir2_leaf_replace(args);
558 else
559 rval = xfs_dir2_node_replace(args);
560out_free:
561 kmem_free(args);
562 return rval;
563}
564
565/*
566 * See if this entry can be added to the directory without allocating space.
567 */
568int
569xfs_dir_canenter(
570 xfs_trans_t *tp,
571 xfs_inode_t *dp,
572 struct xfs_name *name) /* name of entry to add */
573{
574 return xfs_dir_createname(tp, dp, name, 0, NULL, NULL, 0);
575}
576
577/*
578 * Utility routines.
579 */
580
581/*
582 * Add a block to the directory.
583 *
584 * This routine is for data and free blocks, not leaf/node blocks which are
585 * handled by xfs_da_grow_inode.
586 */
587int
588xfs_dir2_grow_inode(
589 struct xfs_da_args *args,
590 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
591 xfs_dir2_db_t *dbp) /* out: block number added */
592{
593 struct xfs_inode *dp = args->dp;
594 struct xfs_mount *mp = dp->i_mount;
595 xfs_fileoff_t bno; /* directory offset of new block */
596 int count; /* count of filesystem blocks */
597 int error;
598
599 trace_xfs_dir2_grow_inode(args, space);
600
601 /*
602 * Set lowest possible block in the space requested.
603 */
604 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
605 count = args->geo->fsbcount;
606
607 error = xfs_da_grow_inode_int(args, &bno, count);
608 if (error)
609 return error;
610
611 *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
612
613 /*
614 * Update file's size if this is the data space and it grew.
615 */
616 if (space == XFS_DIR2_DATA_SPACE) {
617 xfs_fsize_t size; /* directory file (data) size */
618
619 size = XFS_FSB_TO_B(mp, bno + count);
620 if (size > dp->i_d.di_size) {
621 dp->i_d.di_size = size;
622 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
623 }
624 }
625 return 0;
626}
627
628/*
629 * See if the directory is a single-block form directory.
630 */
631int
632xfs_dir2_isblock(
633 struct xfs_da_args *args,
634 int *vp) /* out: 1 is block, 0 is not block */
635{
636 xfs_fileoff_t last; /* last file offset */
637 int rval;
638
639 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
640 return rval;
641 rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
642 if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
643 return -EFSCORRUPTED;
644 *vp = rval;
645 return 0;
646}
647
648/*
649 * See if the directory is a single-leaf form directory.
650 */
651int
652xfs_dir2_isleaf(
653 struct xfs_da_args *args,
654 int *vp) /* out: 1 is block, 0 is not block */
655{
656 xfs_fileoff_t last; /* last file offset */
657 int rval;
658
659 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
660 return rval;
661 *vp = last == args->geo->leafblk + args->geo->fsbcount;
662 return 0;
663}
664
665/*
666 * Remove the given block from the directory.
667 * This routine is used for data and free blocks, leaf/node are done
668 * by xfs_da_shrink_inode.
669 */
670int
671xfs_dir2_shrink_inode(
672 xfs_da_args_t *args,
673 xfs_dir2_db_t db,
674 struct xfs_buf *bp)
675{
676 xfs_fileoff_t bno; /* directory file offset */
677 xfs_dablk_t da; /* directory file offset */
678 int done; /* bunmap is finished */
679 xfs_inode_t *dp;
680 int error;
681 xfs_mount_t *mp;
682 xfs_trans_t *tp;
683
684 trace_xfs_dir2_shrink_inode(args, db);
685
686 dp = args->dp;
687 mp = dp->i_mount;
688 tp = args->trans;
689 da = xfs_dir2_db_to_da(args->geo, db);
690
691 /* Unmap the fsblock(s). */
692 error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0,
693 args->firstblock, args->dfops, &done);
694 if (error) {
695 /*
696 * ENOSPC actually can happen if we're in a removename with no
697 * space reservation, and the resulting block removal would
698 * cause a bmap btree split or conversion from extents to btree.
699 * This can only happen for un-fragmented directory blocks,
700 * since you need to be punching out the middle of an extent.
701 * In this case we need to leave the block in the file, and not
702 * binval it. So the block has to be in a consistent empty
703 * state and appropriately logged. We don't free up the buffer,
704 * the caller can tell it hasn't happened since it got an error
705 * back.
706 */
707 return error;
708 }
709 ASSERT(done);
710 /*
711 * Invalidate the buffer from the transaction.
712 */
713 xfs_trans_binval(tp, bp);
714 /*
715 * If it's not a data block, we're done.
716 */
717 if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
718 return 0;
719 /*
720 * If the block isn't the last one in the directory, we're done.
721 */
722 if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
723 return 0;
724 bno = da;
725 if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
726 /*
727 * This can't really happen unless there's kernel corruption.
728 */
729 return error;
730 }
731 if (db == args->geo->datablk)
732 ASSERT(bno == 0);
733 else
734 ASSERT(bno > 0);
735 /*
736 * Set the size to the new last block.
737 */
738 dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
739 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
740 return 0;
741}