diff options
-rw-r--r-- | fs/xfs/libxfs/xfs_attr_leaf.c | 84 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_da_format.h | 14 |
2 files changed, 92 insertions, 6 deletions
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 3337516feeb0..149ef3f66735 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c | |||
@@ -86,6 +86,80 @@ STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args, | |||
86 | int move_count); | 86 | int move_count); |
87 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); | 87 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); |
88 | 88 | ||
89 | /* | ||
90 | * attr3 block 'firstused' conversion helpers. | ||
91 | * | ||
92 | * firstused refers to the offset of the first used byte of the nameval region | ||
93 | * of an attr leaf block. The region starts at the tail of the block and expands | ||
94 | * backwards towards the middle. As such, firstused is initialized to the block | ||
95 | * size for an empty leaf block and is reduced from there. | ||
96 | * | ||
97 | * The attr3 block size is pegged to the fsb size and the maximum fsb is 64k. | ||
98 | * The in-core firstused field is 32-bit and thus supports the maximum fsb size. | ||
99 | * The on-disk field is only 16-bit, however, and overflows at 64k. Since this | ||
100 | * only occurs at exactly 64k, we use zero as a magic on-disk value to represent | ||
101 | * the attr block size. The following helpers manage the conversion between the | ||
102 | * in-core and on-disk formats. | ||
103 | */ | ||
104 | |||
105 | static void | ||
106 | xfs_attr3_leaf_firstused_from_disk( | ||
107 | struct xfs_da_geometry *geo, | ||
108 | struct xfs_attr3_icleaf_hdr *to, | ||
109 | struct xfs_attr_leafblock *from) | ||
110 | { | ||
111 | struct xfs_attr3_leaf_hdr *hdr3; | ||
112 | |||
113 | if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) { | ||
114 | hdr3 = (struct xfs_attr3_leaf_hdr *) from; | ||
115 | to->firstused = be16_to_cpu(hdr3->firstused); | ||
116 | } else { | ||
117 | to->firstused = be16_to_cpu(from->hdr.firstused); | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * Convert from the magic fsb size value to actual blocksize. This | ||
122 | * should only occur for empty blocks when the block size overflows | ||
123 | * 16-bits. | ||
124 | */ | ||
125 | if (to->firstused == XFS_ATTR3_LEAF_NULLOFF) { | ||
126 | ASSERT(!to->count && !to->usedbytes); | ||
127 | ASSERT(geo->blksize > USHRT_MAX); | ||
128 | to->firstused = geo->blksize; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void | ||
133 | xfs_attr3_leaf_firstused_to_disk( | ||
134 | struct xfs_da_geometry *geo, | ||
135 | struct xfs_attr_leafblock *to, | ||
136 | struct xfs_attr3_icleaf_hdr *from) | ||
137 | { | ||
138 | struct xfs_attr3_leaf_hdr *hdr3; | ||
139 | uint32_t firstused; | ||
140 | |||
141 | /* magic value should only be seen on disk */ | ||
142 | ASSERT(from->firstused != XFS_ATTR3_LEAF_NULLOFF); | ||
143 | |||
144 | /* | ||
145 | * Scale down the 32-bit in-core firstused value to the 16-bit on-disk | ||
146 | * value. This only overflows at the max supported value of 64k. Use the | ||
147 | * magic on-disk value to represent block size in this case. | ||
148 | */ | ||
149 | firstused = from->firstused; | ||
150 | if (firstused > USHRT_MAX) { | ||
151 | ASSERT(from->firstused == geo->blksize); | ||
152 | firstused = XFS_ATTR3_LEAF_NULLOFF; | ||
153 | } | ||
154 | |||
155 | if (from->magic == XFS_ATTR3_LEAF_MAGIC) { | ||
156 | hdr3 = (struct xfs_attr3_leaf_hdr *) to; | ||
157 | hdr3->firstused = cpu_to_be16(firstused); | ||
158 | } else { | ||
159 | to->hdr.firstused = cpu_to_be16(firstused); | ||
160 | } | ||
161 | } | ||
162 | |||
89 | void | 163 | void |
90 | xfs_attr3_leaf_hdr_from_disk( | 164 | xfs_attr3_leaf_hdr_from_disk( |
91 | struct xfs_da_geometry *geo, | 165 | struct xfs_da_geometry *geo, |
@@ -105,7 +179,7 @@ xfs_attr3_leaf_hdr_from_disk( | |||
105 | to->magic = be16_to_cpu(hdr3->info.hdr.magic); | 179 | to->magic = be16_to_cpu(hdr3->info.hdr.magic); |
106 | to->count = be16_to_cpu(hdr3->count); | 180 | to->count = be16_to_cpu(hdr3->count); |
107 | to->usedbytes = be16_to_cpu(hdr3->usedbytes); | 181 | to->usedbytes = be16_to_cpu(hdr3->usedbytes); |
108 | to->firstused = be16_to_cpu(hdr3->firstused); | 182 | xfs_attr3_leaf_firstused_from_disk(geo, to, from); |
109 | to->holes = hdr3->holes; | 183 | to->holes = hdr3->holes; |
110 | 184 | ||
111 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | 185 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { |
@@ -119,7 +193,7 @@ xfs_attr3_leaf_hdr_from_disk( | |||
119 | to->magic = be16_to_cpu(from->hdr.info.magic); | 193 | to->magic = be16_to_cpu(from->hdr.info.magic); |
120 | to->count = be16_to_cpu(from->hdr.count); | 194 | to->count = be16_to_cpu(from->hdr.count); |
121 | to->usedbytes = be16_to_cpu(from->hdr.usedbytes); | 195 | to->usedbytes = be16_to_cpu(from->hdr.usedbytes); |
122 | to->firstused = be16_to_cpu(from->hdr.firstused); | 196 | xfs_attr3_leaf_firstused_from_disk(geo, to, from); |
123 | to->holes = from->hdr.holes; | 197 | to->holes = from->hdr.holes; |
124 | 198 | ||
125 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | 199 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { |
@@ -134,7 +208,7 @@ xfs_attr3_leaf_hdr_to_disk( | |||
134 | struct xfs_attr_leafblock *to, | 208 | struct xfs_attr_leafblock *to, |
135 | struct xfs_attr3_icleaf_hdr *from) | 209 | struct xfs_attr3_icleaf_hdr *from) |
136 | { | 210 | { |
137 | int i; | 211 | int i; |
138 | 212 | ||
139 | ASSERT(from->magic == XFS_ATTR_LEAF_MAGIC || | 213 | ASSERT(from->magic == XFS_ATTR_LEAF_MAGIC || |
140 | from->magic == XFS_ATTR3_LEAF_MAGIC); | 214 | from->magic == XFS_ATTR3_LEAF_MAGIC); |
@@ -147,7 +221,7 @@ xfs_attr3_leaf_hdr_to_disk( | |||
147 | hdr3->info.hdr.magic = cpu_to_be16(from->magic); | 221 | hdr3->info.hdr.magic = cpu_to_be16(from->magic); |
148 | hdr3->count = cpu_to_be16(from->count); | 222 | hdr3->count = cpu_to_be16(from->count); |
149 | hdr3->usedbytes = cpu_to_be16(from->usedbytes); | 223 | hdr3->usedbytes = cpu_to_be16(from->usedbytes); |
150 | hdr3->firstused = cpu_to_be16(from->firstused); | 224 | xfs_attr3_leaf_firstused_to_disk(geo, to, from); |
151 | hdr3->holes = from->holes; | 225 | hdr3->holes = from->holes; |
152 | hdr3->pad1 = 0; | 226 | hdr3->pad1 = 0; |
153 | 227 | ||
@@ -162,7 +236,7 @@ xfs_attr3_leaf_hdr_to_disk( | |||
162 | to->hdr.info.magic = cpu_to_be16(from->magic); | 236 | to->hdr.info.magic = cpu_to_be16(from->magic); |
163 | to->hdr.count = cpu_to_be16(from->count); | 237 | to->hdr.count = cpu_to_be16(from->count); |
164 | to->hdr.usedbytes = cpu_to_be16(from->usedbytes); | 238 | to->hdr.usedbytes = cpu_to_be16(from->usedbytes); |
165 | to->hdr.firstused = cpu_to_be16(from->firstused); | 239 | xfs_attr3_leaf_firstused_to_disk(geo, to, from); |
166 | to->hdr.holes = from->holes; | 240 | to->hdr.holes = from->holes; |
167 | to->hdr.pad1 = 0; | 241 | to->hdr.pad1 = 0; |
168 | 242 | ||
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index 0a49b0286372..74bcbabfa523 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h | |||
@@ -725,7 +725,13 @@ struct xfs_attr3_icleaf_hdr { | |||
725 | __uint16_t magic; | 725 | __uint16_t magic; |
726 | __uint16_t count; | 726 | __uint16_t count; |
727 | __uint16_t usedbytes; | 727 | __uint16_t usedbytes; |
728 | __uint16_t firstused; | 728 | /* |
729 | * firstused is 32-bit here instead of 16-bit like the on-disk variant | ||
730 | * to support maximum fsb size of 64k without overflow issues throughout | ||
731 | * the attr code. Instead, the overflow condition is handled on | ||
732 | * conversion to/from disk. | ||
733 | */ | ||
734 | __uint32_t firstused; | ||
729 | __u8 holes; | 735 | __u8 holes; |
730 | struct { | 736 | struct { |
731 | __uint16_t base; | 737 | __uint16_t base; |
@@ -734,6 +740,12 @@ struct xfs_attr3_icleaf_hdr { | |||
734 | }; | 740 | }; |
735 | 741 | ||
736 | /* | 742 | /* |
743 | * Special value to represent fs block size in the leaf header firstused field. | ||
744 | * Only used when block size overflows the 2-bytes available on disk. | ||
745 | */ | ||
746 | #define XFS_ATTR3_LEAF_NULLOFF 0 | ||
747 | |||
748 | /* | ||
737 | * Flags used in the leaf_entry[i].flags field. | 749 | * Flags used in the leaf_entry[i].flags field. |
738 | * NOTE: the INCOMPLETE bit must not collide with the flags bits specified | 750 | * NOTE: the INCOMPLETE bit must not collide with the flags bits specified |
739 | * on the system call, they are "or"ed together for various operations. | 751 | * on the system call, they are "or"ed together for various operations. |