diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
commit | 0a0fc0ddbe732779366ab6b1b879f62195e65967 (patch) | |
tree | 7b42490a676cf39ae0691b6859ecf7fd410f229b /fs/hfsplus | |
parent | 4d5dbd0945d9e0833dd7964a3d6ee33157f7cc7a (diff) | |
parent | 3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff) |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs/hfsplus')
-rw-r--r-- | fs/hfsplus/bfind.c | 3 | ||||
-rw-r--r-- | fs/hfsplus/bitmap.c | 8 | ||||
-rw-r--r-- | fs/hfsplus/bnode.c | 11 | ||||
-rw-r--r-- | fs/hfsplus/brec.c | 2 | ||||
-rw-r--r-- | fs/hfsplus/btree.c | 37 | ||||
-rw-r--r-- | fs/hfsplus/catalog.c | 44 | ||||
-rw-r--r-- | fs/hfsplus/dir.c | 47 | ||||
-rw-r--r-- | fs/hfsplus/extents.c | 6 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 16 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_raw.h | 25 | ||||
-rw-r--r-- | fs/hfsplus/inode.c | 25 | ||||
-rw-r--r-- | fs/hfsplus/ioctl.c | 1 | ||||
-rw-r--r-- | fs/hfsplus/options.c | 24 | ||||
-rw-r--r-- | fs/hfsplus/super.c | 87 | ||||
-rw-r--r-- | fs/hfsplus/unicode.c | 30 | ||||
-rw-r--r-- | fs/hfsplus/wrapper.c | 17 |
16 files changed, 228 insertions, 155 deletions
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c index 257cdde0514b..5007a41f1be9 100644 --- a/fs/hfsplus/bfind.c +++ b/fs/hfsplus/bfind.c | |||
@@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) | |||
64 | else | 64 | else |
65 | e = rec - 1; | 65 | e = rec - 1; |
66 | } while (b <= e); | 66 | } while (b <= e); |
67 | //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec); | ||
68 | if (rec != e && e >= 0) { | 67 | if (rec != e && e >= 0) { |
69 | len = hfs_brec_lenoff(bnode, e, &off); | 68 | len = hfs_brec_lenoff(bnode, e, &off); |
70 | keylen = hfs_brec_keylen(bnode, e); | 69 | keylen = hfs_brec_keylen(bnode, e); |
@@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd) | |||
127 | return res; | 126 | return res; |
128 | 127 | ||
129 | invalid: | 128 | invalid: |
130 | printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", | 129 | printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", |
131 | height, bnode->height, bnode->type, nidx, parent); | 130 | height, bnode->height, bnode->type, nidx, parent); |
132 | res = -EIO; | 131 | res = -EIO; |
133 | release: | 132 | release: |
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index c7d316455fa0..9fb51632303c 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c | |||
@@ -29,7 +29,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma | |||
29 | return size; | 29 | return size; |
30 | 30 | ||
31 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); | 31 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); |
32 | down(&HFSPLUS_SB(sb).alloc_file->i_sem); | 32 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); |
33 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 33 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; |
34 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, | 34 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, |
35 | (filler_t *)mapping->a_ops->readpage, NULL); | 35 | (filler_t *)mapping->a_ops->readpage, NULL); |
@@ -143,7 +143,7 @@ done: | |||
143 | sb->s_dirt = 1; | 143 | sb->s_dirt = 1; |
144 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); | 144 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); |
145 | out: | 145 | out: |
146 | up(&HFSPLUS_SB(sb).alloc_file->i_sem); | 146 | mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); |
147 | return start; | 147 | return start; |
148 | } | 148 | } |
149 | 149 | ||
@@ -164,7 +164,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | |||
164 | if ((offset + count) > HFSPLUS_SB(sb).total_blocks) | 164 | if ((offset + count) > HFSPLUS_SB(sb).total_blocks) |
165 | return -2; | 165 | return -2; |
166 | 166 | ||
167 | down(&HFSPLUS_SB(sb).alloc_file->i_sem); | 167 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); |
168 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 168 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; |
169 | pnr = offset / PAGE_CACHE_BITS; | 169 | pnr = offset / PAGE_CACHE_BITS; |
170 | page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL); | 170 | page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL); |
@@ -215,7 +215,7 @@ out: | |||
215 | kunmap(page); | 215 | kunmap(page); |
216 | HFSPLUS_SB(sb).free_blocks += len; | 216 | HFSPLUS_SB(sb).free_blocks += len; |
217 | sb->s_dirt = 1; | 217 | sb->s_dirt = 1; |
218 | up(&HFSPLUS_SB(sb).alloc_file->i_sem); | 218 | mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); |
219 | 219 | ||
220 | return 0; | 220 | return 0; |
221 | } | 221 | } |
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 930cd9212de8..8f07e8fbd03d 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c | |||
@@ -358,7 +358,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node) | |||
358 | 358 | ||
359 | // move down? | 359 | // move down? |
360 | if (!node->prev && !node->next) { | 360 | if (!node->prev && !node->next) { |
361 | printk("hfs_btree_del_level\n"); | 361 | printk(KERN_DEBUG "hfs_btree_del_level\n"); |
362 | } | 362 | } |
363 | if (!node->parent) { | 363 | if (!node->parent) { |
364 | tree->root = 0; | 364 | tree->root = 0; |
@@ -379,7 +379,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid) | |||
379 | struct hfs_bnode *node; | 379 | struct hfs_bnode *node; |
380 | 380 | ||
381 | if (cnid >= tree->node_count) { | 381 | if (cnid >= tree->node_count) { |
382 | printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); | 382 | printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid); |
383 | return NULL; | 383 | return NULL; |
384 | } | 384 | } |
385 | 385 | ||
@@ -402,7 +402,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) | |||
402 | loff_t off; | 402 | loff_t off; |
403 | 403 | ||
404 | if (cnid >= tree->node_count) { | 404 | if (cnid >= tree->node_count) { |
405 | printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); | 405 | printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid); |
406 | return NULL; | 406 | return NULL; |
407 | } | 407 | } |
408 | 408 | ||
@@ -576,8 +576,9 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num) | |||
576 | node = hfs_bnode_findhash(tree, num); | 576 | node = hfs_bnode_findhash(tree, num); |
577 | spin_unlock(&tree->hash_lock); | 577 | spin_unlock(&tree->hash_lock); |
578 | if (node) { | 578 | if (node) { |
579 | printk("new node %u already hashed?\n", num); | 579 | printk(KERN_CRIT "new node %u already hashed?\n", num); |
580 | BUG(); | 580 | WARN_ON(1); |
581 | return node; | ||
581 | } | 582 | } |
582 | node = __hfs_bnode_create(tree, num); | 583 | node = __hfs_bnode_create(tree, num); |
583 | if (!node) | 584 | if (!node) |
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c index 0ccef2ab790c..c88e5d72a402 100644 --- a/fs/hfsplus/brec.c +++ b/fs/hfsplus/brec.c | |||
@@ -360,7 +360,7 @@ again: | |||
360 | end_off = hfs_bnode_read_u16(parent, end_rec_off); | 360 | end_off = hfs_bnode_read_u16(parent, end_rec_off); |
361 | if (end_rec_off - end_off < diff) { | 361 | if (end_rec_off - end_off < diff) { |
362 | 362 | ||
363 | printk("splitting index node...\n"); | 363 | printk(KERN_DEBUG "hfs: splitting index node...\n"); |
364 | fd->bnode = parent; | 364 | fd->bnode = parent; |
365 | new_node = hfs_bnode_split(fd); | 365 | new_node = hfs_bnode_split(fd); |
366 | if (IS_ERR(new_node)) | 366 | if (IS_ERR(new_node)) |
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index 44326aa2bd34..a67edfa34e9e 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c | |||
@@ -31,17 +31,8 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
31 | 31 | ||
32 | init_MUTEX(&tree->tree_lock); | 32 | init_MUTEX(&tree->tree_lock); |
33 | spin_lock_init(&tree->hash_lock); | 33 | spin_lock_init(&tree->hash_lock); |
34 | /* Set the correct compare function */ | ||
35 | tree->sb = sb; | 34 | tree->sb = sb; |
36 | tree->cnid = id; | 35 | tree->cnid = id; |
37 | if (id == HFSPLUS_EXT_CNID) { | ||
38 | tree->keycmp = hfsplus_ext_cmp_key; | ||
39 | } else if (id == HFSPLUS_CAT_CNID) { | ||
40 | tree->keycmp = hfsplus_cat_cmp_key; | ||
41 | } else { | ||
42 | printk("HFS+-fs: unknown B*Tree requested\n"); | ||
43 | goto free_tree; | ||
44 | } | ||
45 | tree->inode = iget(sb, id); | 36 | tree->inode = iget(sb, id); |
46 | if (!tree->inode) | 37 | if (!tree->inode) |
47 | goto free_tree; | 38 | goto free_tree; |
@@ -64,6 +55,20 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
64 | tree->max_key_len = be16_to_cpu(head->max_key_len); | 55 | tree->max_key_len = be16_to_cpu(head->max_key_len); |
65 | tree->depth = be16_to_cpu(head->depth); | 56 | tree->depth = be16_to_cpu(head->depth); |
66 | 57 | ||
58 | /* Set the correct compare function */ | ||
59 | if (id == HFSPLUS_EXT_CNID) { | ||
60 | tree->keycmp = hfsplus_ext_cmp_key; | ||
61 | } else if (id == HFSPLUS_CAT_CNID) { | ||
62 | if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) && | ||
63 | (head->key_type == HFSPLUS_KEY_BINARY)) | ||
64 | tree->keycmp = hfsplus_cat_bin_cmp_key; | ||
65 | else | ||
66 | tree->keycmp = hfsplus_cat_case_cmp_key; | ||
67 | } else { | ||
68 | printk(KERN_ERR "hfs: unknown B*Tree requested\n"); | ||
69 | goto fail_page; | ||
70 | } | ||
71 | |||
67 | size = tree->node_size; | 72 | size = tree->node_size; |
68 | if (!size || size & (size - 1)) | 73 | if (!size || size & (size - 1)) |
69 | goto fail_page; | 74 | goto fail_page; |
@@ -99,7 +104,7 @@ void hfs_btree_close(struct hfs_btree *tree) | |||
99 | while ((node = tree->node_hash[i])) { | 104 | while ((node = tree->node_hash[i])) { |
100 | tree->node_hash[i] = node->next_hash; | 105 | tree->node_hash[i] = node->next_hash; |
101 | if (atomic_read(&node->refcnt)) | 106 | if (atomic_read(&node->refcnt)) |
102 | printk("HFS+: node %d:%d still has %d user(s)!\n", | 107 | printk(KERN_CRIT "hfs: node %d:%d still has %d user(s)!\n", |
103 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); | 108 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); |
104 | hfs_bnode_free(node); | 109 | hfs_bnode_free(node); |
105 | tree->node_hash_cnt--; | 110 | tree->node_hash_cnt--; |
@@ -223,10 +228,6 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) | |||
223 | tree->free_nodes--; | 228 | tree->free_nodes--; |
224 | mark_inode_dirty(tree->inode); | 229 | mark_inode_dirty(tree->inode); |
225 | hfs_bnode_put(node); | 230 | hfs_bnode_put(node); |
226 | if (!idx) { | ||
227 | printk("unexpected idx %u (%u)\n", idx, node->this); | ||
228 | BUG(); | ||
229 | } | ||
230 | return hfs_bnode_create(tree, idx); | 231 | return hfs_bnode_create(tree, idx); |
231 | } | 232 | } |
232 | } | 233 | } |
@@ -242,7 +243,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) | |||
242 | kunmap(*pagep); | 243 | kunmap(*pagep); |
243 | nidx = node->next; | 244 | nidx = node->next; |
244 | if (!nidx) { | 245 | if (!nidx) { |
245 | printk("create new bmap node...\n"); | 246 | printk(KERN_DEBUG "hfs: create new bmap node...\n"); |
246 | next_node = hfs_bmap_new_bmap(node, idx); | 247 | next_node = hfs_bmap_new_bmap(node, idx); |
247 | } else | 248 | } else |
248 | next_node = hfs_bnode_find(tree, nidx); | 249 | next_node = hfs_bnode_find(tree, nidx); |
@@ -284,7 +285,7 @@ void hfs_bmap_free(struct hfs_bnode *node) | |||
284 | hfs_bnode_put(node); | 285 | hfs_bnode_put(node); |
285 | if (!i) { | 286 | if (!i) { |
286 | /* panic */; | 287 | /* panic */; |
287 | printk("HFS: unable to free bnode %u. bmap not found!\n", node->this); | 288 | printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this); |
288 | return; | 289 | return; |
289 | } | 290 | } |
290 | node = hfs_bnode_find(tree, i); | 291 | node = hfs_bnode_find(tree, i); |
@@ -292,7 +293,7 @@ void hfs_bmap_free(struct hfs_bnode *node) | |||
292 | return; | 293 | return; |
293 | if (node->type != HFS_NODE_MAP) { | 294 | if (node->type != HFS_NODE_MAP) { |
294 | /* panic */; | 295 | /* panic */; |
295 | printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type); | 296 | printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type); |
296 | hfs_bnode_put(node); | 297 | hfs_bnode_put(node); |
297 | return; | 298 | return; |
298 | } | 299 | } |
@@ -305,7 +306,7 @@ void hfs_bmap_free(struct hfs_bnode *node) | |||
305 | m = 1 << (~nidx & 7); | 306 | m = 1 << (~nidx & 7); |
306 | byte = data[off]; | 307 | byte = data[off]; |
307 | if (!(byte & m)) { | 308 | if (!(byte & m)) { |
308 | printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type); | 309 | printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type); |
309 | kunmap(page); | 310 | kunmap(page); |
310 | hfs_bnode_put(node); | 311 | hfs_bnode_put(node); |
311 | return; | 312 | return; |
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 94712790c8b3..f2d7c49ce759 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c | |||
@@ -13,7 +13,8 @@ | |||
13 | #include "hfsplus_fs.h" | 13 | #include "hfsplus_fs.h" |
14 | #include "hfsplus_raw.h" | 14 | #include "hfsplus_raw.h" |
15 | 15 | ||
16 | int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) | 16 | int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1, |
17 | const hfsplus_btree_key *k2) | ||
17 | { | 18 | { |
18 | __be32 k1p, k2p; | 19 | __be32 k1p, k2p; |
19 | 20 | ||
@@ -22,7 +23,20 @@ int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) | |||
22 | if (k1p != k2p) | 23 | if (k1p != k2p) |
23 | return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; | 24 | return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; |
24 | 25 | ||
25 | return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name); | 26 | return hfsplus_strcasecmp(&k1->cat.name, &k2->cat.name); |
27 | } | ||
28 | |||
29 | int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1, | ||
30 | const hfsplus_btree_key *k2) | ||
31 | { | ||
32 | __be32 k1p, k2p; | ||
33 | |||
34 | k1p = k1->cat.parent; | ||
35 | k2p = k2->cat.parent; | ||
36 | if (k1p != k2p) | ||
37 | return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; | ||
38 | |||
39 | return hfsplus_strcmp(&k1->cat.name, &k2->cat.name); | ||
26 | } | 40 | } |
27 | 41 | ||
28 | void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key, | 42 | void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key, |
@@ -80,8 +94,11 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
80 | memset(folder, 0, sizeof(*folder)); | 94 | memset(folder, 0, sizeof(*folder)); |
81 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); | 95 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); |
82 | folder->id = cpu_to_be32(inode->i_ino); | 96 | folder->id = cpu_to_be32(inode->i_ino); |
83 | folder->create_date = folder->content_mod_date = | 97 | HFSPLUS_I(inode).create_date = |
84 | folder->attribute_mod_date = folder->access_date = hfsp_now2mt(); | 98 | folder->create_date = |
99 | folder->content_mod_date = | ||
100 | folder->attribute_mod_date = | ||
101 | folder->access_date = hfsp_now2mt(); | ||
85 | hfsplus_set_perms(inode, &folder->permissions); | 102 | hfsplus_set_perms(inode, &folder->permissions); |
86 | if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) | 103 | if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) |
87 | /* invisible and namelocked */ | 104 | /* invisible and namelocked */ |
@@ -95,18 +112,27 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
95 | file->type = cpu_to_be16(HFSPLUS_FILE); | 112 | file->type = cpu_to_be16(HFSPLUS_FILE); |
96 | file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); | 113 | file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); |
97 | file->id = cpu_to_be32(cnid); | 114 | file->id = cpu_to_be32(cnid); |
98 | file->create_date = file->content_mod_date = | 115 | HFSPLUS_I(inode).create_date = |
99 | file->attribute_mod_date = file->access_date = hfsp_now2mt(); | 116 | file->create_date = |
117 | file->content_mod_date = | ||
118 | file->attribute_mod_date = | ||
119 | file->access_date = hfsp_now2mt(); | ||
100 | if (cnid == inode->i_ino) { | 120 | if (cnid == inode->i_ino) { |
101 | hfsplus_set_perms(inode, &file->permissions); | 121 | hfsplus_set_perms(inode, &file->permissions); |
102 | file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); | 122 | if (S_ISLNK(inode->i_mode)) { |
103 | file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); | 123 | file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); |
124 | file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); | ||
125 | } else { | ||
126 | file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); | ||
127 | file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); | ||
128 | } | ||
104 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) | 129 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) |
105 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); | 130 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); |
106 | } else { | 131 | } else { |
107 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); | 132 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); |
108 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); | 133 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); |
109 | file->user_info.fdFlags = cpu_to_be16(0x100); | 134 | file->user_info.fdFlags = cpu_to_be16(0x100); |
135 | file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date; | ||
110 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); | 136 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); |
111 | } | 137 | } |
112 | return sizeof(*file); | 138 | return sizeof(*file); |
@@ -139,7 +165,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, | |||
139 | 165 | ||
140 | type = be16_to_cpu(tmp.type); | 166 | type = be16_to_cpu(tmp.type); |
141 | if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) { | 167 | if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) { |
142 | printk("HFS+-fs: Found bad thread record in catalog\n"); | 168 | printk(KERN_ERR "hfs: found bad thread record in catalog\n"); |
143 | return -EIO; | 169 | return -EIO; |
144 | } | 170 | } |
145 | 171 | ||
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 50c8f44b6c66..01a6fe3a395c 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -66,25 +66,32 @@ again: | |||
66 | } | 66 | } |
67 | cnid = be32_to_cpu(entry.file.id); | 67 | cnid = be32_to_cpu(entry.file.id); |
68 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && | 68 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && |
69 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) { | 69 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && |
70 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date || | ||
71 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) && | ||
72 | HFSPLUS_SB(sb).hidden_dir) { | ||
70 | struct qstr str; | 73 | struct qstr str; |
71 | char name[32]; | 74 | char name[32]; |
72 | 75 | ||
73 | if (dentry->d_fsdata) { | 76 | if (dentry->d_fsdata) { |
74 | err = -ENOENT; | 77 | /* |
75 | inode = NULL; | 78 | * We found a link pointing to another link, |
76 | goto out; | 79 | * so ignore it and treat it as regular file. |
80 | */ | ||
81 | cnid = (unsigned long)dentry->d_fsdata; | ||
82 | linkid = 0; | ||
83 | } else { | ||
84 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
85 | linkid = be32_to_cpu(entry.file.permissions.dev); | ||
86 | str.len = sprintf(name, "iNode%d", linkid); | ||
87 | str.name = name; | ||
88 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | ||
89 | goto again; | ||
77 | } | 90 | } |
78 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
79 | linkid = be32_to_cpu(entry.file.permissions.dev); | ||
80 | str.len = sprintf(name, "iNode%d", linkid); | ||
81 | str.name = name; | ||
82 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | ||
83 | goto again; | ||
84 | } else if (!dentry->d_fsdata) | 91 | } else if (!dentry->d_fsdata) |
85 | dentry->d_fsdata = (void *)(unsigned long)cnid; | 92 | dentry->d_fsdata = (void *)(unsigned long)cnid; |
86 | } else { | 93 | } else { |
87 | printk("HFS+-fs: Illegal catalog entry type in lookup\n"); | 94 | printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n"); |
88 | err = -EIO; | 95 | err = -EIO; |
89 | goto fail; | 96 | goto fail; |
90 | } | 97 | } |
@@ -132,12 +139,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
132 | case 1: | 139 | case 1: |
133 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); | 140 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
134 | if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { | 141 | if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { |
135 | printk("HFS+-fs: bad catalog folder thread\n"); | 142 | printk(KERN_ERR "hfs: bad catalog folder thread\n"); |
136 | err = -EIO; | 143 | err = -EIO; |
137 | goto out; | 144 | goto out; |
138 | } | 145 | } |
139 | if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { | 146 | if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { |
140 | printk("HFS+-fs: truncated catalog thread\n"); | 147 | printk(KERN_ERR "hfs: truncated catalog thread\n"); |
141 | err = -EIO; | 148 | err = -EIO; |
142 | goto out; | 149 | goto out; |
143 | } | 150 | } |
@@ -156,7 +163,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
156 | 163 | ||
157 | for (;;) { | 164 | for (;;) { |
158 | if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { | 165 | if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { |
159 | printk("HFS+-fs: walked past end of dir\n"); | 166 | printk(KERN_ERR "hfs: walked past end of dir\n"); |
160 | err = -EIO; | 167 | err = -EIO; |
161 | goto out; | 168 | goto out; |
162 | } | 169 | } |
@@ -168,7 +175,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
168 | goto out; | 175 | goto out; |
169 | if (type == HFSPLUS_FOLDER) { | 176 | if (type == HFSPLUS_FOLDER) { |
170 | if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { | 177 | if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { |
171 | printk("HFS+-fs: small dir entry\n"); | 178 | printk(KERN_ERR "hfs: small dir entry\n"); |
172 | err = -EIO; | 179 | err = -EIO; |
173 | goto out; | 180 | goto out; |
174 | } | 181 | } |
@@ -180,7 +187,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
180 | break; | 187 | break; |
181 | } else if (type == HFSPLUS_FILE) { | 188 | } else if (type == HFSPLUS_FILE) { |
182 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { | 189 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { |
183 | printk("HFS+-fs: small file entry\n"); | 190 | printk(KERN_ERR "hfs: small file entry\n"); |
184 | err = -EIO; | 191 | err = -EIO; |
185 | goto out; | 192 | goto out; |
186 | } | 193 | } |
@@ -188,7 +195,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
188 | be32_to_cpu(entry.file.id), DT_REG)) | 195 | be32_to_cpu(entry.file.id), DT_REG)) |
189 | break; | 196 | break; |
190 | } else { | 197 | } else { |
191 | printk("HFS+-fs: bad catalog entry type\n"); | 198 | printk(KERN_ERR "hfs: bad catalog entry type\n"); |
192 | err = -EIO; | 199 | err = -EIO; |
193 | goto out; | 200 | goto out; |
194 | } | 201 | } |
@@ -330,7 +337,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
330 | if (res) | 337 | if (res) |
331 | return res; | 338 | return res; |
332 | 339 | ||
333 | inode->i_nlink--; | 340 | if (inode->i_nlink > 0) |
341 | inode->i_nlink--; | ||
334 | hfsplus_delete_inode(inode); | 342 | hfsplus_delete_inode(inode); |
335 | if (inode->i_ino != cnid && !inode->i_nlink) { | 343 | if (inode->i_ino != cnid && !inode->i_nlink) { |
336 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { | 344 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { |
@@ -339,7 +347,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
339 | hfsplus_delete_inode(inode); | 347 | hfsplus_delete_inode(inode); |
340 | } else | 348 | } else |
341 | inode->i_flags |= S_DEAD; | 349 | inode->i_flags |= S_DEAD; |
342 | } | 350 | } else |
351 | inode->i_nlink = 0; | ||
343 | inode->i_ctime = CURRENT_TIME_SEC; | 352 | inode->i_ctime = CURRENT_TIME_SEC; |
344 | mark_inode_dirty(inode); | 353 | mark_inode_dirty(inode); |
345 | 354 | ||
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index e3ff56a03011..1a7480089e82 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c | |||
@@ -16,7 +16,8 @@ | |||
16 | #include "hfsplus_raw.h" | 16 | #include "hfsplus_raw.h" |
17 | 17 | ||
18 | /* Compare two extents keys, returns 0 on same, pos/neg for difference */ | 18 | /* Compare two extents keys, returns 0 on same, pos/neg for difference */ |
19 | int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) | 19 | int hfsplus_ext_cmp_key(const hfsplus_btree_key *k1, |
20 | const hfsplus_btree_key *k2) | ||
20 | { | 21 | { |
21 | __be32 k1id, k2id; | 22 | __be32 k1id, k2id; |
22 | __be32 k1s, k2s; | 23 | __be32 k1s, k2s; |
@@ -349,10 +350,9 @@ int hfsplus_file_extend(struct inode *inode) | |||
349 | 350 | ||
350 | if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { | 351 | if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { |
351 | // extend alloc file | 352 | // extend alloc file |
352 | printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, | 353 | printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, |
353 | HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); | 354 | HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); |
354 | return -ENOSPC; | 355 | return -ENOSPC; |
355 | //BUG(); | ||
356 | } | 356 | } |
357 | 357 | ||
358 | down(&HFSPLUS_I(inode).extents_lock); | 358 | down(&HFSPLUS_I(inode).extents_lock); |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index c60e5635498d..7ae393637a0c 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
@@ -36,7 +36,7 @@ | |||
36 | #define HFSPLUS_TYPE_DATA 0x00 | 36 | #define HFSPLUS_TYPE_DATA 0x00 |
37 | #define HFSPLUS_TYPE_RSRC 0xFF | 37 | #define HFSPLUS_TYPE_RSRC 0xFF |
38 | 38 | ||
39 | typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *); | 39 | typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *); |
40 | 40 | ||
41 | #define NODE_HASH_SIZE 256 | 41 | #define NODE_HASH_SIZE 256 |
42 | 42 | ||
@@ -143,14 +143,13 @@ struct hfsplus_sb_info { | |||
143 | 143 | ||
144 | unsigned long flags; | 144 | unsigned long flags; |
145 | 145 | ||
146 | atomic_t inode_cnt; | ||
147 | u32 last_inode_cnt; | ||
148 | |||
149 | struct hlist_head rsrc_inodes; | 146 | struct hlist_head rsrc_inodes; |
150 | }; | 147 | }; |
151 | 148 | ||
152 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 | 149 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 |
153 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 | 150 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 |
151 | #define HFSPLUS_SB_FORCE 0x0004 | ||
152 | #define HFSPLUS_SB_HFSX 0x0008 | ||
154 | 153 | ||
155 | 154 | ||
156 | struct hfsplus_inode_info { | 155 | struct hfsplus_inode_info { |
@@ -167,6 +166,7 @@ struct hfsplus_inode_info { | |||
167 | struct inode *rsrc_inode; | 166 | struct inode *rsrc_inode; |
168 | unsigned long flags; | 167 | unsigned long flags; |
169 | 168 | ||
169 | __be32 create_date; | ||
170 | /* Device number in hfsplus_permissions in catalog */ | 170 | /* Device number in hfsplus_permissions in catalog */ |
171 | u32 dev; | 171 | u32 dev; |
172 | /* BSD system and user file flags */ | 172 | /* BSD system and user file flags */ |
@@ -305,7 +305,8 @@ int hfs_brec_read(struct hfs_find_data *, void *, int); | |||
305 | int hfs_brec_goto(struct hfs_find_data *, int); | 305 | int hfs_brec_goto(struct hfs_find_data *, int); |
306 | 306 | ||
307 | /* catalog.c */ | 307 | /* catalog.c */ |
308 | int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); | 308 | int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); |
309 | int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); | ||
309 | void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *); | 310 | void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *); |
310 | int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *); | 311 | int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *); |
311 | int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); | 312 | int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); |
@@ -314,7 +315,7 @@ int hfsplus_rename_cat(u32, struct inode *, struct qstr *, | |||
314 | struct inode *, struct qstr *); | 315 | struct inode *, struct qstr *); |
315 | 316 | ||
316 | /* extents.c */ | 317 | /* extents.c */ |
317 | int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); | 318 | int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); |
318 | void hfsplus_ext_write_extent(struct inode *); | 319 | void hfsplus_ext_write_extent(struct inode *); |
319 | int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); | 320 | int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); |
320 | int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int); | 321 | int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int); |
@@ -352,7 +353,8 @@ extern u16 hfsplus_decompose_table[]; | |||
352 | extern u16 hfsplus_compose_table[]; | 353 | extern u16 hfsplus_compose_table[]; |
353 | 354 | ||
354 | /* unicode.c */ | 355 | /* unicode.c */ |
355 | int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); | 356 | int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); |
357 | int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); | ||
356 | int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); | 358 | int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); |
357 | int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); | 359 | int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); |
358 | 360 | ||
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index 5bad37cfdb29..49205531a500 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h | |||
@@ -22,8 +22,10 @@ | |||
22 | #define HFSPLUS_SECTOR_SHIFT 9 | 22 | #define HFSPLUS_SECTOR_SHIFT 9 |
23 | #define HFSPLUS_VOLHEAD_SECTOR 2 | 23 | #define HFSPLUS_VOLHEAD_SECTOR 2 |
24 | #define HFSPLUS_VOLHEAD_SIG 0x482b | 24 | #define HFSPLUS_VOLHEAD_SIG 0x482b |
25 | #define HFSPLUS_VOLHEAD_SIGX 0x4858 | ||
25 | #define HFSPLUS_SUPER_MAGIC 0x482b | 26 | #define HFSPLUS_SUPER_MAGIC 0x482b |
26 | #define HFSPLUS_CURRENT_VERSION 4 | 27 | #define HFSPLUS_MIN_VERSION 4 |
28 | #define HFSPLUS_CURRENT_VERSION 5 | ||
27 | 29 | ||
28 | #define HFSP_WRAP_MAGIC 0x4244 | 30 | #define HFSP_WRAP_MAGIC 0x4244 |
29 | #define HFSP_WRAP_ATTRIB_SLOCK 0x8000 | 31 | #define HFSP_WRAP_ATTRIB_SLOCK 0x8000 |
@@ -41,6 +43,9 @@ | |||
41 | #define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */ | 43 | #define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */ |
42 | #define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */ | 44 | #define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */ |
43 | 45 | ||
46 | #define HFSP_SYMLINK_TYPE 0x736c6e6b /* 'slnk' */ | ||
47 | #define HFSP_SYMLINK_CREATOR 0x72686170 /* 'rhap' */ | ||
48 | |||
44 | #define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */ | 49 | #define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */ |
45 | 50 | ||
46 | /* Structures used on disk */ | 51 | /* Structures used on disk */ |
@@ -123,11 +128,13 @@ struct hfsplus_vh { | |||
123 | } __packed; | 128 | } __packed; |
124 | 129 | ||
125 | /* HFS+ volume attributes */ | 130 | /* HFS+ volume attributes */ |
126 | #define HFSPLUS_VOL_UNMNT (1 << 8) | 131 | #define HFSPLUS_VOL_UNMNT (1 << 8) |
127 | #define HFSPLUS_VOL_SPARE_BLK (1 << 9) | 132 | #define HFSPLUS_VOL_SPARE_BLK (1 << 9) |
128 | #define HFSPLUS_VOL_NOCACHE (1 << 10) | 133 | #define HFSPLUS_VOL_NOCACHE (1 << 10) |
129 | #define HFSPLUS_VOL_INCNSTNT (1 << 11) | 134 | #define HFSPLUS_VOL_INCNSTNT (1 << 11) |
130 | #define HFSPLUS_VOL_SOFTLOCK (1 << 15) | 135 | #define HFSPLUS_VOL_NODEID_REUSED (1 << 12) |
136 | #define HFSPLUS_VOL_JOURNALED (1 << 13) | ||
137 | #define HFSPLUS_VOL_SOFTLOCK (1 << 15) | ||
131 | 138 | ||
132 | /* HFS+ BTree node descriptor */ | 139 | /* HFS+ BTree node descriptor */ |
133 | struct hfs_bnode_desc { | 140 | struct hfs_bnode_desc { |
@@ -159,7 +166,7 @@ struct hfs_btree_header_rec { | |||
159 | u16 reserved1; | 166 | u16 reserved1; |
160 | __be32 clump_size; | 167 | __be32 clump_size; |
161 | u8 btree_type; | 168 | u8 btree_type; |
162 | u8 reserved2; | 169 | u8 key_type; |
163 | __be32 attributes; | 170 | __be32 attributes; |
164 | u32 reserved3[16]; | 171 | u32 reserved3[16]; |
165 | } __packed; | 172 | } __packed; |
@@ -184,6 +191,10 @@ struct hfs_btree_header_rec { | |||
184 | #define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */ | 191 | #define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */ |
185 | #define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */ | 192 | #define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */ |
186 | 193 | ||
194 | /* btree key type */ | ||
195 | #define HFSPLUS_KEY_CASEFOLDING 0xCF /* case-insensitive */ | ||
196 | #define HFSPLUS_KEY_BINARY 0xBC /* case-sensitive */ | ||
197 | |||
187 | /* HFS+ catalog entry key */ | 198 | /* HFS+ catalog entry key */ |
188 | struct hfsplus_cat_key { | 199 | struct hfsplus_cat_key { |
189 | __be16 key_len; | 200 | __be16 key_len; |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index fc98583cf045..12ed2b7d046b 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -18,13 +18,11 @@ | |||
18 | 18 | ||
19 | static int hfsplus_readpage(struct file *file, struct page *page) | 19 | static int hfsplus_readpage(struct file *file, struct page *page) |
20 | { | 20 | { |
21 | //printk("readpage: %lu\n", page->index); | ||
22 | return block_read_full_page(page, hfsplus_get_block); | 21 | return block_read_full_page(page, hfsplus_get_block); |
23 | } | 22 | } |
24 | 23 | ||
25 | static int hfsplus_writepage(struct page *page, struct writeback_control *wbc) | 24 | static int hfsplus_writepage(struct page *page, struct writeback_control *wbc) |
26 | { | 25 | { |
27 | //printk("writepage: %lu\n", page->index); | ||
28 | return block_write_full_page(page, hfsplus_get_block, wbc); | 26 | return block_write_full_page(page, hfsplus_get_block, wbc); |
29 | } | 27 | } |
30 | 28 | ||
@@ -92,7 +90,6 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask) | |||
92 | } while (--i && nidx < tree->node_count); | 90 | } while (--i && nidx < tree->node_count); |
93 | spin_unlock(&tree->hash_lock); | 91 | spin_unlock(&tree->hash_lock); |
94 | } | 92 | } |
95 | //printk("releasepage: %lu,%x = %d\n", page->index, mask, res); | ||
96 | return res ? try_to_free_buffers(page) : 0; | 93 | return res ? try_to_free_buffers(page) : 0; |
97 | } | 94 | } |
98 | 95 | ||
@@ -182,11 +179,6 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
182 | igrab(dir); | 179 | igrab(dir); |
183 | hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); | 180 | hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); |
184 | mark_inode_dirty(inode); | 181 | mark_inode_dirty(inode); |
185 | { | ||
186 | void hfsplus_inode_check(struct super_block *sb); | ||
187 | atomic_inc(&HFSPLUS_SB(sb).inode_cnt); | ||
188 | hfsplus_inode_check(sb); | ||
189 | } | ||
190 | out: | 182 | out: |
191 | d_add(dentry, inode); | 183 | d_add(dentry, inode); |
192 | return NULL; | 184 | return NULL; |
@@ -276,13 +268,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) | |||
276 | if (atomic_read(&file->f_count) != 0) | 268 | if (atomic_read(&file->f_count) != 0) |
277 | return 0; | 269 | return 0; |
278 | if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { | 270 | if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { |
279 | down(&inode->i_sem); | 271 | mutex_lock(&inode->i_mutex); |
280 | hfsplus_file_truncate(inode); | 272 | hfsplus_file_truncate(inode); |
281 | if (inode->i_flags & S_DEAD) { | 273 | if (inode->i_flags & S_DEAD) { |
282 | hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); | 274 | hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); |
283 | hfsplus_delete_inode(inode); | 275 | hfsplus_delete_inode(inode); |
284 | } | 276 | } |
285 | up(&inode->i_sem); | 277 | mutex_unlock(&inode->i_mutex); |
286 | } | 278 | } |
287 | return 0; | 279 | return 0; |
288 | } | 280 | } |
@@ -317,11 +309,6 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode) | |||
317 | if (!inode) | 309 | if (!inode) |
318 | return NULL; | 310 | return NULL; |
319 | 311 | ||
320 | { | ||
321 | void hfsplus_inode_check(struct super_block *sb); | ||
322 | atomic_inc(&HFSPLUS_SB(sb).inode_cnt); | ||
323 | hfsplus_inode_check(sb); | ||
324 | } | ||
325 | inode->i_ino = HFSPLUS_SB(sb).next_cnid++; | 312 | inode->i_ino = HFSPLUS_SB(sb).next_cnid++; |
326 | inode->i_mode = mode; | 313 | inode->i_mode = mode; |
327 | inode->i_uid = current->fsuid; | 314 | inode->i_uid = current->fsuid; |
@@ -444,7 +431,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
444 | inode->i_size = 2 + be32_to_cpu(folder->valence); | 431 | inode->i_size = 2 + be32_to_cpu(folder->valence); |
445 | inode->i_atime = hfsp_mt2ut(folder->access_date); | 432 | inode->i_atime = hfsp_mt2ut(folder->access_date); |
446 | inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); | 433 | inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); |
447 | inode->i_ctime = inode->i_mtime; | 434 | inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); |
435 | HFSPLUS_I(inode).create_date = folder->create_date; | ||
448 | HFSPLUS_I(inode).fs_blocks = 0; | 436 | HFSPLUS_I(inode).fs_blocks = 0; |
449 | inode->i_op = &hfsplus_dir_inode_operations; | 437 | inode->i_op = &hfsplus_dir_inode_operations; |
450 | inode->i_fop = &hfsplus_dir_operations; | 438 | inode->i_fop = &hfsplus_dir_operations; |
@@ -475,9 +463,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
475 | } | 463 | } |
476 | inode->i_atime = hfsp_mt2ut(file->access_date); | 464 | inode->i_atime = hfsp_mt2ut(file->access_date); |
477 | inode->i_mtime = hfsp_mt2ut(file->content_mod_date); | 465 | inode->i_mtime = hfsp_mt2ut(file->content_mod_date); |
478 | inode->i_ctime = inode->i_mtime; | 466 | inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); |
467 | HFSPLUS_I(inode).create_date = file->create_date; | ||
479 | } else { | 468 | } else { |
480 | printk("HFS+-fs: bad catalog entry used to create inode\n"); | 469 | printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); |
481 | res = -EIO; | 470 | res = -EIO; |
482 | } | 471 | } |
483 | return res; | 472 | return res; |
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index e07aa096e07c..13cf848ac833 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * hfsplus ioctls | 12 | * hfsplus ioctls |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/capability.h> | ||
15 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
16 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
17 | #include <linux/xattr.h> | 18 | #include <linux/xattr.h> |
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index cca0818aa4ca..dc64fac00831 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c | |||
@@ -22,7 +22,7 @@ enum { | |||
22 | opt_umask, opt_uid, opt_gid, | 22 | opt_umask, opt_uid, opt_gid, |
23 | opt_part, opt_session, opt_nls, | 23 | opt_part, opt_session, opt_nls, |
24 | opt_nodecompose, opt_decompose, | 24 | opt_nodecompose, opt_decompose, |
25 | opt_err | 25 | opt_force, opt_err |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static match_table_t tokens = { | 28 | static match_table_t tokens = { |
@@ -36,6 +36,7 @@ static match_table_t tokens = { | |||
36 | { opt_nls, "nls=%s" }, | 36 | { opt_nls, "nls=%s" }, |
37 | { opt_decompose, "decompose" }, | 37 | { opt_decompose, "decompose" }, |
38 | { opt_nodecompose, "nodecompose" }, | 38 | { opt_nodecompose, "nodecompose" }, |
39 | { opt_force, "force" }, | ||
39 | { opt_err, NULL } | 40 | { opt_err, NULL } |
40 | }; | 41 | }; |
41 | 42 | ||
@@ -82,58 +83,58 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) | |||
82 | switch (token) { | 83 | switch (token) { |
83 | case opt_creator: | 84 | case opt_creator: |
84 | if (match_fourchar(&args[0], &sbi->creator)) { | 85 | if (match_fourchar(&args[0], &sbi->creator)) { |
85 | printk("HFS+-fs: creator requires a 4 character value\n"); | 86 | printk(KERN_ERR "hfs: creator requires a 4 character value\n"); |
86 | return 0; | 87 | return 0; |
87 | } | 88 | } |
88 | break; | 89 | break; |
89 | case opt_type: | 90 | case opt_type: |
90 | if (match_fourchar(&args[0], &sbi->type)) { | 91 | if (match_fourchar(&args[0], &sbi->type)) { |
91 | printk("HFS+-fs: type requires a 4 character value\n"); | 92 | printk(KERN_ERR "hfs: type requires a 4 character value\n"); |
92 | return 0; | 93 | return 0; |
93 | } | 94 | } |
94 | break; | 95 | break; |
95 | case opt_umask: | 96 | case opt_umask: |
96 | if (match_octal(&args[0], &tmp)) { | 97 | if (match_octal(&args[0], &tmp)) { |
97 | printk("HFS+-fs: umask requires a value\n"); | 98 | printk(KERN_ERR "hfs: umask requires a value\n"); |
98 | return 0; | 99 | return 0; |
99 | } | 100 | } |
100 | sbi->umask = (umode_t)tmp; | 101 | sbi->umask = (umode_t)tmp; |
101 | break; | 102 | break; |
102 | case opt_uid: | 103 | case opt_uid: |
103 | if (match_int(&args[0], &tmp)) { | 104 | if (match_int(&args[0], &tmp)) { |
104 | printk("HFS+-fs: uid requires an argument\n"); | 105 | printk(KERN_ERR "hfs: uid requires an argument\n"); |
105 | return 0; | 106 | return 0; |
106 | } | 107 | } |
107 | sbi->uid = (uid_t)tmp; | 108 | sbi->uid = (uid_t)tmp; |
108 | break; | 109 | break; |
109 | case opt_gid: | 110 | case opt_gid: |
110 | if (match_int(&args[0], &tmp)) { | 111 | if (match_int(&args[0], &tmp)) { |
111 | printk("HFS+-fs: gid requires an argument\n"); | 112 | printk(KERN_ERR "hfs: gid requires an argument\n"); |
112 | return 0; | 113 | return 0; |
113 | } | 114 | } |
114 | sbi->gid = (gid_t)tmp; | 115 | sbi->gid = (gid_t)tmp; |
115 | break; | 116 | break; |
116 | case opt_part: | 117 | case opt_part: |
117 | if (match_int(&args[0], &sbi->part)) { | 118 | if (match_int(&args[0], &sbi->part)) { |
118 | printk("HFS+-fs: part requires an argument\n"); | 119 | printk(KERN_ERR "hfs: part requires an argument\n"); |
119 | return 0; | 120 | return 0; |
120 | } | 121 | } |
121 | break; | 122 | break; |
122 | case opt_session: | 123 | case opt_session: |
123 | if (match_int(&args[0], &sbi->session)) { | 124 | if (match_int(&args[0], &sbi->session)) { |
124 | printk("HFS+-fs: session requires an argument\n"); | 125 | printk(KERN_ERR "hfs: session requires an argument\n"); |
125 | return 0; | 126 | return 0; |
126 | } | 127 | } |
127 | break; | 128 | break; |
128 | case opt_nls: | 129 | case opt_nls: |
129 | if (sbi->nls) { | 130 | if (sbi->nls) { |
130 | printk("HFS+-fs: unable to change nls mapping\n"); | 131 | printk(KERN_ERR "hfs: unable to change nls mapping\n"); |
131 | return 0; | 132 | return 0; |
132 | } | 133 | } |
133 | p = match_strdup(&args[0]); | 134 | p = match_strdup(&args[0]); |
134 | sbi->nls = load_nls(p); | 135 | sbi->nls = load_nls(p); |
135 | if (!sbi->nls) { | 136 | if (!sbi->nls) { |
136 | printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p); | 137 | printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p); |
137 | kfree(p); | 138 | kfree(p); |
138 | return 0; | 139 | return 0; |
139 | } | 140 | } |
@@ -145,6 +146,9 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) | |||
145 | case opt_nodecompose: | 146 | case opt_nodecompose: |
146 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; | 147 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; |
147 | break; | 148 | break; |
149 | case opt_force: | ||
150 | sbi->flags |= HFSPLUS_SB_FORCE; | ||
151 | break; | ||
148 | default: | 152 | default: |
149 | return 0; | 153 | return 0; |
150 | } | 154 | } |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 0ce1c455ae55..7843f792a4b7 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -22,29 +22,12 @@ static void hfsplus_destroy_inode(struct inode *inode); | |||
22 | 22 | ||
23 | #include "hfsplus_fs.h" | 23 | #include "hfsplus_fs.h" |
24 | 24 | ||
25 | void hfsplus_inode_check(struct super_block *sb) | ||
26 | { | ||
27 | #if 0 | ||
28 | u32 cnt = atomic_read(&HFSPLUS_SB(sb).inode_cnt); | ||
29 | u32 last_cnt = HFSPLUS_SB(sb).last_inode_cnt; | ||
30 | |||
31 | if (cnt <= (last_cnt / 2) || | ||
32 | cnt >= (last_cnt * 2)) { | ||
33 | HFSPLUS_SB(sb).last_inode_cnt = cnt; | ||
34 | printk("inode_check: %u,%u,%u\n", cnt, last_cnt, | ||
35 | HFSPLUS_SB(sb).cat_tree ? HFSPLUS_SB(sb).cat_tree->node_hash_cnt : 0); | ||
36 | } | ||
37 | #endif | ||
38 | } | ||
39 | |||
40 | static void hfsplus_read_inode(struct inode *inode) | 25 | static void hfsplus_read_inode(struct inode *inode) |
41 | { | 26 | { |
42 | struct hfs_find_data fd; | 27 | struct hfs_find_data fd; |
43 | struct hfsplus_vh *vhdr; | 28 | struct hfsplus_vh *vhdr; |
44 | int err; | 29 | int err; |
45 | 30 | ||
46 | atomic_inc(&HFSPLUS_SB(inode->i_sb).inode_cnt); | ||
47 | hfsplus_inode_check(inode->i_sb); | ||
48 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 31 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); |
49 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | 32 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); |
50 | HFSPLUS_I(inode).flags = 0; | 33 | HFSPLUS_I(inode).flags = 0; |
@@ -155,12 +138,10 @@ static int hfsplus_write_inode(struct inode *inode, int unused) | |||
155 | static void hfsplus_clear_inode(struct inode *inode) | 138 | static void hfsplus_clear_inode(struct inode *inode) |
156 | { | 139 | { |
157 | dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino); | 140 | dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino); |
158 | atomic_dec(&HFSPLUS_SB(inode->i_sb).inode_cnt); | ||
159 | if (HFSPLUS_IS_RSRC(inode)) { | 141 | if (HFSPLUS_IS_RSRC(inode)) { |
160 | HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; | 142 | HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; |
161 | iput(HFSPLUS_I(inode).rsrc_inode); | 143 | iput(HFSPLUS_I(inode).rsrc_inode); |
162 | } | 144 | } |
163 | hfsplus_inode_check(inode->i_sb); | ||
164 | } | 145 | } |
165 | 146 | ||
166 | static void hfsplus_write_super(struct super_block *sb) | 147 | static void hfsplus_write_super(struct super_block *sb) |
@@ -188,7 +169,7 @@ static void hfsplus_write_super(struct super_block *sb) | |||
188 | block = HFSPLUS_SB(sb).blockoffset; | 169 | block = HFSPLUS_SB(sb).blockoffset; |
189 | block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); | 170 | block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); |
190 | offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); | 171 | offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); |
191 | printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, | 172 | printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, |
192 | HFSPLUS_SB(sb).sect_count, block, offset); | 173 | HFSPLUS_SB(sb).sect_count, block, offset); |
193 | bh = sb_bread(sb, block); | 174 | bh = sb_bread(sb, block); |
194 | if (bh) { | 175 | if (bh) { |
@@ -198,7 +179,7 @@ static void hfsplus_write_super(struct super_block *sb) | |||
198 | mark_buffer_dirty(bh); | 179 | mark_buffer_dirty(bh); |
199 | brelse(bh); | 180 | brelse(bh); |
200 | } else | 181 | } else |
201 | printk("backup not found!\n"); | 182 | printk(KERN_WARNING "hfs: backup not found!\n"); |
202 | } | 183 | } |
203 | } | 184 | } |
204 | HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; | 185 | HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; |
@@ -251,14 +232,26 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
251 | return 0; | 232 | return 0; |
252 | if (!(*flags & MS_RDONLY)) { | 233 | if (!(*flags & MS_RDONLY)) { |
253 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 234 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; |
235 | struct hfsplus_sb_info sbi; | ||
236 | |||
237 | memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); | ||
238 | sbi.nls = HFSPLUS_SB(sb).nls; | ||
239 | if (!hfsplus_parse_options(data, &sbi)) | ||
240 | return -EINVAL; | ||
254 | 241 | ||
255 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { | 242 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { |
256 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | 243 | printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, " |
257 | "running fsck.hfsplus is recommended. leaving read-only.\n"); | 244 | "running fsck.hfsplus is recommended. leaving read-only.\n"); |
258 | sb->s_flags |= MS_RDONLY; | 245 | sb->s_flags |= MS_RDONLY; |
259 | *flags |= MS_RDONLY; | 246 | *flags |= MS_RDONLY; |
247 | } else if (sbi.flags & HFSPLUS_SB_FORCE) { | ||
248 | /* nothing */ | ||
260 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 249 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
261 | printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); | 250 | printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); |
251 | sb->s_flags |= MS_RDONLY; | ||
252 | *flags |= MS_RDONLY; | ||
253 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { | ||
254 | printk(KERN_WARNING "hfs: filesystem is marked journaled, leaving read-only.\n"); | ||
262 | sb->s_flags |= MS_RDONLY; | 255 | sb->s_flags |= MS_RDONLY; |
263 | *flags |= MS_RDONLY; | 256 | *flags |= MS_RDONLY; |
264 | } | 257 | } |
@@ -299,8 +292,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
299 | INIT_HLIST_HEAD(&sbi->rsrc_inodes); | 292 | INIT_HLIST_HEAD(&sbi->rsrc_inodes); |
300 | hfsplus_fill_defaults(sbi); | 293 | hfsplus_fill_defaults(sbi); |
301 | if (!hfsplus_parse_options(data, sbi)) { | 294 | if (!hfsplus_parse_options(data, sbi)) { |
302 | if (!silent) | 295 | printk(KERN_ERR "hfs: unable to parse mount options\n"); |
303 | printk("HFS+-fs: unable to parse mount options\n"); | ||
304 | err = -EINVAL; | 296 | err = -EINVAL; |
305 | goto cleanup; | 297 | goto cleanup; |
306 | } | 298 | } |
@@ -308,8 +300,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
308 | /* temporarily use utf8 to correctly find the hidden dir below */ | 300 | /* temporarily use utf8 to correctly find the hidden dir below */ |
309 | nls = sbi->nls; | 301 | nls = sbi->nls; |
310 | sbi->nls = load_nls("utf8"); | 302 | sbi->nls = load_nls("utf8"); |
311 | if (!nls) { | 303 | if (!sbi->nls) { |
312 | printk("HFS+: unable to load nls for utf8\n"); | 304 | printk(KERN_ERR "hfs: unable to load nls for utf8\n"); |
313 | err = -EINVAL; | 305 | err = -EINVAL; |
314 | goto cleanup; | 306 | goto cleanup; |
315 | } | 307 | } |
@@ -317,17 +309,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
317 | /* Grab the volume header */ | 309 | /* Grab the volume header */ |
318 | if (hfsplus_read_wrapper(sb)) { | 310 | if (hfsplus_read_wrapper(sb)) { |
319 | if (!silent) | 311 | if (!silent) |
320 | printk("HFS+-fs: unable to find HFS+ superblock\n"); | 312 | printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n"); |
321 | err = -EINVAL; | 313 | err = -EINVAL; |
322 | goto cleanup; | 314 | goto cleanup; |
323 | } | 315 | } |
324 | vhdr = HFSPLUS_SB(sb).s_vhdr; | 316 | vhdr = HFSPLUS_SB(sb).s_vhdr; |
325 | 317 | ||
326 | /* Copy parts of the volume header into the superblock */ | 318 | /* Copy parts of the volume header into the superblock */ |
327 | sb->s_magic = be16_to_cpu(vhdr->signature); | 319 | sb->s_magic = HFSPLUS_VOLHEAD_SIG; |
328 | if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) { | 320 | if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION || |
329 | if (!silent) | 321 | be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) { |
330 | printk("HFS+-fs: wrong filesystem version\n"); | 322 | printk(KERN_ERR "hfs: wrong filesystem version\n"); |
331 | goto cleanup; | 323 | goto cleanup; |
332 | } | 324 | } |
333 | HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); | 325 | HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); |
@@ -348,34 +340,36 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
348 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 340 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
349 | 341 | ||
350 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { | 342 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { |
351 | if (!silent) | 343 | printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, " |
352 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | 344 | "running fsck.hfsplus is recommended. mounting read-only.\n"); |
353 | "running fsck.hfsplus is recommended. mounting read-only.\n"); | ||
354 | sb->s_flags |= MS_RDONLY; | 345 | sb->s_flags |= MS_RDONLY; |
346 | } else if (sbi->flags & HFSPLUS_SB_FORCE) { | ||
347 | /* nothing */ | ||
355 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 348 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
356 | if (!silent) | 349 | printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n"); |
357 | printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); | 350 | sb->s_flags |= MS_RDONLY; |
351 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { | ||
352 | printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, " | ||
353 | "use the force option at your own risk, mounting read-only.\n"); | ||
358 | sb->s_flags |= MS_RDONLY; | 354 | sb->s_flags |= MS_RDONLY; |
359 | } | 355 | } |
356 | sbi->flags &= ~HFSPLUS_SB_FORCE; | ||
360 | 357 | ||
361 | /* Load metadata objects (B*Trees) */ | 358 | /* Load metadata objects (B*Trees) */ |
362 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); | 359 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); |
363 | if (!HFSPLUS_SB(sb).ext_tree) { | 360 | if (!HFSPLUS_SB(sb).ext_tree) { |
364 | if (!silent) | 361 | printk(KERN_ERR "hfs: failed to load extents file\n"); |
365 | printk("HFS+-fs: failed to load extents file\n"); | ||
366 | goto cleanup; | 362 | goto cleanup; |
367 | } | 363 | } |
368 | HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); | 364 | HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); |
369 | if (!HFSPLUS_SB(sb).cat_tree) { | 365 | if (!HFSPLUS_SB(sb).cat_tree) { |
370 | if (!silent) | 366 | printk(KERN_ERR "hfs: failed to load catalog file\n"); |
371 | printk("HFS+-fs: failed to load catalog file\n"); | ||
372 | goto cleanup; | 367 | goto cleanup; |
373 | } | 368 | } |
374 | 369 | ||
375 | HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID); | 370 | HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID); |
376 | if (!HFSPLUS_SB(sb).alloc_file) { | 371 | if (!HFSPLUS_SB(sb).alloc_file) { |
377 | if (!silent) | 372 | printk(KERN_ERR "hfs: failed to load allocation file\n"); |
378 | printk("HFS+-fs: failed to load allocation file\n"); | ||
379 | goto cleanup; | 373 | goto cleanup; |
380 | } | 374 | } |
381 | 375 | ||
@@ -383,8 +377,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
383 | root = iget(sb, HFSPLUS_ROOT_CNID); | 377 | root = iget(sb, HFSPLUS_ROOT_CNID); |
384 | sb->s_root = d_alloc_root(root); | 378 | sb->s_root = d_alloc_root(root); |
385 | if (!sb->s_root) { | 379 | if (!sb->s_root) { |
386 | if (!silent) | 380 | printk(KERN_ERR "hfs: failed to load root directory\n"); |
387 | printk("HFS+-fs: failed to load root directory\n"); | ||
388 | iput(root); | 381 | iput(root); |
389 | goto cleanup; | 382 | goto cleanup; |
390 | } | 383 | } |
@@ -418,7 +411,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
418 | sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); | 411 | sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); |
419 | 412 | ||
420 | if (!HFSPLUS_SB(sb).hidden_dir) { | 413 | if (!HFSPLUS_SB(sb).hidden_dir) { |
421 | printk("HFS+: create hidden dir...\n"); | 414 | printk(KERN_DEBUG "hfs: create hidden dir...\n"); |
422 | HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); | 415 | HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); |
423 | hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, | 416 | hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, |
424 | &str, HFSPLUS_SB(sb).hidden_dir); | 417 | &str, HFSPLUS_SB(sb).hidden_dir); |
@@ -498,7 +491,7 @@ static void __exit exit_hfsplus_fs(void) | |||
498 | { | 491 | { |
499 | unregister_filesystem(&hfsplus_fs_type); | 492 | unregister_filesystem(&hfsplus_fs_type); |
500 | if (kmem_cache_destroy(hfsplus_inode_cachep)) | 493 | if (kmem_cache_destroy(hfsplus_inode_cachep)) |
501 | printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n"); | 494 | printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n"); |
502 | } | 495 | } |
503 | 496 | ||
504 | module_init(init_hfsplus_fs) | 497 | module_init(init_hfsplus_fs) |
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index 060c69048c3d..689c8bd721fb 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c | |||
@@ -28,7 +28,8 @@ static inline u16 case_fold(u16 c) | |||
28 | } | 28 | } |
29 | 29 | ||
30 | /* Compare unicode strings, return values like normal strcmp */ | 30 | /* Compare unicode strings, return values like normal strcmp */ |
31 | int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2) | 31 | int hfsplus_strcasecmp(const struct hfsplus_unistr *s1, |
32 | const struct hfsplus_unistr *s2) | ||
32 | { | 33 | { |
33 | u16 len1, len2, c1, c2; | 34 | u16 len1, len2, c1, c2; |
34 | const hfsplus_unichr *p1, *p2; | 35 | const hfsplus_unichr *p1, *p2; |
@@ -59,6 +60,33 @@ int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unis | |||
59 | } | 60 | } |
60 | } | 61 | } |
61 | 62 | ||
63 | /* Compare names as a sequence of 16-bit unsigned integers */ | ||
64 | int hfsplus_strcmp(const struct hfsplus_unistr *s1, | ||
65 | const struct hfsplus_unistr *s2) | ||
66 | { | ||
67 | u16 len1, len2, c1, c2; | ||
68 | const hfsplus_unichr *p1, *p2; | ||
69 | int len; | ||
70 | |||
71 | len1 = be16_to_cpu(s1->length); | ||
72 | len2 = be16_to_cpu(s2->length); | ||
73 | p1 = s1->unicode; | ||
74 | p2 = s2->unicode; | ||
75 | |||
76 | for (len = min(len1, len2); len > 0; len--) { | ||
77 | c1 = be16_to_cpu(*p1); | ||
78 | c2 = be16_to_cpu(*p2); | ||
79 | if (c1 != c2) | ||
80 | return c1 < c2 ? -1 : 1; | ||
81 | p1++; | ||
82 | p2++; | ||
83 | } | ||
84 | |||
85 | return len1 < len2 ? -1 : | ||
86 | len1 > len2 ? 1 : 0; | ||
87 | } | ||
88 | |||
89 | |||
62 | #define Hangul_SBase 0xac00 | 90 | #define Hangul_SBase 0xac00 |
63 | #define Hangul_LBase 0x1100 | 91 | #define Hangul_LBase 0x1100 |
64 | #define Hangul_VBase 0x1161 | 92 | #define Hangul_VBase 0x1161 |
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 95455e839231..72cab78f0509 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c | |||
@@ -28,8 +28,11 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) | |||
28 | { | 28 | { |
29 | u32 extent; | 29 | u32 extent; |
30 | u16 attrib; | 30 | u16 attrib; |
31 | __be16 sig; | ||
31 | 32 | ||
32 | if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG) | 33 | sig = *(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG); |
34 | if (sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIG) && | ||
35 | sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) | ||
33 | return 0; | 36 | return 0; |
34 | 37 | ||
35 | attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB)); | 38 | attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB)); |
@@ -70,7 +73,7 @@ static int hfsplus_get_last_session(struct super_block *sb, | |||
70 | *start = (sector_t)te.cdte_addr.lba << 2; | 73 | *start = (sector_t)te.cdte_addr.lba << 2; |
71 | return 0; | 74 | return 0; |
72 | } | 75 | } |
73 | printk(KERN_ERR "HFS: Invalid session number or type of track\n"); | 76 | printk(KERN_ERR "hfs: invalid session number or type of track\n"); |
74 | return -EINVAL; | 77 | return -EINVAL; |
75 | } | 78 | } |
76 | ms_info.addr_format = CDROM_LBA; | 79 | ms_info.addr_format = CDROM_LBA; |
@@ -114,6 +117,10 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
114 | } | 117 | } |
115 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) | 118 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) |
116 | break; | 119 | break; |
120 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) { | ||
121 | HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX; | ||
122 | break; | ||
123 | } | ||
117 | brelse(bh); | 124 | brelse(bh); |
118 | 125 | ||
119 | /* check for a partition block | 126 | /* check for a partition block |
@@ -143,7 +150,7 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
143 | blocksize >>= 1; | 150 | blocksize >>= 1; |
144 | 151 | ||
145 | if (sb_set_blocksize(sb, blocksize) != blocksize) { | 152 | if (sb_set_blocksize(sb, blocksize) != blocksize) { |
146 | printk("HFS+: unable to blocksize to %u!\n", blocksize); | 153 | printk(KERN_ERR "hfs: unable to set blocksize to %u!\n", blocksize); |
147 | return -EINVAL; | 154 | return -EINVAL; |
148 | } | 155 | } |
149 | 156 | ||
@@ -158,7 +165,9 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
158 | return -EIO; | 165 | return -EIO; |
159 | 166 | ||
160 | /* should still be the same... */ | 167 | /* should still be the same... */ |
161 | if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG) | 168 | if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ? |
169 | cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) : | ||
170 | cpu_to_be16(HFSPLUS_VOLHEAD_SIG))) | ||
162 | goto error; | 171 | goto error; |
163 | HFSPLUS_SB(sb).s_vhbh = bh; | 172 | HFSPLUS_SB(sb).s_vhbh = bh; |
164 | HFSPLUS_SB(sb).s_vhdr = vhdr; | 173 | HFSPLUS_SB(sb).s_vhdr = vhdr; |