aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_dir2.c')
-rw-r--r--fs/xfs/xfs_dir2.c156
1 files changed, 29 insertions, 127 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index dba7a71cedf..a2e27010c7f 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -24,20 +24,17 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir2.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h" 29#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h" 30#include "xfs_alloc_btree.h"
32#include "xfs_dir2_sf.h"
33#include "xfs_dinode.h" 31#include "xfs_dinode.h"
34#include "xfs_inode.h" 32#include "xfs_inode.h"
35#include "xfs_inode_item.h" 33#include "xfs_inode_item.h"
36#include "xfs_bmap.h" 34#include "xfs_bmap.h"
37#include "xfs_dir2_data.h" 35#include "xfs_dir2.h"
38#include "xfs_dir2_leaf.h" 36#include "xfs_dir2_format.h"
39#include "xfs_dir2_block.h" 37#include "xfs_dir2_priv.h"
40#include "xfs_dir2_node.h"
41#include "xfs_error.h" 38#include "xfs_error.h"
42#include "xfs_vnodeops.h" 39#include "xfs_vnodeops.h"
43#include "xfs_trace.h" 40#include "xfs_trace.h"
@@ -122,15 +119,15 @@ int
122xfs_dir_isempty( 119xfs_dir_isempty(
123 xfs_inode_t *dp) 120 xfs_inode_t *dp)
124{ 121{
125 xfs_dir2_sf_t *sfp; 122 xfs_dir2_sf_hdr_t *sfp;
126 123
127 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 124 ASSERT(S_ISDIR(dp->i_d.di_mode));
128 if (dp->i_d.di_size == 0) /* might happen during shutdown. */ 125 if (dp->i_d.di_size == 0) /* might happen during shutdown. */
129 return 1; 126 return 1;
130 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 127 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
131 return 0; 128 return 0;
132 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; 129 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
133 return !sfp->hdr.count; 130 return !sfp->count;
134} 131}
135 132
136/* 133/*
@@ -182,7 +179,7 @@ xfs_dir_init(
182 memset((char *)&args, 0, sizeof(args)); 179 memset((char *)&args, 0, sizeof(args));
183 args.dp = dp; 180 args.dp = dp;
184 args.trans = tp; 181 args.trans = tp;
185 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 182 ASSERT(S_ISDIR(dp->i_d.di_mode));
186 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) 183 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
187 return error; 184 return error;
188 return xfs_dir2_sf_create(&args, pdp->i_ino); 185 return xfs_dir2_sf_create(&args, pdp->i_ino);
@@ -205,7 +202,7 @@ xfs_dir_createname(
205 int rval; 202 int rval;
206 int v; /* type-checking value */ 203 int v; /* type-checking value */
207 204
208 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 205 ASSERT(S_ISDIR(dp->i_d.di_mode));
209 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) 206 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
210 return rval; 207 return rval;
211 XFS_STATS_INC(xs_dir_create); 208 XFS_STATS_INC(xs_dir_create);
@@ -281,7 +278,7 @@ xfs_dir_lookup(
281 int rval; 278 int rval;
282 int v; /* type-checking value */ 279 int v; /* type-checking value */
283 280
284 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 281 ASSERT(S_ISDIR(dp->i_d.di_mode));
285 XFS_STATS_INC(xs_dir_lookup); 282 XFS_STATS_INC(xs_dir_lookup);
286 283
287 memset(&args, 0, sizeof(xfs_da_args_t)); 284 memset(&args, 0, sizeof(xfs_da_args_t));
@@ -336,7 +333,7 @@ xfs_dir_removename(
336 int rval; 333 int rval;
337 int v; /* type-checking value */ 334 int v; /* type-checking value */
338 335
339 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 336 ASSERT(S_ISDIR(dp->i_d.di_mode));
340 XFS_STATS_INC(xs_dir_remove); 337 XFS_STATS_INC(xs_dir_remove);
341 338
342 memset(&args, 0, sizeof(xfs_da_args_t)); 339 memset(&args, 0, sizeof(xfs_da_args_t));
@@ -385,7 +382,7 @@ xfs_readdir(
385 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 382 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
386 return XFS_ERROR(EIO); 383 return XFS_ERROR(EIO);
387 384
388 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 385 ASSERT(S_ISDIR(dp->i_d.di_mode));
389 XFS_STATS_INC(xs_dir_getdents); 386 XFS_STATS_INC(xs_dir_getdents);
390 387
391 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 388 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
@@ -417,7 +414,7 @@ xfs_dir_replace(
417 int rval; 414 int rval;
418 int v; /* type-checking value */ 415 int v; /* type-checking value */
419 416
420 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 417 ASSERT(S_ISDIR(dp->i_d.di_mode));
421 418
422 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) 419 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
423 return rval; 420 return rval;
@@ -467,7 +464,7 @@ xfs_dir_canenter(
467 if (resblks) 464 if (resblks)
468 return 0; 465 return 0;
469 466
470 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 467 ASSERT(S_ISDIR(dp->i_d.di_mode));
471 468
472 memset(&args, 0, sizeof(xfs_da_args_t)); 469 memset(&args, 0, sizeof(xfs_da_args_t));
473 args.name = name->name; 470 args.name = name->name;
@@ -500,129 +497,34 @@ xfs_dir_canenter(
500 497
501/* 498/*
502 * Add a block to the directory. 499 * Add a block to the directory.
503 * This routine is for data and free blocks, not leaf/node blocks 500 *
504 * which are handled by xfs_da_grow_inode. 501 * This routine is for data and free blocks, not leaf/node blocks which are
502 * handled by xfs_da_grow_inode.
505 */ 503 */
506int 504int
507xfs_dir2_grow_inode( 505xfs_dir2_grow_inode(
508 xfs_da_args_t *args, 506 struct xfs_da_args *args,
509 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 507 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
510 xfs_dir2_db_t *dbp) /* out: block number added */ 508 xfs_dir2_db_t *dbp) /* out: block number added */
511{ 509{
512 xfs_fileoff_t bno; /* directory offset of new block */ 510 struct xfs_inode *dp = args->dp;
513 int count; /* count of filesystem blocks */ 511 struct xfs_mount *mp = dp->i_mount;
514 xfs_inode_t *dp; /* incore directory inode */ 512 xfs_fileoff_t bno; /* directory offset of new block */
515 int error; 513 int count; /* count of filesystem blocks */
516 int got; /* blocks actually mapped */ 514 int error;
517 int i;
518 xfs_bmbt_irec_t map; /* single structure for bmap */
519 int mapi; /* mapping index */
520 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */
521 xfs_mount_t *mp;
522 int nmap; /* number of bmap entries */
523 xfs_trans_t *tp;
524 xfs_drfsbno_t nblks;
525 515
526 trace_xfs_dir2_grow_inode(args, space); 516 trace_xfs_dir2_grow_inode(args, space);
527 517
528 dp = args->dp;
529 tp = args->trans;
530 mp = dp->i_mount;
531 nblks = dp->i_d.di_nblocks;
532 /* 518 /*
533 * Set lowest possible block in the space requested. 519 * Set lowest possible block in the space requested.
534 */ 520 */
535 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); 521 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
536 count = mp->m_dirblkfsbs; 522 count = mp->m_dirblkfsbs;
537 /*
538 * Find the first hole for our block.
539 */
540 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
541 return error;
542 nmap = 1;
543 ASSERT(args->firstblock != NULL);
544 /*
545 * Try mapping the new block contiguously (one extent).
546 */
547 if ((error = xfs_bmapi(tp, dp, bno, count,
548 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
549 args->firstblock, args->total, &map, &nmap,
550 args->flist)))
551 return error;
552 ASSERT(nmap <= 1);
553 if (nmap == 1) {
554 mapp = &map;
555 mapi = 1;
556 }
557 /*
558 * Didn't work and this is a multiple-fsb directory block.
559 * Try again with contiguous flag turned on.
560 */
561 else if (nmap == 0 && count > 1) {
562 xfs_fileoff_t b; /* current file offset */
563 523
564 /* 524 error = xfs_da_grow_inode_int(args, &bno, count);
565 * Space for maximum number of mappings. 525 if (error)
566 */ 526 return error;
567 mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
568 /*
569 * Iterate until we get to the end of our block.
570 */
571 for (b = bno, mapi = 0; b < bno + count; ) {
572 int c; /* current fsb count */
573
574 /*
575 * Can't map more than MAX_NMAP at once.
576 */
577 nmap = MIN(XFS_BMAP_MAX_NMAP, count);
578 c = (int)(bno + count - b);
579 if ((error = xfs_bmapi(tp, dp, b, c,
580 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
581 args->firstblock, args->total,
582 &mapp[mapi], &nmap, args->flist))) {
583 kmem_free(mapp);
584 return error;
585 }
586 if (nmap < 1)
587 break;
588 /*
589 * Add this bunch into our table, go to the next offset.
590 */
591 mapi += nmap;
592 b = mapp[mapi - 1].br_startoff +
593 mapp[mapi - 1].br_blockcount;
594 }
595 }
596 /*
597 * Didn't work.
598 */
599 else {
600 mapi = 0;
601 mapp = NULL;
602 }
603 /*
604 * See how many fsb's we got.
605 */
606 for (i = 0, got = 0; i < mapi; i++)
607 got += mapp[i].br_blockcount;
608 /*
609 * Didn't get enough fsb's, or the first/last block's are wrong.
610 */
611 if (got != count || mapp[0].br_startoff != bno ||
612 mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
613 bno + count) {
614 if (mapp != &map)
615 kmem_free(mapp);
616 return XFS_ERROR(ENOSPC);
617 }
618 /*
619 * Done with the temporary mapping table.
620 */
621 if (mapp != &map)
622 kmem_free(mapp);
623 527
624 /* account for newly allocated blocks in reserved blocks total */
625 args->total -= dp->i_d.di_nblocks - nblks;
626 *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); 528 *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
627 529
628 /* 530 /*
@@ -634,7 +536,7 @@ xfs_dir2_grow_inode(
634 size = XFS_FSB_TO_B(mp, bno + count); 536 size = XFS_FSB_TO_B(mp, bno + count);
635 if (size > dp->i_d.di_size) { 537 if (size > dp->i_d.di_size) {
636 dp->i_d.di_size = size; 538 dp->i_d.di_size = size;
637 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 539 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
638 } 540 }
639 } 541 }
640 return 0; 542 return 0;