aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.c1
-rw-r--r--fs/xfs/quota/xfs_dquot.c2
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c2
-rw-r--r--fs/xfs/quota/xfs_qm.c2
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c2
-rw-r--r--fs/xfs/quota/xfs_qm_stats.c2
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c2
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c2
-rw-r--r--fs/xfs/xfs_acl.c2
-rw-r--r--fs/xfs/xfs_alloc.c2
-rw-r--r--fs/xfs/xfs_alloc_btree.c2
-rw-r--r--fs/xfs/xfs_attr.c2
-rw-r--r--fs/xfs/xfs_attr_leaf.c2
-rw-r--r--fs/xfs/xfs_bmap.c8
-rw-r--r--fs/xfs/xfs_bmap_btree.c2
-rw-r--r--fs/xfs/xfs_btree.c2
-rw-r--r--fs/xfs/xfs_buf_item.c1
-rw-r--r--fs/xfs/xfs_da_btree.c185
-rw-r--r--fs/xfs/xfs_da_btree.h4
-rw-r--r--fs/xfs/xfs_dfrag.c2
-rw-r--r--fs/xfs/xfs_dinode.h1
-rw-r--r--fs/xfs/xfs_dir.c1213
-rw-r--r--fs/xfs/xfs_dir.h142
-rw-r--r--fs/xfs/xfs_dir2.c391
-rw-r--r--fs/xfs/xfs_dir2.h32
-rw-r--r--fs/xfs/xfs_dir2_block.c15
-rw-r--r--fs/xfs/xfs_dir2_data.c3
-rw-r--r--fs/xfs/xfs_dir2_leaf.c2
-rw-r--r--fs/xfs/xfs_dir2_node.c2
-rw-r--r--fs/xfs/xfs_dir2_sf.c3
-rw-r--r--fs/xfs/xfs_dir2_trace.c2
-rw-r--r--fs/xfs/xfs_dir_leaf.c2230
-rw-r--r--fs/xfs/xfs_dir_leaf.h231
-rw-r--r--fs/xfs/xfs_dir_sf.h155
-rw-r--r--fs/xfs/xfs_dmops.c1
-rw-r--r--fs/xfs/xfs_error.c2
-rw-r--r--fs/xfs/xfs_extfree_item.c1
-rw-r--r--fs/xfs/xfs_fsops.c2
-rw-r--r--fs/xfs/xfs_ialloc.c2
-rw-r--r--fs/xfs/xfs_ialloc_btree.c2
-rw-r--r--fs/xfs/xfs_iget.c2
-rw-r--r--fs/xfs/xfs_inode.c9
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_iocore.c2
-rw-r--r--fs/xfs/xfs_iomap.c2
-rw-r--r--fs/xfs/xfs_itable.c2
-rw-r--r--fs/xfs/xfs_log.c2
-rw-r--r--fs/xfs/xfs_log_recover.c2
-rw-r--r--fs/xfs/xfs_mount.c15
-rw-r--r--fs/xfs/xfs_mount.h2
-rw-r--r--fs/xfs/xfs_qmops.c1
-rw-r--r--fs/xfs/xfs_rename.c54
-rw-r--r--fs/xfs/xfs_rtalloc.c2
-rw-r--r--fs/xfs/xfs_rw.c2
-rw-r--r--fs/xfs/xfs_trans.c2
-rw-r--r--fs/xfs/xfs_trans.h7
-rw-r--r--fs/xfs/xfs_trans_ail.c1
-rw-r--r--fs/xfs/xfs_trans_buf.c2
-rw-r--r--fs/xfs/xfs_trans_extfree.c1
-rw-r--r--fs/xfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/xfs_trans_space.h11
-rw-r--r--fs/xfs/xfs_utils.c5
-rw-r--r--fs/xfs/xfs_vfsops.c8
-rw-r--r--fs/xfs/xfs_vnodeops.c68
71 files changed, 285 insertions, 4595 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index c5ea26d73bea..3e807b828e22 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -21,7 +21,6 @@
21#include "xfs_inum.h" 21#include "xfs_inum.h"
22#include "xfs_sb.h" 22#include "xfs_sb.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_dir.h"
25#include "xfs_dir2.h" 24#include "xfs_dir2.h"
26#include "xfs_trans.h" 25#include "xfs_trans.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
@@ -29,7 +28,6 @@
29#include "xfs_bmap_btree.h" 28#include "xfs_bmap_btree.h"
30#include "xfs_alloc_btree.h" 29#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h" 30#include "xfs_ialloc_btree.h"
32#include "xfs_dir_sf.h"
33#include "xfs_dir2_sf.h" 31#include "xfs_dir2_sf.h"
34#include "xfs_attr_sf.h" 32#include "xfs_attr_sf.h"
35#include "xfs_dinode.h" 33#include "xfs_dinode.h"
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index d32a9edc43a9..5fb75d9151f2 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -21,7 +21,6 @@
21#include "xfs_log.h" 21#include "xfs_log.h"
22#include "xfs_trans.h" 22#include "xfs_trans.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_dir.h"
25#include "xfs_mount.h" 24#include "xfs_mount.h"
26#include "xfs_export.h" 25#include "xfs_export.h"
27 26
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index cf65a8364d5a..70662371bb11 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -21,7 +21,6 @@
21#include "xfs_inum.h" 21#include "xfs_inum.h"
22#include "xfs_sb.h" 22#include "xfs_sb.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_dir.h"
25#include "xfs_dir2.h" 24#include "xfs_dir2.h"
26#include "xfs_trans.h" 25#include "xfs_trans.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_alloc.h" 31#include "xfs_alloc.h"
33#include "xfs_btree.h" 32#include "xfs_btree.h"
34#include "xfs_attr_sf.h" 33#include "xfs_attr_sf.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
38#include "xfs_inode.h" 36#include "xfs_inode.h"
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index a0e247c71323..6e52a5dd38d8 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -31,7 +30,6 @@
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_attr_sf.h" 33#include "xfs_attr_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 484daef91d7f..12810baeb5d4 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 8e5468704816..5d9cfd91ad08 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 7fae922d54de..f2a0778536f4 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
index 4fc884bcb4fd..6145e8bd0be2 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ b/fs/xfs/linux-2.6/xfs_vfs.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_imap.h" 27#include "xfs_imap.h"
29#include "xfs_alloc.h" 28#include "xfs_alloc.h"
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 46bec66bb4d8..3aa771531856 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 21ad5a55e014..5b2dcc58b244 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 00fb54d48999..e23e45535c48 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_alloc.h" 28#include "xfs_alloc.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index d93d3a1064ed..e95e99f7168f 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_alloc.h" 28#include "xfs_alloc.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
index 0570f7733550..6f858fb81a36 100644
--- a/fs/xfs/quota/xfs_qm_stats.c
+++ b/fs/xfs/quota/xfs_qm_stats.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index c93072be6792..ed620c4d1594 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -26,7 +26,6 @@
26#include "xfs_trans.h" 26#include "xfs_trans.h"
27#include "xfs_sb.h" 27#include "xfs_sb.h"
28#include "xfs_ag.h" 28#include "xfs_ag.h"
29#include "xfs_dir.h"
30#include "xfs_dir2.h" 29#include "xfs_dir2.h"
31#include "xfs_alloc.h" 30#include "xfs_alloc.h"
32#include "xfs_dmapi.h" 31#include "xfs_dmapi.h"
@@ -35,7 +34,6 @@
35#include "xfs_bmap_btree.h" 34#include "xfs_bmap_btree.h"
36#include "xfs_alloc_btree.h" 35#include "xfs_alloc_btree.h"
37#include "xfs_ialloc_btree.h" 36#include "xfs_ialloc_btree.h"
38#include "xfs_dir_sf.h"
39#include "xfs_dir2_sf.h" 37#include "xfs_dir2_sf.h"
40#include "xfs_attr_sf.h" 38#include "xfs_attr_sf.h"
41#include "xfs_dinode.h" 39#include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 9168918db252..0242e9666e8e 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
39#include "xfs_inode.h" 37#include "xfs_inode.h"
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index e1074955386f..4b0cb474be4c 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -21,12 +21,10 @@
21#include "xfs_bit.h" 21#include "xfs_bit.h"
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_dir.h"
25#include "xfs_dir2.h" 24#include "xfs_dir2.h"
26#include "xfs_bmap_btree.h" 25#include "xfs_bmap_btree.h"
27#include "xfs_alloc_btree.h" 26#include "xfs_alloc_btree.h"
28#include "xfs_ialloc_btree.h" 27#include "xfs_ialloc_btree.h"
29#include "xfs_dir_sf.h"
30#include "xfs_dir2_sf.h" 28#include "xfs_dir2_sf.h"
31#include "xfs_attr_sf.h" 29#include "xfs_attr_sf.h"
32#include "xfs_dinode.h" 30#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 22af489d3f34..eef6763f3a67 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index a1d92da86ccd..7446556e8021 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 4dcef8d1c32f..1a2101043275 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -27,7 +27,6 @@
27#include "xfs_trans.h" 27#include "xfs_trans.h"
28#include "xfs_sb.h" 28#include "xfs_sb.h"
29#include "xfs_ag.h" 29#include "xfs_ag.h"
30#include "xfs_dir.h"
31#include "xfs_dir2.h" 30#include "xfs_dir2.h"
32#include "xfs_dmapi.h" 31#include "xfs_dmapi.h"
33#include "xfs_mount.h" 32#include "xfs_mount.h"
@@ -35,7 +34,6 @@
35#include "xfs_bmap_btree.h" 34#include "xfs_bmap_btree.h"
36#include "xfs_alloc_btree.h" 35#include "xfs_alloc_btree.h"
37#include "xfs_ialloc_btree.h" 36#include "xfs_ialloc_btree.h"
38#include "xfs_dir_sf.h"
39#include "xfs_dir2_sf.h" 37#include "xfs_dir2_sf.h"
40#include "xfs_attr_sf.h" 38#include "xfs_attr_sf.h"
41#include "xfs_dinode.h" 39#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 5c44343d4a36..9455051f0120 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -34,7 +33,6 @@
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_alloc.h" 34#include "xfs_alloc.h"
36#include "xfs_btree.h" 35#include "xfs_btree.h"
37#include "xfs_dir_sf.h"
38#include "xfs_dir2_sf.h" 36#include "xfs_dir2_sf.h"
39#include "xfs_attr_sf.h" 37#include "xfs_attr_sf.h"
40#include "xfs_dinode.h" 38#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 4d0ca14039af..3a6137539064 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -24,13 +24,11 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.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_ialloc_btree.h" 31#include "xfs_ialloc_btree.h"
33#include "xfs_dir_sf.h"
34#include "xfs_dir2_sf.h" 32#include "xfs_dir2_sf.h"
35#include "xfs_attr_sf.h" 33#include "xfs_attr_sf.h"
36#include "xfs_dinode.h" 34#include "xfs_dinode.h"
@@ -40,13 +38,15 @@
40#include "xfs_mount.h" 38#include "xfs_mount.h"
41#include "xfs_ialloc.h" 39#include "xfs_ialloc.h"
42#include "xfs_itable.h" 40#include "xfs_itable.h"
41#include "xfs_dir2_data.h"
42#include "xfs_dir2_leaf.h"
43#include "xfs_dir2_block.h"
43#include "xfs_inode_item.h" 44#include "xfs_inode_item.h"
44#include "xfs_extfree_item.h" 45#include "xfs_extfree_item.h"
45#include "xfs_alloc.h" 46#include "xfs_alloc.h"
46#include "xfs_bmap.h" 47#include "xfs_bmap.h"
47#include "xfs_rtalloc.h" 48#include "xfs_rtalloc.h"
48#include "xfs_error.h" 49#include "xfs_error.h"
49#include "xfs_dir_leaf.h"
50#include "xfs_attr_leaf.h" 50#include "xfs_attr_leaf.h"
51#include "xfs_rw.h" 51#include "xfs_rw.h"
52#include "xfs_quota.h" 52#include "xfs_quota.h"
@@ -516,7 +516,7 @@ xfs_bmap_add_attrfork_local(
516 dargs.total = mp->m_dirblkfsbs; 516 dargs.total = mp->m_dirblkfsbs;
517 dargs.whichfork = XFS_DATA_FORK; 517 dargs.whichfork = XFS_DATA_FORK;
518 dargs.trans = tp; 518 dargs.trans = tp;
519 error = XFS_DIR_SHORTFORM_TO_SINGLE(mp, &dargs); 519 error = xfs_dir2_sf_to_block(&dargs);
520 } else 520 } else
521 error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, 521 error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
522 XFS_DATA_FORK); 522 XFS_DATA_FORK);
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 3b6dfc9b53af..18fb7385d719 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 52d5d095fc35..ee2255bd6562 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 290912cbff63..a4aa53974f76 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -23,7 +23,6 @@
23#include "xfs_inum.h" 23#include "xfs_inum.h"
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_dir.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_buf_item.h" 28#include "xfs_buf_item.h"
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 260c3d770c02..32ab61d17ace 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -43,7 +41,6 @@
43#include "xfs_bmap.h" 41#include "xfs_bmap.h"
44#include "xfs_attr.h" 42#include "xfs_attr.h"
45#include "xfs_attr_leaf.h" 43#include "xfs_attr_leaf.h"
46#include "xfs_dir_leaf.h"
47#include "xfs_dir2_data.h" 44#include "xfs_dir2_data.h"
48#include "xfs_dir2_leaf.h" 45#include "xfs_dir2_leaf.h"
49#include "xfs_dir2_block.h" 46#include "xfs_dir2_block.h"
@@ -159,7 +156,7 @@ xfs_da_split(xfs_da_state_t *state)
159 max = state->path.active - 1; 156 max = state->path.active - 1;
160 ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH)); 157 ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH));
161 ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC || 158 ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC ||
162 state->path.blk[max].magic == XFS_DIRX_LEAF_MAGIC(state->mp)); 159 state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC);
163 160
164 addblk = &state->path.blk[max]; /* initial dummy value */ 161 addblk = &state->path.blk[max]; /* initial dummy value */
165 for (i = max; (i >= 0) && addblk; state->path.active--, i--) { 162 for (i = max; (i >= 0) && addblk; state->path.active--, i--) {
@@ -199,38 +196,7 @@ xfs_da_split(xfs_da_state_t *state)
199 return(error); /* GROT: attr inconsistent */ 196 return(error); /* GROT: attr inconsistent */
200 addblk = newblk; 197 addblk = newblk;
201 break; 198 break;
202 case XFS_DIR_LEAF_MAGIC:
203 ASSERT(XFS_DIR_IS_V1(state->mp));
204 error = xfs_dir_leaf_split(state, oldblk, newblk);
205 if ((error != 0) && (error != ENOSPC)) {
206 return(error); /* GROT: dir is inconsistent */
207 }
208 if (!error) {
209 addblk = newblk;
210 break;
211 }
212 /*
213 * Entry wouldn't fit, split the leaf again.
214 */
215 state->extravalid = 1;
216 if (state->inleaf) {
217 state->extraafter = 0; /* before newblk */
218 error = xfs_dir_leaf_split(state, oldblk,
219 &state->extrablk);
220 if (error)
221 return(error); /* GROT: dir incon. */
222 addblk = newblk;
223 } else {
224 state->extraafter = 1; /* after newblk */
225 error = xfs_dir_leaf_split(state, newblk,
226 &state->extrablk);
227 if (error)
228 return(error); /* GROT: dir incon. */
229 addblk = newblk;
230 }
231 break;
232 case XFS_DIR2_LEAFN_MAGIC: 199 case XFS_DIR2_LEAFN_MAGIC:
233 ASSERT(XFS_DIR_IS_V2(state->mp));
234 error = xfs_dir2_leafn_split(state, oldblk, newblk); 200 error = xfs_dir2_leafn_split(state, oldblk, newblk);
235 if (error) 201 if (error)
236 return error; 202 return error;
@@ -363,7 +329,6 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
363 size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - 329 size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] -
364 (char *)oldroot); 330 (char *)oldroot);
365 } else { 331 } else {
366 ASSERT(XFS_DIR_IS_V2(mp));
367 ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); 332 ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
368 leaf = (xfs_dir2_leaf_t *)oldroot; 333 leaf = (xfs_dir2_leaf_t *)oldroot;
369 size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] - 334 size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] -
@@ -379,8 +344,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
379 * Set up the new root node. 344 * Set up the new root node.
380 */ 345 */
381 error = xfs_da_node_create(args, 346 error = xfs_da_node_create(args,
382 args->whichfork == XFS_DATA_FORK && 347 (args->whichfork == XFS_DATA_FORK) ? mp->m_dirleafblk : 0,
383 XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0,
384 be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork); 348 be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork);
385 if (error) 349 if (error)
386 return(error); 350 return(error);
@@ -427,10 +391,9 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
427 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); 391 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
428 392
429 /* 393 /*
430 * With V2 the extra block is data or freespace. 394 * With V2 dirs the extra block is data or freespace.
431 */ 395 */
432 useextra = state->extravalid && (XFS_DIR_IS_V1(state->mp) || 396 useextra = state->extravalid && state->args->whichfork == XFS_ATTR_FORK;
433 state->args->whichfork == XFS_ATTR_FORK);
434 newcount = 1 + useextra; 397 newcount = 1 + useextra;
435 /* 398 /*
436 * Do we have to split the node? 399 * Do we have to split the node?
@@ -624,7 +587,7 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
624 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); 587 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
625 ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); 588 ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count)));
626 ASSERT(newblk->blkno != 0); 589 ASSERT(newblk->blkno != 0);
627 if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) 590 if (state->args->whichfork == XFS_DATA_FORK)
628 ASSERT(newblk->blkno >= mp->m_dirleafblk && 591 ASSERT(newblk->blkno >= mp->m_dirleafblk &&
629 newblk->blkno < mp->m_dirfreeblk); 592 newblk->blkno < mp->m_dirfreeblk);
630 593
@@ -670,7 +633,7 @@ xfs_da_join(xfs_da_state_t *state)
670 save_blk = &state->altpath.blk[ state->path.active-1 ]; 633 save_blk = &state->altpath.blk[ state->path.active-1 ];
671 ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC); 634 ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC);
672 ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC || 635 ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC ||
673 drop_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp)); 636 drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
674 637
675 /* 638 /*
676 * Walk back up the tree joining/deallocating as necessary. 639 * Walk back up the tree joining/deallocating as necessary.
@@ -693,17 +656,7 @@ xfs_da_join(xfs_da_state_t *state)
693 return(0); 656 return(0);
694 xfs_attr_leaf_unbalance(state, drop_blk, save_blk); 657 xfs_attr_leaf_unbalance(state, drop_blk, save_blk);
695 break; 658 break;
696 case XFS_DIR_LEAF_MAGIC:
697 ASSERT(XFS_DIR_IS_V1(state->mp));
698 error = xfs_dir_leaf_toosmall(state, &action);
699 if (error)
700 return(error);
701 if (action == 0)
702 return(0);
703 xfs_dir_leaf_unbalance(state, drop_blk, save_blk);
704 break;
705 case XFS_DIR2_LEAFN_MAGIC: 659 case XFS_DIR2_LEAFN_MAGIC:
706 ASSERT(XFS_DIR_IS_V2(state->mp));
707 error = xfs_dir2_leafn_toosmall(state, &action); 660 error = xfs_dir2_leafn_toosmall(state, &action);
708 if (error) 661 if (error)
709 return error; 662 return error;
@@ -790,7 +743,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
790 ASSERT(bp != NULL); 743 ASSERT(bp != NULL);
791 blkinfo = bp->data; 744 blkinfo = bp->data;
792 if (be16_to_cpu(oldroot->hdr.level) == 1) { 745 if (be16_to_cpu(oldroot->hdr.level) == 1) {
793 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || 746 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIR2_LEAFN_MAGIC ||
794 be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC); 747 be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC);
795 } else { 748 } else {
796 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC); 749 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC);
@@ -951,14 +904,7 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path)
951 if (count == 0) 904 if (count == 0)
952 return; 905 return;
953 break; 906 break;
954 case XFS_DIR_LEAF_MAGIC:
955 ASSERT(XFS_DIR_IS_V1(state->mp));
956 lasthash = xfs_dir_leaf_lasthash(blk->bp, &count);
957 if (count == 0)
958 return;
959 break;
960 case XFS_DIR2_LEAFN_MAGIC: 907 case XFS_DIR2_LEAFN_MAGIC:
961 ASSERT(XFS_DIR_IS_V2(state->mp));
962 lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); 908 lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count);
963 if (count == 0) 909 if (count == 0)
964 return; 910 return;
@@ -1117,10 +1063,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1117 * Descend thru the B-tree searching each level for the right 1063 * Descend thru the B-tree searching each level for the right
1118 * node to use, until the right hashval is found. 1064 * node to use, until the right hashval is found.
1119 */ 1065 */
1120 if (args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(state->mp)) 1066 blkno = (args->whichfork == XFS_DATA_FORK)? state->mp->m_dirleafblk : 0;
1121 blkno = state->mp->m_dirleafblk;
1122 else
1123 blkno = 0;
1124 for (blk = &state->path.blk[0], state->path.active = 1; 1067 for (blk = &state->path.blk[0], state->path.active = 1;
1125 state->path.active <= XFS_DA_NODE_MAXDEPTH; 1068 state->path.active <= XFS_DA_NODE_MAXDEPTH;
1126 blk++, state->path.active++) { 1069 blk++, state->path.active++) {
@@ -1137,7 +1080,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1137 } 1080 }
1138 curr = blk->bp->data; 1081 curr = blk->bp->data;
1139 ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC || 1082 ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC ||
1140 be16_to_cpu(curr->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || 1083 be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC ||
1141 be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC); 1084 be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC);
1142 1085
1143 /* 1086 /*
@@ -1190,16 +1133,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1190 blk->index = probe; 1133 blk->index = probe;
1191 blkno = be32_to_cpu(btree->before); 1134 blkno = be32_to_cpu(btree->before);
1192 } 1135 }
1193 } 1136 } else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
1194 else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
1195 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); 1137 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
1196 break; 1138 break;
1197 } 1139 } else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
1198 else if (be16_to_cpu(curr->magic) == XFS_DIR_LEAF_MAGIC) {
1199 blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL);
1200 break;
1201 }
1202 else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
1203 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); 1140 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
1204 break; 1141 break;
1205 } 1142 }
@@ -1212,12 +1149,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1212 * next leaf and keep searching. 1149 * next leaf and keep searching.
1213 */ 1150 */
1214 for (;;) { 1151 for (;;) {
1215 if (blk->magic == XFS_DIR_LEAF_MAGIC) { 1152 if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
1216 ASSERT(XFS_DIR_IS_V1(state->mp));
1217 retval = xfs_dir_leaf_lookup_int(blk->bp, args,
1218 &blk->index);
1219 } else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
1220 ASSERT(XFS_DIR_IS_V2(state->mp));
1221 retval = xfs_dir2_leafn_lookup_int(blk->bp, args, 1153 retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
1222 &blk->index, state); 1154 &blk->index, state);
1223 } 1155 }
@@ -1270,7 +1202,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
1270 old_info = old_blk->bp->data; 1202 old_info = old_blk->bp->data;
1271 new_info = new_blk->bp->data; 1203 new_info = new_blk->bp->data;
1272 ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || 1204 ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC ||
1273 old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || 1205 old_blk->magic == XFS_DIR2_LEAFN_MAGIC ||
1274 old_blk->magic == XFS_ATTR_LEAF_MAGIC); 1206 old_blk->magic == XFS_ATTR_LEAF_MAGIC);
1275 ASSERT(old_blk->magic == be16_to_cpu(old_info->magic)); 1207 ASSERT(old_blk->magic == be16_to_cpu(old_info->magic));
1276 ASSERT(new_blk->magic == be16_to_cpu(new_info->magic)); 1208 ASSERT(new_blk->magic == be16_to_cpu(new_info->magic));
@@ -1280,12 +1212,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
1280 case XFS_ATTR_LEAF_MAGIC: 1212 case XFS_ATTR_LEAF_MAGIC:
1281 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); 1213 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
1282 break; 1214 break;
1283 case XFS_DIR_LEAF_MAGIC:
1284 ASSERT(XFS_DIR_IS_V1(state->mp));
1285 before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp);
1286 break;
1287 case XFS_DIR2_LEAFN_MAGIC: 1215 case XFS_DIR2_LEAFN_MAGIC:
1288 ASSERT(XFS_DIR_IS_V2(state->mp));
1289 before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); 1216 before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp);
1290 break; 1217 break;
1291 case XFS_DA_NODE_MAGIC: 1218 case XFS_DA_NODE_MAGIC:
@@ -1404,7 +1331,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1404 save_info = save_blk->bp->data; 1331 save_info = save_blk->bp->data;
1405 drop_info = drop_blk->bp->data; 1332 drop_info = drop_blk->bp->data;
1406 ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || 1333 ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC ||
1407 save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || 1334 save_blk->magic == XFS_DIR2_LEAFN_MAGIC ||
1408 save_blk->magic == XFS_ATTR_LEAF_MAGIC); 1335 save_blk->magic == XFS_ATTR_LEAF_MAGIC);
1409 ASSERT(save_blk->magic == be16_to_cpu(save_info->magic)); 1336 ASSERT(save_blk->magic == be16_to_cpu(save_info->magic));
1410 ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic)); 1337 ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic));
@@ -1529,7 +1456,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
1529 ASSERT(blk->bp != NULL); 1456 ASSERT(blk->bp != NULL);
1530 info = blk->bp->data; 1457 info = blk->bp->data;
1531 ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC || 1458 ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC ||
1532 be16_to_cpu(info->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || 1459 be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC ||
1533 be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); 1460 be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC);
1534 blk->magic = be16_to_cpu(info->magic); 1461 blk->magic = be16_to_cpu(info->magic);
1535 if (blk->magic == XFS_DA_NODE_MAGIC) { 1462 if (blk->magic == XFS_DA_NODE_MAGIC) {
@@ -1548,20 +1475,13 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
1548 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, 1475 blk->hashval = xfs_attr_leaf_lasthash(blk->bp,
1549 NULL); 1476 NULL);
1550 break; 1477 break;
1551 case XFS_DIR_LEAF_MAGIC:
1552 ASSERT(XFS_DIR_IS_V1(state->mp));
1553 blk->hashval = xfs_dir_leaf_lasthash(blk->bp,
1554 NULL);
1555 break;
1556 case XFS_DIR2_LEAFN_MAGIC: 1478 case XFS_DIR2_LEAFN_MAGIC:
1557 ASSERT(XFS_DIR_IS_V2(state->mp));
1558 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, 1479 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp,
1559 NULL); 1480 NULL);
1560 break; 1481 break;
1561 default: 1482 default:
1562 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC || 1483 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC ||
1563 blk->magic == 1484 blk->magic == XFS_DIR2_LEAFN_MAGIC);
1564 XFS_DIRX_LEAF_MAGIC(state->mp));
1565 break; 1485 break;
1566 } 1486 }
1567 } 1487 }
@@ -1620,7 +1540,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1620 xfs_bmbt_irec_t *mapp; 1540 xfs_bmbt_irec_t *mapp;
1621 xfs_inode_t *dp; 1541 xfs_inode_t *dp;
1622 int nmap, error, w, count, c, got, i, mapi; 1542 int nmap, error, w, count, c, got, i, mapi;
1623 xfs_fsize_t size;
1624 xfs_trans_t *tp; 1543 xfs_trans_t *tp;
1625 xfs_mount_t *mp; 1544 xfs_mount_t *mp;
1626 1545
@@ -1631,7 +1550,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1631 /* 1550 /*
1632 * For new directories adjust the file offset and block count. 1551 * For new directories adjust the file offset and block count.
1633 */ 1552 */
1634 if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) { 1553 if (w == XFS_DATA_FORK) {
1635 bno = mp->m_dirleafblk; 1554 bno = mp->m_dirleafblk;
1636 count = mp->m_dirblkfsbs; 1555 count = mp->m_dirblkfsbs;
1637 } else { 1556 } else {
@@ -1641,10 +1560,9 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1641 /* 1560 /*
1642 * Find a spot in the file space to put the new block. 1561 * Find a spot in the file space to put the new block.
1643 */ 1562 */
1644 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) { 1563 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w)))
1645 return error; 1564 return error;
1646 } 1565 if (w == XFS_DATA_FORK)
1647 if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
1648 ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk); 1566 ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
1649 /* 1567 /*
1650 * Try mapping it in one filesystem block. 1568 * Try mapping it in one filesystem block.
@@ -1706,19 +1624,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1706 if (mapp != &map) 1624 if (mapp != &map)
1707 kmem_free(mapp, sizeof(*mapp) * count); 1625 kmem_free(mapp, sizeof(*mapp) * count);
1708 *new_blkno = (xfs_dablk_t)bno; 1626 *new_blkno = (xfs_dablk_t)bno;
1709 /*
1710 * For version 1 directories, adjust the file size if it changed.
1711 */
1712 if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
1713 ASSERT(mapi == 1);
1714 if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
1715 return error;
1716 size = XFS_FSB_TO_B(mp, bno);
1717 if (size != dp->i_d.di_size) {
1718 dp->i_d.di_size = size;
1719 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1720 }
1721 }
1722 return 0; 1627 return 0;
1723} 1628}
1724 1629
@@ -1743,7 +1648,6 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1743 int error, w, entno, level, dead_level; 1648 int error, w, entno, level, dead_level;
1744 xfs_da_blkinfo_t *dead_info, *sib_info; 1649 xfs_da_blkinfo_t *dead_info, *sib_info;
1745 xfs_da_intnode_t *par_node, *dead_node; 1650 xfs_da_intnode_t *par_node, *dead_node;
1746 xfs_dir_leafblock_t *dead_leaf;
1747 xfs_dir2_leaf_t *dead_leaf2; 1651 xfs_dir2_leaf_t *dead_leaf2;
1748 xfs_dahash_t dead_hash; 1652 xfs_dahash_t dead_hash;
1749 1653
@@ -1754,11 +1658,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1754 w = args->whichfork; 1658 w = args->whichfork;
1755 ASSERT(w == XFS_DATA_FORK); 1659 ASSERT(w == XFS_DATA_FORK);
1756 mp = ip->i_mount; 1660 mp = ip->i_mount;
1757 if (XFS_DIR_IS_V2(mp)) { 1661 lastoff = mp->m_dirfreeblk;
1758 lastoff = mp->m_dirfreeblk; 1662 error = xfs_bmap_last_before(tp, ip, &lastoff, w);
1759 error = xfs_bmap_last_before(tp, ip, &lastoff, w);
1760 } else
1761 error = xfs_bmap_last_offset(tp, ip, &lastoff, w);
1762 if (error) 1663 if (error)
1763 return error; 1664 return error;
1764 if (unlikely(lastoff == 0)) { 1665 if (unlikely(lastoff == 0)) {
@@ -1781,14 +1682,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1781 /* 1682 /*
1782 * Get values from the moved block. 1683 * Get values from the moved block.
1783 */ 1684 */
1784 if (be16_to_cpu(dead_info->magic) == XFS_DIR_LEAF_MAGIC) { 1685 if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
1785 ASSERT(XFS_DIR_IS_V1(mp));
1786 dead_leaf = (xfs_dir_leafblock_t *)dead_info;
1787 dead_level = 0;
1788 dead_hash = be32_to_cpu(dead_leaf->entries[
1789 be16_to_cpu(dead_leaf->hdr.count) - 1].hashval);
1790 } else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
1791 ASSERT(XFS_DIR_IS_V2(mp));
1792 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; 1686 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
1793 dead_level = 0; 1687 dead_level = 0;
1794 dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval); 1688 dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval);
@@ -1843,7 +1737,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1843 xfs_da_buf_done(sib_buf); 1737 xfs_da_buf_done(sib_buf);
1844 sib_buf = NULL; 1738 sib_buf = NULL;
1845 } 1739 }
1846 par_blkno = XFS_DIR_IS_V1(mp) ? 0 : mp->m_dirleafblk; 1740 par_blkno = mp->m_dirleafblk;
1847 level = -1; 1741 level = -1;
1848 /* 1742 /*
1849 * Walk down the tree looking for the parent of the moved block. 1743 * Walk down the tree looking for the parent of the moved block.
@@ -1942,8 +1836,6 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
1942{ 1836{
1943 xfs_inode_t *dp; 1837 xfs_inode_t *dp;
1944 int done, error, w, count; 1838 int done, error, w, count;
1945 xfs_fileoff_t bno;
1946 xfs_fsize_t size;
1947 xfs_trans_t *tp; 1839 xfs_trans_t *tp;
1948 xfs_mount_t *mp; 1840 xfs_mount_t *mp;
1949 1841
@@ -1951,7 +1843,7 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
1951 w = args->whichfork; 1843 w = args->whichfork;
1952 tp = args->trans; 1844 tp = args->trans;
1953 mp = dp->i_mount; 1845 mp = dp->i_mount;
1954 if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) 1846 if (w == XFS_DATA_FORK)
1955 count = mp->m_dirblkfsbs; 1847 count = mp->m_dirblkfsbs;
1956 else 1848 else
1957 count = 1; 1849 count = 1;
@@ -1965,31 +1857,14 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
1965 0, args->firstblock, args->flist, NULL, 1857 0, args->firstblock, args->flist, NULL,
1966 &done)) == ENOSPC) { 1858 &done)) == ENOSPC) {
1967 if (w != XFS_DATA_FORK) 1859 if (w != XFS_DATA_FORK)
1968 goto done; 1860 break;
1969 if ((error = xfs_da_swap_lastblock(args, &dead_blkno, 1861 if ((error = xfs_da_swap_lastblock(args, &dead_blkno,
1970 &dead_buf))) 1862 &dead_buf)))
1971 goto done; 1863 break;
1972 } else if (error) 1864 } else {
1973 goto done;
1974 else
1975 break; 1865 break;
1976 }
1977 ASSERT(done);
1978 xfs_da_binval(tp, dead_buf);
1979 /*
1980 * Adjust the directory size for version 1.
1981 */
1982 if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
1983 if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
1984 return error;
1985 size = XFS_FSB_TO_B(dp->i_mount, bno);
1986 if (size != dp->i_d.di_size) {
1987 dp->i_d.di_size = size;
1988 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1989 } 1866 }
1990 } 1867 }
1991 return 0;
1992done:
1993 xfs_da_binval(tp, dead_buf); 1868 xfs_da_binval(tp, dead_buf);
1994 return error; 1869 return error;
1995} 1870}
@@ -2050,10 +1925,7 @@ xfs_da_do_buf(
2050 xfs_dabuf_t *rbp; 1925 xfs_dabuf_t *rbp;
2051 1926
2052 mp = dp->i_mount; 1927 mp = dp->i_mount;
2053 if (whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) 1928 nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1;
2054 nfsb = mp->m_dirblkfsbs;
2055 else
2056 nfsb = 1;
2057 mappedbno = *mappedbnop; 1929 mappedbno = *mappedbnop;
2058 /* 1930 /*
2059 * Caller doesn't have a mapping. -2 means don't complain 1931 * Caller doesn't have a mapping. -2 means don't complain
@@ -2199,7 +2071,6 @@ xfs_da_do_buf(
2199 magic1 = be32_to_cpu(data->hdr.magic); 2071 magic1 = be32_to_cpu(data->hdr.magic);
2200 if (unlikely( 2072 if (unlikely(
2201 XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && 2073 XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
2202 (magic != XFS_DIR_LEAF_MAGIC) &&
2203 (magic != XFS_ATTR_LEAF_MAGIC) && 2074 (magic != XFS_ATTR_LEAF_MAGIC) &&
2204 (magic != XFS_DIR2_LEAF1_MAGIC) && 2075 (magic != XFS_DIR2_LEAF1_MAGIC) &&
2205 (magic != XFS_DIR2_LEAFN_MAGIC) && 2076 (magic != XFS_DIR2_LEAFN_MAGIC) &&
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 243a730d5ec8..4ab865ec8b82 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -36,14 +36,10 @@ struct zone;
36 * level in the Btree, and to identify which type of block this is. 36 * level in the Btree, and to identify which type of block this is.
37 */ 37 */
38#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ 38#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
39#define XFS_DIR_LEAF_MAGIC 0xfeeb /* magic number: directory leaf blks */
40#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ 39#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
41#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ 40#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
42#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ 41#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
43 42
44#define XFS_DIRX_LEAF_MAGIC(mp) \
45 (XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC)
46
47typedef struct xfs_da_blkinfo { 43typedef struct xfs_da_blkinfo {
48 __be32 forw; /* previous block in list */ 44 __be32 forw; /* previous block in list */
49 __be32 back; /* following block in list */ 45 __be32 back; /* following block in list */
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 29a6c866f2c3..80562b60fb95 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index 77d537782586..b33826961c45 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -85,7 +85,6 @@ typedef struct xfs_dinode
85 union { 85 union {
86 xfs_bmdr_block_t di_bmbt; /* btree root block */ 86 xfs_bmdr_block_t di_bmbt; /* btree root block */
87 xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ 87 xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
88 xfs_dir_shortform_t di_dirsf; /* shortform directory */
89 xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ 88 xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
90 char di_c[1]; /* local contents */ 89 char di_c[1]; /* local contents */
91 xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */ 90 xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */
diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c
index 3cd8657a81f6..e69de29bb2d1 100644
--- a/fs/xfs/xfs_dir.c
+++ b/fs/xfs/xfs_dir.c
@@ -1,1213 +0,0 @@
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_types.h"
21#include "xfs_log.h"
22#include "xfs_inum.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h"
27#include "xfs_dmapi.h"
28#include "xfs_mount.h"
29#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_alloc.h"
34#include "xfs_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h"
38#include "xfs_dinode.h"
39#include "xfs_inode.h"
40#include "xfs_bmap.h"
41#include "xfs_dir_leaf.h"
42#include "xfs_error.h"
43
44/*
45 * xfs_dir.c
46 *
47 * Provide the external interfaces to manage directories.
48 */
49
50/*========================================================================
51 * Function prototypes for the kernel.
52 *========================================================================*/
53
54/*
55 * Functions for the dirops interfaces.
56 */
57static void xfs_dir_mount(struct xfs_mount *mp);
58
59static int xfs_dir_isempty(struct xfs_inode *dp);
60
61static int xfs_dir_init(struct xfs_trans *trans,
62 struct xfs_inode *dir,
63 struct xfs_inode *parent_dir);
64
65static int xfs_dir_createname(struct xfs_trans *trans,
66 struct xfs_inode *dp,
67 char *name_string,
68 int name_len,
69 xfs_ino_t inode_number,
70 xfs_fsblock_t *firstblock,
71 xfs_bmap_free_t *flist,
72 xfs_extlen_t total);
73
74static int xfs_dir_lookup(struct xfs_trans *tp,
75 struct xfs_inode *dp,
76 char *name_string,
77 int name_length,
78 xfs_ino_t *inode_number);
79
80static int xfs_dir_removename(struct xfs_trans *trans,
81 struct xfs_inode *dp,
82 char *name_string,
83 int name_length,
84 xfs_ino_t ino,
85 xfs_fsblock_t *firstblock,
86 xfs_bmap_free_t *flist,
87 xfs_extlen_t total);
88
89static int xfs_dir_getdents(struct xfs_trans *tp,
90 struct xfs_inode *dp,
91 struct uio *uiop,
92 int *eofp);
93
94static int xfs_dir_replace(struct xfs_trans *tp,
95 struct xfs_inode *dp,
96 char *name_string,
97 int name_length,
98 xfs_ino_t inode_number,
99 xfs_fsblock_t *firstblock,
100 xfs_bmap_free_t *flist,
101 xfs_extlen_t total);
102
103static int xfs_dir_canenter(struct xfs_trans *tp,
104 struct xfs_inode *dp,
105 char *name_string,
106 int name_length);
107
108static int xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp,
109 xfs_dinode_t *dip);
110
111xfs_dirops_t xfsv1_dirops = {
112 .xd_mount = xfs_dir_mount,
113 .xd_isempty = xfs_dir_isempty,
114 .xd_init = xfs_dir_init,
115 .xd_createname = xfs_dir_createname,
116 .xd_lookup = xfs_dir_lookup,
117 .xd_removename = xfs_dir_removename,
118 .xd_getdents = xfs_dir_getdents,
119 .xd_replace = xfs_dir_replace,
120 .xd_canenter = xfs_dir_canenter,
121 .xd_shortform_validate_ondisk = xfs_dir_shortform_validate_ondisk,
122 .xd_shortform_to_single = xfs_dir_shortform_to_leaf,
123};
124
125/*
126 * Internal routines when dirsize == XFS_LBSIZE(mp).
127 */
128STATIC int xfs_dir_leaf_lookup(xfs_da_args_t *args);
129STATIC int xfs_dir_leaf_removename(xfs_da_args_t *args, int *number_entries,
130 int *total_namebytes);
131STATIC int xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
132 uio_t *uio, int *eofp,
133 xfs_dirent_t *dbp,
134 xfs_dir_put_t put);
135STATIC int xfs_dir_leaf_replace(xfs_da_args_t *args);
136
137/*
138 * Internal routines when dirsize > XFS_LBSIZE(mp).
139 */
140STATIC int xfs_dir_node_addname(xfs_da_args_t *args);
141STATIC int xfs_dir_node_lookup(xfs_da_args_t *args);
142STATIC int xfs_dir_node_removename(xfs_da_args_t *args);
143STATIC int xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
144 uio_t *uio, int *eofp,
145 xfs_dirent_t *dbp,
146 xfs_dir_put_t put);
147STATIC int xfs_dir_node_replace(xfs_da_args_t *args);
148
149#if defined(XFS_DIR_TRACE)
150ktrace_t *xfs_dir_trace_buf;
151#endif
152
153
154/*========================================================================
155 * Overall external interface routines.
156 *========================================================================*/
157
158xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
159
160/*
161 * One-time startup routine called from xfs_init().
162 */
163void
164xfs_dir_startup(void)
165{
166 xfs_dir_hash_dot = xfs_da_hashname(".", 1);
167 xfs_dir_hash_dotdot = xfs_da_hashname("..", 2);
168}
169
170/*
171 * Initialize directory-related fields in the mount structure.
172 */
173static void
174xfs_dir_mount(xfs_mount_t *mp)
175{
176 uint shortcount, leafcount, count;
177
178 mp->m_dirversion = 1;
179 if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
180 shortcount = (mp->m_attroffset -
181 (uint)sizeof(xfs_dir_sf_hdr_t)) /
182 (uint)sizeof(xfs_dir_sf_entry_t);
183 leafcount = (XFS_LBSIZE(mp) -
184 (uint)sizeof(xfs_dir_leaf_hdr_t)) /
185 ((uint)sizeof(xfs_dir_leaf_entry_t) +
186 (uint)sizeof(xfs_dir_leaf_name_t));
187 } else {
188 shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) -
189 (uint)sizeof(xfs_dir_sf_hdr_t)) /
190 (uint)sizeof(xfs_dir_sf_entry_t);
191 leafcount = (XFS_LBSIZE(mp) -
192 (uint)sizeof(xfs_dir_leaf_hdr_t)) /
193 ((uint)sizeof(xfs_dir_leaf_entry_t) +
194 (uint)sizeof(xfs_dir_leaf_name_t));
195 }
196 count = shortcount > leafcount ? shortcount : leafcount;
197 mp->m_dircook_elog = xfs_da_log2_roundup(count + 1);
198 ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog);
199 mp->m_dir_node_ents = mp->m_attr_node_ents =
200 (XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) /
201 (uint)sizeof(xfs_da_node_entry_t);
202 mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100;
203 mp->m_dirblksize = mp->m_sb.sb_blocksize;
204 mp->m_dirblkfsbs = 1;
205}
206
207/*
208 * Return 1 if directory contains only "." and "..".
209 */
210static int
211xfs_dir_isempty(xfs_inode_t *dp)
212{
213 xfs_dir_sf_hdr_t *hdr;
214
215 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
216 if (dp->i_d.di_size == 0)
217 return(1);
218 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
219 return(0);
220 hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
221 return(hdr->count == 0);
222}
223
224/*
225 * Initialize a directory with its "." and ".." entries.
226 */
227static int
228xfs_dir_init(xfs_trans_t *trans, xfs_inode_t *dir, xfs_inode_t *parent_dir)
229{
230 xfs_da_args_t args;
231 int error;
232
233 memset((char *)&args, 0, sizeof(args));
234 args.dp = dir;
235 args.trans = trans;
236
237 ASSERT((dir->i_d.di_mode & S_IFMT) == S_IFDIR);
238 if ((error = xfs_dir_ino_validate(trans->t_mountp, parent_dir->i_ino)))
239 return error;
240
241 return(xfs_dir_shortform_create(&args, parent_dir->i_ino));
242}
243
244/*
245 * Generic handler routine to add a name to a directory.
246 * Transitions directory from shortform to Btree as necessary.
247 */
248static int /* error */
249xfs_dir_createname(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
250 int namelen, xfs_ino_t inum, xfs_fsblock_t *firstblock,
251 xfs_bmap_free_t *flist, xfs_extlen_t total)
252{
253 xfs_da_args_t args;
254 int retval, newsize, done;
255
256 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
257
258 if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
259 return (retval);
260
261 XFS_STATS_INC(xs_dir_create);
262 /*
263 * Fill in the arg structure for this request.
264 */
265 args.name = name;
266 args.namelen = namelen;
267 args.hashval = xfs_da_hashname(name, namelen);
268 args.inumber = inum;
269 args.dp = dp;
270 args.firstblock = firstblock;
271 args.flist = flist;
272 args.total = total;
273 args.whichfork = XFS_DATA_FORK;
274 args.trans = trans;
275 args.justcheck = 0;
276 args.addname = args.oknoent = 1;
277
278 /*
279 * Decide on what work routines to call based on the inode size.
280 */
281 done = 0;
282 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
283 newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
284 if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) {
285 retval = xfs_dir_shortform_addname(&args);
286 done = 1;
287 } else {
288 if (total == 0)
289 return XFS_ERROR(ENOSPC);
290 retval = xfs_dir_shortform_to_leaf(&args);
291 done = retval != 0;
292 }
293 }
294 if (!done && xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
295 retval = xfs_dir_leaf_addname(&args);
296 done = retval != ENOSPC;
297 if (!done) {
298 if (total == 0)
299 return XFS_ERROR(ENOSPC);
300 retval = xfs_dir_leaf_to_node(&args);
301 done = retval != 0;
302 }
303 }
304 if (!done) {
305 retval = xfs_dir_node_addname(&args);
306 }
307 return(retval);
308}
309
310/*
311 * Generic handler routine to check if a name can be added to a directory,
312 * without adding any blocks to the directory.
313 */
314static int /* error */
315xfs_dir_canenter(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen)
316{
317 xfs_da_args_t args;
318 int retval, newsize;
319
320 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
321 /*
322 * Fill in the arg structure for this request.
323 */
324 args.name = name;
325 args.namelen = namelen;
326 args.hashval = xfs_da_hashname(name, namelen);
327 args.inumber = 0;
328 args.dp = dp;
329 args.firstblock = NULL;
330 args.flist = NULL;
331 args.total = 0;
332 args.whichfork = XFS_DATA_FORK;
333 args.trans = trans;
334 args.justcheck = args.addname = args.oknoent = 1;
335
336 /*
337 * Decide on what work routines to call based on the inode size.
338 */
339 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
340 newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
341 if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp))
342 retval = 0;
343 else
344 retval = XFS_ERROR(ENOSPC);
345 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
346 retval = xfs_dir_leaf_addname(&args);
347 } else {
348 retval = xfs_dir_node_addname(&args);
349 }
350 return(retval);
351}
352
353/*
354 * Generic handler routine to remove a name from a directory.
355 * Transitions directory from Btree to shortform as necessary.
356 */
357static int /* error */
358xfs_dir_removename(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
359 int namelen, xfs_ino_t ino, xfs_fsblock_t *firstblock,
360 xfs_bmap_free_t *flist, xfs_extlen_t total)
361{
362 xfs_da_args_t args;
363 int count, totallen, newsize, retval;
364
365 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
366 XFS_STATS_INC(xs_dir_remove);
367 /*
368 * Fill in the arg structure for this request.
369 */
370 args.name = name;
371 args.namelen = namelen;
372 args.hashval = xfs_da_hashname(name, namelen);
373 args.inumber = ino;
374 args.dp = dp;
375 args.firstblock = firstblock;
376 args.flist = flist;
377 args.total = total;
378 args.whichfork = XFS_DATA_FORK;
379 args.trans = trans;
380 args.justcheck = args.addname = args.oknoent = 0;
381
382 /*
383 * Decide on what work routines to call based on the inode size.
384 */
385 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
386 retval = xfs_dir_shortform_removename(&args);
387 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
388 retval = xfs_dir_leaf_removename(&args, &count, &totallen);
389 if (retval == 0) {
390 newsize = XFS_DIR_SF_ALLFIT(count, totallen);
391 if (newsize <= XFS_IFORK_DSIZE(dp)) {
392 retval = xfs_dir_leaf_to_shortform(&args);
393 }
394 }
395 } else {
396 retval = xfs_dir_node_removename(&args);
397 }
398 return(retval);
399}
400
401static int /* error */
402xfs_dir_lookup(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
403 xfs_ino_t *inum)
404{
405 xfs_da_args_t args;
406 int retval;
407
408 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
409
410 XFS_STATS_INC(xs_dir_lookup);
411 /*
412 * Fill in the arg structure for this request.
413 */
414 args.name = name;
415 args.namelen = namelen;
416 args.hashval = xfs_da_hashname(name, namelen);
417 args.inumber = 0;
418 args.dp = dp;
419 args.firstblock = NULL;
420 args.flist = NULL;
421 args.total = 0;
422 args.whichfork = XFS_DATA_FORK;
423 args.trans = trans;
424 args.justcheck = args.addname = 0;
425 args.oknoent = 1;
426
427 /*
428 * Decide on what work routines to call based on the inode size.
429 */
430 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
431 retval = xfs_dir_shortform_lookup(&args);
432 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
433 retval = xfs_dir_leaf_lookup(&args);
434 } else {
435 retval = xfs_dir_node_lookup(&args);
436 }
437 if (retval == EEXIST)
438 retval = 0;
439 *inum = args.inumber;
440 return(retval);
441}
442
443/*
444 * Implement readdir.
445 */
446static int /* error */
447xfs_dir_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, int *eofp)
448{
449 xfs_dirent_t *dbp;
450 int alignment, retval;
451 xfs_dir_put_t put;
452
453 XFS_STATS_INC(xs_dir_getdents);
454 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
455
456 /*
457 * If our caller has given us a single contiguous memory buffer,
458 * just work directly within that buffer. If it's in user memory,
459 * lock it down first.
460 */
461 alignment = sizeof(xfs_off_t) - 1;
462 if ((uio->uio_iovcnt == 1) &&
463 (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
464 ((uio->uio_iov[0].iov_len & alignment) == 0)) {
465 dbp = NULL;
466 put = xfs_dir_put_dirent64_direct;
467 } else {
468 dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
469 put = xfs_dir_put_dirent64_uio;
470 }
471
472 /*
473 * Decide on what work routines to call based on the inode size.
474 */
475 *eofp = 0;
476
477 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
478 retval = xfs_dir_shortform_getdents(dp, uio, eofp, dbp, put);
479 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
480 retval = xfs_dir_leaf_getdents(trans, dp, uio, eofp, dbp, put);
481 } else {
482 retval = xfs_dir_node_getdents(trans, dp, uio, eofp, dbp, put);
483 }
484 if (dbp != NULL)
485 kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
486
487 return(retval);
488}
489
490static int /* error */
491xfs_dir_replace(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
492 xfs_ino_t inum, xfs_fsblock_t *firstblock,
493 xfs_bmap_free_t *flist, xfs_extlen_t total)
494{
495 xfs_da_args_t args;
496 int retval;
497
498 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
499
500 if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
501 return retval;
502
503 /*
504 * Fill in the arg structure for this request.
505 */
506 args.name = name;
507 args.namelen = namelen;
508 args.hashval = xfs_da_hashname(name, namelen);
509 args.inumber = inum;
510 args.dp = dp;
511 args.firstblock = firstblock;
512 args.flist = flist;
513 args.total = total;
514 args.whichfork = XFS_DATA_FORK;
515 args.trans = trans;
516 args.justcheck = args.addname = args.oknoent = 0;
517
518 /*
519 * Decide on what work routines to call based on the inode size.
520 */
521 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
522 retval = xfs_dir_shortform_replace(&args);
523 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
524 retval = xfs_dir_leaf_replace(&args);
525 } else {
526 retval = xfs_dir_node_replace(&args);
527 }
528
529 return(retval);
530}
531
532static int
533xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp)
534{
535 xfs_ino_t ino;
536 int namelen_sum;
537 int count;
538 xfs_dir_shortform_t *sf;
539 xfs_dir_sf_entry_t *sfe;
540 int i;
541
542
543
544 if ((INT_GET(dp->di_core.di_mode, ARCH_CONVERT) & S_IFMT) != S_IFDIR) {
545 return 0;
546 }
547 if (INT_GET(dp->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_LOCAL) {
548 return 0;
549 }
550 if (INT_GET(dp->di_core.di_size, ARCH_CONVERT) < sizeof(sf->hdr)) {
551 xfs_fs_cmn_err(CE_WARN, mp, "Invalid shortform size: dp 0x%p",
552 dp);
553 return 1;
554 }
555 sf = (xfs_dir_shortform_t *)(&dp->di_u.di_dirsf);
556 ino = XFS_GET_DIR_INO8(sf->hdr.parent);
557 if (xfs_dir_ino_validate(mp, ino))
558 return 1;
559
560 count = sf->hdr.count;
561 if ((count < 0) || ((count * 10) > XFS_LITINO(mp))) {
562 xfs_fs_cmn_err(CE_WARN, mp,
563 "Invalid shortform count: dp 0x%p", dp);
564 return(1);
565 }
566
567 if (count == 0) {
568 return 0;
569 }
570
571 namelen_sum = 0;
572 sfe = &sf->list[0];
573 for (i = sf->hdr.count - 1; i >= 0; i--) {
574 ino = XFS_GET_DIR_INO8(sfe->inumber);
575 xfs_dir_ino_validate(mp, ino);
576 if (sfe->namelen >= XFS_LITINO(mp)) {
577 xfs_fs_cmn_err(CE_WARN, mp,
578 "Invalid shortform namelen: dp 0x%p", dp);
579 return 1;
580 }
581 namelen_sum += sfe->namelen;
582 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
583 }
584 if (namelen_sum >= XFS_LITINO(mp)) {
585 xfs_fs_cmn_err(CE_WARN, mp,
586 "Invalid shortform namelen: dp 0x%p", dp);
587 return 1;
588 }
589
590 return 0;
591}
592
593/*========================================================================
594 * External routines when dirsize == XFS_LBSIZE(dp->i_mount).
595 *========================================================================*/
596
597/*
598 * Add a name to the leaf directory structure
599 * This is the external routine.
600 */
601int
602xfs_dir_leaf_addname(xfs_da_args_t *args)
603{
604 int index, retval;
605 xfs_dabuf_t *bp;
606
607 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
608 XFS_DATA_FORK);
609 if (retval)
610 return(retval);
611 ASSERT(bp != NULL);
612
613 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
614 if (retval == ENOENT)
615 retval = xfs_dir_leaf_add(bp, args, index);
616 xfs_da_buf_done(bp);
617 return(retval);
618}
619
620/*
621 * Remove a name from the leaf directory structure
622 * This is the external routine.
623 */
624STATIC int
625xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen)
626{
627 xfs_dir_leafblock_t *leaf;
628 int index, retval;
629 xfs_dabuf_t *bp;
630
631 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
632 XFS_DATA_FORK);
633 if (retval)
634 return(retval);
635 ASSERT(bp != NULL);
636 leaf = bp->data;
637 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
638 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
639 if (retval == EEXIST) {
640 (void)xfs_dir_leaf_remove(args->trans, bp, index);
641 *count = be16_to_cpu(leaf->hdr.count);
642 *totallen = be16_to_cpu(leaf->hdr.namebytes);
643 retval = 0;
644 }
645 xfs_da_buf_done(bp);
646 return(retval);
647}
648
649/*
650 * Look up a name in a leaf directory structure.
651 * This is the external routine.
652 */
653STATIC int
654xfs_dir_leaf_lookup(xfs_da_args_t *args)
655{
656 int index, retval;
657 xfs_dabuf_t *bp;
658
659 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
660 XFS_DATA_FORK);
661 if (retval)
662 return(retval);
663 ASSERT(bp != NULL);
664 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
665 xfs_da_brelse(args->trans, bp);
666 return(retval);
667}
668
669/*
670 * Copy out directory entries for getdents(), for leaf directories.
671 */
672STATIC int
673xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
674 int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
675{
676 xfs_dabuf_t *bp;
677 int retval, eob;
678
679 retval = xfs_da_read_buf(dp->i_transp, dp, 0, -1, &bp, XFS_DATA_FORK);
680 if (retval)
681 return(retval);
682 ASSERT(bp != NULL);
683 retval = xfs_dir_leaf_getdents_int(bp, dp, 0, uio, &eob, dbp, put, -1);
684 xfs_da_brelse(trans, bp);
685 *eofp = (eob == 0);
686 return(retval);
687}
688
689/*
690 * Look up a name in a leaf directory structure, replace the inode number.
691 * This is the external routine.
692 */
693STATIC int
694xfs_dir_leaf_replace(xfs_da_args_t *args)
695{
696 int index, retval;
697 xfs_dabuf_t *bp;
698 xfs_ino_t inum;
699 xfs_dir_leafblock_t *leaf;
700 xfs_dir_leaf_entry_t *entry;
701 xfs_dir_leaf_name_t *namest;
702
703 inum = args->inumber;
704 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
705 XFS_DATA_FORK);
706 if (retval)
707 return(retval);
708 ASSERT(bp != NULL);
709 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
710 if (retval == EEXIST) {
711 leaf = bp->data;
712 entry = &leaf->entries[index];
713 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx));
714 /* XXX - replace assert? */
715 XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
716 xfs_da_log_buf(args->trans, bp,
717 XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
718 xfs_da_buf_done(bp);
719 retval = 0;
720 } else
721 xfs_da_brelse(args->trans, bp);
722 return(retval);
723}
724
725
726/*========================================================================
727 * External routines when dirsize > XFS_LBSIZE(mp).
728 *========================================================================*/
729
730/*
731 * Add a name to a Btree-format directory.
732 *
733 * This will involve walking down the Btree, and may involve splitting
734 * leaf nodes and even splitting intermediate nodes up to and including
735 * the root node (a special case of an intermediate node).
736 */
737STATIC int
738xfs_dir_node_addname(xfs_da_args_t *args)
739{
740 xfs_da_state_t *state;
741 xfs_da_state_blk_t *blk;
742 int retval, error;
743
744 /*
745 * Fill in bucket of arguments/results/context to carry around.
746 */
747 state = xfs_da_state_alloc();
748 state->args = args;
749 state->mp = args->dp->i_mount;
750 state->blocksize = state->mp->m_sb.sb_blocksize;
751 state->node_ents = state->mp->m_dir_node_ents;
752
753 /*
754 * Search to see if name already exists, and get back a pointer
755 * to where it should go.
756 */
757 error = xfs_da_node_lookup_int(state, &retval);
758 if (error)
759 retval = error;
760 if (retval != ENOENT)
761 goto error;
762 blk = &state->path.blk[ state->path.active-1 ];
763 ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
764 retval = xfs_dir_leaf_add(blk->bp, args, blk->index);
765 if (retval == 0) {
766 /*
767 * Addition succeeded, update Btree hashvals.
768 */
769 if (!args->justcheck)
770 xfs_da_fixhashpath(state, &state->path);
771 } else {
772 /*
773 * Addition failed, split as many Btree elements as required.
774 */
775 if (args->total == 0) {
776 ASSERT(retval == ENOSPC);
777 goto error;
778 }
779 retval = xfs_da_split(state);
780 }
781error:
782 xfs_da_state_free(state);
783
784 return(retval);
785}
786
787/*
788 * Remove a name from a B-tree directory.
789 *
790 * This will involve walking down the Btree, and may involve joining
791 * leaf nodes and even joining intermediate nodes up to and including
792 * the root node (a special case of an intermediate node).
793 */
794STATIC int
795xfs_dir_node_removename(xfs_da_args_t *args)
796{
797 xfs_da_state_t *state;
798 xfs_da_state_blk_t *blk;
799 int retval, error;
800
801 state = xfs_da_state_alloc();
802 state->args = args;
803 state->mp = args->dp->i_mount;
804 state->blocksize = state->mp->m_sb.sb_blocksize;
805 state->node_ents = state->mp->m_dir_node_ents;
806
807 /*
808 * Search to see if name exists, and get back a pointer to it.
809 */
810 error = xfs_da_node_lookup_int(state, &retval);
811 if (error)
812 retval = error;
813 if (retval != EEXIST) {
814 xfs_da_state_free(state);
815 return(retval);
816 }
817
818 /*
819 * Remove the name and update the hashvals in the tree.
820 */
821 blk = &state->path.blk[ state->path.active-1 ];
822 ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
823 retval = xfs_dir_leaf_remove(args->trans, blk->bp, blk->index);
824 xfs_da_fixhashpath(state, &state->path);
825
826 /*
827 * Check to see if the tree needs to be collapsed.
828 */
829 error = 0;
830 if (retval) {
831 error = xfs_da_join(state);
832 }
833
834 xfs_da_state_free(state);
835 if (error)
836 return(error);
837 return(0);
838}
839
840/*
841 * Look up a filename in a int directory.
842 * Use an internal routine to actually do all the work.
843 */
844STATIC int
845xfs_dir_node_lookup(xfs_da_args_t *args)
846{
847 xfs_da_state_t *state;
848 int retval, error, i;
849
850 state = xfs_da_state_alloc();
851 state->args = args;
852 state->mp = args->dp->i_mount;
853 state->blocksize = state->mp->m_sb.sb_blocksize;
854 state->node_ents = state->mp->m_dir_node_ents;
855
856 /*
857 * Search to see if name exists,
858 * and get back a pointer to it.
859 */
860 error = xfs_da_node_lookup_int(state, &retval);
861 if (error) {
862 retval = error;
863 }
864
865 /*
866 * If not in a transaction, we have to release all the buffers.
867 */
868 for (i = 0; i < state->path.active; i++) {
869 xfs_da_brelse(args->trans, state->path.blk[i].bp);
870 state->path.blk[i].bp = NULL;
871 }
872
873 xfs_da_state_free(state);
874 return(retval);
875}
876
877STATIC int
878xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
879 int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
880{
881 xfs_da_intnode_t *node;
882 xfs_da_node_entry_t *btree;
883 xfs_dir_leafblock_t *leaf = NULL;
884 xfs_dablk_t bno, nextbno;
885 xfs_dahash_t cookhash;
886 xfs_mount_t *mp;
887 int error, eob, i;
888 xfs_dabuf_t *bp;
889 xfs_daddr_t nextda;
890
891 /*
892 * Pick up our context.
893 */
894 mp = dp->i_mount;
895 bp = NULL;
896 bno = XFS_DA_COOKIE_BNO(mp, uio->uio_offset);
897 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
898
899 xfs_dir_trace_g_du("node: start", dp, uio);
900
901 /*
902 * Re-find our place, even if we're confused about what our place is.
903 *
904 * First we check the block number from the magic cookie, it is a
905 * cache of where we ended last time. If we find a leaf block, and
906 * the starting hashval in that block is less than our desired
907 * hashval, then we run with it.
908 */
909 if (bno > 0) {
910 error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK);
911 if ((error != 0) && (error != EFSCORRUPTED))
912 return(error);
913 if (bp)
914 leaf = bp->data;
915 if (bp && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
916 xfs_dir_trace_g_dub("node: block not a leaf",
917 dp, uio, bno);
918 xfs_da_brelse(trans, bp);
919 bp = NULL;
920 }
921 if (bp && be32_to_cpu(leaf->entries[0].hashval) > cookhash) {
922 xfs_dir_trace_g_dub("node: leaf hash too large",
923 dp, uio, bno);
924 xfs_da_brelse(trans, bp);
925 bp = NULL;
926 }
927 if (bp && cookhash > be32_to_cpu(leaf->entries[
928 be16_to_cpu(leaf->hdr.count) - 1].hashval)) {
929 xfs_dir_trace_g_dub("node: leaf hash too small",
930 dp, uio, bno);
931 xfs_da_brelse(trans, bp);
932 bp = NULL;
933 }
934 }
935
936 /*
937 * If we did not find a leaf block from the blockno in the cookie,
938 * or we there was no blockno in the cookie (eg: first time thru),
939 * the we start at the top of the Btree and re-find our hashval.
940 */
941 if (bp == NULL) {
942 xfs_dir_trace_g_du("node: start at root" , dp, uio);
943 bno = 0;
944 for (;;) {
945 error = xfs_da_read_buf(trans, dp, bno, -1, &bp,
946 XFS_DATA_FORK);
947 if (error)
948 return(error);
949 if (bp == NULL)
950 return(XFS_ERROR(EFSCORRUPTED));
951 node = bp->data;
952 if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC)
953 break;
954 btree = &node->btree[0];
955 xfs_dir_trace_g_dun("node: node detail", dp, uio, node);
956 for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) {
957 if (be32_to_cpu(btree->hashval) >= cookhash) {
958 bno = be32_to_cpu(btree->before);
959 break;
960 }
961 }
962 if (i == be16_to_cpu(node->hdr.count)) {
963 xfs_da_brelse(trans, bp);
964 xfs_dir_trace_g_du("node: hash beyond EOF",
965 dp, uio);
966 uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0,
967 XFS_DA_MAXHASH);
968 *eofp = 1;
969 return(0);
970 }
971 xfs_dir_trace_g_dub("node: going to block",
972 dp, uio, bno);
973 xfs_da_brelse(trans, bp);
974 }
975 }
976 ASSERT(cookhash != XFS_DA_MAXHASH);
977
978 /*
979 * We've dropped down to the (first) leaf block that contains the
980 * hashval we are interested in. Continue rolling upward thru the
981 * leaf blocks until we fill up our buffer.
982 */
983 for (;;) {
984 leaf = bp->data;
985 if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC)) {
986 xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf);
987 xfs_da_brelse(trans, bp);
988 XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)",
989 XFS_ERRLEVEL_LOW, mp, leaf);
990 return XFS_ERROR(EFSCORRUPTED);
991 }
992 xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf);
993 if ((nextbno = be32_to_cpu(leaf->hdr.info.forw))) {
994 nextda = xfs_da_reada_buf(trans, dp, nextbno,
995 XFS_DATA_FORK);
996 } else
997 nextda = -1;
998 error = xfs_dir_leaf_getdents_int(bp, dp, bno, uio, &eob, dbp,
999 put, nextda);
1000 xfs_da_brelse(trans, bp);
1001 bno = nextbno;
1002 if (eob) {
1003 xfs_dir_trace_g_dub("node: E-O-B", dp, uio, bno);
1004 *eofp = 0;
1005 return(error);
1006 }
1007 if (bno == 0)
1008 break;
1009 error = xfs_da_read_buf(trans, dp, bno, nextda, &bp,
1010 XFS_DATA_FORK);
1011 if (error)
1012 return(error);
1013 if (unlikely(bp == NULL)) {
1014 XFS_ERROR_REPORT("xfs_dir_node_getdents(2)",
1015 XFS_ERRLEVEL_LOW, mp);
1016 return(XFS_ERROR(EFSCORRUPTED));
1017 }
1018 }
1019 *eofp = 1;
1020 xfs_dir_trace_g_du("node: E-O-F", dp, uio);
1021 return(0);
1022}
1023
1024/*
1025 * Look up a filename in an int directory, replace the inode number.
1026 * Use an internal routine to actually do the lookup.
1027 */
1028STATIC int
1029xfs_dir_node_replace(xfs_da_args_t *args)
1030{
1031 xfs_da_state_t *state;
1032 xfs_da_state_blk_t *blk;
1033 xfs_dir_leafblock_t *leaf;
1034 xfs_dir_leaf_entry_t *entry;
1035 xfs_dir_leaf_name_t *namest;
1036 xfs_ino_t inum;
1037 int retval, error, i;
1038 xfs_dabuf_t *bp;
1039
1040 state = xfs_da_state_alloc();
1041 state->args = args;
1042 state->mp = args->dp->i_mount;
1043 state->blocksize = state->mp->m_sb.sb_blocksize;
1044 state->node_ents = state->mp->m_dir_node_ents;
1045 inum = args->inumber;
1046
1047 /*
1048 * Search to see if name exists,
1049 * and get back a pointer to it.
1050 */
1051 error = xfs_da_node_lookup_int(state, &retval);
1052 if (error) {
1053 retval = error;
1054 }
1055
1056 if (retval == EEXIST) {
1057 blk = &state->path.blk[state->path.active - 1];
1058 ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
1059 bp = blk->bp;
1060 leaf = bp->data;
1061 entry = &leaf->entries[blk->index];
1062 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx));
1063 /* XXX - replace assert ? */
1064 XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
1065 xfs_da_log_buf(args->trans, bp,
1066 XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
1067 xfs_da_buf_done(bp);
1068 blk->bp = NULL;
1069 retval = 0;
1070 } else {
1071 i = state->path.active - 1;
1072 xfs_da_brelse(args->trans, state->path.blk[i].bp);
1073 state->path.blk[i].bp = NULL;
1074 }
1075 for (i = 0; i < state->path.active - 1; i++) {
1076 xfs_da_brelse(args->trans, state->path.blk[i].bp);
1077 state->path.blk[i].bp = NULL;
1078 }
1079
1080 xfs_da_state_free(state);
1081 return(retval);
1082}
1083
1084#if defined(XFS_DIR_TRACE)
1085/*
1086 * Add a trace buffer entry for an inode and a uio.
1087 */
1088void
1089xfs_dir_trace_g_du(char *where, xfs_inode_t *dp, uio_t *uio)
1090{
1091 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DU, where,
1092 (void *)dp, (void *)dp->i_mount,
1093 (void *)((unsigned long)(uio->uio_offset >> 32)),
1094 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1095 (void *)(unsigned long)uio->uio_resid,
1096 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1097}
1098
1099/*
1100 * Add a trace buffer entry for an inode and a uio.
1101 */
1102void
1103xfs_dir_trace_g_dub(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dablk_t bno)
1104{
1105 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUB, where,
1106 (void *)dp, (void *)dp->i_mount,
1107 (void *)((unsigned long)(uio->uio_offset >> 32)),
1108 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1109 (void *)(unsigned long)uio->uio_resid,
1110 (void *)(unsigned long)bno,
1111 NULL, NULL, NULL, NULL, NULL, NULL);
1112}
1113
1114/*
1115 * Add a trace buffer entry for an inode and a uio.
1116 */
1117void
1118xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio,
1119 xfs_da_intnode_t *node)
1120{
1121 int last = be16_to_cpu(node->hdr.count) - 1;
1122
1123 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where,
1124 (void *)dp, (void *)dp->i_mount,
1125 (void *)((unsigned long)(uio->uio_offset >> 32)),
1126 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1127 (void *)(unsigned long)uio->uio_resid,
1128 (void *)(unsigned long)be32_to_cpu(node->hdr.info.forw),
1129 (void *)(unsigned long)
1130 be16_to_cpu(node->hdr.count),
1131 (void *)(unsigned long)
1132 be32_to_cpu(node->btree[0].hashval),
1133 (void *)(unsigned long)
1134 be32_to_cpu(node->btree[last].hashval),
1135 NULL, NULL, NULL);
1136}
1137
1138/*
1139 * Add a trace buffer entry for an inode and a uio.
1140 */
1141void
1142xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio,
1143 xfs_dir_leafblock_t *leaf)
1144{
1145 int last = be16_to_cpu(leaf->hdr.count) - 1;
1146
1147 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where,
1148 (void *)dp, (void *)dp->i_mount,
1149 (void *)((unsigned long)(uio->uio_offset >> 32)),
1150 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1151 (void *)(unsigned long)uio->uio_resid,
1152 (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw),
1153 (void *)(unsigned long)be16_to_cpu(leaf->hdr.count),
1154 (void *)(unsigned long)be32_to_cpu(leaf->entries[0].hashval),
1155 (void *)(unsigned long)be32_to_cpu(leaf->entries[last].hashval),
1156 NULL, NULL, NULL);
1157}
1158
1159/*
1160 * Add a trace buffer entry for an inode and a uio.
1161 */
1162void
1163xfs_dir_trace_g_due(char *where, xfs_inode_t *dp, uio_t *uio,
1164 xfs_dir_leaf_entry_t *entry)
1165{
1166 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUE, where,
1167 (void *)dp, (void *)dp->i_mount,
1168 (void *)((unsigned long)(uio->uio_offset >> 32)),
1169 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1170 (void *)(unsigned long)uio->uio_resid,
1171 (void *)(unsigned long)be32_to_cpu(entry->hashval),
1172 NULL, NULL, NULL, NULL, NULL, NULL);
1173}
1174
1175/*
1176 * Add a trace buffer entry for an inode and a uio.
1177 */
1178void
1179xfs_dir_trace_g_duc(char *where, xfs_inode_t *dp, uio_t *uio, xfs_off_t cookie)
1180{
1181 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUC, where,
1182 (void *)dp, (void *)dp->i_mount,
1183 (void *)((unsigned long)(uio->uio_offset >> 32)),
1184 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1185 (void *)(unsigned long)uio->uio_resid,
1186 (void *)((unsigned long)(cookie >> 32)),
1187 (void *)((unsigned long)(cookie & 0xFFFFFFFF)),
1188 NULL, NULL, NULL, NULL, NULL);
1189}
1190
1191/*
1192 * Add a trace buffer entry for the arguments given to the routine,
1193 * generic form.
1194 */
1195void
1196xfs_dir_trace_enter(int type, char *where,
1197 void * a0, void * a1,
1198 void * a2, void * a3,
1199 void * a4, void * a5,
1200 void * a6, void * a7,
1201 void * a8, void * a9,
1202 void * a10, void * a11)
1203{
1204 ASSERT(xfs_dir_trace_buf);
1205 ktrace_enter(xfs_dir_trace_buf, (void *)(unsigned long)type,
1206 (void *)where,
1207 (void *)a0, (void *)a1, (void *)a2,
1208 (void *)a3, (void *)a4, (void *)a5,
1209 (void *)a6, (void *)a7, (void *)a8,
1210 (void *)a9, (void *)a10, (void *)a11,
1211 NULL, NULL);
1212}
1213#endif /* XFS_DIR_TRACE */
diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h
index 8cc8afb9f6c0..e69de29bb2d1 100644
--- a/fs/xfs/xfs_dir.h
+++ b/fs/xfs/xfs_dir.h
@@ -1,142 +0,0 @@
1/*
2 * Copyright (c) 2000,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef __XFS_DIR_H__
19#define __XFS_DIR_H__
20
21/*
22 * Large directories are structured around Btrees where all the data
23 * elements are in the leaf nodes. Filenames are hashed into an int,
24 * then that int is used as the index into the Btree. Since the hashval
25 * of a filename may not be unique, we may have duplicate keys. The
26 * internal links in the Btree are logical block offsets into the file.
27 *
28 * Small directories use a different format and are packed as tightly
29 * as possible so as to fit into the literal area of the inode.
30 */
31
32/*========================================================================
33 * Function prototypes for the kernel.
34 *========================================================================*/
35
36struct uio;
37struct xfs_bmap_free;
38struct xfs_da_args;
39struct xfs_dinode;
40struct xfs_inode;
41struct xfs_mount;
42struct xfs_trans;
43
44/*
45 * Directory function types.
46 * Put in structures (xfs_dirops_t) for v1 and v2 directories.
47 */
48typedef void (*xfs_dir_mount_t)(struct xfs_mount *mp);
49typedef int (*xfs_dir_isempty_t)(struct xfs_inode *dp);
50typedef int (*xfs_dir_init_t)(struct xfs_trans *tp,
51 struct xfs_inode *dp,
52 struct xfs_inode *pdp);
53typedef int (*xfs_dir_createname_t)(struct xfs_trans *tp,
54 struct xfs_inode *dp,
55 char *name,
56 int namelen,
57 xfs_ino_t inum,
58 xfs_fsblock_t *first,
59 struct xfs_bmap_free *flist,
60 xfs_extlen_t total);
61typedef int (*xfs_dir_lookup_t)(struct xfs_trans *tp,
62 struct xfs_inode *dp,
63 char *name,
64 int namelen,
65 xfs_ino_t *inum);
66typedef int (*xfs_dir_removename_t)(struct xfs_trans *tp,
67 struct xfs_inode *dp,
68 char *name,
69 int namelen,
70 xfs_ino_t ino,
71 xfs_fsblock_t *first,
72 struct xfs_bmap_free *flist,
73 xfs_extlen_t total);
74typedef int (*xfs_dir_getdents_t)(struct xfs_trans *tp,
75 struct xfs_inode *dp,
76 struct uio *uio,
77 int *eofp);
78typedef int (*xfs_dir_replace_t)(struct xfs_trans *tp,
79 struct xfs_inode *dp,
80 char *name,
81 int namelen,
82 xfs_ino_t inum,
83 xfs_fsblock_t *first,
84 struct xfs_bmap_free *flist,
85 xfs_extlen_t total);
86typedef int (*xfs_dir_canenter_t)(struct xfs_trans *tp,
87 struct xfs_inode *dp,
88 char *name,
89 int namelen);
90typedef int (*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp,
91 struct xfs_dinode *dip);
92typedef int (*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args);
93
94typedef struct xfs_dirops {
95 xfs_dir_mount_t xd_mount;
96 xfs_dir_isempty_t xd_isempty;
97 xfs_dir_init_t xd_init;
98 xfs_dir_createname_t xd_createname;
99 xfs_dir_lookup_t xd_lookup;
100 xfs_dir_removename_t xd_removename;
101 xfs_dir_getdents_t xd_getdents;
102 xfs_dir_replace_t xd_replace;
103 xfs_dir_canenter_t xd_canenter;
104 xfs_dir_shortform_validate_ondisk_t xd_shortform_validate_ondisk;
105 xfs_dir_shortform_to_single_t xd_shortform_to_single;
106} xfs_dirops_t;
107
108/*
109 * Overall external interface routines.
110 */
111void xfs_dir_startup(void); /* called exactly once */
112
113#define XFS_DIR_MOUNT(mp) \
114 ((mp)->m_dirops.xd_mount(mp))
115#define XFS_DIR_ISEMPTY(mp,dp) \
116 ((mp)->m_dirops.xd_isempty(dp))
117#define XFS_DIR_INIT(mp,tp,dp,pdp) \
118 ((mp)->m_dirops.xd_init(tp,dp,pdp))
119#define XFS_DIR_CREATENAME(mp,tp,dp,name,namelen,inum,first,flist,total) \
120 ((mp)->m_dirops.xd_createname(tp,dp,name,namelen,inum,first,flist,\
121 total))
122#define XFS_DIR_LOOKUP(mp,tp,dp,name,namelen,inum) \
123 ((mp)->m_dirops.xd_lookup(tp,dp,name,namelen,inum))
124#define XFS_DIR_REMOVENAME(mp,tp,dp,name,namelen,ino,first,flist,total) \
125 ((mp)->m_dirops.xd_removename(tp,dp,name,namelen,ino,first,flist,total))
126#define XFS_DIR_GETDENTS(mp,tp,dp,uio,eofp) \
127 ((mp)->m_dirops.xd_getdents(tp,dp,uio,eofp))
128#define XFS_DIR_REPLACE(mp,tp,dp,name,namelen,inum,first,flist,total) \
129 ((mp)->m_dirops.xd_replace(tp,dp,name,namelen,inum,first,flist,total))
130#define XFS_DIR_CANENTER(mp,tp,dp,name,namelen) \
131 ((mp)->m_dirops.xd_canenter(tp,dp,name,namelen))
132#define XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp,dip) \
133 ((mp)->m_dirops.xd_shortform_validate_ondisk(mp,dip))
134#define XFS_DIR_SHORTFORM_TO_SINGLE(mp,args) \
135 ((mp)->m_dirops.xd_shortform_to_single(args))
136
137#define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1)
138#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2)
139extern xfs_dirops_t xfsv1_dirops;
140extern xfs_dirops_t xfsv2_dirops;
141
142#endif /* __XFS_DIR_H__ */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 80238a2263fa..8edbe1adb95b 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -24,21 +24,18 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
38#include "xfs_inode.h" 36#include "xfs_inode.h"
39#include "xfs_inode_item.h" 37#include "xfs_inode_item.h"
40#include "xfs_bmap.h" 38#include "xfs_bmap.h"
41#include "xfs_dir_leaf.h"
42#include "xfs_dir2_data.h" 39#include "xfs_dir2_data.h"
43#include "xfs_dir2_leaf.h" 40#include "xfs_dir2_leaf.h"
44#include "xfs_dir2_block.h" 41#include "xfs_dir2_block.h"
@@ -46,69 +43,14 @@
46#include "xfs_dir2_trace.h" 43#include "xfs_dir2_trace.h"
47#include "xfs_error.h" 44#include "xfs_error.h"
48 45
49/*
50 * Declarations for interface routines.
51 */
52static void xfs_dir2_mount(xfs_mount_t *mp);
53static int xfs_dir2_isempty(xfs_inode_t *dp);
54static int xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp,
55 xfs_inode_t *pdp);
56static int xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp,
57 char *name, int namelen, xfs_ino_t inum,
58 xfs_fsblock_t *first,
59 xfs_bmap_free_t *flist, xfs_extlen_t total);
60static int xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
61 int namelen, xfs_ino_t *inum);
62static int xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp,
63 char *name, int namelen, xfs_ino_t ino,
64 xfs_fsblock_t *first,
65 xfs_bmap_free_t *flist, xfs_extlen_t total);
66static int xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio,
67 int *eofp);
68static int xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
69 int namelen, xfs_ino_t inum,
70 xfs_fsblock_t *first, xfs_bmap_free_t *flist,
71 xfs_extlen_t total);
72static int xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
73 int namelen);
74static int xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp,
75 xfs_dinode_t *dip);
76
77/*
78 * Utility routine declarations.
79 */
80static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); 46static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
81static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); 47static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
82 48
83/* 49void
84 * Directory operations vector. 50xfs_dir_mount(
85 */ 51 xfs_mount_t *mp)
86xfs_dirops_t xfsv2_dirops = {
87 .xd_mount = xfs_dir2_mount,
88 .xd_isempty = xfs_dir2_isempty,
89 .xd_init = xfs_dir2_init,
90 .xd_createname = xfs_dir2_createname,
91 .xd_lookup = xfs_dir2_lookup,
92 .xd_removename = xfs_dir2_removename,
93 .xd_getdents = xfs_dir2_getdents,
94 .xd_replace = xfs_dir2_replace,
95 .xd_canenter = xfs_dir2_canenter,
96 .xd_shortform_validate_ondisk = xfs_dir2_shortform_validate_ondisk,
97 .xd_shortform_to_single = xfs_dir2_sf_to_block,
98};
99
100/*
101 * Interface routines.
102 */
103
104/*
105 * Initialize directory-related fields in the mount structure.
106 */
107static void
108xfs_dir2_mount(
109 xfs_mount_t *mp) /* filesystem mount point */
110{ 52{
111 mp->m_dirversion = 2; 53 ASSERT(XFS_SB_VERSION_HASDIRV2(&mp->m_sb));
112 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= 54 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
113 XFS_MAX_BLOCKSIZE); 55 XFS_MAX_BLOCKSIZE);
114 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); 56 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
@@ -128,19 +70,15 @@ xfs_dir2_mount(
128/* 70/*
129 * Return 1 if directory contains only "." and "..". 71 * Return 1 if directory contains only "." and "..".
130 */ 72 */
131static int /* return code */ 73int
132xfs_dir2_isempty( 74xfs_dir_isempty(
133 xfs_inode_t *dp) /* incore inode structure */ 75 xfs_inode_t *dp)
134{ 76{
135 xfs_dir2_sf_t *sfp; /* shortform directory structure */ 77 xfs_dir2_sf_t *sfp;
136 78
137 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 79 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
138 /* 80 if (dp->i_d.di_size == 0) /* might happen during shutdown. */
139 * Might happen during shutdown.
140 */
141 if (dp->i_d.di_size == 0) {
142 return 1; 81 return 1;
143 }
144 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 82 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
145 return 0; 83 return 0;
146 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; 84 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
@@ -148,53 +86,83 @@ xfs_dir2_isempty(
148} 86}
149 87
150/* 88/*
89 * Validate a given inode number.
90 */
91int
92xfs_dir_ino_validate(
93 xfs_mount_t *mp,
94 xfs_ino_t ino)
95{
96 xfs_agblock_t agblkno;
97 xfs_agino_t agino;
98 xfs_agnumber_t agno;
99 int ino_ok;
100 int ioff;
101
102 agno = XFS_INO_TO_AGNO(mp, ino);
103 agblkno = XFS_INO_TO_AGBNO(mp, ino);
104 ioff = XFS_INO_TO_OFFSET(mp, ino);
105 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
106 ino_ok =
107 agno < mp->m_sb.sb_agcount &&
108 agblkno < mp->m_sb.sb_agblocks &&
109 agblkno != 0 &&
110 ioff < (1 << mp->m_sb.sb_inopblog) &&
111 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
112 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
113 XFS_RANDOM_DIR_INO_VALIDATE))) {
114 xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
115 (unsigned long long) ino);
116 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
117 return XFS_ERROR(EFSCORRUPTED);
118 }
119 return 0;
120}
121
122/*
151 * Initialize a directory with its "." and ".." entries. 123 * Initialize a directory with its "." and ".." entries.
152 */ 124 */
153static int /* error */ 125int
154xfs_dir2_init( 126xfs_dir_init(
155 xfs_trans_t *tp, /* transaction pointer */ 127 xfs_trans_t *tp,
156 xfs_inode_t *dp, /* incore directory inode */ 128 xfs_inode_t *dp,
157 xfs_inode_t *pdp) /* incore parent directory inode */ 129 xfs_inode_t *pdp)
158{ 130{
159 xfs_da_args_t args; /* operation arguments */ 131 xfs_da_args_t args;
160 int error; /* error return value */ 132 int error;
161 133
162 memset((char *)&args, 0, sizeof(args)); 134 memset((char *)&args, 0, sizeof(args));
163 args.dp = dp; 135 args.dp = dp;
164 args.trans = tp; 136 args.trans = tp;
165 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 137 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
166 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) { 138 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
167 return error; 139 return error;
168 }
169 return xfs_dir2_sf_create(&args, pdp->i_ino); 140 return xfs_dir2_sf_create(&args, pdp->i_ino);
170} 141}
171 142
172/* 143/*
173 Enter a name in a directory. 144 Enter a name in a directory.
174 */ 145 */
175static int /* error */ 146int
176xfs_dir2_createname( 147xfs_dir_createname(
177 xfs_trans_t *tp, /* transaction pointer */ 148 xfs_trans_t *tp,
178 xfs_inode_t *dp, /* incore directory inode */ 149 xfs_inode_t *dp,
179 char *name, /* new entry name */ 150 char *name,
180 int namelen, /* new entry name length */ 151 int namelen,
181 xfs_ino_t inum, /* new entry inode number */ 152 xfs_ino_t inum, /* new entry inode number */
182 xfs_fsblock_t *first, /* bmap's firstblock */ 153 xfs_fsblock_t *first, /* bmap's firstblock */
183 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 154 xfs_bmap_free_t *flist, /* bmap's freeblock list */
184 xfs_extlen_t total) /* bmap's total block count */ 155 xfs_extlen_t total) /* bmap's total block count */
185{ 156{
186 xfs_da_args_t args; /* operation arguments */ 157 xfs_da_args_t args;
187 int rval; /* return value */ 158 int rval;
188 int v; /* type-checking value */ 159 int v; /* type-checking value */
189 160
190 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 161 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
191 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { 162 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
192 return rval; 163 return rval;
193 }
194 XFS_STATS_INC(xs_dir_create); 164 XFS_STATS_INC(xs_dir_create);
195 /* 165
196 * Fill in the arg structure for this request.
197 */
198 args.name = name; 166 args.name = name;
199 args.namelen = namelen; 167 args.namelen = namelen;
200 args.hashval = xfs_da_hashname(name, namelen); 168 args.hashval = xfs_da_hashname(name, namelen);
@@ -207,18 +175,16 @@ xfs_dir2_createname(
207 args.trans = tp; 175 args.trans = tp;
208 args.justcheck = 0; 176 args.justcheck = 0;
209 args.addname = args.oknoent = 1; 177 args.addname = args.oknoent = 1;
210 /* 178
211 * Decide on what work routines to call based on the inode size.
212 */
213 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 179 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
214 rval = xfs_dir2_sf_addname(&args); 180 rval = xfs_dir2_sf_addname(&args);
215 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 181 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
216 return rval; 182 return rval;
217 } else if (v) 183 else if (v)
218 rval = xfs_dir2_block_addname(&args); 184 rval = xfs_dir2_block_addname(&args);
219 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 185 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
220 return rval; 186 return rval;
221 } else if (v) 187 else if (v)
222 rval = xfs_dir2_leaf_addname(&args); 188 rval = xfs_dir2_leaf_addname(&args);
223 else 189 else
224 rval = xfs_dir2_node_addname(&args); 190 rval = xfs_dir2_node_addname(&args);
@@ -228,24 +194,21 @@ xfs_dir2_createname(
228/* 194/*
229 * Lookup a name in a directory, give back the inode number. 195 * Lookup a name in a directory, give back the inode number.
230 */ 196 */
231static int /* error */ 197int
232xfs_dir2_lookup( 198xfs_dir_lookup(
233 xfs_trans_t *tp, /* transaction pointer */ 199 xfs_trans_t *tp,
234 xfs_inode_t *dp, /* incore directory inode */ 200 xfs_inode_t *dp,
235 char *name, /* lookup name */ 201 char *name,
236 int namelen, /* lookup name length */ 202 int namelen,
237 xfs_ino_t *inum) /* out: inode number */ 203 xfs_ino_t *inum) /* out: inode number */
238{ 204{
239 xfs_da_args_t args; /* operation arguments */ 205 xfs_da_args_t args;
240 int rval; /* return value */ 206 int rval;
241 int v; /* type-checking value */ 207 int v; /* type-checking value */
242 208
243 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 209 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
244 XFS_STATS_INC(xs_dir_lookup); 210 XFS_STATS_INC(xs_dir_lookup);
245 211
246 /*
247 * Fill in the arg structure for this request.
248 */
249 args.name = name; 212 args.name = name;
250 args.namelen = namelen; 213 args.namelen = namelen;
251 args.hashval = xfs_da_hashname(name, namelen); 214 args.hashval = xfs_da_hashname(name, namelen);
@@ -258,18 +221,16 @@ xfs_dir2_lookup(
258 args.trans = tp; 221 args.trans = tp;
259 args.justcheck = args.addname = 0; 222 args.justcheck = args.addname = 0;
260 args.oknoent = 1; 223 args.oknoent = 1;
261 /* 224
262 * Decide on what work routines to call based on the inode size.
263 */
264 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 225 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
265 rval = xfs_dir2_sf_lookup(&args); 226 rval = xfs_dir2_sf_lookup(&args);
266 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 227 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
267 return rval; 228 return rval;
268 } else if (v) 229 else if (v)
269 rval = xfs_dir2_block_lookup(&args); 230 rval = xfs_dir2_block_lookup(&args);
270 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 231 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
271 return rval; 232 return rval;
272 } else if (v) 233 else if (v)
273 rval = xfs_dir2_leaf_lookup(&args); 234 rval = xfs_dir2_leaf_lookup(&args);
274 else 235 else
275 rval = xfs_dir2_node_lookup(&args); 236 rval = xfs_dir2_node_lookup(&args);
@@ -283,26 +244,24 @@ xfs_dir2_lookup(
283/* 244/*
284 * Remove an entry from a directory. 245 * Remove an entry from a directory.
285 */ 246 */
286static int /* error */ 247int
287xfs_dir2_removename( 248xfs_dir_removename(
288 xfs_trans_t *tp, /* transaction pointer */ 249 xfs_trans_t *tp,
289 xfs_inode_t *dp, /* incore directory inode */ 250 xfs_inode_t *dp,
290 char *name, /* name of entry to remove */ 251 char *name,
291 int namelen, /* name length of entry to remove */ 252 int namelen,
292 xfs_ino_t ino, /* inode number of entry to remove */ 253 xfs_ino_t ino,
293 xfs_fsblock_t *first, /* bmap's firstblock */ 254 xfs_fsblock_t *first, /* bmap's firstblock */
294 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 255 xfs_bmap_free_t *flist, /* bmap's freeblock list */
295 xfs_extlen_t total) /* bmap's total block count */ 256 xfs_extlen_t total) /* bmap's total block count */
296{ 257{
297 xfs_da_args_t args; /* operation arguments */ 258 xfs_da_args_t args;
298 int rval; /* return value */ 259 int rval;
299 int v; /* type-checking value */ 260 int v; /* type-checking value */
300 261
301 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 262 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
302 XFS_STATS_INC(xs_dir_remove); 263 XFS_STATS_INC(xs_dir_remove);
303 /* 264
304 * Fill in the arg structure for this request.
305 */
306 args.name = name; 265 args.name = name;
307 args.namelen = namelen; 266 args.namelen = namelen;
308 args.hashval = xfs_da_hashname(name, namelen); 267 args.hashval = xfs_da_hashname(name, namelen);
@@ -314,18 +273,16 @@ xfs_dir2_removename(
314 args.whichfork = XFS_DATA_FORK; 273 args.whichfork = XFS_DATA_FORK;
315 args.trans = tp; 274 args.trans = tp;
316 args.justcheck = args.addname = args.oknoent = 0; 275 args.justcheck = args.addname = args.oknoent = 0;
317 /* 276
318 * Decide on what work routines to call based on the inode size.
319 */
320 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 277 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
321 rval = xfs_dir2_sf_removename(&args); 278 rval = xfs_dir2_sf_removename(&args);
322 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 279 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
323 return rval; 280 return rval;
324 } else if (v) 281 else if (v)
325 rval = xfs_dir2_block_removename(&args); 282 rval = xfs_dir2_block_removename(&args);
326 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 283 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
327 return rval; 284 return rval;
328 } else if (v) 285 else if (v)
329 rval = xfs_dir2_leaf_removename(&args); 286 rval = xfs_dir2_leaf_removename(&args);
330 else 287 else
331 rval = xfs_dir2_node_removename(&args); 288 rval = xfs_dir2_node_removename(&args);
@@ -335,10 +292,10 @@ xfs_dir2_removename(
335/* 292/*
336 * Read a directory. 293 * Read a directory.
337 */ 294 */
338static int /* error */ 295int
339xfs_dir2_getdents( 296xfs_dir_getdents(
340 xfs_trans_t *tp, /* transaction pointer */ 297 xfs_trans_t *tp,
341 xfs_inode_t *dp, /* incore directory inode */ 298 xfs_inode_t *dp,
342 uio_t *uio, /* caller's buffer control */ 299 uio_t *uio, /* caller's buffer control */
343 int *eofp) /* out: eof reached */ 300 int *eofp) /* out: eof reached */
344{ 301{
@@ -367,14 +324,11 @@ xfs_dir2_getdents(
367 } 324 }
368 325
369 *eofp = 0; 326 *eofp = 0;
370 /*
371 * Decide on what work routines to call based on the inode size.
372 */
373 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 327 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
374 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); 328 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
375 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 329 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
376 ; 330 ;
377 } else if (v) 331 else if (v)
378 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); 332 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
379 else 333 else
380 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); 334 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
@@ -386,29 +340,26 @@ xfs_dir2_getdents(
386/* 340/*
387 * Replace the inode number of a directory entry. 341 * Replace the inode number of a directory entry.
388 */ 342 */
389static int /* error */ 343int
390xfs_dir2_replace( 344xfs_dir_replace(
391 xfs_trans_t *tp, /* transaction pointer */ 345 xfs_trans_t *tp,
392 xfs_inode_t *dp, /* incore directory inode */ 346 xfs_inode_t *dp,
393 char *name, /* name of entry to replace */ 347 char *name, /* name of entry to replace */
394 int namelen, /* name length of entry to replace */ 348 int namelen,
395 xfs_ino_t inum, /* new inode number */ 349 xfs_ino_t inum, /* new inode number */
396 xfs_fsblock_t *first, /* bmap's firstblock */ 350 xfs_fsblock_t *first, /* bmap's firstblock */
397 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 351 xfs_bmap_free_t *flist, /* bmap's freeblock list */
398 xfs_extlen_t total) /* bmap's total block count */ 352 xfs_extlen_t total) /* bmap's total block count */
399{ 353{
400 xfs_da_args_t args; /* operation arguments */ 354 xfs_da_args_t args;
401 int rval; /* return value */ 355 int rval;
402 int v; /* type-checking value */ 356 int v; /* type-checking value */
403 357
404 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 358 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
405 359
406 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { 360 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
407 return rval; 361 return rval;
408 } 362
409 /*
410 * Fill in the arg structure for this request.
411 */
412 args.name = name; 363 args.name = name;
413 args.namelen = namelen; 364 args.namelen = namelen;
414 args.hashval = xfs_da_hashname(name, namelen); 365 args.hashval = xfs_da_hashname(name, namelen);
@@ -420,18 +371,16 @@ xfs_dir2_replace(
420 args.whichfork = XFS_DATA_FORK; 371 args.whichfork = XFS_DATA_FORK;
421 args.trans = tp; 372 args.trans = tp;
422 args.justcheck = args.addname = args.oknoent = 0; 373 args.justcheck = args.addname = args.oknoent = 0;
423 /* 374
424 * Decide on what work routines to call based on the inode size.
425 */
426 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 375 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
427 rval = xfs_dir2_sf_replace(&args); 376 rval = xfs_dir2_sf_replace(&args);
428 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 377 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
429 return rval; 378 return rval;
430 } else if (v) 379 else if (v)
431 rval = xfs_dir2_block_replace(&args); 380 rval = xfs_dir2_block_replace(&args);
432 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 381 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
433 return rval; 382 return rval;
434 } else if (v) 383 else if (v)
435 rval = xfs_dir2_leaf_replace(&args); 384 rval = xfs_dir2_leaf_replace(&args);
436 else 385 else
437 rval = xfs_dir2_node_replace(&args); 386 rval = xfs_dir2_node_replace(&args);
@@ -441,21 +390,19 @@ xfs_dir2_replace(
441/* 390/*
442 * See if this entry can be added to the directory without allocating space. 391 * See if this entry can be added to the directory without allocating space.
443 */ 392 */
444static int /* error */ 393int
445xfs_dir2_canenter( 394xfs_dir_canenter(
446 xfs_trans_t *tp, /* transaction pointer */ 395 xfs_trans_t *tp,
447 xfs_inode_t *dp, /* incore directory inode */ 396 xfs_inode_t *dp,
448 char *name, /* name of entry to add */ 397 char *name, /* name of entry to add */
449 int namelen) /* name length of entry to add */ 398 int namelen)
450{ 399{
451 xfs_da_args_t args; /* operation arguments */ 400 xfs_da_args_t args;
452 int rval; /* return value */ 401 int rval;
453 int v; /* type-checking value */ 402 int v; /* type-checking value */
454 403
455 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 404 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
456 /* 405
457 * Fill in the arg structure for this request.
458 */
459 args.name = name; 406 args.name = name;
460 args.namelen = namelen; 407 args.namelen = namelen;
461 args.hashval = xfs_da_hashname(name, namelen); 408 args.hashval = xfs_da_hashname(name, namelen);
@@ -467,18 +414,16 @@ xfs_dir2_canenter(
467 args.whichfork = XFS_DATA_FORK; 414 args.whichfork = XFS_DATA_FORK;
468 args.trans = tp; 415 args.trans = tp;
469 args.justcheck = args.addname = args.oknoent = 1; 416 args.justcheck = args.addname = args.oknoent = 1;
470 /* 417
471 * Decide on what work routines to call based on the inode size.
472 */
473 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 418 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
474 rval = xfs_dir2_sf_addname(&args); 419 rval = xfs_dir2_sf_addname(&args);
475 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 420 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
476 return rval; 421 return rval;
477 } else if (v) 422 else if (v)
478 rval = xfs_dir2_block_addname(&args); 423 rval = xfs_dir2_block_addname(&args);
479 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 424 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
480 return rval; 425 return rval;
481 } else if (v) 426 else if (v)
482 rval = xfs_dir2_leaf_addname(&args); 427 rval = xfs_dir2_leaf_addname(&args);
483 else 428 else
484 rval = xfs_dir2_node_addname(&args); 429 rval = xfs_dir2_node_addname(&args);
@@ -486,19 +431,6 @@ xfs_dir2_canenter(
486} 431}
487 432
488/* 433/*
489 * Dummy routine for shortform inode validation.
490 * Can't really do this.
491 */
492/* ARGSUSED */
493static int /* error */
494xfs_dir2_shortform_validate_ondisk(
495 xfs_mount_t *mp, /* filesystem mount point */
496 xfs_dinode_t *dip) /* ondisk inode */
497{
498 return 0;
499}
500
501/*
502 * Utility routines. 434 * Utility routines.
503 */ 435 */
504 436
@@ -507,24 +439,24 @@ xfs_dir2_shortform_validate_ondisk(
507 * This routine is for data and free blocks, not leaf/node blocks 439 * This routine is for data and free blocks, not leaf/node blocks
508 * which are handled by xfs_da_grow_inode. 440 * which are handled by xfs_da_grow_inode.
509 */ 441 */
510int /* error */ 442int
511xfs_dir2_grow_inode( 443xfs_dir2_grow_inode(
512 xfs_da_args_t *args, /* operation arguments */ 444 xfs_da_args_t *args,
513 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 445 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
514 xfs_dir2_db_t *dbp) /* out: block number added */ 446 xfs_dir2_db_t *dbp) /* out: block number added */
515{ 447{
516 xfs_fileoff_t bno; /* directory offset of new block */ 448 xfs_fileoff_t bno; /* directory offset of new block */
517 int count; /* count of filesystem blocks */ 449 int count; /* count of filesystem blocks */
518 xfs_inode_t *dp; /* incore directory inode */ 450 xfs_inode_t *dp; /* incore directory inode */
519 int error; /* error return value */ 451 int error;
520 int got; /* blocks actually mapped */ 452 int got; /* blocks actually mapped */
521 int i; /* temp mapping index */ 453 int i;
522 xfs_bmbt_irec_t map; /* single structure for bmap */ 454 xfs_bmbt_irec_t map; /* single structure for bmap */
523 int mapi; /* mapping index */ 455 int mapi; /* mapping index */
524 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ 456 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */
525 xfs_mount_t *mp; /* filesystem mount point */ 457 xfs_mount_t *mp;
526 int nmap; /* number of bmap entries */ 458 int nmap; /* number of bmap entries */
527 xfs_trans_t *tp; /* transaction pointer */ 459 xfs_trans_t *tp;
528 460
529 xfs_dir2_trace_args_s("grow_inode", args, space); 461 xfs_dir2_trace_args_s("grow_inode", args, space);
530 dp = args->dp; 462 dp = args->dp;
@@ -538,9 +470,8 @@ xfs_dir2_grow_inode(
538 /* 470 /*
539 * Find the first hole for our block. 471 * Find the first hole for our block.
540 */ 472 */
541 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) { 473 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
542 return error; 474 return error;
543 }
544 nmap = 1; 475 nmap = 1;
545 ASSERT(args->firstblock != NULL); 476 ASSERT(args->firstblock != NULL);
546 /* 477 /*
@@ -549,13 +480,9 @@ xfs_dir2_grow_inode(
549 if ((error = xfs_bmapi(tp, dp, bno, count, 480 if ((error = xfs_bmapi(tp, dp, bno, count,
550 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, 481 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
551 args->firstblock, args->total, &map, &nmap, 482 args->firstblock, args->total, &map, &nmap,
552 args->flist, NULL))) { 483 args->flist, NULL)))
553 return error; 484 return error;
554 }
555 ASSERT(nmap <= 1); 485 ASSERT(nmap <= 1);
556 /*
557 * Got it in 1.
558 */
559 if (nmap == 1) { 486 if (nmap == 1) {
560 mapp = &map; 487 mapp = &map;
561 mapi = 1; 488 mapi = 1;
@@ -646,20 +573,19 @@ xfs_dir2_grow_inode(
646/* 573/*
647 * See if the directory is a single-block form directory. 574 * See if the directory is a single-block form directory.
648 */ 575 */
649int /* error */ 576int
650xfs_dir2_isblock( 577xfs_dir2_isblock(
651 xfs_trans_t *tp, /* transaction pointer */ 578 xfs_trans_t *tp,
652 xfs_inode_t *dp, /* incore directory inode */ 579 xfs_inode_t *dp,
653 int *vp) /* out: 1 is block, 0 is not block */ 580 int *vp) /* out: 1 is block, 0 is not block */
654{ 581{
655 xfs_fileoff_t last; /* last file offset */ 582 xfs_fileoff_t last; /* last file offset */
656 xfs_mount_t *mp; /* filesystem mount point */ 583 xfs_mount_t *mp;
657 int rval; /* return value */ 584 int rval;
658 585
659 mp = dp->i_mount; 586 mp = dp->i_mount;
660 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { 587 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
661 return rval; 588 return rval;
662 }
663 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; 589 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
664 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); 590 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
665 *vp = rval; 591 *vp = rval;
@@ -669,20 +595,19 @@ xfs_dir2_isblock(
669/* 595/*
670 * See if the directory is a single-leaf form directory. 596 * See if the directory is a single-leaf form directory.
671 */ 597 */
672int /* error */ 598int
673xfs_dir2_isleaf( 599xfs_dir2_isleaf(
674 xfs_trans_t *tp, /* transaction pointer */ 600 xfs_trans_t *tp,
675 xfs_inode_t *dp, /* incore directory inode */ 601 xfs_inode_t *dp,
676 int *vp) /* out: 1 is leaf, 0 is not leaf */ 602 int *vp) /* out: 1 is leaf, 0 is not leaf */
677{ 603{
678 xfs_fileoff_t last; /* last file offset */ 604 xfs_fileoff_t last; /* last file offset */
679 xfs_mount_t *mp; /* filesystem mount point */ 605 xfs_mount_t *mp;
680 int rval; /* return value */ 606 int rval;
681 607
682 mp = dp->i_mount; 608 mp = dp->i_mount;
683 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { 609 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
684 return rval; 610 return rval;
685 }
686 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); 611 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
687 return 0; 612 return 0;
688} 613}
@@ -690,9 +615,9 @@ xfs_dir2_isleaf(
690/* 615/*
691 * Getdents put routine for 64-bit ABI, direct form. 616 * Getdents put routine for 64-bit ABI, direct form.
692 */ 617 */
693static int /* error */ 618static int
694xfs_dir2_put_dirent64_direct( 619xfs_dir2_put_dirent64_direct(
695 xfs_dir2_put_args_t *pa) /* argument bundle */ 620 xfs_dir2_put_args_t *pa)
696{ 621{
697 xfs_dirent_t *idbp; /* dirent pointer */ 622 xfs_dirent_t *idbp; /* dirent pointer */
698 iovec_t *iovp; /* io vector */ 623 iovec_t *iovp; /* io vector */
@@ -727,9 +652,9 @@ xfs_dir2_put_dirent64_direct(
727/* 652/*
728 * Getdents put routine for 64-bit ABI, uio form. 653 * Getdents put routine for 64-bit ABI, uio form.
729 */ 654 */
730static int /* error */ 655static int
731xfs_dir2_put_dirent64_uio( 656xfs_dir2_put_dirent64_uio(
732 xfs_dir2_put_args_t *pa) /* argument bundle */ 657 xfs_dir2_put_args_t *pa)
733{ 658{
734 xfs_dirent_t *idbp; /* dirent pointer */ 659 xfs_dirent_t *idbp; /* dirent pointer */
735 int namelen; /* entry name length */ 660 int namelen; /* entry name length */
@@ -765,17 +690,17 @@ xfs_dir2_put_dirent64_uio(
765 */ 690 */
766int 691int
767xfs_dir2_shrink_inode( 692xfs_dir2_shrink_inode(
768 xfs_da_args_t *args, /* operation arguments */ 693 xfs_da_args_t *args,
769 xfs_dir2_db_t db, /* directory block number */ 694 xfs_dir2_db_t db,
770 xfs_dabuf_t *bp) /* block's buffer */ 695 xfs_dabuf_t *bp)
771{ 696{
772 xfs_fileoff_t bno; /* directory file offset */ 697 xfs_fileoff_t bno; /* directory file offset */
773 xfs_dablk_t da; /* directory file offset */ 698 xfs_dablk_t da; /* directory file offset */
774 int done; /* bunmap is finished */ 699 int done; /* bunmap is finished */
775 xfs_inode_t *dp; /* incore directory inode */ 700 xfs_inode_t *dp;
776 int error; /* error return value */ 701 int error;
777 xfs_mount_t *mp; /* filesystem mount point */ 702 xfs_mount_t *mp;
778 xfs_trans_t *tp; /* transaction pointer */ 703 xfs_trans_t *tp;
779 704
780 xfs_dir2_trace_args_db("shrink_inode", args, db, bp); 705 xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
781 dp = args->dp; 706 dp = args->dp;
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 7dd364b1e038..86560b6f794c 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -22,7 +22,9 @@ struct uio;
22struct xfs_dabuf; 22struct xfs_dabuf;
23struct xfs_da_args; 23struct xfs_da_args;
24struct xfs_dir2_put_args; 24struct xfs_dir2_put_args;
25struct xfs_bmap_free;
25struct xfs_inode; 26struct xfs_inode;
27struct xfs_mount;
26struct xfs_trans; 28struct xfs_trans;
27 29
28/* 30/*
@@ -73,7 +75,35 @@ typedef struct xfs_dir2_put_args {
73} xfs_dir2_put_args_t; 75} xfs_dir2_put_args_t;
74 76
75/* 77/*
76 * Other interfaces used by the rest of the dir v2 code. 78 * Generic directory interface routines
79 */
80extern void xfs_dir_startup(void);
81extern void xfs_dir_mount(struct xfs_mount *mp);
82extern int xfs_dir_isempty(struct xfs_inode *dp);
83extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
84 struct xfs_inode *pdp);
85extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
86 char *name, int namelen, xfs_ino_t inum,
87 xfs_fsblock_t *first,
88 struct xfs_bmap_free *flist, xfs_extlen_t tot);
89extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
90 char *name, int namelen, xfs_ino_t *inum);
91extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
92 char *name, int namelen, xfs_ino_t ino,
93 xfs_fsblock_t *first,
94 struct xfs_bmap_free *flist, xfs_extlen_t tot);
95extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
96 uio_t *uio, int *eofp);
97extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
98 char *name, int namelen, xfs_ino_t inum,
99 xfs_fsblock_t *first,
100 struct xfs_bmap_free *flist, xfs_extlen_t tot);
101extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
102 char *name, int namelen);
103extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
104
105/*
106 * Utility routines for v2 directories.
77 */ 107 */
78extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, 108extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
79 xfs_dir2_db_t *dbp); 109 xfs_dir2_db_t *dbp);
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 2621ff521dbd..9d7438bba30d 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -22,19 +22,16 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.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_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
35#include "xfs_inode.h" 33#include "xfs_inode.h"
36#include "xfs_inode_item.h" 34#include "xfs_inode_item.h"
37#include "xfs_dir_leaf.h"
38#include "xfs_dir2_data.h" 35#include "xfs_dir2_data.h"
39#include "xfs_dir2_leaf.h" 36#include "xfs_dir2_leaf.h"
40#include "xfs_dir2_block.h" 37#include "xfs_dir2_block.h"
@@ -51,6 +48,18 @@ static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **bpp,
51 int *entno); 48 int *entno);
52static int xfs_dir2_block_sort(const void *a, const void *b); 49static int xfs_dir2_block_sort(const void *a, const void *b);
53 50
51static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
52
53/*
54 * One-time startup routine called from xfs_init().
55 */
56void
57xfs_dir_startup(void)
58{
59 xfs_dir_hash_dot = xfs_da_hashname(".", 1);
60 xfs_dir_hash_dotdot = xfs_da_hashname("..", 2);
61}
62
54/* 63/*
55 * Add an entry to a block directory. 64 * Add an entry to a block directory.
56 */ 65 */
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 7be37d38961f..f7c799217072 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -22,18 +22,15 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.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_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
35#include "xfs_inode.h" 33#include "xfs_inode.h"
36#include "xfs_dir_leaf.h"
37#include "xfs_dir2_data.h" 34#include "xfs_dir2_data.h"
38#include "xfs_dir2_leaf.h" 35#include "xfs_dir2_leaf.h"
39#include "xfs_dir2_block.h" 36#include "xfs_dir2_block.h"
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 74ef99f2ee5f..b1cf1fbf423d 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_attr_sf.h" 32#include "xfs_attr_sf.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_dinode.h" 34#include "xfs_dinode.h"
37#include "xfs_inode.h" 35#include "xfs_inode.h"
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index b1f85cc7795a..9ca71719b683 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -22,13 +22,11 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.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_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 06afa1b324cf..0cd77b17bf92 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -22,19 +22,16 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.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_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
35#include "xfs_inode.h" 33#include "xfs_inode.h"
36#include "xfs_inode_item.h" 34#include "xfs_inode_item.h"
37#include "xfs_dir_leaf.h"
38#include "xfs_error.h" 35#include "xfs_error.h"
39#include "xfs_dir2_data.h" 36#include "xfs_dir2_data.h"
40#include "xfs_dir2_leaf.h" 37#include "xfs_dir2_leaf.h"
diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c
index c626943b4112..f3fb2ffd6f5c 100644
--- a/fs/xfs/xfs_dir2_trace.c
+++ b/fs/xfs/xfs_dir2_trace.c
@@ -19,11 +19,9 @@
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_types.h"
21#include "xfs_inum.h" 21#include "xfs_inum.h"
22#include "xfs_dir.h"
23#include "xfs_dir2.h" 22#include "xfs_dir2.h"
24#include "xfs_da_btree.h" 23#include "xfs_da_btree.h"
25#include "xfs_bmap_btree.h" 24#include "xfs_bmap_btree.h"
26#include "xfs_dir_sf.h"
27#include "xfs_dir2_sf.h" 25#include "xfs_dir2_sf.h"
28#include "xfs_attr_sf.h" 26#include "xfs_attr_sf.h"
29#include "xfs_dinode.h" 27#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index e7121040cd9d..e69de29bb2d1 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -1,2230 +0,0 @@
1/*
2 * Copyright (c) 2000-2003,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_types.h"
21#include "xfs_log.h"
22#include "xfs_inum.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h"
27#include "xfs_dmapi.h"
28#include "xfs_mount.h"
29#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_dir_sf.h"
34#include "xfs_dir2_sf.h"
35#include "xfs_attr_sf.h"
36#include "xfs_dinode.h"
37#include "xfs_inode.h"
38#include "xfs_inode_item.h"
39#include "xfs_alloc.h"
40#include "xfs_btree.h"
41#include "xfs_bmap.h"
42#include "xfs_dir_leaf.h"
43#include "xfs_error.h"
44
45/*
46 * xfs_dir_leaf.c
47 *
48 * Routines to implement leaf blocks of directories as Btrees of hashed names.
49 */
50
51/*========================================================================
52 * Function prototypes for the kernel.
53 *========================================================================*/
54
55/*
56 * Routines used for growing the Btree.
57 */
58STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
59 int insertion_index,
60 int freemap_index);
61STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer,
62 int musthave, int justcheck);
63STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state,
64 xfs_da_state_blk_t *blk1,
65 xfs_da_state_blk_t *blk2);
66STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
67 xfs_da_state_blk_t *leaf_blk_1,
68 xfs_da_state_blk_t *leaf_blk_2,
69 int *number_entries_in_blk1,
70 int *number_namebytes_in_blk1);
71
72STATIC int xfs_dir_leaf_create(struct xfs_da_args *args,
73 xfs_dablk_t which_block,
74 struct xfs_dabuf **bpp);
75
76/*
77 * Utility routines.
78 */
79STATIC void xfs_dir_leaf_moveents(xfs_dir_leafblock_t *src_leaf,
80 int src_start,
81 xfs_dir_leafblock_t *dst_leaf,
82 int dst_start, int move_count,
83 xfs_mount_t *mp);
84
85
86/*========================================================================
87 * External routines when dirsize < XFS_IFORK_DSIZE(dp).
88 *========================================================================*/
89
90
91/*
92 * Validate a given inode number.
93 */
94int
95xfs_dir_ino_validate(xfs_mount_t *mp, xfs_ino_t ino)
96{
97 xfs_agblock_t agblkno;
98 xfs_agino_t agino;
99 xfs_agnumber_t agno;
100 int ino_ok;
101 int ioff;
102
103 agno = XFS_INO_TO_AGNO(mp, ino);
104 agblkno = XFS_INO_TO_AGBNO(mp, ino);
105 ioff = XFS_INO_TO_OFFSET(mp, ino);
106 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
107 ino_ok =
108 agno < mp->m_sb.sb_agcount &&
109 agblkno < mp->m_sb.sb_agblocks &&
110 agblkno != 0 &&
111 ioff < (1 << mp->m_sb.sb_inopblog) &&
112 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
113 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
114 XFS_RANDOM_DIR_INO_VALIDATE))) {
115 xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
116 (unsigned long long) ino);
117 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
118 return XFS_ERROR(EFSCORRUPTED);
119 }
120 return 0;
121}
122
123/*
124 * Create the initial contents of a shortform directory.
125 */
126int
127xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent)
128{
129 xfs_dir_sf_hdr_t *hdr;
130 xfs_inode_t *dp;
131
132 dp = args->dp;
133 ASSERT(dp != NULL);
134 ASSERT(dp->i_d.di_size == 0);
135 if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
136 dp->i_df.if_flags &= ~XFS_IFEXTENTS; /* just in case */
137 dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
138 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
139 dp->i_df.if_flags |= XFS_IFINLINE;
140 }
141 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
142 ASSERT(dp->i_df.if_bytes == 0);
143 xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK);
144 hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
145 XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent);
146
147 hdr->count = 0;
148 dp->i_d.di_size = sizeof(*hdr);
149 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
150 return 0;
151}
152
153/*
154 * Add a name to the shortform directory structure.
155 * Overflow from the inode has already been checked for.
156 */
157int
158xfs_dir_shortform_addname(xfs_da_args_t *args)
159{
160 xfs_dir_shortform_t *sf;
161 xfs_dir_sf_entry_t *sfe;
162 int i, offset, size;
163 xfs_inode_t *dp;
164
165 dp = args->dp;
166 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
167 /*
168 * Catch the case where the conversion from shortform to leaf
169 * failed part way through.
170 */
171 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
172 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
173 return XFS_ERROR(EIO);
174 }
175 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
176 ASSERT(dp->i_df.if_u1.if_data != NULL);
177 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
178 sfe = &sf->list[0];
179 for (i = sf->hdr.count-1; i >= 0; i--) {
180 if (sfe->namelen == args->namelen &&
181 args->name[0] == sfe->name[0] &&
182 memcmp(args->name, sfe->name, args->namelen) == 0)
183 return XFS_ERROR(EEXIST);
184 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
185 }
186
187 offset = (int)((char *)sfe - (char *)sf);
188 size = XFS_DIR_SF_ENTSIZE_BYNAME(args->namelen);
189 xfs_idata_realloc(dp, size, XFS_DATA_FORK);
190 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
191 sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset);
192
193 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
194 sfe->namelen = args->namelen;
195 memcpy(sfe->name, args->name, sfe->namelen);
196 sf->hdr.count++;
197
198 dp->i_d.di_size += size;
199 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
200
201 return 0;
202}
203
204/*
205 * Remove a name from the shortform directory structure.
206 */
207int
208xfs_dir_shortform_removename(xfs_da_args_t *args)
209{
210 xfs_dir_shortform_t *sf;
211 xfs_dir_sf_entry_t *sfe;
212 int base, size = 0, i;
213 xfs_inode_t *dp;
214
215 dp = args->dp;
216 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
217 /*
218 * Catch the case where the conversion from shortform to leaf
219 * failed part way through.
220 */
221 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
222 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
223 return XFS_ERROR(EIO);
224 }
225 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
226 ASSERT(dp->i_df.if_u1.if_data != NULL);
227 base = sizeof(xfs_dir_sf_hdr_t);
228 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
229 sfe = &sf->list[0];
230 for (i = sf->hdr.count-1; i >= 0; i--) {
231 size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe);
232 if (sfe->namelen == args->namelen &&
233 sfe->name[0] == args->name[0] &&
234 memcmp(sfe->name, args->name, args->namelen) == 0)
235 break;
236 base += size;
237 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
238 }
239 if (i < 0) {
240 ASSERT(args->oknoent);
241 return XFS_ERROR(ENOENT);
242 }
243
244 if ((base + size) != dp->i_d.di_size) {
245 memmove(&((char *)sf)[base], &((char *)sf)[base+size],
246 dp->i_d.di_size - (base+size));
247 }
248 sf->hdr.count--;
249
250 xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
251 dp->i_d.di_size -= size;
252 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
253
254 return 0;
255}
256
257/*
258 * Look up a name in a shortform directory structure.
259 */
260int
261xfs_dir_shortform_lookup(xfs_da_args_t *args)
262{
263 xfs_dir_shortform_t *sf;
264 xfs_dir_sf_entry_t *sfe;
265 int i;
266 xfs_inode_t *dp;
267
268 dp = args->dp;
269 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
270 /*
271 * Catch the case where the conversion from shortform to leaf
272 * failed part way through.
273 */
274 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
275 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
276 return XFS_ERROR(EIO);
277 }
278 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
279 ASSERT(dp->i_df.if_u1.if_data != NULL);
280 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
281 if (args->namelen == 2 &&
282 args->name[0] == '.' && args->name[1] == '.') {
283 XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber);
284 return(XFS_ERROR(EEXIST));
285 }
286 if (args->namelen == 1 && args->name[0] == '.') {
287 args->inumber = dp->i_ino;
288 return(XFS_ERROR(EEXIST));
289 }
290 sfe = &sf->list[0];
291 for (i = sf->hdr.count-1; i >= 0; i--) {
292 if (sfe->namelen == args->namelen &&
293 sfe->name[0] == args->name[0] &&
294 memcmp(args->name, sfe->name, args->namelen) == 0) {
295 XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber);
296 return(XFS_ERROR(EEXIST));
297 }
298 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
299 }
300 ASSERT(args->oknoent);
301 return(XFS_ERROR(ENOENT));
302}
303
304/*
305 * Convert from using the shortform to the leaf.
306 */
307int
308xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs)
309{
310 xfs_inode_t *dp;
311 xfs_dir_shortform_t *sf;
312 xfs_dir_sf_entry_t *sfe;
313 xfs_da_args_t args;
314 xfs_ino_t inumber;
315 char *tmpbuffer;
316 int retval, i, size;
317 xfs_dablk_t blkno;
318 xfs_dabuf_t *bp;
319
320 dp = iargs->dp;
321 /*
322 * Catch the case where the conversion from shortform to leaf
323 * failed part way through.
324 */
325 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
326 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
327 return XFS_ERROR(EIO);
328 }
329 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
330 ASSERT(dp->i_df.if_u1.if_data != NULL);
331 size = dp->i_df.if_bytes;
332 tmpbuffer = kmem_alloc(size, KM_SLEEP);
333 ASSERT(tmpbuffer != NULL);
334
335 memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size);
336
337 sf = (xfs_dir_shortform_t *)tmpbuffer;
338 XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber);
339
340 xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
341 dp->i_d.di_size = 0;
342 xfs_trans_log_inode(iargs->trans, dp, XFS_ILOG_CORE);
343 retval = xfs_da_grow_inode(iargs, &blkno);
344 if (retval)
345 goto out;
346
347 ASSERT(blkno == 0);
348 retval = xfs_dir_leaf_create(iargs, blkno, &bp);
349 if (retval)
350 goto out;
351 xfs_da_buf_done(bp);
352
353 args.name = ".";
354 args.namelen = 1;
355 args.hashval = xfs_dir_hash_dot;
356 args.inumber = dp->i_ino;
357 args.dp = dp;
358 args.firstblock = iargs->firstblock;
359 args.flist = iargs->flist;
360 args.total = iargs->total;
361 args.whichfork = XFS_DATA_FORK;
362 args.trans = iargs->trans;
363 args.justcheck = 0;
364 args.addname = args.oknoent = 1;
365 retval = xfs_dir_leaf_addname(&args);
366 if (retval)
367 goto out;
368
369 args.name = "..";
370 args.namelen = 2;
371 args.hashval = xfs_dir_hash_dotdot;
372 args.inumber = inumber;
373 retval = xfs_dir_leaf_addname(&args);
374 if (retval)
375 goto out;
376
377 sfe = &sf->list[0];
378 for (i = 0; i < sf->hdr.count; i++) {
379 args.name = (char *)(sfe->name);
380 args.namelen = sfe->namelen;
381 args.hashval = xfs_da_hashname((char *)(sfe->name),
382 sfe->namelen);
383 XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber);
384 retval = xfs_dir_leaf_addname(&args);
385 if (retval)
386 goto out;
387 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
388 }
389 retval = 0;
390
391out:
392 kmem_free(tmpbuffer, size);
393 return retval;
394}
395
396STATIC int
397xfs_dir_shortform_compare(const void *a, const void *b)
398{
399 xfs_dir_sf_sort_t *sa, *sb;
400
401 sa = (xfs_dir_sf_sort_t *)a;
402 sb = (xfs_dir_sf_sort_t *)b;
403 if (sa->hash < sb->hash)
404 return -1;
405 else if (sa->hash > sb->hash)
406 return 1;
407 else
408 return sa->entno - sb->entno;
409}
410
411/*
412 * Copy out directory entries for getdents(), for shortform directories.
413 */
414/*ARGSUSED*/
415int
416xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
417 xfs_dirent_t *dbp, xfs_dir_put_t put)
418{
419 xfs_dir_shortform_t *sf;
420 xfs_dir_sf_entry_t *sfe;
421 int retval, i, sbsize, nsbuf, lastresid=0, want_entno;
422 xfs_mount_t *mp;
423 xfs_dahash_t cookhash, hash;
424 xfs_dir_put_args_t p;
425 xfs_dir_sf_sort_t *sbuf, *sbp;
426
427 mp = dp->i_mount;
428 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
429 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
430 want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
431 nsbuf = sf->hdr.count + 2;
432 sbsize = (nsbuf + 1) * sizeof(*sbuf);
433 sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP);
434
435 xfs_dir_trace_g_du("sf: start", dp, uio);
436
437 /*
438 * Collect all the entries into the buffer.
439 * Entry 0 is .
440 */
441 sbp->entno = 0;
442 sbp->seqno = 0;
443 sbp->hash = xfs_dir_hash_dot;
444 sbp->ino = dp->i_ino;
445 sbp->name = ".";
446 sbp->namelen = 1;
447 sbp++;
448
449 /*
450 * Entry 1 is ..
451 */
452 sbp->entno = 1;
453 sbp->seqno = 0;
454 sbp->hash = xfs_dir_hash_dotdot;
455 sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent);
456 sbp->name = "..";
457 sbp->namelen = 2;
458 sbp++;
459
460 /*
461 * Scan the directory data for the rest of the entries.
462 */
463 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
464
465 if (unlikely(
466 ((char *)sfe < (char *)sf) ||
467 ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)))) {
468 xfs_dir_trace_g_du("sf: corrupted", dp, uio);
469 XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents",
470 XFS_ERRLEVEL_LOW, mp, sfe);
471 kmem_free(sbuf, sbsize);
472 return XFS_ERROR(EFSCORRUPTED);
473 }
474
475 sbp->entno = i + 2;
476 sbp->seqno = 0;
477 sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen);
478 sbp->ino = XFS_GET_DIR_INO8(sfe->inumber);
479 sbp->name = (char *)sfe->name;
480 sbp->namelen = sfe->namelen;
481 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
482 sbp++;
483 }
484
485 /*
486 * Sort the entries on hash then entno.
487 */
488 xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_dir_shortform_compare);
489 /*
490 * Stuff in last entry.
491 */
492 sbp->entno = nsbuf;
493 sbp->hash = XFS_DA_MAXHASH;
494 sbp->seqno = 0;
495 /*
496 * Figure out the sequence numbers in case there's a hash duplicate.
497 */
498 for (hash = sbuf->hash, sbp = sbuf + 1;
499 sbp < &sbuf[nsbuf + 1]; sbp++) {
500 if (sbp->hash == hash)
501 sbp->seqno = sbp[-1].seqno + 1;
502 else
503 hash = sbp->hash;
504 }
505
506 /*
507 * Set up put routine.
508 */
509 p.dbp = dbp;
510 p.put = put;
511 p.uio = uio;
512
513 /*
514 * Find our place.
515 */
516 for (sbp = sbuf; sbp < &sbuf[nsbuf + 1]; sbp++) {
517 if (sbp->hash > cookhash ||
518 (sbp->hash == cookhash && sbp->seqno >= want_entno))
519 break;
520 }
521
522 /*
523 * Did we fail to find anything? We stop at the last entry,
524 * the one we put maxhash into.
525 */
526 if (sbp == &sbuf[nsbuf]) {
527 kmem_free(sbuf, sbsize);
528 xfs_dir_trace_g_du("sf: hash beyond end", dp, uio);
529 uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
530 *eofp = 1;
531 return 0;
532 }
533
534 /*
535 * Loop putting entries into the user buffer.
536 */
537 while (sbp < &sbuf[nsbuf]) {
538 /*
539 * Save the first resid in a run of equal-hashval entries
540 * so that we can back them out if they don't all fit.
541 */
542 if (sbp->seqno == 0 || sbp == sbuf)
543 lastresid = uio->uio_resid;
544 XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash);
545 p.ino = sbp->ino;
546#if XFS_BIG_INUMS
547 p.ino += mp->m_inoadd;
548#endif
549 p.name = sbp->name;
550 p.namelen = sbp->namelen;
551 retval = p.put(&p);
552 if (!p.done) {
553 uio->uio_offset =
554 XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash);
555 kmem_free(sbuf, sbsize);
556 uio->uio_resid = lastresid;
557 xfs_dir_trace_g_du("sf: E-O-B", dp, uio);
558 return retval;
559 }
560 sbp++;
561 }
562 kmem_free(sbuf, sbsize);
563 uio->uio_offset = p.cook.o;
564 *eofp = 1;
565 xfs_dir_trace_g_du("sf: E-O-F", dp, uio);
566 return 0;
567}
568
569/*
570 * Look up a name in a shortform directory structure, replace the inode number.
571 */
572int
573xfs_dir_shortform_replace(xfs_da_args_t *args)
574{
575 xfs_dir_shortform_t *sf;
576 xfs_dir_sf_entry_t *sfe;
577 xfs_inode_t *dp;
578 int i;
579
580 dp = args->dp;
581 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
582 /*
583 * Catch the case where the conversion from shortform to leaf
584 * failed part way through.
585 */
586 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
587 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
588 return XFS_ERROR(EIO);
589 }
590 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
591 ASSERT(dp->i_df.if_u1.if_data != NULL);
592 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
593 if (args->namelen == 2 &&
594 args->name[0] == '.' && args->name[1] == '.') {
595 /* XXX - replace assert? */
596 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent);
597 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
598 return 0;
599 }
600 ASSERT(args->namelen != 1 || args->name[0] != '.');
601 sfe = &sf->list[0];
602 for (i = sf->hdr.count-1; i >= 0; i--) {
603 if (sfe->namelen == args->namelen &&
604 sfe->name[0] == args->name[0] &&
605 memcmp(args->name, sfe->name, args->namelen) == 0) {
606 ASSERT(memcmp((char *)&args->inumber,
607 (char *)&sfe->inumber, sizeof(xfs_ino_t)));
608 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
609 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
610 return 0;
611 }
612 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
613 }
614 ASSERT(args->oknoent);
615 return XFS_ERROR(ENOENT);
616}
617
618/*
619 * Convert a leaf directory to shortform structure
620 */
621int
622xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
623{
624 xfs_dir_leafblock_t *leaf;
625 xfs_dir_leaf_hdr_t *hdr;
626 xfs_dir_leaf_entry_t *entry;
627 xfs_dir_leaf_name_t *namest;
628 xfs_da_args_t args;
629 xfs_inode_t *dp;
630 xfs_ino_t parent = 0;
631 char *tmpbuffer;
632 int retval, i;
633 xfs_dabuf_t *bp;
634
635 dp = iargs->dp;
636 tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
637 ASSERT(tmpbuffer != NULL);
638
639 retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp,
640 XFS_DATA_FORK);
641 if (retval)
642 goto out;
643 ASSERT(bp != NULL);
644 memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
645 leaf = (xfs_dir_leafblock_t *)tmpbuffer;
646 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
647 memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));
648
649 /*
650 * Find and special case the parent inode number
651 */
652 hdr = &leaf->hdr;
653 entry = &leaf->entries[0];
654 for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) {
655 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx));
656 if ((entry->namelen == 2) &&
657 (namest->name[0] == '.') &&
658 (namest->name[1] == '.')) {
659 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent);
660 entry->nameidx = 0;
661 } else if ((entry->namelen == 1) && (namest->name[0] == '.')) {
662 entry->nameidx = 0;
663 }
664 }
665 retval = xfs_da_shrink_inode(iargs, 0, bp);
666 if (retval)
667 goto out;
668 retval = xfs_dir_shortform_create(iargs, parent);
669 if (retval)
670 goto out;
671
672 /*
673 * Copy the rest of the filenames
674 */
675 entry = &leaf->entries[0];
676 args.dp = dp;
677 args.firstblock = iargs->firstblock;
678 args.flist = iargs->flist;
679 args.total = iargs->total;
680 args.whichfork = XFS_DATA_FORK;
681 args.trans = iargs->trans;
682 args.justcheck = 0;
683 args.addname = args.oknoent = 1;
684 for (i = 0; i < be16_to_cpu(hdr->count); entry++, i++) {
685 if (!entry->nameidx)
686 continue;
687 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx));
688 args.name = (char *)(namest->name);
689 args.namelen = entry->namelen;
690 args.hashval = be32_to_cpu(entry->hashval);
691 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber);
692 xfs_dir_shortform_addname(&args);
693 }
694
695out:
696 kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount));
697 return retval;
698}
699
700/*
701 * Convert from using a single leaf to a root node and a leaf.
702 */
703int
704xfs_dir_leaf_to_node(xfs_da_args_t *args)
705{
706 xfs_dir_leafblock_t *leaf;
707 xfs_da_intnode_t *node;
708 xfs_inode_t *dp;
709 xfs_dabuf_t *bp1, *bp2;
710 xfs_dablk_t blkno;
711 int retval;
712
713 dp = args->dp;
714 retval = xfs_da_grow_inode(args, &blkno);
715 ASSERT(blkno == 1);
716 if (retval)
717 return retval;
718 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,
719 XFS_DATA_FORK);
720 if (retval)
721 return retval;
722 ASSERT(bp1 != NULL);
723 retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2,
724 XFS_DATA_FORK);
725 if (retval) {
726 xfs_da_buf_done(bp1);
727 return retval;
728 }
729 ASSERT(bp2 != NULL);
730 memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));
731 xfs_da_buf_done(bp1);
732 xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
733
734 /*
735 * Set up the new root node.
736 */
737 retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK);
738 if (retval) {
739 xfs_da_buf_done(bp2);
740 return retval;
741 }
742 node = bp1->data;
743 leaf = bp2->data;
744 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
745 node->btree[0].hashval = leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval;
746 xfs_da_buf_done(bp2);
747 node->btree[0].before = cpu_to_be32(blkno);
748 node->hdr.count = cpu_to_be16(1);
749 xfs_da_log_buf(args->trans, bp1,
750 XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0])));
751 xfs_da_buf_done(bp1);
752
753 return retval;
754}
755
756
757/*========================================================================
758 * Routines used for growing the Btree.
759 *========================================================================*/
760
761/*
762 * Create the initial contents of a leaf directory
763 * or a leaf in a node directory.
764 */
765STATIC int
766xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
767{
768 xfs_dir_leafblock_t *leaf;
769 xfs_dir_leaf_hdr_t *hdr;
770 xfs_inode_t *dp;
771 xfs_dabuf_t *bp;
772 int retval;
773
774 dp = args->dp;
775 ASSERT(dp != NULL);
776 retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK);
777 if (retval)
778 return retval;
779 ASSERT(bp != NULL);
780 leaf = bp->data;
781 memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
782 hdr = &leaf->hdr;
783 hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC);
784 hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount));
785 if (!hdr->firstused)
786 hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount) - 1);
787 hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t));
788 hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) -
789 be16_to_cpu(hdr->freemap[0].base));
790
791 xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
792
793 *bpp = bp;
794 return 0;
795}
796
797/*
798 * Split the leaf node, rebalance, then add the new entry.
799 */
800int
801xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
802 xfs_da_state_blk_t *newblk)
803{
804 xfs_dablk_t blkno;
805 xfs_da_args_t *args;
806 int error;
807
808 /*
809 * Allocate space for a new leaf node.
810 */
811 args = state->args;
812 ASSERT(args != NULL);
813 ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC);
814 error = xfs_da_grow_inode(args, &blkno);
815 if (error)
816 return error;
817 error = xfs_dir_leaf_create(args, blkno, &newblk->bp);
818 if (error)
819 return error;
820 newblk->blkno = blkno;
821 newblk->magic = XFS_DIR_LEAF_MAGIC;
822
823 /*
824 * Rebalance the entries across the two leaves.
825 */
826 xfs_dir_leaf_rebalance(state, oldblk, newblk);
827 error = xfs_da_blk_link(state, oldblk, newblk);
828 if (error)
829 return error;
830
831 /*
832 * Insert the new entry in the correct block.
833 */
834 if (state->inleaf) {
835 error = xfs_dir_leaf_add(oldblk->bp, args, oldblk->index);
836 } else {
837 error = xfs_dir_leaf_add(newblk->bp, args, newblk->index);
838 }
839
840 /*
841 * Update last hashval in each block since we added the name.
842 */
843 oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL);
844 newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL);
845 return error;
846}
847
848/*
849 * Add a name to the leaf directory structure.
850 *
851 * Must take into account fragmented leaves and leaves where spacemap has
852 * lost some freespace information (ie: holes).
853 */
854int
855xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
856{
857 xfs_dir_leafblock_t *leaf;
858 xfs_dir_leaf_hdr_t *hdr;
859 xfs_dir_leaf_map_t *map;
860 int tablesize, entsize, sum, i, tmp, error;
861
862 leaf = bp->data;
863 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
864 ASSERT((index >= 0) && (index <= be16_to_cpu(leaf->hdr.count)));
865 hdr = &leaf->hdr;
866 entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen);
867
868 /*
869 * Search through freemap for first-fit on new name length.
870 * (may need to figure in size of entry struct too)
871 */
872 tablesize = (be16_to_cpu(hdr->count) + 1) *
873 sizeof(xfs_dir_leaf_entry_t) + sizeof(xfs_dir_leaf_hdr_t);
874 map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1];
875 for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) {
876 if (tablesize > be16_to_cpu(hdr->firstused)) {
877 sum += be16_to_cpu(map->size);
878 continue;
879 }
880 if (!map->size)
881 continue; /* no space in this map */
882 tmp = entsize;
883 if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused))
884 tmp += (uint)sizeof(xfs_dir_leaf_entry_t);
885 if (be16_to_cpu(map->size) >= tmp) {
886 if (!args->justcheck)
887 xfs_dir_leaf_add_work(bp, args, index, i);
888 return 0;
889 }
890 sum += be16_to_cpu(map->size);
891 }
892
893 /*
894 * If there are no holes in the address space of the block,
895 * and we don't have enough freespace, then compaction will do us
896 * no good and we should just give up.
897 */
898 if (!hdr->holes && (sum < entsize))
899 return XFS_ERROR(ENOSPC);
900
901 /*
902 * Compact the entries to coalesce free space.
903 * Pass the justcheck flag so the checking pass can return
904 * an error, without changing anything, if it won't fit.
905 */
906 error = xfs_dir_leaf_compact(args->trans, bp,
907 args->total == 0 ?
908 entsize +
909 (uint)sizeof(xfs_dir_leaf_entry_t) : 0,
910 args->justcheck);
911 if (error)
912 return error;
913 /*
914 * After compaction, the block is guaranteed to have only one
915 * free region, in freemap[0]. If it is not big enough, give up.
916 */
917 if (be16_to_cpu(hdr->freemap[0].size) <
918 (entsize + (uint)sizeof(xfs_dir_leaf_entry_t)))
919 return XFS_ERROR(ENOSPC);
920
921 if (!args->justcheck)
922 xfs_dir_leaf_add_work(bp, args, index, 0);
923 return 0;
924}
925
926/*
927 * Add a name to a leaf directory structure.
928 */
929STATIC void
930xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index,
931 int mapindex)
932{
933 xfs_dir_leafblock_t *leaf;
934 xfs_dir_leaf_hdr_t *hdr;
935 xfs_dir_leaf_entry_t *entry;
936 xfs_dir_leaf_name_t *namest;
937 xfs_dir_leaf_map_t *map;
938 /* REFERENCED */
939 xfs_mount_t *mp;
940 int tmp, i;
941
942 leaf = bp->data;
943 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
944 hdr = &leaf->hdr;
945 ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE));
946 ASSERT((index >= 0) && (index <= be16_to_cpu(hdr->count)));
947
948 /*
949 * Force open some space in the entry array and fill it in.
950 */
951 entry = &leaf->entries[index];
952 if (index < be16_to_cpu(hdr->count)) {
953 tmp = be16_to_cpu(hdr->count) - index;
954 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
955 memmove(entry + 1, entry, tmp);
956 xfs_da_log_buf(args->trans, bp,
957 XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
958 }
959 be16_add(&hdr->count, 1);
960
961 /*
962 * Allocate space for the new string (at the end of the run).
963 */
964 map = &hdr->freemap[mapindex];
965 mp = args->trans->t_mountp;
966 ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp));
967 ASSERT(be16_to_cpu(map->size) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen));
968 ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp));
969
970 be16_add(&map->size, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)));
971 entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) +
972 be16_to_cpu(map->size));
973 entry->hashval = cpu_to_be32(args->hashval);
974 entry->namelen = args->namelen;
975 xfs_da_log_buf(args->trans, bp,
976 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
977
978 /*
979 * Copy the string and inode number into the new space.
980 */
981 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx));
982 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber);
983 memcpy(namest->name, args->name, args->namelen);
984 xfs_da_log_buf(args->trans, bp,
985 XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry)));
986
987 /*
988 * Update the control info for this leaf node
989 */
990 if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused))
991 hdr->firstused = entry->nameidx;
992 ASSERT(be16_to_cpu(hdr->firstused) >=
993 ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr)));
994 tmp = (be16_to_cpu(hdr->count)-1) * (uint)sizeof(xfs_dir_leaf_entry_t)
995 + (uint)sizeof(xfs_dir_leaf_hdr_t);
996 map = &hdr->freemap[0];
997 for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
998 if (be16_to_cpu(map->base) == tmp) {
999 int entry_size = sizeof(xfs_dir_leaf_entry_t);
1000 be16_add(&map->base, entry_size);
1001 be16_add(&map->size, -entry_size);
1002 }
1003 }
1004 be16_add(&hdr->namebytes, args->namelen);
1005 xfs_da_log_buf(args->trans, bp,
1006 XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
1007}
1008
1009/*
1010 * Garbage collect a leaf directory block by copying it to a new buffer.
1011 */
1012STATIC int
1013xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave,
1014 int justcheck)
1015{
1016 xfs_dir_leafblock_t *leaf_s, *leaf_d;
1017 xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
1018 xfs_mount_t *mp;
1019 char *tmpbuffer;
1020 char *tmpbuffer2=NULL;
1021 int rval;
1022 int lbsize;
1023
1024 mp = trans->t_mountp;
1025 lbsize = XFS_LBSIZE(mp);
1026 tmpbuffer = kmem_alloc(lbsize, KM_SLEEP);
1027 ASSERT(tmpbuffer != NULL);
1028 memcpy(tmpbuffer, bp->data, lbsize);
1029
1030 /*
1031 * Make a second copy in case xfs_dir_leaf_moveents()
1032 * below destroys the original.
1033 */
1034 if (musthave || justcheck) {
1035 tmpbuffer2 = kmem_alloc(lbsize, KM_SLEEP);
1036 memcpy(tmpbuffer2, bp->data, lbsize);
1037 }
1038 memset(bp->data, 0, lbsize);
1039
1040 /*
1041 * Copy basic information
1042 */
1043 leaf_s = (xfs_dir_leafblock_t *)tmpbuffer;
1044 leaf_d = bp->data;
1045 hdr_s = &leaf_s->hdr;
1046 hdr_d = &leaf_d->hdr;
1047 hdr_d->info = hdr_s->info; /* struct copy */
1048 hdr_d->firstused = cpu_to_be16(lbsize);
1049 if (!hdr_d->firstused)
1050 hdr_d->firstused = cpu_to_be16(lbsize - 1);
1051 hdr_d->namebytes = 0;
1052 hdr_d->count = 0;
1053 hdr_d->holes = 0;
1054 hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t));
1055 hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) -
1056 be16_to_cpu(hdr_d->freemap[0].base));
1057
1058 /*
1059 * Copy all entry's in the same (sorted) order,
1060 * but allocate filenames packed and in sequence.
1061 * This changes the source (leaf_s) as well.
1062 */
1063 xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, be16_to_cpu(hdr_s->count), mp);
1064
1065 if (musthave && be16_to_cpu(hdr_d->freemap[0].size) < musthave)
1066 rval = XFS_ERROR(ENOSPC);
1067 else
1068 rval = 0;
1069
1070 if (justcheck || rval == ENOSPC) {
1071 ASSERT(tmpbuffer2);
1072 memcpy(bp->data, tmpbuffer2, lbsize);
1073 } else {
1074 xfs_da_log_buf(trans, bp, 0, lbsize - 1);
1075 }
1076
1077 kmem_free(tmpbuffer, lbsize);
1078 if (musthave || justcheck)
1079 kmem_free(tmpbuffer2, lbsize);
1080 return rval;
1081}
1082
1083/*
1084 * Redistribute the directory entries between two leaf nodes,
1085 * taking into account the size of the new entry.
1086 *
1087 * NOTE: if new block is empty, then it will get the upper half of old block.
1088 */
1089STATIC void
1090xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
1091 xfs_da_state_blk_t *blk2)
1092{
1093 xfs_da_state_blk_t *tmp_blk;
1094 xfs_dir_leafblock_t *leaf1, *leaf2;
1095 xfs_dir_leaf_hdr_t *hdr1, *hdr2;
1096 int count, totallen, max, space, swap;
1097
1098 /*
1099 * Set up environment.
1100 */
1101 ASSERT(blk1->magic == XFS_DIR_LEAF_MAGIC);
1102 ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC);
1103 leaf1 = blk1->bp->data;
1104 leaf2 = blk2->bp->data;
1105 ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1106 ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1107
1108 /*
1109 * Check ordering of blocks, reverse if it makes things simpler.
1110 */
1111 swap = 0;
1112 if (xfs_dir_leaf_order(blk1->bp, blk2->bp)) {
1113 tmp_blk = blk1;
1114 blk1 = blk2;
1115 blk2 = tmp_blk;
1116 leaf1 = blk1->bp->data;
1117 leaf2 = blk2->bp->data;
1118 swap = 1;
1119 }
1120 hdr1 = &leaf1->hdr;
1121 hdr2 = &leaf2->hdr;
1122
1123 /*
1124 * Examine entries until we reduce the absolute difference in
1125 * byte usage between the two blocks to a minimum. Then get
1126 * the direction to copy and the number of elements to move.
1127 */
1128 state->inleaf = xfs_dir_leaf_figure_balance(state, blk1, blk2,
1129 &count, &totallen);
1130 if (swap)
1131 state->inleaf = !state->inleaf;
1132
1133 /*
1134 * Move any entries required from leaf to leaf:
1135 */
1136 if (count < be16_to_cpu(hdr1->count)) {
1137 /*
1138 * Figure the total bytes to be added to the destination leaf.
1139 */
1140 count = be16_to_cpu(hdr1->count) - count; /* number entries being moved */
1141 space = be16_to_cpu(hdr1->namebytes) - totallen;
1142 space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
1143 space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
1144
1145 /*
1146 * leaf2 is the destination, compact it if it looks tight.
1147 */
1148 max = be16_to_cpu(hdr2->firstused) - (uint)sizeof(xfs_dir_leaf_hdr_t);
1149 max -= be16_to_cpu(hdr2->count) * (uint)sizeof(xfs_dir_leaf_entry_t);
1150 if (space > max) {
1151 xfs_dir_leaf_compact(state->args->trans, blk2->bp,
1152 0, 0);
1153 }
1154
1155 /*
1156 * Move high entries from leaf1 to low end of leaf2.
1157 */
1158 xfs_dir_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count,
1159 leaf2, 0, count, state->mp);
1160
1161 xfs_da_log_buf(state->args->trans, blk1->bp, 0,
1162 state->blocksize-1);
1163 xfs_da_log_buf(state->args->trans, blk2->bp, 0,
1164 state->blocksize-1);
1165
1166 } else if (count > be16_to_cpu(hdr1->count)) {
1167 /*
1168 * Figure the total bytes to be added to the destination leaf.
1169 */
1170 count -= be16_to_cpu(hdr1->count); /* number entries being moved */
1171 space = totallen - be16_to_cpu(hdr1->namebytes);
1172 space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
1173 space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
1174
1175 /*
1176 * leaf1 is the destination, compact it if it looks tight.
1177 */
1178 max = be16_to_cpu(hdr1->firstused) - (uint)sizeof(xfs_dir_leaf_hdr_t);
1179 max -= be16_to_cpu(hdr1->count) * (uint)sizeof(xfs_dir_leaf_entry_t);
1180 if (space > max) {
1181 xfs_dir_leaf_compact(state->args->trans, blk1->bp,
1182 0, 0);
1183 }
1184
1185 /*
1186 * Move low entries from leaf2 to high end of leaf1.
1187 */
1188 xfs_dir_leaf_moveents(leaf2, 0, leaf1, be16_to_cpu(hdr1->count),
1189 count, state->mp);
1190
1191 xfs_da_log_buf(state->args->trans, blk1->bp, 0,
1192 state->blocksize-1);
1193 xfs_da_log_buf(state->args->trans, blk2->bp, 0,
1194 state->blocksize-1);
1195 }
1196
1197 /*
1198 * Copy out last hashval in each block for B-tree code.
1199 */
1200 blk1->hashval = be32_to_cpu(leaf1->entries[
1201 be16_to_cpu(leaf1->hdr.count)-1].hashval);
1202 blk2->hashval = be32_to_cpu(leaf2->entries[
1203 be16_to_cpu(leaf2->hdr.count)-1].hashval);
1204
1205 /*
1206 * Adjust the expected index for insertion.
1207 * GROT: this doesn't work unless blk2 was originally empty.
1208 */
1209 if (!state->inleaf) {
1210 blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count);
1211 }
1212}
1213
1214/*
1215 * Examine entries until we reduce the absolute difference in
1216 * byte usage between the two blocks to a minimum.
1217 * GROT: Is this really necessary? With other than a 512 byte blocksize,
1218 * GROT: there will always be enough room in either block for a new entry.
1219 * GROT: Do a double-split for this case?
1220 */
1221STATIC int
1222xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
1223 xfs_da_state_blk_t *blk1,
1224 xfs_da_state_blk_t *blk2,
1225 int *countarg, int *namebytesarg)
1226{
1227 xfs_dir_leafblock_t *leaf1, *leaf2;
1228 xfs_dir_leaf_hdr_t *hdr1, *hdr2;
1229 xfs_dir_leaf_entry_t *entry;
1230 int count, max, totallen, half;
1231 int lastdelta, foundit, tmp;
1232
1233 /*
1234 * Set up environment.
1235 */
1236 leaf1 = blk1->bp->data;
1237 leaf2 = blk2->bp->data;
1238 hdr1 = &leaf1->hdr;
1239 hdr2 = &leaf2->hdr;
1240 foundit = 0;
1241 totallen = 0;
1242
1243 /*
1244 * Examine entries until we reduce the absolute difference in
1245 * byte usage between the two blocks to a minimum.
1246 */
1247 max = be16_to_cpu(hdr1->count) + be16_to_cpu(hdr2->count);
1248 half = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
1249 half += be16_to_cpu(hdr1->namebytes) + be16_to_cpu(hdr2->namebytes) +
1250 state->args->namelen;
1251 half /= 2;
1252 lastdelta = state->blocksize;
1253 entry = &leaf1->entries[0];
1254 for (count = 0; count < max; entry++, count++) {
1255
1256#define XFS_DIR_ABS(A) (((A) < 0) ? -(A) : (A))
1257 /*
1258 * The new entry is in the first block, account for it.
1259 */
1260 if (count == blk1->index) {
1261 tmp = totallen + (uint)sizeof(*entry)
1262 + XFS_DIR_LEAF_ENTSIZE_BYNAME(state->args->namelen);
1263 if (XFS_DIR_ABS(half - tmp) > lastdelta)
1264 break;
1265 lastdelta = XFS_DIR_ABS(half - tmp);
1266 totallen = tmp;
1267 foundit = 1;
1268 }
1269
1270 /*
1271 * Wrap around into the second block if necessary.
1272 */
1273 if (count == be16_to_cpu(hdr1->count)) {
1274 leaf1 = leaf2;
1275 entry = &leaf1->entries[0];
1276 }
1277
1278 /*
1279 * Figure out if next leaf entry would be too much.
1280 */
1281 tmp = totallen + (uint)sizeof(*entry)
1282 + XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
1283 if (XFS_DIR_ABS(half - tmp) > lastdelta)
1284 break;
1285 lastdelta = XFS_DIR_ABS(half - tmp);
1286 totallen = tmp;
1287#undef XFS_DIR_ABS
1288 }
1289
1290 /*
1291 * Calculate the number of namebytes that will end up in lower block.
1292 * If new entry not in lower block, fix up the count.
1293 */
1294 totallen -=
1295 count * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
1296 if (foundit) {
1297 totallen -= (sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1) +
1298 state->args->namelen;
1299 }
1300
1301 *countarg = count;
1302 *namebytesarg = totallen;
1303 return foundit;
1304}
1305
1306/*========================================================================
1307 * Routines used for shrinking the Btree.
1308 *========================================================================*/
1309
1310/*
1311 * Check a leaf block and its neighbors to see if the block should be
1312 * collapsed into one or the other neighbor. Always keep the block
1313 * with the smaller block number.
1314 * If the current block is over 50% full, don't try to join it, return 0.
1315 * If the block is empty, fill in the state structure and return 2.
1316 * If it can be collapsed, fill in the state structure and return 1.
1317 * If nothing can be done, return 0.
1318 */
1319int
1320xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
1321{
1322 xfs_dir_leafblock_t *leaf;
1323 xfs_da_state_blk_t *blk;
1324 xfs_da_blkinfo_t *info;
1325 int count, bytes, forward, error, retval, i;
1326 xfs_dablk_t blkno;
1327 xfs_dabuf_t *bp;
1328
1329 /*
1330 * Check for the degenerate case of the block being over 50% full.
1331 * If so, it's not worth even looking to see if we might be able
1332 * to coalesce with a sibling.
1333 */
1334 blk = &state->path.blk[ state->path.active-1 ];
1335 info = blk->bp->data;
1336 ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC);
1337 leaf = (xfs_dir_leafblock_t *)info;
1338 count = be16_to_cpu(leaf->hdr.count);
1339 bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) +
1340 count * (uint)sizeof(xfs_dir_leaf_entry_t) +
1341 count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) +
1342 be16_to_cpu(leaf->hdr.namebytes);
1343 if (bytes > (state->blocksize >> 1)) {
1344 *action = 0; /* blk over 50%, don't try to join */
1345 return 0;
1346 }
1347
1348 /*
1349 * Check for the degenerate case of the block being empty.
1350 * If the block is empty, we'll simply delete it, no need to
1351 * coalesce it with a sibling block. We choose (arbitrarily)
1352 * to merge with the forward block unless it is NULL.
1353 */
1354 if (count == 0) {
1355 /*
1356 * Make altpath point to the block we want to keep and
1357 * path point to the block we want to drop (this one).
1358 */
1359 forward = (info->forw != 0);
1360 memcpy(&state->altpath, &state->path, sizeof(state->path));
1361 error = xfs_da_path_shift(state, &state->altpath, forward,
1362 0, &retval);
1363 if (error)
1364 return error;
1365 if (retval) {
1366 *action = 0;
1367 } else {
1368 *action = 2;
1369 }
1370 return 0;
1371 }
1372
1373 /*
1374 * Examine each sibling block to see if we can coalesce with
1375 * at least 25% free space to spare. We need to figure out
1376 * whether to merge with the forward or the backward block.
1377 * We prefer coalescing with the lower numbered sibling so as
1378 * to shrink a directory over time.
1379 */
1380 forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); /* start with smaller blk num */
1381 for (i = 0; i < 2; forward = !forward, i++) {
1382 if (forward)
1383 blkno = be32_to_cpu(info->forw);
1384 else
1385 blkno = be32_to_cpu(info->back);
1386 if (blkno == 0)
1387 continue;
1388 error = xfs_da_read_buf(state->args->trans, state->args->dp,
1389 blkno, -1, &bp,
1390 XFS_DATA_FORK);
1391 if (error)
1392 return error;
1393 ASSERT(bp != NULL);
1394
1395 leaf = (xfs_dir_leafblock_t *)info;
1396 count = be16_to_cpu(leaf->hdr.count);
1397 bytes = state->blocksize - (state->blocksize>>2);
1398 bytes -= be16_to_cpu(leaf->hdr.namebytes);
1399 leaf = bp->data;
1400 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1401 count += be16_to_cpu(leaf->hdr.count);
1402 bytes -= be16_to_cpu(leaf->hdr.namebytes);
1403 bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
1404 bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t);
1405 bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t);
1406 if (bytes >= 0)
1407 break; /* fits with at least 25% to spare */
1408
1409 xfs_da_brelse(state->args->trans, bp);
1410 }
1411 if (i >= 2) {
1412 *action = 0;
1413 return 0;
1414 }
1415 xfs_da_buf_done(bp);
1416
1417 /*
1418 * Make altpath point to the block we want to keep (the lower
1419 * numbered block) and path point to the block we want to drop.
1420 */
1421 memcpy(&state->altpath, &state->path, sizeof(state->path));
1422 if (blkno < blk->blkno) {
1423 error = xfs_da_path_shift(state, &state->altpath, forward,
1424 0, &retval);
1425 } else {
1426 error = xfs_da_path_shift(state, &state->path, forward,
1427 0, &retval);
1428 }
1429 if (error)
1430 return error;
1431 if (retval) {
1432 *action = 0;
1433 } else {
1434 *action = 1;
1435 }
1436 return 0;
1437}
1438
1439/*
1440 * Remove a name from the leaf directory structure.
1441 *
1442 * Return 1 if leaf is less than 37% full, 0 if >= 37% full.
1443 * If two leaves are 37% full, when combined they will leave 25% free.
1444 */
1445int
1446xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index)
1447{
1448 xfs_dir_leafblock_t *leaf;
1449 xfs_dir_leaf_hdr_t *hdr;
1450 xfs_dir_leaf_map_t *map;
1451 xfs_dir_leaf_entry_t *entry;
1452 xfs_dir_leaf_name_t *namest;
1453 int before, after, smallest, entsize;
1454 int tablesize, tmp, i;
1455 xfs_mount_t *mp;
1456
1457 leaf = bp->data;
1458 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1459 hdr = &leaf->hdr;
1460 mp = trans->t_mountp;
1461 ASSERT(hdr->count && (be16_to_cpu(hdr->count) < (XFS_LBSIZE(mp)/8)));
1462 ASSERT((index >= 0) && (index < be16_to_cpu(hdr->count)));
1463 ASSERT(be16_to_cpu(hdr->firstused) >=
1464 ((be16_to_cpu(hdr->count)*sizeof(*entry))+sizeof(*hdr)));
1465 entry = &leaf->entries[index];
1466 ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused));
1467 ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp));
1468
1469 /*
1470 * Scan through free region table:
1471 * check for adjacency of free'd entry with an existing one,
1472 * find smallest free region in case we need to replace it,
1473 * adjust any map that borders the entry table,
1474 */
1475 tablesize = be16_to_cpu(hdr->count) * (uint)sizeof(xfs_dir_leaf_entry_t)
1476 + (uint)sizeof(xfs_dir_leaf_hdr_t);
1477 map = &hdr->freemap[0];
1478 tmp = be16_to_cpu(map->size);
1479 before = after = -1;
1480 smallest = XFS_DIR_LEAF_MAPSIZE - 1;
1481 entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
1482 for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
1483 ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp));
1484 ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp));
1485 if (be16_to_cpu(map->base) == tablesize) {
1486 int entry_size = sizeof(xfs_dir_leaf_entry_t);
1487 be16_add(&map->base, -entry_size);
1488 be16_add(&map->size, entry_size);
1489 }
1490
1491 if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) ==
1492 be16_to_cpu(entry->nameidx)) {
1493 before = i;
1494 } else if (be16_to_cpu(map->base) ==
1495 (be16_to_cpu(entry->nameidx) + entsize)) {
1496 after = i;
1497 } else if (be16_to_cpu(map->size) < tmp) {
1498 tmp = be16_to_cpu(map->size);
1499 smallest = i;
1500 }
1501 }
1502
1503 /*
1504 * Coalesce adjacent freemap regions,
1505 * or replace the smallest region.
1506 */
1507 if ((before >= 0) || (after >= 0)) {
1508 if ((before >= 0) && (after >= 0)) {
1509 map = &hdr->freemap[before];
1510 be16_add(&map->size, entsize);
1511 be16_add(&map->size, be16_to_cpu(hdr->freemap[after].size));
1512 hdr->freemap[after].base = 0;
1513 hdr->freemap[after].size = 0;
1514 } else if (before >= 0) {
1515 map = &hdr->freemap[before];
1516 be16_add(&map->size, entsize);
1517 } else {
1518 map = &hdr->freemap[after];
1519 map->base = entry->nameidx;
1520 be16_add(&map->size, entsize);
1521 }
1522 } else {
1523 /*
1524 * Replace smallest region (if it is smaller than free'd entry)
1525 */
1526 map = &hdr->freemap[smallest];
1527 if (be16_to_cpu(map->size) < entsize) {
1528 map->base = entry->nameidx;
1529 map->size = cpu_to_be16(entsize);
1530 }
1531 }
1532
1533 /*
1534 * Did we remove the first entry?
1535 */
1536 if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused))
1537 smallest = 1;
1538 else
1539 smallest = 0;
1540
1541 /*
1542 * Compress the remaining entries and zero out the removed stuff.
1543 */
1544 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx));
1545 memset((char *)namest, 0, entsize);
1546 xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize));
1547
1548 be16_add(&hdr->namebytes, -(entry->namelen));
1549 tmp = (be16_to_cpu(hdr->count) - index) * (uint)sizeof(xfs_dir_leaf_entry_t);
1550 memmove(entry, entry + 1, tmp);
1551 be16_add(&hdr->count, -1);
1552 xfs_da_log_buf(trans, bp,
1553 XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
1554 entry = &leaf->entries[be16_to_cpu(hdr->count)];
1555 memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t));
1556
1557 /*
1558 * If we removed the first entry, re-find the first used byte
1559 * in the name area. Note that if the entry was the "firstused",
1560 * then we don't have a "hole" in our block resulting from
1561 * removing the name.
1562 */
1563 if (smallest) {
1564 tmp = XFS_LBSIZE(mp);
1565 entry = &leaf->entries[0];
1566 for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) {
1567 ASSERT(be16_to_cpu(entry->nameidx) >=
1568 be16_to_cpu(hdr->firstused));
1569 ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp));
1570 if (be16_to_cpu(entry->nameidx) < tmp)
1571 tmp = be16_to_cpu(entry->nameidx);
1572 }
1573 hdr->firstused = cpu_to_be16(tmp);
1574 if (!hdr->firstused)
1575 hdr->firstused = cpu_to_be16(tmp - 1);
1576 } else {
1577 hdr->holes = 1; /* mark as needing compaction */
1578 }
1579
1580 xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
1581
1582 /*
1583 * Check if leaf is less than 50% full, caller may want to
1584 * "join" the leaf with a sibling if so.
1585 */
1586 tmp = (uint)sizeof(xfs_dir_leaf_hdr_t);
1587 tmp += be16_to_cpu(leaf->hdr.count) * (uint)sizeof(xfs_dir_leaf_entry_t);
1588 tmp += be16_to_cpu(leaf->hdr.count) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
1589 tmp += be16_to_cpu(leaf->hdr.namebytes);
1590 if (tmp < mp->m_dir_magicpct)
1591 return 1; /* leaf is < 37% full */
1592 return 0;
1593}
1594
1595/*
1596 * Move all the directory entries from drop_leaf into save_leaf.
1597 */
1598void
1599xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1600 xfs_da_state_blk_t *save_blk)
1601{
1602 xfs_dir_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf;
1603 xfs_dir_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr;
1604 xfs_mount_t *mp;
1605 char *tmpbuffer;
1606
1607 /*
1608 * Set up environment.
1609 */
1610 mp = state->mp;
1611 ASSERT(drop_blk->magic == XFS_DIR_LEAF_MAGIC);
1612 ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC);
1613 drop_leaf = drop_blk->bp->data;
1614 save_leaf = save_blk->bp->data;
1615 ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1616 ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1617 drop_hdr = &drop_leaf->hdr;
1618 save_hdr = &save_leaf->hdr;
1619
1620 /*
1621 * Save last hashval from dying block for later Btree fixup.
1622 */
1623 drop_blk->hashval = be32_to_cpu(drop_leaf->entries[
1624 be16_to_cpu(drop_leaf->hdr.count)-1].hashval);
1625
1626 /*
1627 * Check if we need a temp buffer, or can we do it in place.
1628 * Note that we don't check "leaf" for holes because we will
1629 * always be dropping it, toosmall() decided that for us already.
1630 */
1631 if (save_hdr->holes == 0) {
1632 /*
1633 * dest leaf has no holes, so we add there. May need
1634 * to make some room in the entry array.
1635 */
1636 if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
1637 xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0,
1638 be16_to_cpu(drop_hdr->count), mp);
1639 } else {
1640 xfs_dir_leaf_moveents(drop_leaf, 0,
1641 save_leaf, be16_to_cpu(save_hdr->count),
1642 be16_to_cpu(drop_hdr->count), mp);
1643 }
1644 } else {
1645 /*
1646 * Destination has holes, so we make a temporary copy
1647 * of the leaf and add them both to that.
1648 */
1649 tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP);
1650 ASSERT(tmpbuffer != NULL);
1651 memset(tmpbuffer, 0, state->blocksize);
1652 tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer;
1653 tmp_hdr = &tmp_leaf->hdr;
1654 tmp_hdr->info = save_hdr->info; /* struct copy */
1655 tmp_hdr->count = 0;
1656 tmp_hdr->firstused = cpu_to_be16(state->blocksize);
1657 if (!tmp_hdr->firstused)
1658 tmp_hdr->firstused = cpu_to_be16(state->blocksize - 1);
1659 tmp_hdr->namebytes = 0;
1660 if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
1661 xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
1662 be16_to_cpu(drop_hdr->count), mp);
1663 xfs_dir_leaf_moveents(save_leaf, 0,
1664 tmp_leaf, be16_to_cpu(tmp_leaf->hdr.count),
1665 be16_to_cpu(save_hdr->count), mp);
1666 } else {
1667 xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0,
1668 be16_to_cpu(save_hdr->count), mp);
1669 xfs_dir_leaf_moveents(drop_leaf, 0,
1670 tmp_leaf, be16_to_cpu(tmp_leaf->hdr.count),
1671 be16_to_cpu(drop_hdr->count), mp);
1672 }
1673 memcpy(save_leaf, tmp_leaf, state->blocksize);
1674 kmem_free(tmpbuffer, state->blocksize);
1675 }
1676
1677 xfs_da_log_buf(state->args->trans, save_blk->bp, 0,
1678 state->blocksize - 1);
1679
1680 /*
1681 * Copy out last hashval in each block for B-tree code.
1682 */
1683 save_blk->hashval = be32_to_cpu(save_leaf->entries[
1684 be16_to_cpu(save_leaf->hdr.count)-1].hashval);
1685}
1686
1687/*========================================================================
1688 * Routines used for finding things in the Btree.
1689 *========================================================================*/
1690
1691/*
1692 * Look up a name in a leaf directory structure.
1693 * This is the internal routine, it uses the caller's buffer.
1694 *
1695 * Note that duplicate keys are allowed, but only check within the
1696 * current leaf node. The Btree code must check in adjacent leaf nodes.
1697 *
1698 * Return in *index the index into the entry[] array of either the found
1699 * entry, or where the entry should have been (insert before that entry).
1700 *
1701 * Don't change the args->inumber unless we find the filename.
1702 */
1703int
1704xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
1705{
1706 xfs_dir_leafblock_t *leaf;
1707 xfs_dir_leaf_entry_t *entry;
1708 xfs_dir_leaf_name_t *namest;
1709 int probe, span;
1710 xfs_dahash_t hashval;
1711
1712 leaf = bp->data;
1713 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1714 ASSERT(be16_to_cpu(leaf->hdr.count) < (XFS_LBSIZE(args->dp->i_mount)/8));
1715
1716 /*
1717 * Binary search. (note: small blocks will skip this loop)
1718 */
1719 hashval = args->hashval;
1720 probe = span = be16_to_cpu(leaf->hdr.count) / 2;
1721 for (entry = &leaf->entries[probe]; span > 4;
1722 entry = &leaf->entries[probe]) {
1723 span /= 2;
1724 if (be32_to_cpu(entry->hashval) < hashval)
1725 probe += span;
1726 else if (be32_to_cpu(entry->hashval) > hashval)
1727 probe -= span;
1728 else
1729 break;
1730 }
1731 ASSERT((probe >= 0) && \
1732 ((!leaf->hdr.count) || (probe < be16_to_cpu(leaf->hdr.count))));
1733 ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval));
1734
1735 /*
1736 * Since we may have duplicate hashval's, find the first matching
1737 * hashval in the leaf.
1738 */
1739 while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) {
1740 entry--;
1741 probe--;
1742 }
1743 while ((probe < be16_to_cpu(leaf->hdr.count)) &&
1744 (be32_to_cpu(entry->hashval) < hashval)) {
1745 entry++;
1746 probe++;
1747 }
1748 if ((probe == be16_to_cpu(leaf->hdr.count)) ||
1749 (be32_to_cpu(entry->hashval) != hashval)) {
1750 *index = probe;
1751 ASSERT(args->oknoent);
1752 return XFS_ERROR(ENOENT);
1753 }
1754
1755 /*
1756 * Duplicate keys may be present, so search all of them for a match.
1757 */
1758 while ((probe < be16_to_cpu(leaf->hdr.count)) &&
1759 (be32_to_cpu(entry->hashval) == hashval)) {
1760 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, be16_to_cpu(entry->nameidx));
1761 if (entry->namelen == args->namelen &&
1762 namest->name[0] == args->name[0] &&
1763 memcmp(args->name, namest->name, args->namelen) == 0) {
1764 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber);
1765 *index = probe;
1766 return XFS_ERROR(EEXIST);
1767 }
1768 entry++;
1769 probe++;
1770 }
1771 *index = probe;
1772 ASSERT(probe == be16_to_cpu(leaf->hdr.count) || args->oknoent);
1773 return XFS_ERROR(ENOENT);
1774}
1775
1776/*========================================================================
1777 * Utility routines.
1778 *========================================================================*/
1779
1780/*
1781 * Move the indicated entries from one leaf to another.
1782 * NOTE: this routine modifies both source and destination leaves.
1783 */
1784/* ARGSUSED */
1785STATIC void
1786xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s,
1787 xfs_dir_leafblock_t *leaf_d, int start_d,
1788 int count, xfs_mount_t *mp)
1789{
1790 xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
1791 xfs_dir_leaf_entry_t *entry_s, *entry_d;
1792 int tmp, i;
1793
1794 /*
1795 * Check for nothing to do.
1796 */
1797 if (count == 0)
1798 return;
1799
1800 /*
1801 * Set up environment.
1802 */
1803 ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1804 ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1805 hdr_s = &leaf_s->hdr;
1806 hdr_d = &leaf_d->hdr;
1807 ASSERT(hdr_s->count && (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8)));
1808 ASSERT(be16_to_cpu(hdr_s->firstused) >=
1809 ((be16_to_cpu(hdr_s->count)*sizeof(*entry_s))+sizeof(*hdr_s)));
1810 ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8));
1811 ASSERT(be16_to_cpu(hdr_d->firstused) >=
1812 ((be16_to_cpu(hdr_d->count)*sizeof(*entry_d))+sizeof(*hdr_d)));
1813
1814 ASSERT(start_s < be16_to_cpu(hdr_s->count));
1815 ASSERT(start_d <= be16_to_cpu(hdr_d->count));
1816 ASSERT(count <= be16_to_cpu(hdr_s->count));
1817
1818 /*
1819 * Move the entries in the destination leaf up to make a hole?
1820 */
1821 if (start_d < be16_to_cpu(hdr_d->count)) {
1822 tmp = be16_to_cpu(hdr_d->count) - start_d;
1823 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
1824 entry_s = &leaf_d->entries[start_d];
1825 entry_d = &leaf_d->entries[start_d + count];
1826 memcpy(entry_d, entry_s, tmp);
1827 }
1828
1829 /*
1830 * Copy all entry's in the same (sorted) order,
1831 * but allocate filenames packed and in sequence.
1832 */
1833 entry_s = &leaf_s->entries[start_s];
1834 entry_d = &leaf_d->entries[start_d];
1835 for (i = 0; i < count; entry_s++, entry_d++, i++) {
1836 ASSERT(be16_to_cpu(entry_s->nameidx) >=
1837 be16_to_cpu(hdr_s->firstused));
1838 tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s);
1839 be16_add(&hdr_d->firstused, -(tmp));
1840 entry_d->hashval = entry_s->hashval;
1841 entry_d->nameidx = hdr_d->firstused;
1842 entry_d->namelen = entry_s->namelen;
1843 ASSERT(be16_to_cpu(entry_d->nameidx) + tmp <= XFS_LBSIZE(mp));
1844 memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, be16_to_cpu(entry_d->nameidx)),
1845 XFS_DIR_LEAF_NAMESTRUCT(leaf_s, be16_to_cpu(entry_s->nameidx)), tmp);
1846 ASSERT(be16_to_cpu(entry_s->nameidx) + tmp <= XFS_LBSIZE(mp));
1847 memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s,
1848 be16_to_cpu(entry_s->nameidx)), 0, tmp);
1849 be16_add(&hdr_s->namebytes, -(entry_d->namelen));
1850 be16_add(&hdr_d->namebytes, entry_d->namelen);
1851 be16_add(&hdr_s->count, -1);
1852 be16_add(&hdr_d->count, +1);
1853 tmp = be16_to_cpu(hdr_d->count) * (uint)sizeof(xfs_dir_leaf_entry_t)
1854 + (uint)sizeof(xfs_dir_leaf_hdr_t);
1855 ASSERT(be16_to_cpu(hdr_d->firstused) >= tmp);
1856
1857 }
1858
1859 /*
1860 * Zero out the entries we just copied.
1861 */
1862 if (start_s == be16_to_cpu(hdr_s->count)) {
1863 tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
1864 entry_s = &leaf_s->entries[start_s];
1865 ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
1866 memset((char *)entry_s, 0, tmp);
1867 } else {
1868 /*
1869 * Move the remaining entries down to fill the hole,
1870 * then zero the entries at the top.
1871 */
1872 tmp = be16_to_cpu(hdr_s->count) - count;
1873 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
1874 entry_s = &leaf_s->entries[start_s + count];
1875 entry_d = &leaf_s->entries[start_s];
1876 memcpy(entry_d, entry_s, tmp);
1877
1878 tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
1879 entry_s = &leaf_s->entries[be16_to_cpu(hdr_s->count)];
1880 ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
1881 memset((char *)entry_s, 0, tmp);
1882 }
1883
1884 /*
1885 * Fill in the freemap information
1886 */
1887 hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_dir_leaf_hdr_t) +
1888 be16_to_cpu(hdr_d->count) * sizeof(xfs_dir_leaf_entry_t));
1889 hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) -
1890 be16_to_cpu(hdr_d->freemap[0].base));
1891 hdr_d->freemap[1].base = 0;
1892 hdr_d->freemap[1].size = 0;
1893 hdr_d->freemap[2].base = 0;
1894 hdr_d->freemap[2].size = 0;
1895 hdr_s->holes = 1; /* leaf may not be compact */
1896}
1897
1898/*
1899 * Compare two leaf blocks "order".
1900 */
1901int
1902xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
1903{
1904 xfs_dir_leafblock_t *leaf1, *leaf2;
1905
1906 leaf1 = leaf1_bp->data;
1907 leaf2 = leaf2_bp->data;
1908 ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) &&
1909 (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC));
1910 if (leaf1->hdr.count && leaf2->hdr.count &&
1911 ((be32_to_cpu(leaf2->entries[0].hashval) <
1912 be32_to_cpu(leaf1->entries[0 ].hashval)) ||
1913 (be32_to_cpu(leaf2->entries[
1914 be16_to_cpu(leaf2->hdr.count)-1].hashval) <
1915 be32_to_cpu(leaf1->entries[
1916 be16_to_cpu(leaf1->hdr.count)-1].hashval)))) {
1917 return 1;
1918 }
1919 return 0;
1920}
1921
1922/*
1923 * Pick up the last hashvalue from a leaf block.
1924 */
1925xfs_dahash_t
1926xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count)
1927{
1928 xfs_dir_leafblock_t *leaf;
1929
1930 leaf = bp->data;
1931 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1932 if (count)
1933 *count = be16_to_cpu(leaf->hdr.count);
1934 if (!leaf->hdr.count)
1935 return(0);
1936 return be32_to_cpu(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval);
1937}
1938
1939/*
1940 * Copy out directory entries for getdents(), for leaf directories.
1941 */
1942int
1943xfs_dir_leaf_getdents_int(
1944 xfs_dabuf_t *bp,
1945 xfs_inode_t *dp,
1946 xfs_dablk_t bno,
1947 uio_t *uio,
1948 int *eobp,
1949 xfs_dirent_t *dbp,
1950 xfs_dir_put_t put,
1951 xfs_daddr_t nextda)
1952{
1953 xfs_dir_leafblock_t *leaf;
1954 xfs_dir_leaf_entry_t *entry;
1955 xfs_dir_leaf_name_t *namest;
1956 int entno, want_entno, i, nextentno;
1957 xfs_mount_t *mp;
1958 xfs_dahash_t cookhash;
1959 xfs_dahash_t nexthash = 0;
1960#if (BITS_PER_LONG == 32)
1961 xfs_dahash_t lasthash = XFS_DA_MAXHASH;
1962#endif
1963 xfs_dir_put_args_t p;
1964
1965 mp = dp->i_mount;
1966 leaf = bp->data;
1967 if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
1968 *eobp = 1;
1969 return XFS_ERROR(ENOENT); /* XXX wrong code */
1970 }
1971
1972 want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
1973
1974 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
1975
1976 xfs_dir_trace_g_dul("leaf: start", dp, uio, leaf);
1977
1978 /*
1979 * Re-find our place.
1980 */
1981 for (i = entno = 0, entry = &leaf->entries[0];
1982 i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
1983
1984 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
1985 be16_to_cpu(entry->nameidx));
1986
1987 if (unlikely(
1988 ((char *)namest < (char *)leaf) ||
1989 ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
1990 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)",
1991 XFS_ERRLEVEL_LOW, mp, leaf);
1992 xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
1993 return XFS_ERROR(EFSCORRUPTED);
1994 }
1995 if (be32_to_cpu(entry->hashval) >= cookhash) {
1996 if (entno < want_entno &&
1997 be32_to_cpu(entry->hashval) == cookhash) {
1998 /*
1999 * Trying to get to a particular offset in a
2000 * run of equal-hashval entries.
2001 */
2002 entno++;
2003 } else if (want_entno > 0 && entno == want_entno &&
2004 be32_to_cpu(entry->hashval) == cookhash) {
2005 break;
2006 } else {
2007 entno = 0;
2008 break;
2009 }
2010 }
2011 }
2012
2013 if (i == be16_to_cpu(leaf->hdr.count)) {
2014 xfs_dir_trace_g_du("leaf: hash not found", dp, uio);
2015 if (!leaf->hdr.info.forw)
2016 uio->uio_offset =
2017 XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
2018 /*
2019 * Don't set uio_offset if there's another block:
2020 * the node code will be setting uio_offset anyway.
2021 */
2022 *eobp = 0;
2023 return 0;
2024 }
2025 xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry);
2026
2027 p.dbp = dbp;
2028 p.put = put;
2029 p.uio = uio;
2030
2031 /*
2032 * We're synchronized, start copying entries out to the user.
2033 */
2034 for (; entno >= 0 && i < be16_to_cpu(leaf->hdr.count);
2035 entry++, i++, (entno = nextentno)) {
2036 int lastresid=0, retval;
2037 xfs_dircook_t lastoffset;
2038 xfs_dahash_t thishash;
2039
2040 /*
2041 * Check for a damaged directory leaf block and pick up
2042 * the inode number from this entry.
2043 */
2044 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
2045 be16_to_cpu(entry->nameidx));
2046
2047 if (unlikely(
2048 ((char *)namest < (char *)leaf) ||
2049 ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
2050 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)",
2051 XFS_ERRLEVEL_LOW, mp, leaf);
2052 xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
2053 return XFS_ERROR(EFSCORRUPTED);
2054 }
2055
2056 xfs_dir_trace_g_duc("leaf: middle cookie ",
2057 dp, uio, p.cook.o);
2058
2059 if (i < (be16_to_cpu(leaf->hdr.count) - 1)) {
2060 nexthash = be32_to_cpu(entry[1].hashval);
2061
2062 if (nexthash == be32_to_cpu(entry->hashval))
2063 nextentno = entno + 1;
2064 else
2065 nextentno = 0;
2066 XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash);
2067 xfs_dir_trace_g_duc("leaf: middle cookie ",
2068 dp, uio, p.cook.o);
2069
2070 } else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) {
2071 xfs_dabuf_t *bp2;
2072 xfs_dir_leafblock_t *leaf2;
2073
2074 ASSERT(nextda != -1);
2075
2076 retval = xfs_da_read_buf(dp->i_transp, dp, thishash,
2077 nextda, &bp2, XFS_DATA_FORK);
2078 if (retval)
2079 return retval;
2080
2081 ASSERT(bp2 != NULL);
2082
2083 leaf2 = bp2->data;
2084
2085 if (unlikely(
2086 (be16_to_cpu(leaf2->hdr.info.magic)
2087 != XFS_DIR_LEAF_MAGIC)
2088 || (be32_to_cpu(leaf2->hdr.info.back)
2089 != bno))) { /* GROT */
2090 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)",
2091 XFS_ERRLEVEL_LOW, mp,
2092 leaf2);
2093 xfs_da_brelse(dp->i_transp, bp2);
2094
2095 return XFS_ERROR(EFSCORRUPTED);
2096 }
2097
2098 nexthash = be32_to_cpu(leaf2->entries[0].hashval);
2099 nextentno = -1;
2100 XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash);
2101 xfs_da_brelse(dp->i_transp, bp2);
2102 xfs_dir_trace_g_duc("leaf: next blk cookie",
2103 dp, uio, p.cook.o);
2104 } else {
2105 nextentno = -1;
2106 XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH);
2107 }
2108
2109 /*
2110 * Save off the cookie so we can fall back should the
2111 * 'put' into the outgoing buffer fails. To handle a run
2112 * of equal-hashvals, the off_t structure on 64bit
2113 * builds has entno built into the cookie to ID the
2114 * entry. On 32bit builds, we only have space for the
2115 * hashval so we can't ID specific entries within a group
2116 * of same hashval entries. For this, lastoffset is set
2117 * to the first in the run of equal hashvals so we don't
2118 * include any entries unless we can include all entries
2119 * that share the same hashval. Hopefully the buffer
2120 * provided is big enough to handle it (see pv763517).
2121 */
2122 thishash = be32_to_cpu(entry->hashval);
2123#if (BITS_PER_LONG == 32)
2124 if (thishash != lasthash) {
2125 XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
2126 lastresid = uio->uio_resid;
2127 lasthash = thishash;
2128 } else {
2129 xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped",
2130 dp, uio, p.cook.o);
2131 }
2132#else
2133 XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
2134 lastresid = uio->uio_resid;
2135#endif /* BITS_PER_LONG == 32 */
2136
2137 /*
2138 * Put the current entry into the outgoing buffer. If we fail
2139 * then restore the UIO to the first entry in the current
2140 * run of equal-hashval entries (probably one 1 entry long).
2141 */
2142 p.ino = XFS_GET_DIR_INO8(namest->inumber);
2143#if XFS_BIG_INUMS
2144 p.ino += mp->m_inoadd;
2145#endif
2146 p.name = (char *)namest->name;
2147 p.namelen = entry->namelen;
2148
2149 retval = p.put(&p);
2150
2151 if (!p.done) {
2152 uio->uio_offset = lastoffset.o;
2153 uio->uio_resid = lastresid;
2154
2155 *eobp = 1;
2156
2157 xfs_dir_trace_g_du("leaf: E-O-B", dp, uio);
2158
2159 return retval;
2160 }
2161 }
2162
2163 uio->uio_offset = p.cook.o;
2164
2165 *eobp = 0;
2166
2167 xfs_dir_trace_g_du("leaf: E-O-F", dp, uio);
2168
2169 return 0;
2170}
2171
2172/*
2173 * Format a dirent64 structure and copy it out the the user's buffer.
2174 */
2175int
2176xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa)
2177{
2178 iovec_t *iovp;
2179 int reclen, namelen;
2180 xfs_dirent_t *idbp;
2181 uio_t *uio;
2182
2183 namelen = pa->namelen;
2184 reclen = DIRENTSIZE(namelen);
2185 uio = pa->uio;
2186 if (reclen > uio->uio_resid) {
2187 pa->done = 0;
2188 return 0;
2189 }
2190 iovp = uio->uio_iov;
2191 idbp = (xfs_dirent_t *)iovp->iov_base;
2192 iovp->iov_base = (char *)idbp + reclen;
2193 iovp->iov_len -= reclen;
2194 uio->uio_resid -= reclen;
2195 idbp->d_reclen = reclen;
2196 idbp->d_ino = pa->ino;
2197 idbp->d_off = pa->cook.o;
2198 idbp->d_name[namelen] = '\0';
2199 pa->done = 1;
2200 memcpy(idbp->d_name, pa->name, namelen);
2201 return 0;
2202}
2203
2204/*
2205 * Format a dirent64 structure and copy it out the the user's buffer.
2206 */
2207int
2208xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa)
2209{
2210 int retval, reclen, namelen;
2211 xfs_dirent_t *idbp;
2212 uio_t *uio;
2213
2214 namelen = pa->namelen;
2215 reclen = DIRENTSIZE(namelen);
2216 uio = pa->uio;
2217 if (reclen > uio->uio_resid) {
2218 pa->done = 0;
2219 return 0;
2220 }
2221 idbp = pa->dbp;
2222 idbp->d_reclen = reclen;
2223 idbp->d_ino = pa->ino;
2224 idbp->d_off = pa->cook.o;
2225 idbp->d_name[namelen] = '\0';
2226 memcpy(idbp->d_name, pa->name, namelen);
2227 retval = uio_read((caddr_t)idbp, reclen, uio);
2228 pa->done = (retval == 0);
2229 return retval;
2230}
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
index 7ca5845195d5..e69de29bb2d1 100644
--- a/fs/xfs/xfs_dir_leaf.h
+++ b/fs/xfs/xfs_dir_leaf.h
@@ -1,231 +0,0 @@
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#ifndef __XFS_DIR_LEAF_H__
19#define __XFS_DIR_LEAF_H__
20
21/*
22 * Directory layout, internal structure, access macros, etc.
23 *
24 * Large directories are structured around Btrees where all the data
25 * elements are in the leaf nodes. Filenames are hashed into an int,
26 * then that int is used as the index into the Btree. Since the hashval
27 * of a filename may not be unique, we may have duplicate keys. The
28 * internal links in the Btree are logical block offsets into the file.
29 */
30
31struct uio;
32struct xfs_bmap_free;
33struct xfs_dabuf;
34struct xfs_da_args;
35struct xfs_da_state;
36struct xfs_da_state_blk;
37struct xfs_dir_put_args;
38struct xfs_inode;
39struct xfs_mount;
40struct xfs_trans;
41
42/*========================================================================
43 * Directory Structure when equal to XFS_LBSIZE(mp) bytes.
44 *========================================================================*/
45
46/*
47 * This is the structure of the leaf nodes in the Btree.
48 *
49 * Struct leaf_entry's are packed from the top. Names grow from the bottom
50 * but are not packed. The freemap contains run-length-encoded entries
51 * for the free bytes after the leaf_entry's, but only the N largest such,
52 * smaller runs are dropped. When the freemap doesn't show enough space
53 * for an allocation, we compact the namelist area and try again. If we
54 * still don't have enough space, then we have to split the block.
55 *
56 * Since we have duplicate hash keys, for each key that matches, compare
57 * the actual string. The root and intermediate node search always takes
58 * the first-in-the-block key match found, so we should only have to work
59 * "forw"ard. If none matches, continue with the "forw"ard leaf nodes
60 * until the hash key changes or the filename is found.
61 *
62 * The parent directory and the self-pointer are explicitly represented
63 * (ie: there are entries for "." and "..").
64 *
65 * Note that the count being a __uint16_t limits us to something like a
66 * blocksize of 1.3MB in the face of worst case (short) filenames.
67 */
68#define XFS_DIR_LEAF_MAPSIZE 3 /* how many freespace slots */
69
70typedef struct xfs_dir_leaf_map { /* RLE map of free bytes */
71 __be16 base; /* base of free region */
72 __be16 size; /* run length of free region */
73} xfs_dir_leaf_map_t;
74
75typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */
76 xfs_da_blkinfo_t info; /* block type, links, etc. */
77 __be16 count; /* count of active leaf_entry's */
78 __be16 namebytes; /* num bytes of name strings stored */
79 __be16 firstused; /* first used byte in name area */
80 __u8 holes; /* != 0 if blk needs compaction */
81 __u8 pad1;
82 xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE];
83} xfs_dir_leaf_hdr_t;
84
85typedef struct xfs_dir_leaf_entry { /* sorted on key, not name */
86 __be32 hashval; /* hash value of name */
87 __be16 nameidx; /* index into buffer of name */
88 __u8 namelen; /* length of name string */
89 __u8 pad2;
90} xfs_dir_leaf_entry_t;
91
92typedef struct xfs_dir_leaf_name {
93 xfs_dir_ino_t inumber; /* inode number for this key */
94 __uint8_t name[1]; /* name string itself */
95} xfs_dir_leaf_name_t;
96
97typedef struct xfs_dir_leafblock {
98 xfs_dir_leaf_hdr_t hdr; /* constant-structure header block */
99 xfs_dir_leaf_entry_t entries[1]; /* var sized array */
100 xfs_dir_leaf_name_t namelist[1]; /* grows from bottom of buf */
101} xfs_dir_leafblock_t;
102
103/*
104 * Length of name for which a 512-byte block filesystem
105 * can get a double split.
106 */
107#define XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN \
108 (512 - (uint)sizeof(xfs_dir_leaf_hdr_t) - \
109 (uint)sizeof(xfs_dir_leaf_entry_t) * 2 - \
110 (uint)sizeof(xfs_dir_leaf_name_t) * 2 - (MAXNAMELEN - 2) + 1 + 1)
111
112typedef int (*xfs_dir_put_t)(struct xfs_dir_put_args *pa);
113
114typedef union {
115 xfs_off_t o; /* offset (cookie) */
116 /*
117 * Watch the order here (endian-ness dependent).
118 */
119 struct {
120#ifndef XFS_NATIVE_HOST
121 xfs_dahash_t h; /* hash value */
122 __uint32_t be; /* block and entry */
123#else
124 __uint32_t be; /* block and entry */
125 xfs_dahash_t h; /* hash value */
126#endif /* XFS_NATIVE_HOST */
127 } s;
128} xfs_dircook_t;
129
130#define XFS_PUT_COOKIE(c,mp,bno,entry,hash) \
131 ((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash))
132
133typedef struct xfs_dir_put_args {
134 xfs_dircook_t cook; /* cookie of (next) entry */
135 xfs_intino_t ino; /* inode number */
136 struct xfs_dirent *dbp; /* buffer pointer */
137 char *name; /* directory entry name */
138 int namelen; /* length of name */
139 int done; /* output: set if value was stored */
140 xfs_dir_put_t put; /* put function ptr (i/o) */
141 struct uio *uio; /* uio control structure */
142} xfs_dir_put_args_t;
143
144#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) \
145 xfs_dir_leaf_entsize_byname(len)
146static inline int xfs_dir_leaf_entsize_byname(int len)
147{
148 return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len;
149}
150
151#define XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry) \
152 xfs_dir_leaf_entsize_byentry(entry)
153static inline int xfs_dir_leaf_entsize_byentry(xfs_dir_leaf_entry_t *entry)
154{
155 return (uint)sizeof(xfs_dir_leaf_name_t)-1 + (entry)->namelen;
156}
157
158#define XFS_DIR_LEAF_NAMESTRUCT(leafp,offset) \
159 xfs_dir_leaf_namestruct(leafp,offset)
160static inline xfs_dir_leaf_name_t *
161xfs_dir_leaf_namestruct(xfs_dir_leafblock_t *leafp, int offset)
162{
163 return (xfs_dir_leaf_name_t *)&((char *)(leafp))[offset];
164}
165
166/*========================================================================
167 * Function prototypes for the kernel.
168 *========================================================================*/
169
170/*
171 * Internal routines when dirsize < XFS_LITINO(mp).
172 */
173int xfs_dir_shortform_create(struct xfs_da_args *args, xfs_ino_t parent);
174int xfs_dir_shortform_addname(struct xfs_da_args *args);
175int xfs_dir_shortform_lookup(struct xfs_da_args *args);
176int xfs_dir_shortform_to_leaf(struct xfs_da_args *args);
177int xfs_dir_shortform_removename(struct xfs_da_args *args);
178int xfs_dir_shortform_getdents(struct xfs_inode *dp, struct uio *uio, int *eofp,
179 struct xfs_dirent *dbp, xfs_dir_put_t put);
180int xfs_dir_shortform_replace(struct xfs_da_args *args);
181
182/*
183 * Internal routines when dirsize == XFS_LBSIZE(mp).
184 */
185int xfs_dir_leaf_to_node(struct xfs_da_args *args);
186int xfs_dir_leaf_to_shortform(struct xfs_da_args *args);
187
188/*
189 * Routines used for growing the Btree.
190 */
191int xfs_dir_leaf_split(struct xfs_da_state *state,
192 struct xfs_da_state_blk *oldblk,
193 struct xfs_da_state_blk *newblk);
194int xfs_dir_leaf_add(struct xfs_dabuf *leaf_buffer,
195 struct xfs_da_args *args, int insertion_index);
196int xfs_dir_leaf_addname(struct xfs_da_args *args);
197int xfs_dir_leaf_lookup_int(struct xfs_dabuf *leaf_buffer,
198 struct xfs_da_args *args,
199 int *index_found_at);
200int xfs_dir_leaf_remove(struct xfs_trans *trans,
201 struct xfs_dabuf *leaf_buffer,
202 int index_to_remove);
203int xfs_dir_leaf_getdents_int(struct xfs_dabuf *bp, struct xfs_inode *dp,
204 xfs_dablk_t bno, struct uio *uio,
205 int *eobp, struct xfs_dirent *dbp,
206 xfs_dir_put_t put, xfs_daddr_t nextda);
207
208/*
209 * Routines used for shrinking the Btree.
210 */
211int xfs_dir_leaf_toosmall(struct xfs_da_state *state, int *retval);
212void xfs_dir_leaf_unbalance(struct xfs_da_state *state,
213 struct xfs_da_state_blk *drop_blk,
214 struct xfs_da_state_blk *save_blk);
215
216/*
217 * Utility routines.
218 */
219uint xfs_dir_leaf_lasthash(struct xfs_dabuf *bp, int *count);
220int xfs_dir_leaf_order(struct xfs_dabuf *leaf1_bp,
221 struct xfs_dabuf *leaf2_bp);
222int xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa);
223int xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa);
224int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
225
226/*
227 * Global data.
228 */
229extern xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
230
231#endif /* __XFS_DIR_LEAF_H__ */
diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h
index 5b20b4d3f57d..e69de29bb2d1 100644
--- a/fs/xfs/xfs_dir_sf.h
+++ b/fs/xfs/xfs_dir_sf.h
@@ -1,155 +0,0 @@
1/*
2 * Copyright (c) 2000,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef __XFS_DIR_SF_H__
19#define __XFS_DIR_SF_H__
20
21/*
22 * Directory layout when stored internal to an inode.
23 *
24 * Small directories are packed as tightly as possible so as to
25 * fit into the literal area of the inode.
26 */
27
28typedef struct { __uint8_t i[sizeof(xfs_ino_t)]; } xfs_dir_ino_t;
29
30/*
31 * The parent directory has a dedicated field, and the self-pointer must
32 * be calculated on the fly.
33 *
34 * Entries are packed toward the top as tight as possible. The header
35 * and the elements much be memcpy'd out into a work area to get correct
36 * alignment for the inode number fields.
37 */
38typedef struct xfs_dir_sf_hdr { /* constant-structure header block */
39 xfs_dir_ino_t parent; /* parent dir inode number */
40 __uint8_t count; /* count of active entries */
41} xfs_dir_sf_hdr_t;
42
43typedef struct xfs_dir_sf_entry {
44 xfs_dir_ino_t inumber; /* referenced inode number */
45 __uint8_t namelen; /* actual length of name (no NULL) */
46 __uint8_t name[1]; /* name */
47} xfs_dir_sf_entry_t;
48
49typedef struct xfs_dir_shortform {
50 xfs_dir_sf_hdr_t hdr;
51 xfs_dir_sf_entry_t list[1]; /* variable sized array */
52} xfs_dir_shortform_t;
53
54/*
55 * We generate this then sort it, so that readdirs are returned in
56 * hash-order. Else seekdir won't work.
57 */
58typedef struct xfs_dir_sf_sort {
59 __uint8_t entno; /* .=0, ..=1, else entry# + 2 */
60 __uint8_t seqno; /* sequence # with same hash value */
61 __uint8_t namelen; /* length of name value (no null) */
62 xfs_dahash_t hash; /* this entry's hash value */
63 xfs_intino_t ino; /* this entry's inode number */
64 char *name; /* name value, pointer into buffer */
65} xfs_dir_sf_sort_t;
66
67#define XFS_DIR_SF_GET_DIRINO(from,to) xfs_dir_sf_get_dirino(from, to)
68static inline void xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to)
69{
70 *(to) = XFS_GET_DIR_INO8(*from);
71}
72
73#define XFS_DIR_SF_PUT_DIRINO(from,to) xfs_dir_sf_put_dirino(from, to)
74static inline void xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to)
75{
76 XFS_PUT_DIR_INO8(*(from), *(to));
77}
78
79#define XFS_DIR_SF_ENTSIZE_BYNAME(len) xfs_dir_sf_entsize_byname(len)
80static inline int xfs_dir_sf_entsize_byname(int len)
81{
82 return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (len);
83}
84
85#define XFS_DIR_SF_ENTSIZE_BYENTRY(sfep) xfs_dir_sf_entsize_byentry(sfep)
86static inline int xfs_dir_sf_entsize_byentry(xfs_dir_sf_entry_t *sfep)
87{
88 return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (sfep)->namelen;
89}
90
91#define XFS_DIR_SF_NEXTENTRY(sfep) xfs_dir_sf_nextentry(sfep)
92static inline xfs_dir_sf_entry_t *xfs_dir_sf_nextentry(xfs_dir_sf_entry_t *sfep)
93{
94 return (xfs_dir_sf_entry_t *) \
95 ((char *)(sfep) + XFS_DIR_SF_ENTSIZE_BYENTRY(sfep));
96}
97
98#define XFS_DIR_SF_ALLFIT(count,totallen) \
99 xfs_dir_sf_allfit(count,totallen)
100static inline int xfs_dir_sf_allfit(int count, int totallen)
101{
102 return ((uint)sizeof(xfs_dir_sf_hdr_t) + \
103 ((uint)sizeof(xfs_dir_sf_entry_t)-1)*(count) + (totallen));
104}
105
106#if defined(XFS_DIR_TRACE)
107
108/*
109 * Kernel tracing support for directories.
110 */
111struct uio;
112struct xfs_inode;
113struct xfs_da_intnode;
114struct xfs_dinode;
115struct xfs_dir_leafblock;
116struct xfs_dir_leaf_entry;
117
118#define XFS_DIR_TRACE_SIZE 4096 /* size of global trace buffer */
119extern ktrace_t *xfs_dir_trace_buf;
120
121/*
122 * Trace record types.
123 */
124#define XFS_DIR_KTRACE_G_DU 1 /* dp, uio */
125#define XFS_DIR_KTRACE_G_DUB 2 /* dp, uio, bno */
126#define XFS_DIR_KTRACE_G_DUN 3 /* dp, uio, node */
127#define XFS_DIR_KTRACE_G_DUL 4 /* dp, uio, leaf */
128#define XFS_DIR_KTRACE_G_DUE 5 /* dp, uio, leaf entry */
129#define XFS_DIR_KTRACE_G_DUC 6 /* dp, uio, cookie */
130
131void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio);
132void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio,
133 xfs_dablk_t bno);
134void xfs_dir_trace_g_dun(char *where, struct xfs_inode *dp, struct uio *uio,
135 struct xfs_da_intnode *node);
136void xfs_dir_trace_g_dul(char *where, struct xfs_inode *dp, struct uio *uio,
137 struct xfs_dir_leafblock *leaf);
138void xfs_dir_trace_g_due(char *where, struct xfs_inode *dp, struct uio *uio,
139 struct xfs_dir_leaf_entry *entry);
140void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio,
141 xfs_off_t cookie);
142void xfs_dir_trace_enter(int type, char *where,
143 void *a0, void *a1, void *a2, void *a3,
144 void *a4, void *a5, void *a6, void *a7,
145 void *a8, void *a9, void *a10, void *a11);
146#else
147#define xfs_dir_trace_g_du(w,d,u)
148#define xfs_dir_trace_g_dub(w,d,u,b)
149#define xfs_dir_trace_g_dun(w,d,u,n)
150#define xfs_dir_trace_g_dul(w,d,u,l)
151#define xfs_dir_trace_g_due(w,d,u,e)
152#define xfs_dir_trace_g_duc(w,d,u,c)
153#endif /* DEBUG */
154
155#endif /* __XFS_DIR_SF_H__ */
diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c
index 629795b3b3d5..1e4a35ddf7f9 100644
--- a/fs/xfs/xfs_dmops.c
+++ b/fs/xfs/xfs_dmops.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_dmapi.h" 27#include "xfs_dmapi.h"
29#include "xfs_mount.h" 28#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 2a21c5024017..b95681b03d81 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -22,12 +22,10 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_bmap_btree.h" 28#include "xfs_bmap_btree.h"
30#include "xfs_dir_sf.h"
31#include "xfs_dir2_sf.h" 29#include "xfs_dir2_sf.h"
32#include "xfs_attr_sf.h" 30#include "xfs_attr_sf.h"
33#include "xfs_dinode.h" 31#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 8b028f128547..6cf6d8769b97 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_buf_item.h" 24#include "xfs_buf_item.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_dir.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_trans_priv.h" 28#include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 650d35f537b7..077629bab532 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 7e5ccfec92be..33164a85aa9d 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 60c65683462d..616eeeb6953e 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 7894b72a7177..0724df7fabb7 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e799f0d00873..5fa0adb7e173 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -26,14 +26,12 @@
26#include "xfs_trans_priv.h" 26#include "xfs_trans_priv.h"
27#include "xfs_sb.h" 27#include "xfs_sb.h"
28#include "xfs_ag.h" 28#include "xfs_ag.h"
29#include "xfs_dir.h"
30#include "xfs_dir2.h" 29#include "xfs_dir2.h"
31#include "xfs_dmapi.h" 30#include "xfs_dmapi.h"
32#include "xfs_mount.h" 31#include "xfs_mount.h"
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
@@ -2925,13 +2923,6 @@ xfs_iflush_fork(
2925 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); 2923 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
2926 memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes); 2924 memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
2927 } 2925 }
2928 if (whichfork == XFS_DATA_FORK) {
2929 if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) {
2930 XFS_ERROR_REPORT("xfs_iflush_fork",
2931 XFS_ERRLEVEL_LOW, mp);
2932 return XFS_ERROR(EFSCORRUPTED);
2933 }
2934 }
2935 break; 2926 break;
2936 2927
2937 case XFS_DINODE_FMT_EXTENTS: 2928 case XFS_DINODE_FMT_EXTENTS:
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 2caa91b89714..f8e80d8e7237 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -25,7 +25,6 @@
25#include "xfs_buf_item.h" 25#include "xfs_buf_item.h"
26#include "xfs_sb.h" 26#include "xfs_sb.h"
27#include "xfs_ag.h" 27#include "xfs_ag.h"
28#include "xfs_dir.h"
29#include "xfs_dir2.h" 28#include "xfs_dir2.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
31#include "xfs_mount.h" 30#include "xfs_mount.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c
index 89441e69cdde..06d710c9ce4b 100644
--- a/fs/xfs/xfs_iocore.c
+++ b/fs/xfs/xfs_iocore.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dfrag.h" 28#include "xfs_dfrag.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index d79055207fbf..f1949c16df15 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index a0182ced29c4..46249e4d1fea 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 95d679cd4e75..d8f5d4cbe8b7 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -36,7 +35,6 @@
36#include "xfs_ialloc_btree.h" 35#include "xfs_ialloc_btree.h"
37#include "xfs_log_recover.h" 36#include "xfs_log_recover.h"
38#include "xfs_trans_priv.h" 37#include "xfs_trans_priv.h"
39#include "xfs_dir_sf.h"
40#include "xfs_dir2_sf.h" 38#include "xfs_dir2_sf.h"
41#include "xfs_attr_sf.h" 39#include "xfs_attr_sf.h"
42#include "xfs_dinode.h" 40#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index f952f9dbf74a..55b4237c2153 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 5ce6416fbd33..10dbf203c62f 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -934,18 +932,7 @@ xfs_mountfs(
934 vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid; 932 vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
935 mp->m_dmevmask = 0; /* not persistent; set after each mount */ 933 mp->m_dmevmask = 0; /* not persistent; set after each mount */
936 934
937 /* 935 xfs_dir_mount(mp);
938 * Select the right directory manager.
939 */
940 mp->m_dirops =
941 XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ?
942 xfsv2_dirops :
943 xfsv1_dirops;
944
945 /*
946 * Initialize directory manager's entries.
947 */
948 XFS_DIR_MOUNT(mp);
949 936
950 /* 937 /*
951 * Initialize the attribute manager's entries. 938 * Initialize the attribute manager's entries.
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 761f42f989cd..b2bd4be4200a 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -403,8 +403,6 @@ typedef struct xfs_mount {
403 __uint8_t m_inode_quiesce;/* call quiesce on new inodes. 403 __uint8_t m_inode_quiesce;/* call quiesce on new inodes.
404 field governed by m_ilock */ 404 field governed by m_ilock */
405 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ 405 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
406 __uint8_t m_dirversion; /* 1 or 2 */
407 xfs_dirops_t m_dirops; /* table of dir funcs */
408 int m_dirblksize; /* directory block sz--bytes */ 406 int m_dirblksize; /* directory block sz--bytes */
409 int m_dirblkfsbs; /* directory block sz--fsbs */ 407 int m_dirblkfsbs; /* directory block sz--fsbs */
410 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ 408 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c
index 1408a32eef88..320d63ff9ca2 100644
--- a/fs/xfs/xfs_qmops.c
+++ b/fs/xfs/xfs_qmops.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_dmapi.h" 27#include "xfs_dmapi.h"
29#include "xfs_mount.h" 28#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 7d5f9b6ffdb8..d98171deaa1c 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -22,13 +22,11 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.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_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
@@ -40,7 +38,6 @@
40#include "xfs_refcache.h" 38#include "xfs_refcache.h"
41#include "xfs_utils.h" 39#include "xfs_utils.h"
42#include "xfs_trans_space.h" 40#include "xfs_trans_space.h"
43#include "xfs_dir_leaf.h"
44 41
45 42
46/* 43/*
@@ -398,34 +395,29 @@ xfs_rename(
398 * fit before actually inserting it. 395 * fit before actually inserting it.
399 */ 396 */
400 if (spaceres == 0 && 397 if (spaceres == 0 &&
401 (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name, 398 (error = xfs_dir_canenter(tp, target_dp, target_name,
402 target_namelen))) { 399 target_namelen)))
403 goto error_return; 400 goto error_return;
404 }
405 /* 401 /*
406 * If target does not exist and the rename crosses 402 * If target does not exist and the rename crosses
407 * directories, adjust the target directory link count 403 * directories, adjust the target directory link count
408 * to account for the ".." reference from the new entry. 404 * to account for the ".." reference from the new entry.
409 */ 405 */
410 error = XFS_DIR_CREATENAME(mp, tp, target_dp, target_name, 406 error = xfs_dir_createname(tp, target_dp, target_name,
411 target_namelen, src_ip->i_ino, 407 target_namelen, src_ip->i_ino,
412 &first_block, &free_list, spaceres); 408 &first_block, &free_list, spaceres);
413 if (error == ENOSPC) { 409 if (error == ENOSPC)
414 goto error_return; 410 goto error_return;
415 } 411 if (error)
416 if (error) {
417 goto abort_return; 412 goto abort_return;
418 }
419 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 413 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
420 414
421 if (new_parent && src_is_directory) { 415 if (new_parent && src_is_directory) {
422 error = xfs_bumplink(tp, target_dp); 416 error = xfs_bumplink(tp, target_dp);
423 if (error) { 417 if (error)
424 goto abort_return; 418 goto abort_return;
425 }
426 } 419 }
427 } else { /* target_ip != NULL */ 420 } else { /* target_ip != NULL */
428
429 /* 421 /*
430 * If target exists and it's a directory, check that both 422 * If target exists and it's a directory, check that both
431 * target and source are directories and that target can be 423 * target and source are directories and that target can be
@@ -435,7 +427,7 @@ xfs_rename(
435 /* 427 /*
436 * Make sure target dir is empty. 428 * Make sure target dir is empty.
437 */ 429 */
438 if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) || 430 if (!(xfs_dir_isempty(target_ip)) ||
439 (target_ip->i_d.di_nlink > 2)) { 431 (target_ip->i_d.di_nlink > 2)) {
440 error = XFS_ERROR(EEXIST); 432 error = XFS_ERROR(EEXIST);
441 goto error_return; 433 goto error_return;
@@ -451,12 +443,11 @@ xfs_rename(
451 * In case there is already an entry with the same 443 * In case there is already an entry with the same
452 * name at the destination directory, remove it first. 444 * name at the destination directory, remove it first.
453 */ 445 */
454 error = XFS_DIR_REPLACE(mp, tp, target_dp, target_name, 446 error = xfs_dir_replace(tp, target_dp, target_name,
455 target_namelen, src_ip->i_ino, &first_block, 447 target_namelen, src_ip->i_ino,
456 &free_list, spaceres); 448 &first_block, &free_list, spaceres);
457 if (error) { 449 if (error)
458 goto abort_return; 450 goto abort_return;
459 }
460 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 451 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
461 452
462 /* 453 /*
@@ -464,9 +455,8 @@ xfs_rename(
464 * dir no longer points to it. 455 * dir no longer points to it.
465 */ 456 */
466 error = xfs_droplink(tp, target_ip); 457 error = xfs_droplink(tp, target_ip);
467 if (error) { 458 if (error)
468 goto abort_return; 459 goto abort_return;
469 }
470 target_ip_dropped = 1; 460 target_ip_dropped = 1;
471 461
472 if (src_is_directory) { 462 if (src_is_directory) {
@@ -474,9 +464,8 @@ xfs_rename(
474 * Drop the link from the old "." entry. 464 * Drop the link from the old "." entry.
475 */ 465 */
476 error = xfs_droplink(tp, target_ip); 466 error = xfs_droplink(tp, target_ip);
477 if (error) { 467 if (error)
478 goto abort_return; 468 goto abort_return;
479 }
480 } 469 }
481 470
482 /* Do this test while we still hold the locks */ 471 /* Do this test while we still hold the locks */
@@ -488,18 +477,15 @@ xfs_rename(
488 * Remove the source. 477 * Remove the source.
489 */ 478 */
490 if (new_parent && src_is_directory) { 479 if (new_parent && src_is_directory) {
491
492 /* 480 /*
493 * Rewrite the ".." entry to point to the new 481 * Rewrite the ".." entry to point to the new
494 * directory. 482 * directory.
495 */ 483 */
496 error = XFS_DIR_REPLACE(mp, tp, src_ip, "..", 2, 484 error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino,
497 target_dp->i_ino, &first_block, 485 &first_block, &free_list, spaceres);
498 &free_list, spaceres);
499 ASSERT(error != EEXIST); 486 ASSERT(error != EEXIST);
500 if (error) { 487 if (error)
501 goto abort_return; 488 goto abort_return;
502 }
503 xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 489 xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
504 490
505 } else { 491 } else {
@@ -527,16 +513,14 @@ xfs_rename(
527 * entry that's moved no longer points to it. 513 * entry that's moved no longer points to it.
528 */ 514 */
529 error = xfs_droplink(tp, src_dp); 515 error = xfs_droplink(tp, src_dp);
530 if (error) { 516 if (error)
531 goto abort_return; 517 goto abort_return;
532 }
533 } 518 }
534 519
535 error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen, 520 error = xfs_dir_removename(tp, src_dp, src_name, src_namelen,
536 src_ip->i_ino, &first_block, &free_list, spaceres); 521 src_ip->i_ino, &first_block, &free_list, spaceres);
537 if (error) { 522 if (error)
538 goto abort_return; 523 goto abort_return;
539 }
540 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 524 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
541 525
542 /* 526 /*
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index af290cf37ac1..0c1e42b037ef 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index c55e28189aba..defb2febaaf5 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 39f0b1ed3224..ee2721e0de4d 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 100d9a4b38ee..cb65c3a603f5 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -805,12 +805,9 @@ typedef struct xfs_trans {
805 ((mp)->m_sb.sb_inodesize + \ 805 ((mp)->m_sb.sb_inodesize + \
806 (mp)->m_sb.sb_sectsize * 2 + \ 806 (mp)->m_sb.sb_sectsize * 2 + \
807 (mp)->m_dirblksize + \ 807 (mp)->m_dirblksize + \
808 (XFS_DIR_IS_V1(mp) ? 0 : \ 808 XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \
809 XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1))) + \
810 XFS_ALLOCFREE_LOG_RES(mp, 1) + \ 809 XFS_ALLOCFREE_LOG_RES(mp, 1) + \
811 (128 * (4 + \ 810 (128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
812 (XFS_DIR_IS_V1(mp) ? 0 : \
813 XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
814 XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) 811 XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
815 812
816#define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork) 813#define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork)
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index e1ca7b6fde42..558c87ff0c41 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -22,7 +22,6 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dmapi.h" 25#include "xfs_dmapi.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
28#include "xfs_trans_priv.h" 27#include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 8cedd1583bc8..60b6b898022b 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index 7d7d627f25df..b290270dd4a6 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -22,7 +22,6 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dmapi.h" 25#include "xfs_dmapi.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
28#include "xfs_trans_priv.h" 27#include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 7c5894d59f81..b8db1d5cde5a 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -24,14 +24,12 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h
index 7fe3792b18df..4ea2e5074bdd 100644
--- a/fs/xfs/xfs_trans_space.h
+++ b/fs/xfs/xfs_trans_space.h
@@ -30,8 +30,7 @@
30 XFS_EXTENTADD_SPACE_RES(mp,w)) 30 XFS_EXTENTADD_SPACE_RES(mp,w))
31#define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1) 31#define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1)
32#define XFS_DAENTER_DBS(mp,w) \ 32#define XFS_DAENTER_DBS(mp,w) \
33 (XFS_DA_NODE_MAXDEPTH + \ 33 (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0))
34 ((XFS_DIR_IS_V2(mp) && (w) == XFS_DATA_FORK) ? 2 : 0))
35#define XFS_DAENTER_BLOCKS(mp,w) \ 34#define XFS_DAENTER_BLOCKS(mp,w) \
36 (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w)) 35 (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
37#define XFS_DAENTER_BMAP1B(mp,w) \ 36#define XFS_DAENTER_BMAP1B(mp,w) \
@@ -41,10 +40,7 @@
41#define XFS_DAENTER_SPACE_RES(mp,w) \ 40#define XFS_DAENTER_SPACE_RES(mp,w) \
42 (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w)) 41 (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w))
43#define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w) 42#define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w)
44#define XFS_DIRENTER_MAX_SPLIT(mp,nl) \ 43#define XFS_DIRENTER_MAX_SPLIT(mp,nl) 1
45 (((mp)->m_sb.sb_blocksize == 512 && \
46 XFS_DIR_IS_V1(mp) && \
47 (nl) >= XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN) ? 2 : 1)
48#define XFS_DIRENTER_SPACE_RES(mp,nl) \ 44#define XFS_DIRENTER_SPACE_RES(mp,nl) \
49 (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \ 45 (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \
50 XFS_DIRENTER_MAX_SPLIT(mp,nl)) 46 XFS_DIRENTER_MAX_SPLIT(mp,nl))
@@ -57,8 +53,7 @@
57 * Space reservation values for various transactions. 53 * Space reservation values for various transactions.
58 */ 54 */
59#define XFS_ADDAFORK_SPACE_RES(mp) \ 55#define XFS_ADDAFORK_SPACE_RES(mp) \
60 ((mp)->m_dirblkfsbs + \ 56 ((mp)->m_dirblkfsbs + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
61 (XFS_DIR_IS_V1(mp) ? 0 : XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)))
62#define XFS_ATTRRM_SPACE_RES(mp) \ 57#define XFS_ATTRRM_SPACE_RES(mp) \
63 XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) 58 XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
64/* This macro is not used - see inline code in xfs_attr_set */ 59/* This macro is not used - see inline code in xfs_attr_set */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 37fdc2dc00b4..9014d7e44488 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -24,12 +24,10 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_dir_sf.h"
33#include "xfs_dir2_sf.h" 31#include "xfs_dir2_sf.h"
34#include "xfs_attr_sf.h" 32#include "xfs_attr_sf.h"
35#include "xfs_dinode.h" 33#include "xfs_dinode.h"
@@ -82,8 +80,7 @@ xfs_dir_lookup_int(
82 80
83 dp = XFS_BHVTOI(dir_bdp); 81 dp = XFS_BHVTOI(dir_bdp);
84 82
85 error = XFS_DIR_LOOKUP(dp->i_mount, NULL, dp, 83 error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
86 VNAME(dentry), VNAMELEN(dentry), inum);
87 if (!error) { 84 if (!error) {
88 /* 85 /*
89 * Unlock the directory. We do this because we can't 86 * Unlock the directory. We do this because we can't
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 918531b64787..6c96391f3f1a 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -24,7 +24,6 @@
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_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -131,9 +129,6 @@ xfs_init(void)
131#ifdef XFS_BMBT_TRACE 129#ifdef XFS_BMBT_TRACE
132 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP); 130 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);
133#endif 131#endif
134#ifdef XFS_DIR_TRACE
135 xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_TRACE_SIZE, KM_SLEEP);
136#endif
137#ifdef XFS_ATTR_TRACE 132#ifdef XFS_ATTR_TRACE
138 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP); 133 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);
139#endif 134#endif
@@ -177,9 +172,6 @@ xfs_cleanup(void)
177#ifdef XFS_ATTR_TRACE 172#ifdef XFS_ATTR_TRACE
178 ktrace_free(xfs_attr_trace_buf); 173 ktrace_free(xfs_attr_trace_buf);
179#endif 174#endif
180#ifdef XFS_DIR_TRACE
181 ktrace_free(xfs_dir_trace_buf);
182#endif
183#ifdef XFS_BMBT_TRACE 175#ifdef XFS_BMBT_TRACE
184 ktrace_free(xfs_bmbt_trace_buf); 176 ktrace_free(xfs_bmbt_trace_buf);
185#endif 177#endif
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 26d96d1b25cd..00a6b7dc24a0 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -25,7 +25,6 @@
25#include "xfs_trans.h" 25#include "xfs_trans.h"
26#include "xfs_sb.h" 26#include "xfs_sb.h"
27#include "xfs_ag.h" 27#include "xfs_ag.h"
28#include "xfs_dir.h"
29#include "xfs_dir2.h" 28#include "xfs_dir2.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
31#include "xfs_mount.h" 30#include "xfs_mount.h"
@@ -33,13 +32,11 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
40#include "xfs_inode.h" 38#include "xfs_inode.h"
41#include "xfs_inode_item.h" 39#include "xfs_inode_item.h"
42#include "xfs_dir_leaf.h"
43#include "xfs_itable.h" 40#include "xfs_itable.h"
44#include "xfs_btree.h" 41#include "xfs_btree.h"
45#include "xfs_ialloc.h" 42#include "xfs_ialloc.h"
@@ -1958,8 +1955,7 @@ xfs_create(
1958 if (error) 1955 if (error)
1959 goto error_return; 1956 goto error_return;
1960 1957
1961 if (resblks == 0 && 1958 if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen)))
1962 (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen)))
1963 goto error_return; 1959 goto error_return;
1964 rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0; 1960 rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0;
1965 error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1, 1961 error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1,
@@ -1990,9 +1986,9 @@ xfs_create(
1990 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); 1986 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
1991 dp_joined_to_trans = B_TRUE; 1987 dp_joined_to_trans = B_TRUE;
1992 1988
1993 error = XFS_DIR_CREATENAME(mp, tp, dp, name, namelen, ip->i_ino, 1989 error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino,
1994 &first_block, &free_list, 1990 &first_block, &free_list, resblks ?
1995 resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); 1991 resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
1996 if (error) { 1992 if (error) {
1997 ASSERT(error != ENOSPC); 1993 ASSERT(error != ENOSPC);
1998 goto abort_return; 1994 goto abort_return;
@@ -2468,8 +2464,8 @@ xfs_remove(
2468 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. 2464 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
2469 */ 2465 */
2470 XFS_BMAP_INIT(&free_list, &first_block); 2466 XFS_BMAP_INIT(&free_list, &first_block);
2471 error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, ip->i_ino, 2467 error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino,
2472 &first_block, &free_list, 0); 2468 &first_block, &free_list, 0);
2473 if (error) { 2469 if (error) {
2474 ASSERT(error != ENOENT); 2470 ASSERT(error != ENOENT);
2475 REMOVE_DEBUG_TRACE(__LINE__); 2471 REMOVE_DEBUG_TRACE(__LINE__);
@@ -2688,13 +2684,12 @@ xfs_link(
2688 } 2684 }
2689 2685
2690 if (resblks == 0 && 2686 if (resblks == 0 &&
2691 (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name, 2687 (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen)))
2692 target_namelen)))
2693 goto error_return; 2688 goto error_return;
2694 2689
2695 XFS_BMAP_INIT(&free_list, &first_block); 2690 XFS_BMAP_INIT(&free_list, &first_block);
2696 2691
2697 error = XFS_DIR_CREATENAME(mp, tp, tdp, target_name, target_namelen, 2692 error = xfs_dir_createname(tp, tdp, target_name, target_namelen,
2698 sip->i_ino, &first_block, &free_list, 2693 sip->i_ino, &first_block, &free_list,
2699 resblks); 2694 resblks);
2700 if (error) 2695 if (error)
@@ -2860,7 +2855,7 @@ xfs_mkdir(
2860 goto error_return; 2855 goto error_return;
2861 2856
2862 if (resblks == 0 && 2857 if (resblks == 0 &&
2863 (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen))) 2858 (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen)))
2864 goto error_return; 2859 goto error_return;
2865 /* 2860 /*
2866 * create the directory inode. 2861 * create the directory inode.
@@ -2887,9 +2882,9 @@ xfs_mkdir(
2887 2882
2888 XFS_BMAP_INIT(&free_list, &first_block); 2883 XFS_BMAP_INIT(&free_list, &first_block);
2889 2884
2890 error = XFS_DIR_CREATENAME(mp, tp, dp, dir_name, dir_namelen, 2885 error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino,
2891 cdp->i_ino, &first_block, &free_list, 2886 &first_block, &free_list, resblks ?
2892 resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); 2887 resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
2893 if (error) { 2888 if (error) {
2894 ASSERT(error != ENOSPC); 2889 ASSERT(error != ENOSPC);
2895 goto error1; 2890 goto error1;
@@ -2903,16 +2898,14 @@ xfs_mkdir(
2903 */ 2898 */
2904 dp->i_gen++; 2899 dp->i_gen++;
2905 2900
2906 error = XFS_DIR_INIT(mp, tp, cdp, dp); 2901 error = xfs_dir_init(tp, cdp, dp);
2907 if (error) { 2902 if (error)
2908 goto error2; 2903 goto error2;
2909 }
2910 2904
2911 cdp->i_gen = 1; 2905 cdp->i_gen = 1;
2912 error = xfs_bumplink(tp, dp); 2906 error = xfs_bumplink(tp, dp);
2913 if (error) { 2907 if (error)
2914 goto error2; 2908 goto error2;
2915 }
2916 2909
2917 cvp = XFS_ITOV(cdp); 2910 cvp = XFS_ITOV(cdp);
2918 2911
@@ -3121,16 +3114,15 @@ xfs_rmdir(
3121 error = XFS_ERROR(ENOTEMPTY); 3114 error = XFS_ERROR(ENOTEMPTY);
3122 goto error_return; 3115 goto error_return;
3123 } 3116 }
3124 if (!XFS_DIR_ISEMPTY(mp, cdp)) { 3117 if (!xfs_dir_isempty(cdp)) {
3125 error = XFS_ERROR(ENOTEMPTY); 3118 error = XFS_ERROR(ENOTEMPTY);
3126 goto error_return; 3119 goto error_return;
3127 } 3120 }
3128 3121
3129 error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, cdp->i_ino, 3122 error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino,
3130 &first_block, &free_list, resblks); 3123 &first_block, &free_list, resblks);
3131 if (error) { 3124 if (error)
3132 goto error1; 3125 goto error1;
3133 }
3134 3126
3135 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 3127 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
3136 3128
@@ -3229,8 +3221,6 @@ xfs_rmdir(
3229 3221
3230 3222
3231/* 3223/*
3232 * xfs_readdir
3233 *
3234 * Read dp's entries starting at uiop->uio_offset and translate them into 3224 * Read dp's entries starting at uiop->uio_offset and translate them into
3235 * bufsize bytes worth of struct dirents starting at bufbase. 3225 * bufsize bytes worth of struct dirents starting at bufbase.
3236 */ 3226 */
@@ -3250,21 +3240,16 @@ xfs_readdir(
3250 (inst_t *)__return_address); 3240 (inst_t *)__return_address);
3251 dp = XFS_BHVTOI(dir_bdp); 3241 dp = XFS_BHVTOI(dir_bdp);
3252 3242
3253 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) { 3243 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
3254 return XFS_ERROR(EIO); 3244 return XFS_ERROR(EIO);
3255 }
3256 3245
3257 lock_mode = xfs_ilock_map_shared(dp); 3246 lock_mode = xfs_ilock_map_shared(dp);
3258 error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); 3247 error = xfs_dir_getdents(tp, dp, uiop, eofp);
3259 xfs_iunlock_map_shared(dp, lock_mode); 3248 xfs_iunlock_map_shared(dp, lock_mode);
3260 return error; 3249 return error;
3261} 3250}
3262 3251
3263 3252
3264/*
3265 * xfs_symlink
3266 *
3267 */
3268STATIC int 3253STATIC int
3269xfs_symlink( 3254xfs_symlink(
3270 bhv_desc_t *dir_bdp, 3255 bhv_desc_t *dir_bdp,
@@ -3328,7 +3313,7 @@ xfs_symlink(
3328 int len, total; 3313 int len, total;
3329 char *path; 3314 char *path;
3330 3315
3331 for(total = 0, path = target_path; total < pathlen;) { 3316 for (total = 0, path = target_path; total < pathlen;) {
3332 /* 3317 /*
3333 * Skip any slashes. 3318 * Skip any slashes.
3334 */ 3319 */
@@ -3422,7 +3407,7 @@ xfs_symlink(
3422 * Check for ability to enter directory entry, if no space reserved. 3407 * Check for ability to enter directory entry, if no space reserved.
3423 */ 3408 */
3424 if (resblks == 0 && 3409 if (resblks == 0 &&
3425 (error = XFS_DIR_CANENTER(mp, tp, dp, link_name, link_namelen))) 3410 (error = xfs_dir_canenter(tp, dp, link_name, link_namelen)))
3426 goto error_return; 3411 goto error_return;
3427 /* 3412 /*
3428 * Initialize the bmap freelist prior to calling either 3413 * Initialize the bmap freelist prior to calling either
@@ -3509,11 +3494,10 @@ xfs_symlink(
3509 /* 3494 /*
3510 * Create the directory entry for the symlink. 3495 * Create the directory entry for the symlink.
3511 */ 3496 */
3512 error = XFS_DIR_CREATENAME(mp, tp, dp, link_name, link_namelen, 3497 error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino,
3513 ip->i_ino, &first_block, &free_list, resblks); 3498 &first_block, &free_list, resblks);
3514 if (error) { 3499 if (error)
3515 goto error1; 3500 goto error1;
3516 }
3517 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 3501 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
3518 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 3502 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
3519 3503