diff options
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; | ||
1992 | done: | ||
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 | |||
47 | typedef struct xfs_da_blkinfo { | 43 | typedef 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 | */ | ||
57 | static void xfs_dir_mount(struct xfs_mount *mp); | ||
58 | |||
59 | static int xfs_dir_isempty(struct xfs_inode *dp); | ||
60 | |||
61 | static int xfs_dir_init(struct xfs_trans *trans, | ||
62 | struct xfs_inode *dir, | ||
63 | struct xfs_inode *parent_dir); | ||
64 | |||
65 | static 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 | |||
74 | static 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 | |||
80 | static 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 | |||
89 | static int xfs_dir_getdents(struct xfs_trans *tp, | ||
90 | struct xfs_inode *dp, | ||
91 | struct uio *uiop, | ||
92 | int *eofp); | ||
93 | |||
94 | static 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 | |||
103 | static int xfs_dir_canenter(struct xfs_trans *tp, | ||
104 | struct xfs_inode *dp, | ||
105 | char *name_string, | ||
106 | int name_length); | ||
107 | |||
108 | static int xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, | ||
109 | xfs_dinode_t *dip); | ||
110 | |||
111 | xfs_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 | */ | ||
128 | STATIC int xfs_dir_leaf_lookup(xfs_da_args_t *args); | ||
129 | STATIC int xfs_dir_leaf_removename(xfs_da_args_t *args, int *number_entries, | ||
130 | int *total_namebytes); | ||
131 | STATIC 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); | ||
135 | STATIC int xfs_dir_leaf_replace(xfs_da_args_t *args); | ||
136 | |||
137 | /* | ||
138 | * Internal routines when dirsize > XFS_LBSIZE(mp). | ||
139 | */ | ||
140 | STATIC int xfs_dir_node_addname(xfs_da_args_t *args); | ||
141 | STATIC int xfs_dir_node_lookup(xfs_da_args_t *args); | ||
142 | STATIC int xfs_dir_node_removename(xfs_da_args_t *args); | ||
143 | STATIC 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); | ||
147 | STATIC int xfs_dir_node_replace(xfs_da_args_t *args); | ||
148 | |||
149 | #if defined(XFS_DIR_TRACE) | ||
150 | ktrace_t *xfs_dir_trace_buf; | ||
151 | #endif | ||
152 | |||
153 | |||
154 | /*======================================================================== | ||
155 | * Overall external interface routines. | ||
156 | *========================================================================*/ | ||
157 | |||
158 | xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; | ||
159 | |||
160 | /* | ||
161 | * One-time startup routine called from xfs_init(). | ||
162 | */ | ||
163 | void | ||
164 | xfs_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 | */ | ||
173 | static void | ||
174 | xfs_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 | */ | ||
210 | static int | ||
211 | xfs_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 | */ | ||
227 | static int | ||
228 | xfs_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 | */ | ||
248 | static int /* error */ | ||
249 | xfs_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 | */ | ||
314 | static int /* error */ | ||
315 | xfs_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 | */ | ||
357 | static int /* error */ | ||
358 | xfs_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 | |||
401 | static int /* error */ | ||
402 | xfs_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 | */ | ||
446 | static int /* error */ | ||
447 | xfs_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 | |||
490 | static int /* error */ | ||
491 | xfs_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 | |||
532 | static int | ||
533 | xfs_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 | */ | ||
601 | int | ||
602 | xfs_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 | */ | ||
624 | STATIC int | ||
625 | xfs_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 | */ | ||
653 | STATIC int | ||
654 | xfs_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 | */ | ||
672 | STATIC int | ||
673 | xfs_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 | */ | ||
693 | STATIC int | ||
694 | xfs_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 | */ | ||
737 | STATIC int | ||
738 | xfs_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 | } | ||
781 | error: | ||
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 | */ | ||
794 | STATIC int | ||
795 | xfs_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 | */ | ||
844 | STATIC int | ||
845 | xfs_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 | |||
877 | STATIC int | ||
878 | xfs_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 | */ | ||
1028 | STATIC int | ||
1029 | xfs_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 | */ | ||
1088 | void | ||
1089 | xfs_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 | */ | ||
1102 | void | ||
1103 | xfs_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 | */ | ||
1117 | void | ||
1118 | xfs_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 | */ | ||
1141 | void | ||
1142 | xfs_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 | */ | ||
1162 | void | ||
1163 | xfs_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 | */ | ||
1178 | void | ||
1179 | xfs_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 | */ | ||
1195 | void | ||
1196 | xfs_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 | |||
36 | struct uio; | ||
37 | struct xfs_bmap_free; | ||
38 | struct xfs_da_args; | ||
39 | struct xfs_dinode; | ||
40 | struct xfs_inode; | ||
41 | struct xfs_mount; | ||
42 | struct xfs_trans; | ||
43 | |||
44 | /* | ||
45 | * Directory function types. | ||
46 | * Put in structures (xfs_dirops_t) for v1 and v2 directories. | ||
47 | */ | ||
48 | typedef void (*xfs_dir_mount_t)(struct xfs_mount *mp); | ||
49 | typedef int (*xfs_dir_isempty_t)(struct xfs_inode *dp); | ||
50 | typedef int (*xfs_dir_init_t)(struct xfs_trans *tp, | ||
51 | struct xfs_inode *dp, | ||
52 | struct xfs_inode *pdp); | ||
53 | typedef 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); | ||
61 | typedef 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); | ||
66 | typedef 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); | ||
74 | typedef int (*xfs_dir_getdents_t)(struct xfs_trans *tp, | ||
75 | struct xfs_inode *dp, | ||
76 | struct uio *uio, | ||
77 | int *eofp); | ||
78 | typedef 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); | ||
86 | typedef int (*xfs_dir_canenter_t)(struct xfs_trans *tp, | ||
87 | struct xfs_inode *dp, | ||
88 | char *name, | ||
89 | int namelen); | ||
90 | typedef int (*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp, | ||
91 | struct xfs_dinode *dip); | ||
92 | typedef int (*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args); | ||
93 | |||
94 | typedef 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 | */ | ||
111 | void 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) | ||
139 | extern xfs_dirops_t xfsv1_dirops; | ||
140 | extern 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 | */ | ||
52 | static void xfs_dir2_mount(xfs_mount_t *mp); | ||
53 | static int xfs_dir2_isempty(xfs_inode_t *dp); | ||
54 | static int xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp, | ||
55 | xfs_inode_t *pdp); | ||
56 | static 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); | ||
60 | static int xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name, | ||
61 | int namelen, xfs_ino_t *inum); | ||
62 | static 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); | ||
66 | static int xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio, | ||
67 | int *eofp); | ||
68 | static 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); | ||
72 | static int xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name, | ||
73 | int namelen); | ||
74 | static int xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp, | ||
75 | xfs_dinode_t *dip); | ||
76 | |||
77 | /* | ||
78 | * Utility routine declarations. | ||
79 | */ | ||
80 | static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); | 46 | static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); |
81 | static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); | 47 | static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); |
82 | 48 | ||
83 | /* | 49 | void |
84 | * Directory operations vector. | 50 | xfs_dir_mount( |
85 | */ | 51 | xfs_mount_t *mp) |
86 | xfs_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 | */ | ||
107 | static void | ||
108 | xfs_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 | */ |
131 | static int /* return code */ | 73 | int |
132 | xfs_dir2_isempty( | 74 | xfs_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 | */ | ||
91 | int | ||
92 | xfs_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 | */ |
153 | static int /* error */ | 125 | int |
154 | xfs_dir2_init( | 126 | xfs_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 | */ |
175 | static int /* error */ | 146 | int |
176 | xfs_dir2_createname( | 147 | xfs_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 | */ |
231 | static int /* error */ | 197 | int |
232 | xfs_dir2_lookup( | 198 | xfs_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 | */ |
286 | static int /* error */ | 247 | int |
287 | xfs_dir2_removename( | 248 | xfs_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 | */ |
338 | static int /* error */ | 295 | int |
339 | xfs_dir2_getdents( | 296 | xfs_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 | */ |
389 | static int /* error */ | 343 | int |
390 | xfs_dir2_replace( | 344 | xfs_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 | */ |
444 | static int /* error */ | 393 | int |
445 | xfs_dir2_canenter( | 394 | xfs_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 */ | ||
493 | static int /* error */ | ||
494 | xfs_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 | */ |
510 | int /* error */ | 442 | int |
511 | xfs_dir2_grow_inode( | 443 | xfs_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 = ↦ | 487 | mapp = ↦ |
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 | */ |
649 | int /* error */ | 576 | int |
650 | xfs_dir2_isblock( | 577 | xfs_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 | */ |
672 | int /* error */ | 598 | int |
673 | xfs_dir2_isleaf( | 599 | xfs_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 | */ |
693 | static int /* error */ | 618 | static int |
694 | xfs_dir2_put_dirent64_direct( | 619 | xfs_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 | */ |
730 | static int /* error */ | 655 | static int |
731 | xfs_dir2_put_dirent64_uio( | 656 | xfs_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 | */ |
766 | int | 691 | int |
767 | xfs_dir2_shrink_inode( | 692 | xfs_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; | |||
22 | struct xfs_dabuf; | 22 | struct xfs_dabuf; |
23 | struct xfs_da_args; | 23 | struct xfs_da_args; |
24 | struct xfs_dir2_put_args; | 24 | struct xfs_dir2_put_args; |
25 | struct xfs_bmap_free; | ||
25 | struct xfs_inode; | 26 | struct xfs_inode; |
27 | struct xfs_mount; | ||
26 | struct xfs_trans; | 28 | struct 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 | */ | ||
80 | extern void xfs_dir_startup(void); | ||
81 | extern void xfs_dir_mount(struct xfs_mount *mp); | ||
82 | extern int xfs_dir_isempty(struct xfs_inode *dp); | ||
83 | extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, | ||
84 | struct xfs_inode *pdp); | ||
85 | extern 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); | ||
89 | extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, | ||
90 | char *name, int namelen, xfs_ino_t *inum); | ||
91 | extern 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); | ||
95 | extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp, | ||
96 | uio_t *uio, int *eofp); | ||
97 | extern 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); | ||
101 | extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, | ||
102 | char *name, int namelen); | ||
103 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); | ||
104 | |||
105 | /* | ||
106 | * Utility routines for v2 directories. | ||
77 | */ | 107 | */ |
78 | extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, | 108 | extern 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); |
52 | static int xfs_dir2_block_sort(const void *a, const void *b); | 49 | static int xfs_dir2_block_sort(const void *a, const void *b); |
53 | 50 | ||
51 | static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; | ||
52 | |||
53 | /* | ||
54 | * One-time startup routine called from xfs_init(). | ||
55 | */ | ||
56 | void | ||
57 | xfs_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 | */ | ||
58 | STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args, | ||
59 | int insertion_index, | ||
60 | int freemap_index); | ||
61 | STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer, | ||
62 | int musthave, int justcheck); | ||
63 | STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state, | ||
64 | xfs_da_state_blk_t *blk1, | ||
65 | xfs_da_state_blk_t *blk2); | ||
66 | STATIC 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 | |||
72 | STATIC 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 | */ | ||
79 | STATIC 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 | */ | ||
94 | int | ||
95 | xfs_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 | */ | ||
126 | int | ||
127 | xfs_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 | */ | ||
157 | int | ||
158 | xfs_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 | */ | ||
207 | int | ||
208 | xfs_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 | */ | ||
260 | int | ||
261 | xfs_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 | */ | ||
307 | int | ||
308 | xfs_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 | |||
391 | out: | ||
392 | kmem_free(tmpbuffer, size); | ||
393 | return retval; | ||
394 | } | ||
395 | |||
396 | STATIC int | ||
397 | xfs_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*/ | ||
415 | int | ||
416 | xfs_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 | */ | ||
572 | int | ||
573 | xfs_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 | */ | ||
621 | int | ||
622 | xfs_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 | |||
695 | out: | ||
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 | */ | ||
703 | int | ||
704 | xfs_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 | */ | ||
765 | STATIC int | ||
766 | xfs_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 | */ | ||
800 | int | ||
801 | xfs_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 | */ | ||
854 | int | ||
855 | xfs_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 | */ | ||
929 | STATIC void | ||
930 | xfs_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 | */ | ||
1012 | STATIC int | ||
1013 | xfs_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 | */ | ||
1089 | STATIC void | ||
1090 | xfs_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 | */ | ||
1221 | STATIC int | ||
1222 | xfs_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 | */ | ||
1319 | int | ||
1320 | xfs_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 | */ | ||
1445 | int | ||
1446 | xfs_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 | */ | ||
1598 | void | ||
1599 | xfs_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 | */ | ||
1703 | int | ||
1704 | xfs_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 */ | ||
1785 | STATIC void | ||
1786 | xfs_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 | */ | ||
1901 | int | ||
1902 | xfs_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 | */ | ||
1925 | xfs_dahash_t | ||
1926 | xfs_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 | */ | ||
1942 | int | ||
1943 | xfs_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 | */ | ||
2175 | int | ||
2176 | xfs_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 | */ | ||
2207 | int | ||
2208 | xfs_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 | |||
31 | struct uio; | ||
32 | struct xfs_bmap_free; | ||
33 | struct xfs_dabuf; | ||
34 | struct xfs_da_args; | ||
35 | struct xfs_da_state; | ||
36 | struct xfs_da_state_blk; | ||
37 | struct xfs_dir_put_args; | ||
38 | struct xfs_inode; | ||
39 | struct xfs_mount; | ||
40 | struct 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 | |||
70 | typedef 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 | |||
75 | typedef 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 | |||
85 | typedef 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 | |||
92 | typedef 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 | |||
97 | typedef 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 | |||
112 | typedef int (*xfs_dir_put_t)(struct xfs_dir_put_args *pa); | ||
113 | |||
114 | typedef 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 | |||
133 | typedef 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) | ||
146 | static 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) | ||
153 | static 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) | ||
160 | static inline xfs_dir_leaf_name_t * | ||
161 | xfs_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 | */ | ||
173 | int xfs_dir_shortform_create(struct xfs_da_args *args, xfs_ino_t parent); | ||
174 | int xfs_dir_shortform_addname(struct xfs_da_args *args); | ||
175 | int xfs_dir_shortform_lookup(struct xfs_da_args *args); | ||
176 | int xfs_dir_shortform_to_leaf(struct xfs_da_args *args); | ||
177 | int xfs_dir_shortform_removename(struct xfs_da_args *args); | ||
178 | int xfs_dir_shortform_getdents(struct xfs_inode *dp, struct uio *uio, int *eofp, | ||
179 | struct xfs_dirent *dbp, xfs_dir_put_t put); | ||
180 | int xfs_dir_shortform_replace(struct xfs_da_args *args); | ||
181 | |||
182 | /* | ||
183 | * Internal routines when dirsize == XFS_LBSIZE(mp). | ||
184 | */ | ||
185 | int xfs_dir_leaf_to_node(struct xfs_da_args *args); | ||
186 | int xfs_dir_leaf_to_shortform(struct xfs_da_args *args); | ||
187 | |||
188 | /* | ||
189 | * Routines used for growing the Btree. | ||
190 | */ | ||
191 | int xfs_dir_leaf_split(struct xfs_da_state *state, | ||
192 | struct xfs_da_state_blk *oldblk, | ||
193 | struct xfs_da_state_blk *newblk); | ||
194 | int xfs_dir_leaf_add(struct xfs_dabuf *leaf_buffer, | ||
195 | struct xfs_da_args *args, int insertion_index); | ||
196 | int xfs_dir_leaf_addname(struct xfs_da_args *args); | ||
197 | int xfs_dir_leaf_lookup_int(struct xfs_dabuf *leaf_buffer, | ||
198 | struct xfs_da_args *args, | ||
199 | int *index_found_at); | ||
200 | int xfs_dir_leaf_remove(struct xfs_trans *trans, | ||
201 | struct xfs_dabuf *leaf_buffer, | ||
202 | int index_to_remove); | ||
203 | int 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 | */ | ||
211 | int xfs_dir_leaf_toosmall(struct xfs_da_state *state, int *retval); | ||
212 | void 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 | */ | ||
219 | uint xfs_dir_leaf_lasthash(struct xfs_dabuf *bp, int *count); | ||
220 | int xfs_dir_leaf_order(struct xfs_dabuf *leaf1_bp, | ||
221 | struct xfs_dabuf *leaf2_bp); | ||
222 | int xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa); | ||
223 | int xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa); | ||
224 | int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); | ||
225 | |||
226 | /* | ||
227 | * Global data. | ||
228 | */ | ||
229 | extern 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 | |||
28 | typedef 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 | */ | ||
38 | typedef 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 | |||
43 | typedef 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 | |||
49 | typedef 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 | */ | ||
58 | typedef 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) | ||
68 | static 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) | ||
74 | static 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) | ||
80 | static 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) | ||
86 | static 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) | ||
92 | static 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) | ||
100 | static 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 | */ | ||
111 | struct uio; | ||
112 | struct xfs_inode; | ||
113 | struct xfs_da_intnode; | ||
114 | struct xfs_dinode; | ||
115 | struct xfs_dir_leafblock; | ||
116 | struct xfs_dir_leaf_entry; | ||
117 | |||
118 | #define XFS_DIR_TRACE_SIZE 4096 /* size of global trace buffer */ | ||
119 | extern 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 | |||
131 | void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio); | ||
132 | void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio, | ||
133 | xfs_dablk_t bno); | ||
134 | void xfs_dir_trace_g_dun(char *where, struct xfs_inode *dp, struct uio *uio, | ||
135 | struct xfs_da_intnode *node); | ||
136 | void xfs_dir_trace_g_dul(char *where, struct xfs_inode *dp, struct uio *uio, | ||
137 | struct xfs_dir_leafblock *leaf); | ||
138 | void xfs_dir_trace_g_due(char *where, struct xfs_inode *dp, struct uio *uio, | ||
139 | struct xfs_dir_leaf_entry *entry); | ||
140 | void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio, | ||
141 | xfs_off_t cookie); | ||
142 | void 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 | */ | ||
3268 | STATIC int | 3253 | STATIC int |
3269 | xfs_symlink( | 3254 | xfs_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 | ||