@@ -50,7 +50,7 @@ static bool is_known_namespace(const char *name)
5050 return true;
5151}
5252
53- static void hfsplus_init_header_node (struct inode * attr_file ,
53+ static u32 hfsplus_init_header_node (struct inode * attr_file ,
5454 u32 clump_size ,
5555 char * buf , u16 node_size )
5656{
@@ -59,6 +59,7 @@ static void hfsplus_init_header_node(struct inode *attr_file,
5959 u16 offset ;
6060 __be16 * rec_offsets ;
6161 u32 hdr_node_map_rec_bits ;
62+ u32 map_nodes = 0 ;
6263 char * bmp ;
6364 u32 used_nodes ;
6465 u32 used_bmp_bytes ;
@@ -93,7 +94,6 @@ static void hfsplus_init_header_node(struct inode *attr_file,
9394 hdr_node_map_rec_bits = 8 * (node_size - offset - (4 * sizeof (u16 )));
9495 if (be32_to_cpu (head -> node_count ) > hdr_node_map_rec_bits ) {
9596 u32 map_node_bits ;
96- u32 map_nodes ;
9797
9898 desc -> next = cpu_to_be32 (be32_to_cpu (head -> leaf_tail ) + 1 );
9999 map_node_bits = 8 * (node_size - sizeof (struct hfs_bnode_desc ) -
@@ -116,21 +116,100 @@ static void hfsplus_init_header_node(struct inode *attr_file,
116116 * bmp = ~(0xFF >> used_nodes );
117117 offset += hdr_node_map_rec_bits / 8 ;
118118 * -- rec_offsets = cpu_to_be16 (offset );
119+
120+ return map_nodes ;
121+ }
122+
123+ /*
124+ * Initialize a map node buffer. Map nodes have a single bitmap record.
125+ */
126+ static void hfsplus_init_map_node (u8 * buf , u16 node_size , u32 next_node )
127+ {
128+ struct hfs_bnode_desc * desc ;
129+ __be16 * rec_offsets ;
130+ size_t rec_size = sizeof (__be16 );
131+ u16 offset ;
132+
133+ memset (buf , 0 , node_size );
134+
135+ desc = (struct hfs_bnode_desc * )buf ;
136+ desc -> type = HFS_NODE_MAP ;
137+ desc -> num_recs = cpu_to_be16 (1 );
138+ desc -> next = cpu_to_be32 (next_node );
139+
140+ /*
141+ * A map node consists of the node descriptor and a single
142+ * map record. The map record is a continuation of the map
143+ * record contained in the header node. The size of the map
144+ * record is the size of the node, minus the size of
145+ * the node descriptor (14 bytes), minus the size of two offsets
146+ * (4 bytes), minus two bytes of free space. That is, the size of
147+ * the map record is the size of the node minus 20 bytes;
148+ * this keeps the length of the map record an even multiple of 4 bytes.
149+ * The start of the map record is not aligned to a 4-byte boundary:
150+ * it starts immediately after the node descriptor
151+ * (at an offset of 14 bytes).
152+ *
153+ * Two record offsets stored at the end of the node:
154+ * record[1] = start of record 0 -> sizeof(hfs_bnode_desc)
155+ * record[2] = start of free space
156+ */
157+ rec_offsets = (__be16 * )(buf + node_size );
158+
159+ /* record #1 */
160+ offset = sizeof (struct hfs_bnode_desc );
161+ * -- rec_offsets = cpu_to_be16 (offset );
162+
163+ /* record #2 */
164+ offset = node_size ;
165+ offset -= (u16 )HFSPLUS_BTREE_MAP_NODE_RECS_COUNT * rec_size ;
166+ offset -= HFSPLUS_BTREE_MAP_NODE_RESERVED_BYTES ;
167+ * -- rec_offsets = cpu_to_be16 (offset );
168+ }
169+
170+ static inline
171+ int hfsplus_write_attributes_file_node (struct inode * attr_file , char * buf ,
172+ u16 node_size , int * index )
173+ {
174+ struct address_space * mapping ;
175+ struct page * page ;
176+ void * kaddr ;
177+ u32 written = 0 ;
178+
179+ mapping = attr_file -> i_mapping ;
180+
181+ for (; written < node_size ; (* index )++ , written += PAGE_SIZE ) {
182+ page = read_mapping_page (mapping , * index , NULL );
183+ if (IS_ERR (page ))
184+ return PTR_ERR (page );
185+
186+ kaddr = kmap_local_page (page );
187+ memcpy (kaddr , buf + written ,
188+ min_t (size_t , PAGE_SIZE , node_size - written ));
189+ kunmap_local (kaddr );
190+
191+ set_page_dirty (page );
192+ put_page (page );
193+ }
194+
195+ return 0 ;
119196}
120197
121198static int hfsplus_create_attributes_file (struct super_block * sb )
122199{
123- int err = 0 ;
124200 struct hfsplus_sb_info * sbi = HFSPLUS_SB (sb );
125201 struct inode * attr_file ;
126202 struct hfsplus_inode_info * hip ;
203+ struct hfs_bnode_desc * desc ;
127204 u32 clump_size ;
128205 u16 node_size = HFSPLUS_ATTR_TREE_NODE_SIZE ;
206+ u32 next_node ;
207+ u32 map_node_idx ;
208+ u32 map_nodes ;
129209 char * buf ;
130- int index , written ;
131- struct address_space * mapping ;
132- struct page * page ;
210+ int index ;
133211 int old_state = HFSPLUS_EMPTY_ATTR_TREE ;
212+ int err = 0 ;
134213
135214 hfs_dbg ("ino %d\n" , HFSPLUS_ATTR_CNID );
136215
@@ -195,7 +274,7 @@ static int hfsplus_create_attributes_file(struct super_block *sb)
195274 }
196275
197276 while (hip -> alloc_blocks < hip -> clump_blocks ) {
198- err = hfsplus_file_extend (attr_file , false );
277+ err = hfsplus_file_extend (attr_file , true );
199278 if (unlikely (err )) {
200279 pr_err ("failed to extend attributes file\n" );
201280 goto end_attr_file_creation ;
@@ -212,28 +291,30 @@ static int hfsplus_create_attributes_file(struct super_block *sb)
212291 goto end_attr_file_creation ;
213292 }
214293
215- hfsplus_init_header_node (attr_file , clump_size , buf , node_size );
294+ map_nodes = hfsplus_init_header_node (attr_file , clump_size , buf , node_size );
216295
217- mapping = attr_file -> i_mapping ;
296+ desc = (struct hfs_bnode_desc * )buf ;
297+ next_node = be32_to_cpu (desc -> next );
218298
219299 index = 0 ;
220- written = 0 ;
221- for (; written < node_size ; index ++ , written += PAGE_SIZE ) {
222- void * kaddr ;
223300
224- page = read_mapping_page (mapping , index , NULL );
225- if (IS_ERR (page )) {
226- err = PTR_ERR (page );
227- goto failed_header_node_init ;
228- }
301+ err = hfsplus_write_attributes_file_node (attr_file , buf ,
302+ node_size , & index );
303+ if (unlikely (err ))
304+ goto failed_header_node_init ;
229305
230- kaddr = kmap_atomic (page );
231- memcpy (kaddr , buf + written ,
232- min_t (size_t , PAGE_SIZE , node_size - written ));
233- kunmap_atomic (kaddr );
306+ for (map_node_idx = 0 ; map_node_idx < map_nodes ; map_node_idx ++ ) {
307+ if (next_node >= map_nodes )
308+ next_node = 0 ;
234309
235- set_page_dirty (page );
236- put_page (page );
310+ hfsplus_init_map_node (buf , node_size , next_node );
311+
312+ err = hfsplus_write_attributes_file_node (attr_file , buf ,
313+ node_size , & index );
314+ if (unlikely (err ))
315+ goto failed_header_node_init ;
316+
317+ next_node ++ ;
237318 }
238319
239320 hfsplus_mark_inode_dirty (HFSPLUS_ATTR_TREE_I (sb ), HFSPLUS_I_ATTR_DIRTY );
0 commit comments