aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_dir2_leaf.c34
-rw-r--r--fs/xfs/xfs_dir2_leaf.h37
2 files changed, 56 insertions, 15 deletions
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 067a6abdeabe..5d2651f1c759 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -367,9 +367,12 @@ xfs_dir2_leaf_addname(
367 /* 367 /*
368 * How many bytes do we need in the leaf block? 368 * How many bytes do we need in the leaf block?
369 */ 369 */
370 needbytes = 370 needbytes = 0;
371 (leaf->hdr.stale ? 0 : (uint)sizeof(leaf->ents[0])) + 371 if (!leaf->hdr.stale)
372 (use_block != -1 ? 0 : (uint)sizeof(leaf->bests[0])); 372 needbytes += sizeof(xfs_dir2_leaf_entry_t);
373 if (use_block == -1)
374 needbytes += sizeof(xfs_dir2_data_off_t);
375
373 /* 376 /*
374 * Now kill use_block if it refers to a missing block, so we 377 * Now kill use_block if it refers to a missing block, so we
375 * can use it as an indication of allocation needed. 378 * can use it as an indication of allocation needed.
@@ -1763,6 +1766,20 @@ xfs_dir2_leaf_trim_data(
1763 return 0; 1766 return 0;
1764} 1767}
1765 1768
1769static inline size_t
1770xfs_dir2_leaf_size(
1771 struct xfs_dir2_leaf_hdr *hdr,
1772 int counts)
1773{
1774 int entries;
1775
1776 entries = be16_to_cpu(hdr->count) - be16_to_cpu(hdr->stale);
1777 return sizeof(xfs_dir2_leaf_hdr_t) +
1778 entries * sizeof(xfs_dir2_leaf_entry_t) +
1779 counts * sizeof(xfs_dir2_data_off_t) +
1780 sizeof(xfs_dir2_leaf_tail_t);
1781}
1782
1766/* 1783/*
1767 * Convert node form directory to leaf form directory. 1784 * Convert node form directory to leaf form directory.
1768 * The root of the node form dir needs to already be a LEAFN block. 1785 * The root of the node form dir needs to already be a LEAFN block.
@@ -1844,18 +1861,17 @@ xfs_dir2_node_to_leaf(
1844 free = fbp->data; 1861 free = fbp->data;
1845 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); 1862 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
1846 ASSERT(!free->hdr.firstdb); 1863 ASSERT(!free->hdr.firstdb);
1864
1847 /* 1865 /*
1848 * Now see if the leafn and free data will fit in a leaf1. 1866 * Now see if the leafn and free data will fit in a leaf1.
1849 * If not, release the buffer and give up. 1867 * If not, release the buffer and give up.
1850 */ 1868 */
1851 if ((uint)sizeof(leaf->hdr) + 1869 if (xfs_dir2_leaf_size(&leaf->hdr, be32_to_cpu(free->hdr.nvalid)) >
1852 (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)) * (uint)sizeof(leaf->ents[0]) + 1870 mp->m_dirblksize) {
1853 be32_to_cpu(free->hdr.nvalid) * (uint)sizeof(leaf->bests[0]) +
1854 (uint)sizeof(leaf->tail) >
1855 mp->m_dirblksize) {
1856 xfs_da_brelse(tp, fbp); 1871 xfs_da_brelse(tp, fbp);
1857 return 0; 1872 return 0;
1858 } 1873 }
1874
1859 /* 1875 /*
1860 * If the leaf has any stale entries in it, compress them out. 1876 * If the leaf has any stale entries in it, compress them out.
1861 * The compact routine will log the header. 1877 * The compact routine will log the header.
@@ -1874,7 +1890,7 @@ xfs_dir2_node_to_leaf(
1874 * Set up the leaf bests table. 1890 * Set up the leaf bests table.
1875 */ 1891 */
1876 memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests, 1892 memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests,
1877 be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0])); 1893 be32_to_cpu(ltp->bestcount) * sizeof(xfs_dir2_data_off_t));
1878 xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); 1894 xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
1879 xfs_dir2_leaf_log_tail(tp, lbp); 1895 xfs_dir2_leaf_log_tail(tp, lbp);
1880 xfs_dir2_leaf_check(dp, lbp); 1896 xfs_dir2_leaf_check(dp, lbp);
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index bc620622c342..140281adc7e5 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -18,6 +18,36 @@
18#ifndef __XFS_DIR2_LEAF_H__ 18#ifndef __XFS_DIR2_LEAF_H__
19#define __XFS_DIR2_LEAF_H__ 19#define __XFS_DIR2_LEAF_H__
20 20
21/*
22 * Directory format 2, leaf block structures.
23 *
24 * A pure data block looks like the following drawing on disk:
25 *
26 * +---------------------------+
27 * | xfs_dir2_leaf_hdr_t |
28 * +---------------------------+
29 * | xfs_dir2_leaf_entry_t |
30 * | xfs_dir2_leaf_entry_t |
31 * | xfs_dir2_leaf_entry_t |
32 * | xfs_dir2_leaf_entry_t |
33 * | ... |
34 * +---------------------------+
35 * | xfs_dir2_data_off_t |
36 * | xfs_dir2_data_off_t |
37 * | xfs_dir2_data_off_t |
38 * | ... |
39 * +---------------------------+
40 * | xfs_dir2_leaf_tail_t |
41 * +---------------------------+
42 *
43 * The bests (xfs_dir2_data_off_t members) and tail are at the end of the
44 * block for single-leaf only (magic = XFS_DIR2_LEAF1_MAGIC not
45 * XFS_DIR2_LEAFN_MAGIC).
46 *
47 * As all the entries are variable size structures the accessors in this
48 * file should be used to iterate over them.
49 */
50
21struct uio; 51struct uio;
22struct xfs_dabuf; 52struct xfs_dabuf;
23struct xfs_da_args; 53struct xfs_da_args;
@@ -67,15 +97,10 @@ typedef struct xfs_dir2_leaf_tail {
67 97
68/* 98/*
69 * Leaf block. 99 * Leaf block.
70 * bests and tail are at the end of the block for single-leaf only
71 * (magic = XFS_DIR2_LEAF1_MAGIC not XFS_DIR2_LEAFN_MAGIC).
72 */ 100 */
73typedef struct xfs_dir2_leaf { 101typedef struct xfs_dir2_leaf {
74 xfs_dir2_leaf_hdr_t hdr; /* leaf header */ 102 xfs_dir2_leaf_hdr_t hdr; /* leaf header */
75 xfs_dir2_leaf_entry_t ents[1]; /* entries */ 103 xfs_dir2_leaf_entry_t ents[]; /* entries */
76 /* ... */
77 xfs_dir2_data_off_t bests[1]; /* best free counts */
78 xfs_dir2_leaf_tail_t tail; /* leaf tail */
79} xfs_dir2_leaf_t; 104} xfs_dir2_leaf_t;
80 105
81/* 106/*