aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorVyacheslav Dubeyko <slava@dubeyko.com>2013-11-12 18:11:08 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-12 22:09:32 -0500
commit099e9245e04d50bb12ed621b4fa61df0a4c9dba9 (patch)
treeafd87de0ccc84d5cd5c8854b1861b5a8b6800bec /fs/hfsplus
parentb3b5b0f03cc4ea074ed0ac110d0afd17e0ccdf9e (diff)
hfsplus: implement attributes file's header node initialization code
Implement functionality of AttributesFile's header node initialization. Signed-off-by: Vyacheslav Dubeyko <slava@dubeyko.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@infradead.org> Cc: Hin-Tak Leung <htl10@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hfsplus')
-rw-r--r--fs/hfsplus/hfsplus_raw.h3
-rw-r--r--fs/hfsplus/xattr.c65
2 files changed, 68 insertions, 0 deletions
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 2c54dd81def4..8ffb3a8ffe75 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -187,6 +187,9 @@ struct hfs_btree_header_rec {
187/* HFS+ BTree misc info */ 187/* HFS+ BTree misc info */
188#define HFSPLUS_TREE_HEAD 0 188#define HFSPLUS_TREE_HEAD 0
189#define HFSPLUS_NODE_MXSZ 32768 189#define HFSPLUS_NODE_MXSZ 32768
190#define HFSPLUS_ATTR_TREE_NODE_SIZE 8192
191#define HFSPLUS_BTREE_HDR_NODE_RECS_COUNT 3
192#define HFSPLUS_BTREE_HDR_USER_BYTES 128
190 193
191/* Some special File ID numbers (stolen from hfs.h) */ 194/* Some special File ID numbers (stolen from hfs.h) */
192#define HFSPLUS_POR_CNID 1 /* Parent Of the Root */ 195#define HFSPLUS_POR_CNID 1 /* Parent Of the Root */
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index bd8471fb9a6a..568a45cb1145 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -127,6 +127,71 @@ static int can_set_xattr(struct inode *inode, const char *name,
127 return 0; 127 return 0;
128} 128}
129 129
130static void hfsplus_init_header_node(struct inode *attr_file,
131 u32 clump_size,
132 char *buf, size_t node_size)
133{
134 struct hfs_bnode_desc *desc;
135 struct hfs_btree_header_rec *head;
136 u16 offset;
137 __be16 *rec_offsets;
138 u32 hdr_node_map_rec_bits;
139 char *bmp;
140 u32 used_nodes;
141 u32 used_bmp_bytes;
142
143 hfs_dbg(ATTR_MOD, "init_hdr_attr_file: clump %u, node_size %zu\n",
144 clump_size, node_size);
145
146 /* The end of the node contains list of record offsets */
147 rec_offsets = (__be16 *)(buf + node_size);
148
149 desc = (struct hfs_bnode_desc *)buf;
150 desc->type = HFS_NODE_HEADER;
151 desc->num_recs = cpu_to_be16(HFSPLUS_BTREE_HDR_NODE_RECS_COUNT);
152 offset = sizeof(struct hfs_bnode_desc);
153 *--rec_offsets = cpu_to_be16(offset);
154
155 head = (struct hfs_btree_header_rec *)(buf + offset);
156 head->node_size = cpu_to_be16(node_size);
157 head->node_count = cpu_to_be32(i_size_read(attr_file) / node_size);
158 head->free_nodes = cpu_to_be32(be32_to_cpu(head->node_count) - 1);
159 head->clump_size = cpu_to_be32(clump_size);
160 head->attributes |= cpu_to_be32(HFS_TREE_BIGKEYS | HFS_TREE_VARIDXKEYS);
161 head->max_key_len = cpu_to_be16(HFSPLUS_ATTR_KEYLEN - sizeof(u16));
162 offset += sizeof(struct hfs_btree_header_rec);
163 *--rec_offsets = cpu_to_be16(offset);
164 offset += HFSPLUS_BTREE_HDR_USER_BYTES;
165 *--rec_offsets = cpu_to_be16(offset);
166
167 hdr_node_map_rec_bits = 8 * (node_size - offset - (4 * sizeof(u16)));
168 if (be32_to_cpu(head->node_count) > hdr_node_map_rec_bits) {
169 u32 map_node_bits;
170 u32 map_nodes;
171
172 desc->next = cpu_to_be32(be32_to_cpu(head->leaf_tail) + 1);
173 map_node_bits = 8 * (node_size - sizeof(struct hfs_bnode_desc) -
174 (2 * sizeof(u16)) - 2);
175 map_nodes = (be32_to_cpu(head->node_count) -
176 hdr_node_map_rec_bits +
177 (map_node_bits - 1)) / map_node_bits;
178 be32_add_cpu(&head->free_nodes, 0 - map_nodes);
179 }
180
181 bmp = buf + offset;
182 used_nodes =
183 be32_to_cpu(head->node_count) - be32_to_cpu(head->free_nodes);
184 used_bmp_bytes = used_nodes / 8;
185 if (used_bmp_bytes) {
186 memset(bmp, 0xFF, used_bmp_bytes);
187 bmp += used_bmp_bytes;
188 used_nodes %= 8;
189 }
190 *bmp = ~(0xFF >> used_nodes);
191 offset += hdr_node_map_rec_bits / 8;
192 *--rec_offsets = cpu_to_be16(offset);
193}
194
130int __hfsplus_setxattr(struct inode *inode, const char *name, 195int __hfsplus_setxattr(struct inode *inode, const char *name,
131 const void *value, size_t size, int flags) 196 const void *value, size_t size, int flags)
132{ 197{