diff options
| -rw-r--r-- | fs/hfsplus/bfind.c | 17 | ||||
| -rw-r--r-- | fs/hfsplus/bitmap.c | 20 | ||||
| -rw-r--r-- | fs/hfsplus/brec.c | 29 | ||||
| -rw-r--r-- | fs/hfsplus/btree.c | 67 | ||||
| -rw-r--r-- | fs/hfsplus/catalog.c | 50 | ||||
| -rw-r--r-- | fs/hfsplus/dir.c | 201 | ||||
| -rw-r--r-- | fs/hfsplus/extents.c | 223 | ||||
| -rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 85 | ||||
| -rw-r--r-- | fs/hfsplus/hfsplus_raw.h | 3 | ||||
| -rw-r--r-- | fs/hfsplus/inode.c | 185 | ||||
| -rw-r--r-- | fs/hfsplus/ioctl.c | 153 | ||||
| -rw-r--r-- | fs/hfsplus/options.c | 10 | ||||
| -rw-r--r-- | fs/hfsplus/part_tbl.c | 5 | ||||
| -rw-r--r-- | fs/hfsplus/super.c | 310 | ||||
| -rw-r--r-- | fs/hfsplus/unicode.c | 16 | ||||
| -rw-r--r-- | fs/hfsplus/wrapper.c | 40 |
16 files changed, 765 insertions, 649 deletions
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c index 5007a41f1be9..d182438c7ae4 100644 --- a/fs/hfsplus/bfind.c +++ b/fs/hfsplus/bfind.c | |||
| @@ -23,7 +23,7 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) | |||
| 23 | fd->search_key = ptr; | 23 | fd->search_key = ptr; |
| 24 | fd->key = ptr + tree->max_key_len + 2; | 24 | fd->key = ptr + tree->max_key_len + 2; |
| 25 | dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0)); | 25 | dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0)); |
| 26 | down(&tree->tree_lock); | 26 | mutex_lock(&tree->tree_lock); |
| 27 | return 0; | 27 | return 0; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| @@ -32,7 +32,7 @@ void hfs_find_exit(struct hfs_find_data *fd) | |||
| 32 | hfs_bnode_put(fd->bnode); | 32 | hfs_bnode_put(fd->bnode); |
| 33 | kfree(fd->search_key); | 33 | kfree(fd->search_key); |
| 34 | dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0)); | 34 | dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0)); |
| 35 | up(&fd->tree->tree_lock); | 35 | mutex_unlock(&fd->tree->tree_lock); |
| 36 | fd->tree = NULL; | 36 | fd->tree = NULL; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| @@ -52,6 +52,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) | |||
| 52 | rec = (e + b) / 2; | 52 | rec = (e + b) / 2; |
| 53 | len = hfs_brec_lenoff(bnode, rec, &off); | 53 | len = hfs_brec_lenoff(bnode, rec, &off); |
| 54 | keylen = hfs_brec_keylen(bnode, rec); | 54 | keylen = hfs_brec_keylen(bnode, rec); |
| 55 | if (keylen == 0) { | ||
| 56 | res = -EINVAL; | ||
| 57 | goto fail; | ||
| 58 | } | ||
| 55 | hfs_bnode_read(bnode, fd->key, off, keylen); | 59 | hfs_bnode_read(bnode, fd->key, off, keylen); |
| 56 | cmpval = bnode->tree->keycmp(fd->key, fd->search_key); | 60 | cmpval = bnode->tree->keycmp(fd->key, fd->search_key); |
| 57 | if (!cmpval) { | 61 | if (!cmpval) { |
| @@ -67,6 +71,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) | |||
| 67 | if (rec != e && e >= 0) { | 71 | if (rec != e && e >= 0) { |
| 68 | len = hfs_brec_lenoff(bnode, e, &off); | 72 | len = hfs_brec_lenoff(bnode, e, &off); |
| 69 | keylen = hfs_brec_keylen(bnode, e); | 73 | keylen = hfs_brec_keylen(bnode, e); |
| 74 | if (keylen == 0) { | ||
| 75 | res = -EINVAL; | ||
| 76 | goto fail; | ||
| 77 | } | ||
| 70 | hfs_bnode_read(bnode, fd->key, off, keylen); | 78 | hfs_bnode_read(bnode, fd->key, off, keylen); |
| 71 | } | 79 | } |
| 72 | done: | 80 | done: |
| @@ -75,6 +83,7 @@ done: | |||
| 75 | fd->keylength = keylen; | 83 | fd->keylength = keylen; |
| 76 | fd->entryoffset = off + keylen; | 84 | fd->entryoffset = off + keylen; |
| 77 | fd->entrylength = len - keylen; | 85 | fd->entrylength = len - keylen; |
| 86 | fail: | ||
| 78 | return res; | 87 | return res; |
| 79 | } | 88 | } |
| 80 | 89 | ||
| @@ -198,6 +207,10 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt) | |||
| 198 | 207 | ||
| 199 | len = hfs_brec_lenoff(bnode, fd->record, &off); | 208 | len = hfs_brec_lenoff(bnode, fd->record, &off); |
| 200 | keylen = hfs_brec_keylen(bnode, fd->record); | 209 | keylen = hfs_brec_keylen(bnode, fd->record); |
| 210 | if (keylen == 0) { | ||
| 211 | res = -EINVAL; | ||
| 212 | goto out; | ||
| 213 | } | ||
| 201 | fd->keyoffset = off; | 214 | fd->keyoffset = off; |
| 202 | fd->keylength = keylen; | 215 | fd->keylength = keylen; |
| 203 | fd->entryoffset = off + keylen; | 216 | fd->entryoffset = off + keylen; |
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index ea30afc2a03c..ad57f5991eb1 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max) | 18 | int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max) |
| 19 | { | 19 | { |
| 20 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 20 | struct page *page; | 21 | struct page *page; |
| 21 | struct address_space *mapping; | 22 | struct address_space *mapping; |
| 22 | __be32 *pptr, *curr, *end; | 23 | __be32 *pptr, *curr, *end; |
| @@ -29,8 +30,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma | |||
| 29 | return size; | 30 | return size; |
| 30 | 31 | ||
| 31 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); | 32 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); |
| 32 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 33 | mutex_lock(&sbi->alloc_mutex); |
| 33 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 34 | mapping = sbi->alloc_file->i_mapping; |
| 34 | page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); | 35 | page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); |
| 35 | if (IS_ERR(page)) { | 36 | if (IS_ERR(page)) { |
| 36 | start = size; | 37 | start = size; |
| @@ -150,16 +151,17 @@ done: | |||
| 150 | set_page_dirty(page); | 151 | set_page_dirty(page); |
| 151 | kunmap(page); | 152 | kunmap(page); |
| 152 | *max = offset + (curr - pptr) * 32 + i - start; | 153 | *max = offset + (curr - pptr) * 32 + i - start; |
| 153 | HFSPLUS_SB(sb).free_blocks -= *max; | 154 | sbi->free_blocks -= *max; |
| 154 | sb->s_dirt = 1; | 155 | sb->s_dirt = 1; |
| 155 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); | 156 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); |
| 156 | out: | 157 | out: |
| 157 | mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 158 | mutex_unlock(&sbi->alloc_mutex); |
| 158 | return start; | 159 | return start; |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | 162 | int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) |
| 162 | { | 163 | { |
| 164 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 163 | struct page *page; | 165 | struct page *page; |
| 164 | struct address_space *mapping; | 166 | struct address_space *mapping; |
| 165 | __be32 *pptr, *curr, *end; | 167 | __be32 *pptr, *curr, *end; |
| @@ -172,11 +174,11 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | |||
| 172 | 174 | ||
| 173 | dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count); | 175 | dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count); |
| 174 | /* are all of the bits in range? */ | 176 | /* are all of the bits in range? */ |
| 175 | if ((offset + count) > HFSPLUS_SB(sb).total_blocks) | 177 | if ((offset + count) > sbi->total_blocks) |
| 176 | return -2; | 178 | return -2; |
| 177 | 179 | ||
| 178 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 180 | mutex_lock(&sbi->alloc_mutex); |
| 179 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 181 | mapping = sbi->alloc_file->i_mapping; |
| 180 | pnr = offset / PAGE_CACHE_BITS; | 182 | pnr = offset / PAGE_CACHE_BITS; |
| 181 | page = read_mapping_page(mapping, pnr, NULL); | 183 | page = read_mapping_page(mapping, pnr, NULL); |
| 182 | pptr = kmap(page); | 184 | pptr = kmap(page); |
| @@ -224,9 +226,9 @@ done: | |||
| 224 | out: | 226 | out: |
| 225 | set_page_dirty(page); | 227 | set_page_dirty(page); |
| 226 | kunmap(page); | 228 | kunmap(page); |
| 227 | HFSPLUS_SB(sb).free_blocks += len; | 229 | sbi->free_blocks += len; |
| 228 | sb->s_dirt = 1; | 230 | sb->s_dirt = 1; |
| 229 | mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 231 | mutex_unlock(&sbi->alloc_mutex); |
| 230 | 232 | ||
| 231 | return 0; | 233 | return 0; |
| 232 | } | 234 | } |
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c index c88e5d72a402..2f39d05443e1 100644 --- a/fs/hfsplus/brec.c +++ b/fs/hfsplus/brec.c | |||
| @@ -42,10 +42,13 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec) | |||
| 42 | recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2); | 42 | recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2); |
| 43 | if (!recoff) | 43 | if (!recoff) |
| 44 | return 0; | 44 | return 0; |
| 45 | if (node->tree->attributes & HFS_TREE_BIGKEYS) | 45 | |
| 46 | retval = hfs_bnode_read_u16(node, recoff) + 2; | 46 | retval = hfs_bnode_read_u16(node, recoff) + 2; |
| 47 | else | 47 | if (retval > node->tree->max_key_len + 2) { |
| 48 | retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1; | 48 | printk(KERN_ERR "hfs: keylen %d too large\n", |
| 49 | retval); | ||
| 50 | retval = 0; | ||
| 51 | } | ||
| 49 | } | 52 | } |
| 50 | return retval; | 53 | return retval; |
| 51 | } | 54 | } |
| @@ -216,7 +219,7 @@ skip: | |||
| 216 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | 219 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) |
| 217 | { | 220 | { |
| 218 | struct hfs_btree *tree; | 221 | struct hfs_btree *tree; |
| 219 | struct hfs_bnode *node, *new_node; | 222 | struct hfs_bnode *node, *new_node, *next_node; |
| 220 | struct hfs_bnode_desc node_desc; | 223 | struct hfs_bnode_desc node_desc; |
| 221 | int num_recs, new_rec_off, new_off, old_rec_off; | 224 | int num_recs, new_rec_off, new_off, old_rec_off; |
| 222 | int data_start, data_end, size; | 225 | int data_start, data_end, size; |
| @@ -235,6 +238,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
| 235 | new_node->type = node->type; | 238 | new_node->type = node->type; |
| 236 | new_node->height = node->height; | 239 | new_node->height = node->height; |
| 237 | 240 | ||
| 241 | if (node->next) | ||
| 242 | next_node = hfs_bnode_find(tree, node->next); | ||
| 243 | else | ||
| 244 | next_node = NULL; | ||
| 245 | |||
| 246 | if (IS_ERR(next_node)) { | ||
| 247 | hfs_bnode_put(node); | ||
| 248 | hfs_bnode_put(new_node); | ||
| 249 | return next_node; | ||
| 250 | } | ||
| 251 | |||
| 238 | size = tree->node_size / 2 - node->num_recs * 2 - 14; | 252 | size = tree->node_size / 2 - node->num_recs * 2 - 14; |
| 239 | old_rec_off = tree->node_size - 4; | 253 | old_rec_off = tree->node_size - 4; |
| 240 | num_recs = 1; | 254 | num_recs = 1; |
| @@ -248,6 +262,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
| 248 | /* panic? */ | 262 | /* panic? */ |
| 249 | hfs_bnode_put(node); | 263 | hfs_bnode_put(node); |
| 250 | hfs_bnode_put(new_node); | 264 | hfs_bnode_put(new_node); |
| 265 | if (next_node) | ||
| 266 | hfs_bnode_put(next_node); | ||
| 251 | return ERR_PTR(-ENOSPC); | 267 | return ERR_PTR(-ENOSPC); |
| 252 | } | 268 | } |
| 253 | 269 | ||
| @@ -302,8 +318,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
| 302 | hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); | 318 | hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); |
| 303 | 319 | ||
| 304 | /* update next bnode header */ | 320 | /* update next bnode header */ |
| 305 | if (new_node->next) { | 321 | if (next_node) { |
| 306 | struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next); | ||
| 307 | next_node->prev = new_node->this; | 322 | next_node->prev = new_node->this; |
| 308 | hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); | 323 | hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); |
| 309 | node_desc.prev = cpu_to_be32(next_node->prev); | 324 | node_desc.prev = cpu_to_be32(next_node->prev); |
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index e49fcee1e293..22e4d4e32999 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c | |||
| @@ -30,7 +30,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
| 30 | if (!tree) | 30 | if (!tree) |
| 31 | return NULL; | 31 | return NULL; |
| 32 | 32 | ||
| 33 | init_MUTEX(&tree->tree_lock); | 33 | mutex_init(&tree->tree_lock); |
| 34 | spin_lock_init(&tree->hash_lock); | 34 | spin_lock_init(&tree->hash_lock); |
| 35 | tree->sb = sb; | 35 | tree->sb = sb; |
| 36 | tree->cnid = id; | 36 | tree->cnid = id; |
| @@ -39,10 +39,16 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
| 39 | goto free_tree; | 39 | goto free_tree; |
| 40 | tree->inode = inode; | 40 | tree->inode = inode; |
| 41 | 41 | ||
| 42 | if (!HFSPLUS_I(tree->inode)->first_blocks) { | ||
| 43 | printk(KERN_ERR | ||
| 44 | "hfs: invalid btree extent records (0 size).\n"); | ||
| 45 | goto free_inode; | ||
| 46 | } | ||
| 47 | |||
| 42 | mapping = tree->inode->i_mapping; | 48 | mapping = tree->inode->i_mapping; |
| 43 | page = read_mapping_page(mapping, 0, NULL); | 49 | page = read_mapping_page(mapping, 0, NULL); |
| 44 | if (IS_ERR(page)) | 50 | if (IS_ERR(page)) |
| 45 | goto free_tree; | 51 | goto free_inode; |
| 46 | 52 | ||
| 47 | /* Load the header */ | 53 | /* Load the header */ |
| 48 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); | 54 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); |
| @@ -57,27 +63,56 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
| 57 | tree->max_key_len = be16_to_cpu(head->max_key_len); | 63 | tree->max_key_len = be16_to_cpu(head->max_key_len); |
| 58 | tree->depth = be16_to_cpu(head->depth); | 64 | tree->depth = be16_to_cpu(head->depth); |
| 59 | 65 | ||
| 60 | /* Set the correct compare function */ | 66 | /* Verify the tree and set the correct compare function */ |
| 61 | if (id == HFSPLUS_EXT_CNID) { | 67 | switch (id) { |
| 68 | case HFSPLUS_EXT_CNID: | ||
| 69 | if (tree->max_key_len != HFSPLUS_EXT_KEYLEN - sizeof(u16)) { | ||
| 70 | printk(KERN_ERR "hfs: invalid extent max_key_len %d\n", | ||
| 71 | tree->max_key_len); | ||
| 72 | goto fail_page; | ||
| 73 | } | ||
| 74 | if (tree->attributes & HFS_TREE_VARIDXKEYS) { | ||
| 75 | printk(KERN_ERR "hfs: invalid extent btree flag\n"); | ||
| 76 | goto fail_page; | ||
| 77 | } | ||
| 78 | |||
| 62 | tree->keycmp = hfsplus_ext_cmp_key; | 79 | tree->keycmp = hfsplus_ext_cmp_key; |
| 63 | } else if (id == HFSPLUS_CAT_CNID) { | 80 | break; |
| 64 | if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) && | 81 | case HFSPLUS_CAT_CNID: |
| 82 | if (tree->max_key_len != HFSPLUS_CAT_KEYLEN - sizeof(u16)) { | ||
| 83 | printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n", | ||
| 84 | tree->max_key_len); | ||
| 85 | goto fail_page; | ||
| 86 | } | ||
| 87 | if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) { | ||
| 88 | printk(KERN_ERR "hfs: invalid catalog btree flag\n"); | ||
| 89 | goto fail_page; | ||
| 90 | } | ||
| 91 | |||
| 92 | if (test_bit(HFSPLUS_SB_HFSX, &HFSPLUS_SB(sb)->flags) && | ||
| 65 | (head->key_type == HFSPLUS_KEY_BINARY)) | 93 | (head->key_type == HFSPLUS_KEY_BINARY)) |
| 66 | tree->keycmp = hfsplus_cat_bin_cmp_key; | 94 | tree->keycmp = hfsplus_cat_bin_cmp_key; |
| 67 | else { | 95 | else { |
| 68 | tree->keycmp = hfsplus_cat_case_cmp_key; | 96 | tree->keycmp = hfsplus_cat_case_cmp_key; |
| 69 | HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD; | 97 | set_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); |
| 70 | } | 98 | } |
| 71 | } else { | 99 | break; |
| 100 | default: | ||
| 72 | printk(KERN_ERR "hfs: unknown B*Tree requested\n"); | 101 | printk(KERN_ERR "hfs: unknown B*Tree requested\n"); |
| 73 | goto fail_page; | 102 | goto fail_page; |
| 74 | } | 103 | } |
| 75 | 104 | ||
| 105 | if (!(tree->attributes & HFS_TREE_BIGKEYS)) { | ||
| 106 | printk(KERN_ERR "hfs: invalid btree flag\n"); | ||
| 107 | goto fail_page; | ||
| 108 | } | ||
| 109 | |||
| 76 | size = tree->node_size; | 110 | size = tree->node_size; |
| 77 | if (!is_power_of_2(size)) | 111 | if (!is_power_of_2(size)) |
| 78 | goto fail_page; | 112 | goto fail_page; |
| 79 | if (!tree->node_count) | 113 | if (!tree->node_count) |
| 80 | goto fail_page; | 114 | goto fail_page; |
| 115 | |||
| 81 | tree->node_size_shift = ffs(size) - 1; | 116 | tree->node_size_shift = ffs(size) - 1; |
| 82 | 117 | ||
| 83 | tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 118 | tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| @@ -87,10 +122,11 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
| 87 | return tree; | 122 | return tree; |
| 88 | 123 | ||
| 89 | fail_page: | 124 | fail_page: |
| 90 | tree->inode->i_mapping->a_ops = &hfsplus_aops; | ||
| 91 | page_cache_release(page); | 125 | page_cache_release(page); |
| 92 | free_tree: | 126 | free_inode: |
| 127 | tree->inode->i_mapping->a_ops = &hfsplus_aops; | ||
| 93 | iput(tree->inode); | 128 | iput(tree->inode); |
| 129 | free_tree: | ||
| 94 | kfree(tree); | 130 | kfree(tree); |
| 95 | return NULL; | 131 | return NULL; |
| 96 | } | 132 | } |
| @@ -192,17 +228,18 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) | |||
| 192 | 228 | ||
| 193 | while (!tree->free_nodes) { | 229 | while (!tree->free_nodes) { |
| 194 | struct inode *inode = tree->inode; | 230 | struct inode *inode = tree->inode; |
| 231 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 195 | u32 count; | 232 | u32 count; |
| 196 | int res; | 233 | int res; |
| 197 | 234 | ||
| 198 | res = hfsplus_file_extend(inode); | 235 | res = hfsplus_file_extend(inode); |
| 199 | if (res) | 236 | if (res) |
| 200 | return ERR_PTR(res); | 237 | return ERR_PTR(res); |
| 201 | HFSPLUS_I(inode).phys_size = inode->i_size = | 238 | hip->phys_size = inode->i_size = |
| 202 | (loff_t)HFSPLUS_I(inode).alloc_blocks << | 239 | (loff_t)hip->alloc_blocks << |
| 203 | HFSPLUS_SB(tree->sb).alloc_blksz_shift; | 240 | HFSPLUS_SB(tree->sb)->alloc_blksz_shift; |
| 204 | HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks << | 241 | hip->fs_blocks = |
| 205 | HFSPLUS_SB(tree->sb).fs_shift; | 242 | hip->alloc_blocks << HFSPLUS_SB(tree->sb)->fs_shift; |
| 206 | inode_set_bytes(inode, inode->i_size); | 243 | inode_set_bytes(inode, inode->i_size); |
| 207 | count = inode->i_size >> tree->node_size_shift; | 244 | count = inode->i_size >> tree->node_size_shift; |
| 208 | tree->free_nodes = count - tree->node_count; | 245 | tree->free_nodes = count - tree->node_count; |
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index f6874acb2cf2..8af45fc5b051 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c | |||
| @@ -67,7 +67,7 @@ static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent, | |||
| 67 | key->key_len = cpu_to_be16(6 + ustrlen); | 67 | key->key_len = cpu_to_be16(6 + ustrlen); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | 70 | void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms) |
| 71 | { | 71 | { |
| 72 | if (inode->i_flags & S_IMMUTABLE) | 72 | if (inode->i_flags & S_IMMUTABLE) |
| 73 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; | 73 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; |
| @@ -77,15 +77,24 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | |||
| 77 | perms->rootflags |= HFSPLUS_FLG_APPEND; | 77 | perms->rootflags |= HFSPLUS_FLG_APPEND; |
| 78 | else | 78 | else |
| 79 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; | 79 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; |
| 80 | HFSPLUS_I(inode).rootflags = perms->rootflags; | 80 | |
| 81 | HFSPLUS_I(inode).userflags = perms->userflags; | 81 | perms->userflags = HFSPLUS_I(inode)->userflags; |
| 82 | perms->mode = cpu_to_be16(inode->i_mode); | 82 | perms->mode = cpu_to_be16(inode->i_mode); |
| 83 | perms->owner = cpu_to_be32(inode->i_uid); | 83 | perms->owner = cpu_to_be32(inode->i_uid); |
| 84 | perms->group = cpu_to_be32(inode->i_gid); | 84 | perms->group = cpu_to_be32(inode->i_gid); |
| 85 | |||
| 86 | if (S_ISREG(inode->i_mode)) | ||
| 87 | perms->dev = cpu_to_be32(inode->i_nlink); | ||
| 88 | else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) | ||
| 89 | perms->dev = cpu_to_be32(inode->i_rdev); | ||
| 90 | else | ||
| 91 | perms->dev = 0; | ||
| 85 | } | 92 | } |
| 86 | 93 | ||
| 87 | static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode) | 94 | static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode) |
| 88 | { | 95 | { |
| 96 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); | ||
| 97 | |||
| 89 | if (S_ISDIR(inode->i_mode)) { | 98 | if (S_ISDIR(inode->i_mode)) { |
| 90 | struct hfsplus_cat_folder *folder; | 99 | struct hfsplus_cat_folder *folder; |
| 91 | 100 | ||
| @@ -93,13 +102,13 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
| 93 | memset(folder, 0, sizeof(*folder)); | 102 | memset(folder, 0, sizeof(*folder)); |
| 94 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); | 103 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); |
| 95 | folder->id = cpu_to_be32(inode->i_ino); | 104 | folder->id = cpu_to_be32(inode->i_ino); |
| 96 | HFSPLUS_I(inode).create_date = | 105 | HFSPLUS_I(inode)->create_date = |
| 97 | folder->create_date = | 106 | folder->create_date = |
| 98 | folder->content_mod_date = | 107 | folder->content_mod_date = |
| 99 | folder->attribute_mod_date = | 108 | folder->attribute_mod_date = |
| 100 | folder->access_date = hfsp_now2mt(); | 109 | folder->access_date = hfsp_now2mt(); |
| 101 | hfsplus_set_perms(inode, &folder->permissions); | 110 | hfsplus_cat_set_perms(inode, &folder->permissions); |
| 102 | if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) | 111 | if (inode == sbi->hidden_dir) |
| 103 | /* invisible and namelocked */ | 112 | /* invisible and namelocked */ |
| 104 | folder->user_info.frFlags = cpu_to_be16(0x5000); | 113 | folder->user_info.frFlags = cpu_to_be16(0x5000); |
| 105 | return sizeof(*folder); | 114 | return sizeof(*folder); |
| @@ -111,19 +120,19 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
| 111 | file->type = cpu_to_be16(HFSPLUS_FILE); | 120 | file->type = cpu_to_be16(HFSPLUS_FILE); |
| 112 | file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); | 121 | file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); |
| 113 | file->id = cpu_to_be32(cnid); | 122 | file->id = cpu_to_be32(cnid); |
| 114 | HFSPLUS_I(inode).create_date = | 123 | HFSPLUS_I(inode)->create_date = |
| 115 | file->create_date = | 124 | file->create_date = |
| 116 | file->content_mod_date = | 125 | file->content_mod_date = |
| 117 | file->attribute_mod_date = | 126 | file->attribute_mod_date = |
| 118 | file->access_date = hfsp_now2mt(); | 127 | file->access_date = hfsp_now2mt(); |
| 119 | if (cnid == inode->i_ino) { | 128 | if (cnid == inode->i_ino) { |
| 120 | hfsplus_set_perms(inode, &file->permissions); | 129 | hfsplus_cat_set_perms(inode, &file->permissions); |
| 121 | if (S_ISLNK(inode->i_mode)) { | 130 | if (S_ISLNK(inode->i_mode)) { |
| 122 | file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); | 131 | file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); |
| 123 | file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); | 132 | file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); |
| 124 | } else { | 133 | } else { |
| 125 | file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); | 134 | file->user_info.fdType = cpu_to_be32(sbi->type); |
| 126 | file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); | 135 | file->user_info.fdCreator = cpu_to_be32(sbi->creator); |
| 127 | } | 136 | } |
| 128 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) | 137 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) |
| 129 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); | 138 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); |
| @@ -131,8 +140,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
| 131 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); | 140 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); |
| 132 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); | 141 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); |
| 133 | file->user_info.fdFlags = cpu_to_be16(0x100); | 142 | file->user_info.fdFlags = cpu_to_be16(0x100); |
| 134 | file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date; | 143 | file->create_date = HFSPLUS_I(sbi->hidden_dir)->create_date; |
| 135 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); | 144 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode)->linkid); |
| 136 | } | 145 | } |
| 137 | return sizeof(*file); | 146 | return sizeof(*file); |
| 138 | } | 147 | } |
| @@ -180,15 +189,14 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, | |||
| 180 | 189 | ||
| 181 | int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode) | 190 | int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode) |
| 182 | { | 191 | { |
| 192 | struct super_block *sb = dir->i_sb; | ||
| 183 | struct hfs_find_data fd; | 193 | struct hfs_find_data fd; |
| 184 | struct super_block *sb; | ||
| 185 | hfsplus_cat_entry entry; | 194 | hfsplus_cat_entry entry; |
| 186 | int entry_size; | 195 | int entry_size; |
| 187 | int err; | 196 | int err; |
| 188 | 197 | ||
| 189 | dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink); | 198 | dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink); |
| 190 | sb = dir->i_sb; | 199 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
| 191 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
| 192 | 200 | ||
| 193 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); | 201 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); |
| 194 | entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ? | 202 | entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ? |
| @@ -234,7 +242,7 @@ err2: | |||
| 234 | 242 | ||
| 235 | int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | 243 | int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) |
| 236 | { | 244 | { |
| 237 | struct super_block *sb; | 245 | struct super_block *sb = dir->i_sb; |
| 238 | struct hfs_find_data fd; | 246 | struct hfs_find_data fd; |
| 239 | struct hfsplus_fork_raw fork; | 247 | struct hfsplus_fork_raw fork; |
| 240 | struct list_head *pos; | 248 | struct list_head *pos; |
| @@ -242,8 +250,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | |||
| 242 | u16 type; | 250 | u16 type; |
| 243 | 251 | ||
| 244 | dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid); | 252 | dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid); |
| 245 | sb = dir->i_sb; | 253 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
| 246 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
| 247 | 254 | ||
| 248 | if (!str) { | 255 | if (!str) { |
| 249 | int len; | 256 | int len; |
| @@ -279,7 +286,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | |||
| 279 | hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC); | 286 | hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC); |
| 280 | } | 287 | } |
| 281 | 288 | ||
| 282 | list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) { | 289 | list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) { |
| 283 | struct hfsplus_readdir_data *rd = | 290 | struct hfsplus_readdir_data *rd = |
| 284 | list_entry(pos, struct hfsplus_readdir_data, list); | 291 | list_entry(pos, struct hfsplus_readdir_data, list); |
| 285 | if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) | 292 | if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) |
| @@ -312,7 +319,7 @@ int hfsplus_rename_cat(u32 cnid, | |||
| 312 | struct inode *src_dir, struct qstr *src_name, | 319 | struct inode *src_dir, struct qstr *src_name, |
| 313 | struct inode *dst_dir, struct qstr *dst_name) | 320 | struct inode *dst_dir, struct qstr *dst_name) |
| 314 | { | 321 | { |
| 315 | struct super_block *sb; | 322 | struct super_block *sb = src_dir->i_sb; |
| 316 | struct hfs_find_data src_fd, dst_fd; | 323 | struct hfs_find_data src_fd, dst_fd; |
| 317 | hfsplus_cat_entry entry; | 324 | hfsplus_cat_entry entry; |
| 318 | int entry_size, type; | 325 | int entry_size, type; |
| @@ -320,8 +327,7 @@ int hfsplus_rename_cat(u32 cnid, | |||
| 320 | 327 | ||
| 321 | dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name, | 328 | dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name, |
| 322 | dst_dir->i_ino, dst_name->name); | 329 | dst_dir->i_ino, dst_name->name); |
| 323 | sb = src_dir->i_sb; | 330 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd); |
| 324 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd); | ||
| 325 | dst_fd = src_fd; | 331 | dst_fd = src_fd; |
| 326 | 332 | ||
| 327 | /* find the old dir entry and read the data */ | 333 | /* find the old dir entry and read the data */ |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 764fd1bdca88..d236d85ec9d7 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
| @@ -39,7 +39,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, | |||
| 39 | 39 | ||
| 40 | dentry->d_op = &hfsplus_dentry_operations; | 40 | dentry->d_op = &hfsplus_dentry_operations; |
| 41 | dentry->d_fsdata = NULL; | 41 | dentry->d_fsdata = NULL; |
| 42 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 42 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
| 43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); | 43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); |
| 44 | again: | 44 | again: |
| 45 | err = hfs_brec_read(&fd, &entry, sizeof(entry)); | 45 | err = hfs_brec_read(&fd, &entry, sizeof(entry)); |
| @@ -68,9 +68,9 @@ again: | |||
| 68 | cnid = be32_to_cpu(entry.file.id); | 68 | cnid = be32_to_cpu(entry.file.id); |
| 69 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && | 69 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && |
| 70 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && | 70 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && |
| 71 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date || | 71 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->create_date || |
| 72 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) && | 72 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode)->create_date) && |
| 73 | HFSPLUS_SB(sb).hidden_dir) { | 73 | HFSPLUS_SB(sb)->hidden_dir) { |
| 74 | struct qstr str; | 74 | struct qstr str; |
| 75 | char name[32]; | 75 | char name[32]; |
| 76 | 76 | ||
| @@ -86,7 +86,8 @@ again: | |||
| 86 | linkid = be32_to_cpu(entry.file.permissions.dev); | 86 | linkid = be32_to_cpu(entry.file.permissions.dev); |
| 87 | str.len = sprintf(name, "iNode%d", linkid); | 87 | str.len = sprintf(name, "iNode%d", linkid); |
| 88 | str.name = name; | 88 | str.name = name; |
| 89 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | 89 | hfsplus_cat_build_key(sb, fd.search_key, |
| 90 | HFSPLUS_SB(sb)->hidden_dir->i_ino, &str); | ||
| 90 | goto again; | 91 | goto again; |
| 91 | } | 92 | } |
| 92 | } else if (!dentry->d_fsdata) | 93 | } else if (!dentry->d_fsdata) |
| @@ -101,7 +102,7 @@ again: | |||
| 101 | if (IS_ERR(inode)) | 102 | if (IS_ERR(inode)) |
| 102 | return ERR_CAST(inode); | 103 | return ERR_CAST(inode); |
| 103 | if (S_ISREG(inode->i_mode)) | 104 | if (S_ISREG(inode->i_mode)) |
| 104 | HFSPLUS_I(inode).dev = linkid; | 105 | HFSPLUS_I(inode)->linkid = linkid; |
| 105 | out: | 106 | out: |
| 106 | d_add(dentry, inode); | 107 | d_add(dentry, inode); |
| 107 | return NULL; | 108 | return NULL; |
| @@ -124,7 +125,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 124 | if (filp->f_pos >= inode->i_size) | 125 | if (filp->f_pos >= inode->i_size) |
| 125 | return 0; | 126 | return 0; |
| 126 | 127 | ||
| 127 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 128 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
| 128 | hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); | 129 | hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); |
| 129 | err = hfs_brec_find(&fd); | 130 | err = hfs_brec_find(&fd); |
| 130 | if (err) | 131 | if (err) |
| @@ -180,8 +181,9 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 180 | err = -EIO; | 181 | err = -EIO; |
| 181 | goto out; | 182 | goto out; |
| 182 | } | 183 | } |
| 183 | if (HFSPLUS_SB(sb).hidden_dir && | 184 | if (HFSPLUS_SB(sb)->hidden_dir && |
| 184 | HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id)) | 185 | HFSPLUS_SB(sb)->hidden_dir->i_ino == |
| 186 | be32_to_cpu(entry.folder.id)) | ||
| 185 | goto next; | 187 | goto next; |
| 186 | if (filldir(dirent, strbuf, len, filp->f_pos, | 188 | if (filldir(dirent, strbuf, len, filp->f_pos, |
| 187 | be32_to_cpu(entry.folder.id), DT_DIR)) | 189 | be32_to_cpu(entry.folder.id), DT_DIR)) |
| @@ -217,7 +219,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 217 | } | 219 | } |
| 218 | filp->private_data = rd; | 220 | filp->private_data = rd; |
| 219 | rd->file = filp; | 221 | rd->file = filp; |
| 220 | list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list); | 222 | list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list); |
| 221 | } | 223 | } |
| 222 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); | 224 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); |
| 223 | out: | 225 | out: |
| @@ -229,38 +231,18 @@ static int hfsplus_dir_release(struct inode *inode, struct file *file) | |||
| 229 | { | 231 | { |
| 230 | struct hfsplus_readdir_data *rd = file->private_data; | 232 | struct hfsplus_readdir_data *rd = file->private_data; |
| 231 | if (rd) { | 233 | if (rd) { |
| 234 | mutex_lock(&inode->i_mutex); | ||
| 232 | list_del(&rd->list); | 235 | list_del(&rd->list); |
| 236 | mutex_unlock(&inode->i_mutex); | ||
| 233 | kfree(rd); | 237 | kfree(rd); |
| 234 | } | 238 | } |
| 235 | return 0; | 239 | return 0; |
| 236 | } | 240 | } |
| 237 | 241 | ||
| 238 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, | ||
| 239 | struct nameidata *nd) | ||
| 240 | { | ||
| 241 | struct inode *inode; | ||
| 242 | int res; | ||
| 243 | |||
| 244 | inode = hfsplus_new_inode(dir->i_sb, mode); | ||
| 245 | if (!inode) | ||
| 246 | return -ENOSPC; | ||
| 247 | |||
| 248 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
| 249 | if (res) { | ||
| 250 | inode->i_nlink = 0; | ||
| 251 | hfsplus_delete_inode(inode); | ||
| 252 | iput(inode); | ||
| 253 | return res; | ||
| 254 | } | ||
| 255 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
| 256 | mark_inode_dirty(inode); | ||
| 257 | return 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | 242 | static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, |
| 261 | struct dentry *dst_dentry) | 243 | struct dentry *dst_dentry) |
| 262 | { | 244 | { |
| 263 | struct super_block *sb = dst_dir->i_sb; | 245 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb); |
| 264 | struct inode *inode = src_dentry->d_inode; | 246 | struct inode *inode = src_dentry->d_inode; |
| 265 | struct inode *src_dir = src_dentry->d_parent->d_inode; | 247 | struct inode *src_dir = src_dentry->d_parent->d_inode; |
| 266 | struct qstr str; | 248 | struct qstr str; |
| @@ -270,7 +252,10 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
| 270 | 252 | ||
| 271 | if (HFSPLUS_IS_RSRC(inode)) | 253 | if (HFSPLUS_IS_RSRC(inode)) |
| 272 | return -EPERM; | 254 | return -EPERM; |
| 255 | if (!S_ISREG(inode->i_mode)) | ||
| 256 | return -EPERM; | ||
| 273 | 257 | ||
| 258 | mutex_lock(&sbi->vh_mutex); | ||
| 274 | if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { | 259 | if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { |
| 275 | for (;;) { | 260 | for (;;) { |
| 276 | get_random_bytes(&id, sizeof(cnid)); | 261 | get_random_bytes(&id, sizeof(cnid)); |
| @@ -279,40 +264,41 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
| 279 | str.len = sprintf(name, "iNode%d", id); | 264 | str.len = sprintf(name, "iNode%d", id); |
| 280 | res = hfsplus_rename_cat(inode->i_ino, | 265 | res = hfsplus_rename_cat(inode->i_ino, |
| 281 | src_dir, &src_dentry->d_name, | 266 | src_dir, &src_dentry->d_name, |
| 282 | HFSPLUS_SB(sb).hidden_dir, &str); | 267 | sbi->hidden_dir, &str); |
| 283 | if (!res) | 268 | if (!res) |
| 284 | break; | 269 | break; |
| 285 | if (res != -EEXIST) | 270 | if (res != -EEXIST) |
| 286 | return res; | 271 | goto out; |
| 287 | } | 272 | } |
| 288 | HFSPLUS_I(inode).dev = id; | 273 | HFSPLUS_I(inode)->linkid = id; |
| 289 | cnid = HFSPLUS_SB(sb).next_cnid++; | 274 | cnid = sbi->next_cnid++; |
| 290 | src_dentry->d_fsdata = (void *)(unsigned long)cnid; | 275 | src_dentry->d_fsdata = (void *)(unsigned long)cnid; |
| 291 | res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); | 276 | res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); |
| 292 | if (res) | 277 | if (res) |
| 293 | /* panic? */ | 278 | /* panic? */ |
| 294 | return res; | 279 | goto out; |
| 295 | HFSPLUS_SB(sb).file_count++; | 280 | sbi->file_count++; |
| 296 | } | 281 | } |
| 297 | cnid = HFSPLUS_SB(sb).next_cnid++; | 282 | cnid = sbi->next_cnid++; |
| 298 | res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); | 283 | res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); |
| 299 | if (res) | 284 | if (res) |
| 300 | return res; | 285 | goto out; |
| 301 | 286 | ||
| 302 | inc_nlink(inode); | 287 | inc_nlink(inode); |
| 303 | hfsplus_instantiate(dst_dentry, inode, cnid); | 288 | hfsplus_instantiate(dst_dentry, inode, cnid); |
| 304 | atomic_inc(&inode->i_count); | 289 | atomic_inc(&inode->i_count); |
| 305 | inode->i_ctime = CURRENT_TIME_SEC; | 290 | inode->i_ctime = CURRENT_TIME_SEC; |
| 306 | mark_inode_dirty(inode); | 291 | mark_inode_dirty(inode); |
| 307 | HFSPLUS_SB(sb).file_count++; | 292 | sbi->file_count++; |
| 308 | sb->s_dirt = 1; | 293 | dst_dir->i_sb->s_dirt = 1; |
| 309 | 294 | out: | |
| 310 | return 0; | 295 | mutex_unlock(&sbi->vh_mutex); |
| 296 | return res; | ||
| 311 | } | 297 | } |
| 312 | 298 | ||
| 313 | static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | 299 | static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) |
| 314 | { | 300 | { |
| 315 | struct super_block *sb = dir->i_sb; | 301 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 316 | struct inode *inode = dentry->d_inode; | 302 | struct inode *inode = dentry->d_inode; |
| 317 | struct qstr str; | 303 | struct qstr str; |
| 318 | char name[32]; | 304 | char name[32]; |
| @@ -322,21 +308,22 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
| 322 | if (HFSPLUS_IS_RSRC(inode)) | 308 | if (HFSPLUS_IS_RSRC(inode)) |
| 323 | return -EPERM; | 309 | return -EPERM; |
| 324 | 310 | ||
| 311 | mutex_lock(&sbi->vh_mutex); | ||
| 325 | cnid = (u32)(unsigned long)dentry->d_fsdata; | 312 | cnid = (u32)(unsigned long)dentry->d_fsdata; |
| 326 | if (inode->i_ino == cnid && | 313 | if (inode->i_ino == cnid && |
| 327 | atomic_read(&HFSPLUS_I(inode).opencnt)) { | 314 | atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
| 328 | str.name = name; | 315 | str.name = name; |
| 329 | str.len = sprintf(name, "temp%lu", inode->i_ino); | 316 | str.len = sprintf(name, "temp%lu", inode->i_ino); |
| 330 | res = hfsplus_rename_cat(inode->i_ino, | 317 | res = hfsplus_rename_cat(inode->i_ino, |
| 331 | dir, &dentry->d_name, | 318 | dir, &dentry->d_name, |
| 332 | HFSPLUS_SB(sb).hidden_dir, &str); | 319 | sbi->hidden_dir, &str); |
| 333 | if (!res) | 320 | if (!res) |
| 334 | inode->i_flags |= S_DEAD; | 321 | inode->i_flags |= S_DEAD; |
| 335 | return res; | 322 | goto out; |
| 336 | } | 323 | } |
| 337 | res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); | 324 | res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); |
| 338 | if (res) | 325 | if (res) |
| 339 | return res; | 326 | goto out; |
| 340 | 327 | ||
| 341 | if (inode->i_nlink > 0) | 328 | if (inode->i_nlink > 0) |
| 342 | drop_nlink(inode); | 329 | drop_nlink(inode); |
| @@ -344,10 +331,10 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
| 344 | clear_nlink(inode); | 331 | clear_nlink(inode); |
| 345 | if (!inode->i_nlink) { | 332 | if (!inode->i_nlink) { |
| 346 | if (inode->i_ino != cnid) { | 333 | if (inode->i_ino != cnid) { |
| 347 | HFSPLUS_SB(sb).file_count--; | 334 | sbi->file_count--; |
| 348 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { | 335 | if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
| 349 | res = hfsplus_delete_cat(inode->i_ino, | 336 | res = hfsplus_delete_cat(inode->i_ino, |
| 350 | HFSPLUS_SB(sb).hidden_dir, | 337 | sbi->hidden_dir, |
| 351 | NULL); | 338 | NULL); |
| 352 | if (!res) | 339 | if (!res) |
| 353 | hfsplus_delete_inode(inode); | 340 | hfsplus_delete_inode(inode); |
| @@ -356,107 +343,108 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
| 356 | } else | 343 | } else |
| 357 | hfsplus_delete_inode(inode); | 344 | hfsplus_delete_inode(inode); |
| 358 | } else | 345 | } else |
| 359 | HFSPLUS_SB(sb).file_count--; | 346 | sbi->file_count--; |
| 360 | inode->i_ctime = CURRENT_TIME_SEC; | 347 | inode->i_ctime = CURRENT_TIME_SEC; |
| 361 | mark_inode_dirty(inode); | 348 | mark_inode_dirty(inode); |
| 362 | 349 | out: | |
| 350 | mutex_unlock(&sbi->vh_mutex); | ||
| 363 | return res; | 351 | return res; |
| 364 | } | 352 | } |
| 365 | 353 | ||
| 366 | static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
| 367 | { | ||
| 368 | struct inode *inode; | ||
| 369 | int res; | ||
| 370 | |||
| 371 | inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode); | ||
| 372 | if (!inode) | ||
| 373 | return -ENOSPC; | ||
| 374 | |||
| 375 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
| 376 | if (res) { | ||
| 377 | inode->i_nlink = 0; | ||
| 378 | hfsplus_delete_inode(inode); | ||
| 379 | iput(inode); | ||
| 380 | return res; | ||
| 381 | } | ||
| 382 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
| 383 | mark_inode_dirty(inode); | ||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) | 354 | static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) |
| 388 | { | 355 | { |
| 389 | struct inode *inode; | 356 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 357 | struct inode *inode = dentry->d_inode; | ||
| 390 | int res; | 358 | int res; |
| 391 | 359 | ||
| 392 | inode = dentry->d_inode; | ||
| 393 | if (inode->i_size != 2) | 360 | if (inode->i_size != 2) |
| 394 | return -ENOTEMPTY; | 361 | return -ENOTEMPTY; |
| 362 | |||
| 363 | mutex_lock(&sbi->vh_mutex); | ||
| 395 | res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); | 364 | res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); |
| 396 | if (res) | 365 | if (res) |
| 397 | return res; | 366 | goto out; |
| 398 | clear_nlink(inode); | 367 | clear_nlink(inode); |
| 399 | inode->i_ctime = CURRENT_TIME_SEC; | 368 | inode->i_ctime = CURRENT_TIME_SEC; |
| 400 | hfsplus_delete_inode(inode); | 369 | hfsplus_delete_inode(inode); |
| 401 | mark_inode_dirty(inode); | 370 | mark_inode_dirty(inode); |
| 402 | return 0; | 371 | out: |
| 372 | mutex_unlock(&sbi->vh_mutex); | ||
| 373 | return res; | ||
| 403 | } | 374 | } |
| 404 | 375 | ||
| 405 | static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, | 376 | static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, |
| 406 | const char *symname) | 377 | const char *symname) |
| 407 | { | 378 | { |
| 408 | struct super_block *sb; | 379 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 409 | struct inode *inode; | 380 | struct inode *inode; |
| 410 | int res; | 381 | int res = -ENOSPC; |
| 411 | 382 | ||
| 412 | sb = dir->i_sb; | 383 | mutex_lock(&sbi->vh_mutex); |
| 413 | inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO); | 384 | inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); |
| 414 | if (!inode) | 385 | if (!inode) |
| 415 | return -ENOSPC; | 386 | goto out; |
| 416 | 387 | ||
| 417 | res = page_symlink(inode, symname, strlen(symname) + 1); | 388 | res = page_symlink(inode, symname, strlen(symname) + 1); |
| 418 | if (res) { | 389 | if (res) |
| 419 | inode->i_nlink = 0; | 390 | goto out_err; |
| 420 | hfsplus_delete_inode(inode); | ||
| 421 | iput(inode); | ||
| 422 | return res; | ||
| 423 | } | ||
| 424 | 391 | ||
| 425 | mark_inode_dirty(inode); | ||
| 426 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | 392 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
| 393 | if (res) | ||
| 394 | goto out_err; | ||
| 427 | 395 | ||
| 428 | if (!res) { | 396 | hfsplus_instantiate(dentry, inode, inode->i_ino); |
| 429 | hfsplus_instantiate(dentry, inode, inode->i_ino); | 397 | mark_inode_dirty(inode); |
| 430 | mark_inode_dirty(inode); | 398 | goto out; |
| 431 | } | ||
| 432 | 399 | ||
| 400 | out_err: | ||
| 401 | inode->i_nlink = 0; | ||
| 402 | hfsplus_delete_inode(inode); | ||
| 403 | iput(inode); | ||
| 404 | out: | ||
| 405 | mutex_unlock(&sbi->vh_mutex); | ||
| 433 | return res; | 406 | return res; |
| 434 | } | 407 | } |
| 435 | 408 | ||
| 436 | static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, | 409 | static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, |
| 437 | int mode, dev_t rdev) | 410 | int mode, dev_t rdev) |
| 438 | { | 411 | { |
| 439 | struct super_block *sb; | 412 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
| 440 | struct inode *inode; | 413 | struct inode *inode; |
| 441 | int res; | 414 | int res = -ENOSPC; |
| 442 | 415 | ||
| 443 | sb = dir->i_sb; | 416 | mutex_lock(&sbi->vh_mutex); |
| 444 | inode = hfsplus_new_inode(sb, mode); | 417 | inode = hfsplus_new_inode(dir->i_sb, mode); |
| 445 | if (!inode) | 418 | if (!inode) |
| 446 | return -ENOSPC; | 419 | goto out; |
| 420 | |||
| 421 | if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) | ||
| 422 | init_special_inode(inode, mode, rdev); | ||
| 447 | 423 | ||
| 448 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | 424 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
| 449 | if (res) { | 425 | if (res) { |
| 450 | inode->i_nlink = 0; | 426 | inode->i_nlink = 0; |
| 451 | hfsplus_delete_inode(inode); | 427 | hfsplus_delete_inode(inode); |
| 452 | iput(inode); | 428 | iput(inode); |
| 453 | return res; | 429 | goto out; |
| 454 | } | 430 | } |
| 455 | init_special_inode(inode, mode, rdev); | 431 | |
| 456 | hfsplus_instantiate(dentry, inode, inode->i_ino); | 432 | hfsplus_instantiate(dentry, inode, inode->i_ino); |
| 457 | mark_inode_dirty(inode); | 433 | mark_inode_dirty(inode); |
| 434 | out: | ||
| 435 | mutex_unlock(&sbi->vh_mutex); | ||
| 436 | return res; | ||
| 437 | } | ||
| 458 | 438 | ||
| 459 | return 0; | 439 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, |
| 440 | struct nameidata *nd) | ||
| 441 | { | ||
| 442 | return hfsplus_mknod(dir, dentry, mode, 0); | ||
| 443 | } | ||
| 444 | |||
| 445 | static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
| 446 | { | ||
| 447 | return hfsplus_mknod(dir, dentry, mode | S_IFDIR, 0); | ||
| 460 | } | 448 | } |
| 461 | 449 | ||
| 462 | static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | 450 | static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, |
| @@ -466,7 +454,10 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 466 | 454 | ||
| 467 | /* Unlink destination if it already exists */ | 455 | /* Unlink destination if it already exists */ |
| 468 | if (new_dentry->d_inode) { | 456 | if (new_dentry->d_inode) { |
| 469 | res = hfsplus_unlink(new_dir, new_dentry); | 457 | if (S_ISDIR(new_dentry->d_inode->i_mode)) |
| 458 | res = hfsplus_rmdir(new_dir, new_dentry); | ||
| 459 | else | ||
| 460 | res = hfsplus_unlink(new_dir, new_dentry); | ||
| 470 | if (res) | 461 | if (res) |
| 471 | return res; | 462 | return res; |
| 472 | } | 463 | } |
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 0022eec63cda..0c9cb1820a52 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c | |||
| @@ -85,35 +85,49 @@ static u32 hfsplus_ext_lastblock(struct hfsplus_extent *ext) | |||
| 85 | 85 | ||
| 86 | static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd) | 86 | static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd) |
| 87 | { | 87 | { |
| 88 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 88 | int res; | 89 | int res; |
| 89 | 90 | ||
| 90 | hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start, | 91 | WARN_ON(!mutex_is_locked(&hip->extents_lock)); |
| 91 | HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | 92 | |
| 93 | hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start, | ||
| 94 | HFSPLUS_IS_RSRC(inode) ? | ||
| 95 | HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | ||
| 96 | |||
| 92 | res = hfs_brec_find(fd); | 97 | res = hfs_brec_find(fd); |
| 93 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) { | 98 | if (hip->flags & HFSPLUS_FLG_EXT_NEW) { |
| 94 | if (res != -ENOENT) | 99 | if (res != -ENOENT) |
| 95 | return; | 100 | return; |
| 96 | hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec)); | 101 | hfs_brec_insert(fd, hip->cached_extents, |
| 97 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | 102 | sizeof(hfsplus_extent_rec)); |
| 103 | hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | ||
| 98 | } else { | 104 | } else { |
| 99 | if (res) | 105 | if (res) |
| 100 | return; | 106 | return; |
| 101 | hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength); | 107 | hfs_bnode_write(fd->bnode, hip->cached_extents, |
| 102 | HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY; | 108 | fd->entryoffset, fd->entrylength); |
| 109 | hip->flags &= ~HFSPLUS_FLG_EXT_DIRTY; | ||
| 103 | } | 110 | } |
| 104 | } | 111 | } |
| 105 | 112 | ||
| 106 | void hfsplus_ext_write_extent(struct inode *inode) | 113 | static void hfsplus_ext_write_extent_locked(struct inode *inode) |
| 107 | { | 114 | { |
| 108 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) { | 115 | if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) { |
| 109 | struct hfs_find_data fd; | 116 | struct hfs_find_data fd; |
| 110 | 117 | ||
| 111 | hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); | 118 | hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd); |
| 112 | __hfsplus_ext_write_extent(inode, &fd); | 119 | __hfsplus_ext_write_extent(inode, &fd); |
| 113 | hfs_find_exit(&fd); | 120 | hfs_find_exit(&fd); |
| 114 | } | 121 | } |
| 115 | } | 122 | } |
| 116 | 123 | ||
| 124 | void hfsplus_ext_write_extent(struct inode *inode) | ||
| 125 | { | ||
| 126 | mutex_lock(&HFSPLUS_I(inode)->extents_lock); | ||
| 127 | hfsplus_ext_write_extent_locked(inode); | ||
| 128 | mutex_unlock(&HFSPLUS_I(inode)->extents_lock); | ||
| 129 | } | ||
| 130 | |||
| 117 | static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, | 131 | static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, |
| 118 | struct hfsplus_extent *extent, | 132 | struct hfsplus_extent *extent, |
| 119 | u32 cnid, u32 block, u8 type) | 133 | u32 cnid, u32 block, u8 type) |
| @@ -136,33 +150,39 @@ static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, | |||
| 136 | 150 | ||
| 137 | static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block) | 151 | static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block) |
| 138 | { | 152 | { |
| 153 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 139 | int res; | 154 | int res; |
| 140 | 155 | ||
| 141 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) | 156 | WARN_ON(!mutex_is_locked(&hip->extents_lock)); |
| 157 | |||
| 158 | if (hip->flags & HFSPLUS_FLG_EXT_DIRTY) | ||
| 142 | __hfsplus_ext_write_extent(inode, fd); | 159 | __hfsplus_ext_write_extent(inode, fd); |
| 143 | 160 | ||
| 144 | res = __hfsplus_ext_read_extent(fd, HFSPLUS_I(inode).cached_extents, inode->i_ino, | 161 | res = __hfsplus_ext_read_extent(fd, hip->cached_extents, inode->i_ino, |
| 145 | block, HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | 162 | block, HFSPLUS_IS_RSRC(inode) ? |
| 163 | HFSPLUS_TYPE_RSRC : | ||
| 164 | HFSPLUS_TYPE_DATA); | ||
| 146 | if (!res) { | 165 | if (!res) { |
| 147 | HFSPLUS_I(inode).cached_start = be32_to_cpu(fd->key->ext.start_block); | 166 | hip->cached_start = be32_to_cpu(fd->key->ext.start_block); |
| 148 | HFSPLUS_I(inode).cached_blocks = hfsplus_ext_block_count(HFSPLUS_I(inode).cached_extents); | 167 | hip->cached_blocks = hfsplus_ext_block_count(hip->cached_extents); |
| 149 | } else { | 168 | } else { |
| 150 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; | 169 | hip->cached_start = hip->cached_blocks = 0; |
| 151 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | 170 | hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); |
| 152 | } | 171 | } |
| 153 | return res; | 172 | return res; |
| 154 | } | 173 | } |
| 155 | 174 | ||
| 156 | static int hfsplus_ext_read_extent(struct inode *inode, u32 block) | 175 | static int hfsplus_ext_read_extent(struct inode *inode, u32 block) |
| 157 | { | 176 | { |
| 177 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 158 | struct hfs_find_data fd; | 178 | struct hfs_find_data fd; |
| 159 | int res; | 179 | int res; |
| 160 | 180 | ||
| 161 | if (block >= HFSPLUS_I(inode).cached_start && | 181 | if (block >= hip->cached_start && |
| 162 | block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks) | 182 | block < hip->cached_start + hip->cached_blocks) |
| 163 | return 0; | 183 | return 0; |
| 164 | 184 | ||
| 165 | hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); | 185 | hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd); |
| 166 | res = __hfsplus_ext_cache_extent(&fd, inode, block); | 186 | res = __hfsplus_ext_cache_extent(&fd, inode, block); |
| 167 | hfs_find_exit(&fd); | 187 | hfs_find_exit(&fd); |
| 168 | return res; | 188 | return res; |
| @@ -172,21 +192,21 @@ static int hfsplus_ext_read_extent(struct inode *inode, u32 block) | |||
| 172 | int hfsplus_get_block(struct inode *inode, sector_t iblock, | 192 | int hfsplus_get_block(struct inode *inode, sector_t iblock, |
| 173 | struct buffer_head *bh_result, int create) | 193 | struct buffer_head *bh_result, int create) |
| 174 | { | 194 | { |
| 175 | struct super_block *sb; | 195 | struct super_block *sb = inode->i_sb; |
| 196 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 197 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 176 | int res = -EIO; | 198 | int res = -EIO; |
| 177 | u32 ablock, dblock, mask; | 199 | u32 ablock, dblock, mask; |
| 178 | int shift; | 200 | int shift; |
| 179 | 201 | ||
| 180 | sb = inode->i_sb; | ||
| 181 | |||
| 182 | /* Convert inode block to disk allocation block */ | 202 | /* Convert inode block to disk allocation block */ |
| 183 | shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits; | 203 | shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits; |
| 184 | ablock = iblock >> HFSPLUS_SB(sb).fs_shift; | 204 | ablock = iblock >> sbi->fs_shift; |
| 185 | 205 | ||
| 186 | if (iblock >= HFSPLUS_I(inode).fs_blocks) { | 206 | if (iblock >= hip->fs_blocks) { |
| 187 | if (iblock > HFSPLUS_I(inode).fs_blocks || !create) | 207 | if (iblock > hip->fs_blocks || !create) |
| 188 | return -EIO; | 208 | return -EIO; |
| 189 | if (ablock >= HFSPLUS_I(inode).alloc_blocks) { | 209 | if (ablock >= hip->alloc_blocks) { |
| 190 | res = hfsplus_file_extend(inode); | 210 | res = hfsplus_file_extend(inode); |
| 191 | if (res) | 211 | if (res) |
| 192 | return res; | 212 | return res; |
| @@ -194,33 +214,33 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock, | |||
| 194 | } else | 214 | } else |
| 195 | create = 0; | 215 | create = 0; |
| 196 | 216 | ||
| 197 | if (ablock < HFSPLUS_I(inode).first_blocks) { | 217 | if (ablock < hip->first_blocks) { |
| 198 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock); | 218 | dblock = hfsplus_ext_find_block(hip->first_extents, ablock); |
| 199 | goto done; | 219 | goto done; |
| 200 | } | 220 | } |
| 201 | 221 | ||
| 202 | if (inode->i_ino == HFSPLUS_EXT_CNID) | 222 | if (inode->i_ino == HFSPLUS_EXT_CNID) |
| 203 | return -EIO; | 223 | return -EIO; |
| 204 | 224 | ||
| 205 | mutex_lock(&HFSPLUS_I(inode).extents_lock); | 225 | mutex_lock(&hip->extents_lock); |
| 206 | res = hfsplus_ext_read_extent(inode, ablock); | 226 | res = hfsplus_ext_read_extent(inode, ablock); |
| 207 | if (!res) { | 227 | if (!res) { |
| 208 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - | 228 | dblock = hfsplus_ext_find_block(hip->cached_extents, |
| 209 | HFSPLUS_I(inode).cached_start); | 229 | ablock - hip->cached_start); |
| 210 | } else { | 230 | } else { |
| 211 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 231 | mutex_unlock(&hip->extents_lock); |
| 212 | return -EIO; | 232 | return -EIO; |
| 213 | } | 233 | } |
| 214 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 234 | mutex_unlock(&hip->extents_lock); |
| 215 | 235 | ||
| 216 | done: | 236 | done: |
| 217 | dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); | 237 | dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); |
| 218 | mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1; | 238 | mask = (1 << sbi->fs_shift) - 1; |
| 219 | map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask)); | 239 | map_bh(bh_result, sb, (dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask)); |
| 220 | if (create) { | 240 | if (create) { |
| 221 | set_buffer_new(bh_result); | 241 | set_buffer_new(bh_result); |
| 222 | HFSPLUS_I(inode).phys_size += sb->s_blocksize; | 242 | hip->phys_size += sb->s_blocksize; |
| 223 | HFSPLUS_I(inode).fs_blocks++; | 243 | hip->fs_blocks++; |
| 224 | inode_add_bytes(inode, sb->s_blocksize); | 244 | inode_add_bytes(inode, sb->s_blocksize); |
| 225 | mark_inode_dirty(inode); | 245 | mark_inode_dirty(inode); |
| 226 | } | 246 | } |
| @@ -327,7 +347,7 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw | |||
| 327 | if (total_blocks == blocks) | 347 | if (total_blocks == blocks) |
| 328 | return 0; | 348 | return 0; |
| 329 | 349 | ||
| 330 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); | 350 | hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd); |
| 331 | do { | 351 | do { |
| 332 | res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid, | 352 | res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid, |
| 333 | total_blocks, type); | 353 | total_blocks, type); |
| @@ -348,29 +368,33 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw | |||
| 348 | int hfsplus_file_extend(struct inode *inode) | 368 | int hfsplus_file_extend(struct inode *inode) |
| 349 | { | 369 | { |
| 350 | struct super_block *sb = inode->i_sb; | 370 | struct super_block *sb = inode->i_sb; |
| 371 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 372 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 351 | u32 start, len, goal; | 373 | u32 start, len, goal; |
| 352 | int res; | 374 | int res; |
| 353 | 375 | ||
| 354 | if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { | 376 | if (sbi->alloc_file->i_size * 8 < |
| 377 | sbi->total_blocks - sbi->free_blocks + 8) { | ||
| 355 | // extend alloc file | 378 | // extend alloc file |
| 356 | printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, | 379 | printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", |
| 357 | HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); | 380 | sbi->alloc_file->i_size * 8, |
| 381 | sbi->total_blocks, sbi->free_blocks); | ||
| 358 | return -ENOSPC; | 382 | return -ENOSPC; |
| 359 | } | 383 | } |
| 360 | 384 | ||
| 361 | mutex_lock(&HFSPLUS_I(inode).extents_lock); | 385 | mutex_lock(&hip->extents_lock); |
| 362 | if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks) | 386 | if (hip->alloc_blocks == hip->first_blocks) |
| 363 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents); | 387 | goal = hfsplus_ext_lastblock(hip->first_extents); |
| 364 | else { | 388 | else { |
| 365 | res = hfsplus_ext_read_extent(inode, HFSPLUS_I(inode).alloc_blocks); | 389 | res = hfsplus_ext_read_extent(inode, hip->alloc_blocks); |
| 366 | if (res) | 390 | if (res) |
| 367 | goto out; | 391 | goto out; |
| 368 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).cached_extents); | 392 | goal = hfsplus_ext_lastblock(hip->cached_extents); |
| 369 | } | 393 | } |
| 370 | 394 | ||
| 371 | len = HFSPLUS_I(inode).clump_blocks; | 395 | len = hip->clump_blocks; |
| 372 | start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len); | 396 | start = hfsplus_block_allocate(sb, sbi->total_blocks, goal, &len); |
| 373 | if (start >= HFSPLUS_SB(sb).total_blocks) { | 397 | if (start >= sbi->total_blocks) { |
| 374 | start = hfsplus_block_allocate(sb, goal, 0, &len); | 398 | start = hfsplus_block_allocate(sb, goal, 0, &len); |
| 375 | if (start >= goal) { | 399 | if (start >= goal) { |
| 376 | res = -ENOSPC; | 400 | res = -ENOSPC; |
| @@ -379,56 +403,56 @@ int hfsplus_file_extend(struct inode *inode) | |||
| 379 | } | 403 | } |
| 380 | 404 | ||
| 381 | dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len); | 405 | dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len); |
| 382 | if (HFSPLUS_I(inode).alloc_blocks <= HFSPLUS_I(inode).first_blocks) { | 406 | |
| 383 | if (!HFSPLUS_I(inode).first_blocks) { | 407 | if (hip->alloc_blocks <= hip->first_blocks) { |
| 408 | if (!hip->first_blocks) { | ||
| 384 | dprint(DBG_EXTENT, "first extents\n"); | 409 | dprint(DBG_EXTENT, "first extents\n"); |
| 385 | /* no extents yet */ | 410 | /* no extents yet */ |
| 386 | HFSPLUS_I(inode).first_extents[0].start_block = cpu_to_be32(start); | 411 | hip->first_extents[0].start_block = cpu_to_be32(start); |
| 387 | HFSPLUS_I(inode).first_extents[0].block_count = cpu_to_be32(len); | 412 | hip->first_extents[0].block_count = cpu_to_be32(len); |
| 388 | res = 0; | 413 | res = 0; |
| 389 | } else { | 414 | } else { |
| 390 | /* try to append to extents in inode */ | 415 | /* try to append to extents in inode */ |
| 391 | res = hfsplus_add_extent(HFSPLUS_I(inode).first_extents, | 416 | res = hfsplus_add_extent(hip->first_extents, |
| 392 | HFSPLUS_I(inode).alloc_blocks, | 417 | hip->alloc_blocks, |
| 393 | start, len); | 418 | start, len); |
| 394 | if (res == -ENOSPC) | 419 | if (res == -ENOSPC) |
| 395 | goto insert_extent; | 420 | goto insert_extent; |
| 396 | } | 421 | } |
| 397 | if (!res) { | 422 | if (!res) { |
| 398 | hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); | 423 | hfsplus_dump_extent(hip->first_extents); |
| 399 | HFSPLUS_I(inode).first_blocks += len; | 424 | hip->first_blocks += len; |
| 400 | } | 425 | } |
| 401 | } else { | 426 | } else { |
| 402 | res = hfsplus_add_extent(HFSPLUS_I(inode).cached_extents, | 427 | res = hfsplus_add_extent(hip->cached_extents, |
| 403 | HFSPLUS_I(inode).alloc_blocks - | 428 | hip->alloc_blocks - hip->cached_start, |
| 404 | HFSPLUS_I(inode).cached_start, | ||
| 405 | start, len); | 429 | start, len); |
| 406 | if (!res) { | 430 | if (!res) { |
| 407 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | 431 | hfsplus_dump_extent(hip->cached_extents); |
| 408 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; | 432 | hip->flags |= HFSPLUS_FLG_EXT_DIRTY; |
| 409 | HFSPLUS_I(inode).cached_blocks += len; | 433 | hip->cached_blocks += len; |
| 410 | } else if (res == -ENOSPC) | 434 | } else if (res == -ENOSPC) |
| 411 | goto insert_extent; | 435 | goto insert_extent; |
| 412 | } | 436 | } |
| 413 | out: | 437 | out: |
| 414 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 438 | mutex_unlock(&hip->extents_lock); |
| 415 | if (!res) { | 439 | if (!res) { |
| 416 | HFSPLUS_I(inode).alloc_blocks += len; | 440 | hip->alloc_blocks += len; |
| 417 | mark_inode_dirty(inode); | 441 | mark_inode_dirty(inode); |
| 418 | } | 442 | } |
| 419 | return res; | 443 | return res; |
| 420 | 444 | ||
| 421 | insert_extent: | 445 | insert_extent: |
| 422 | dprint(DBG_EXTENT, "insert new extent\n"); | 446 | dprint(DBG_EXTENT, "insert new extent\n"); |
| 423 | hfsplus_ext_write_extent(inode); | 447 | hfsplus_ext_write_extent_locked(inode); |
| 424 | 448 | ||
| 425 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | 449 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); |
| 426 | HFSPLUS_I(inode).cached_extents[0].start_block = cpu_to_be32(start); | 450 | hip->cached_extents[0].start_block = cpu_to_be32(start); |
| 427 | HFSPLUS_I(inode).cached_extents[0].block_count = cpu_to_be32(len); | 451 | hip->cached_extents[0].block_count = cpu_to_be32(len); |
| 428 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | 452 | hfsplus_dump_extent(hip->cached_extents); |
| 429 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW; | 453 | hip->flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW; |
| 430 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).alloc_blocks; | 454 | hip->cached_start = hip->alloc_blocks; |
| 431 | HFSPLUS_I(inode).cached_blocks = len; | 455 | hip->cached_blocks = len; |
| 432 | 456 | ||
| 433 | res = 0; | 457 | res = 0; |
| 434 | goto out; | 458 | goto out; |
| @@ -437,13 +461,15 @@ insert_extent: | |||
| 437 | void hfsplus_file_truncate(struct inode *inode) | 461 | void hfsplus_file_truncate(struct inode *inode) |
| 438 | { | 462 | { |
| 439 | struct super_block *sb = inode->i_sb; | 463 | struct super_block *sb = inode->i_sb; |
| 464 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 440 | struct hfs_find_data fd; | 465 | struct hfs_find_data fd; |
| 441 | u32 alloc_cnt, blk_cnt, start; | 466 | u32 alloc_cnt, blk_cnt, start; |
| 442 | int res; | 467 | int res; |
| 443 | 468 | ||
| 444 | dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino, | 469 | dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", |
| 445 | (long long)HFSPLUS_I(inode).phys_size, inode->i_size); | 470 | inode->i_ino, (long long)hip->phys_size, inode->i_size); |
| 446 | if (inode->i_size > HFSPLUS_I(inode).phys_size) { | 471 | |
| 472 | if (inode->i_size > hip->phys_size) { | ||
| 447 | struct address_space *mapping = inode->i_mapping; | 473 | struct address_space *mapping = inode->i_mapping; |
| 448 | struct page *page; | 474 | struct page *page; |
| 449 | void *fsdata; | 475 | void *fsdata; |
| @@ -460,47 +486,48 @@ void hfsplus_file_truncate(struct inode *inode) | |||
| 460 | return; | 486 | return; |
| 461 | mark_inode_dirty(inode); | 487 | mark_inode_dirty(inode); |
| 462 | return; | 488 | return; |
| 463 | } else if (inode->i_size == HFSPLUS_I(inode).phys_size) | 489 | } else if (inode->i_size == hip->phys_size) |
| 464 | return; | 490 | return; |
| 465 | 491 | ||
| 466 | blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 492 | blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >> |
| 467 | alloc_cnt = HFSPLUS_I(inode).alloc_blocks; | 493 | HFSPLUS_SB(sb)->alloc_blksz_shift; |
| 494 | alloc_cnt = hip->alloc_blocks; | ||
| 468 | if (blk_cnt == alloc_cnt) | 495 | if (blk_cnt == alloc_cnt) |
| 469 | goto out; | 496 | goto out; |
| 470 | 497 | ||
| 471 | mutex_lock(&HFSPLUS_I(inode).extents_lock); | 498 | mutex_lock(&hip->extents_lock); |
| 472 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); | 499 | hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd); |
| 473 | while (1) { | 500 | while (1) { |
| 474 | if (alloc_cnt == HFSPLUS_I(inode).first_blocks) { | 501 | if (alloc_cnt == hip->first_blocks) { |
| 475 | hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents, | 502 | hfsplus_free_extents(sb, hip->first_extents, |
| 476 | alloc_cnt, alloc_cnt - blk_cnt); | 503 | alloc_cnt, alloc_cnt - blk_cnt); |
| 477 | hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); | 504 | hfsplus_dump_extent(hip->first_extents); |
| 478 | HFSPLUS_I(inode).first_blocks = blk_cnt; | 505 | hip->first_blocks = blk_cnt; |
| 479 | break; | 506 | break; |
| 480 | } | 507 | } |
| 481 | res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); | 508 | res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); |
| 482 | if (res) | 509 | if (res) |
| 483 | break; | 510 | break; |
| 484 | start = HFSPLUS_I(inode).cached_start; | 511 | start = hip->cached_start; |
| 485 | hfsplus_free_extents(sb, HFSPLUS_I(inode).cached_extents, | 512 | hfsplus_free_extents(sb, hip->cached_extents, |
| 486 | alloc_cnt - start, alloc_cnt - blk_cnt); | 513 | alloc_cnt - start, alloc_cnt - blk_cnt); |
| 487 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | 514 | hfsplus_dump_extent(hip->cached_extents); |
| 488 | if (blk_cnt > start) { | 515 | if (blk_cnt > start) { |
| 489 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; | 516 | hip->flags |= HFSPLUS_FLG_EXT_DIRTY; |
| 490 | break; | 517 | break; |
| 491 | } | 518 | } |
| 492 | alloc_cnt = start; | 519 | alloc_cnt = start; |
| 493 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; | 520 | hip->cached_start = hip->cached_blocks = 0; |
| 494 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | 521 | hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); |
| 495 | hfs_brec_remove(&fd); | 522 | hfs_brec_remove(&fd); |
| 496 | } | 523 | } |
| 497 | hfs_find_exit(&fd); | 524 | hfs_find_exit(&fd); |
| 498 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 525 | mutex_unlock(&hip->extents_lock); |
| 499 | 526 | ||
| 500 | HFSPLUS_I(inode).alloc_blocks = blk_cnt; | 527 | hip->alloc_blocks = blk_cnt; |
| 501 | out: | 528 | out: |
| 502 | HFSPLUS_I(inode).phys_size = inode->i_size; | 529 | hip->phys_size = inode->i_size; |
| 503 | HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; | 530 | hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; |
| 504 | inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); | 531 | inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); |
| 505 | mark_inode_dirty(inode); | 532 | mark_inode_dirty(inode); |
| 506 | } | 533 | } |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index dc856be3c2b0..cb3653efb57a 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
| @@ -62,7 +62,7 @@ struct hfs_btree { | |||
| 62 | unsigned int depth; | 62 | unsigned int depth; |
| 63 | 63 | ||
| 64 | //unsigned int map1_size, map_size; | 64 | //unsigned int map1_size, map_size; |
| 65 | struct semaphore tree_lock; | 65 | struct mutex tree_lock; |
| 66 | 66 | ||
| 67 | unsigned int pages_per_bnode; | 67 | unsigned int pages_per_bnode; |
| 68 | spinlock_t hash_lock; | 68 | spinlock_t hash_lock; |
| @@ -121,16 +121,21 @@ struct hfsplus_sb_info { | |||
| 121 | u32 sect_count; | 121 | u32 sect_count; |
| 122 | int fs_shift; | 122 | int fs_shift; |
| 123 | 123 | ||
| 124 | /* Stuff in host order from Vol Header */ | 124 | /* immutable data from the volume header */ |
| 125 | u32 alloc_blksz; | 125 | u32 alloc_blksz; |
| 126 | int alloc_blksz_shift; | 126 | int alloc_blksz_shift; |
| 127 | u32 total_blocks; | 127 | u32 total_blocks; |
| 128 | u32 data_clump_blocks, rsrc_clump_blocks; | ||
| 129 | |||
| 130 | /* mutable data from the volume header, protected by alloc_mutex */ | ||
| 128 | u32 free_blocks; | 131 | u32 free_blocks; |
| 129 | u32 next_alloc; | 132 | struct mutex alloc_mutex; |
| 133 | |||
| 134 | /* mutable data from the volume header, protected by vh_mutex */ | ||
| 130 | u32 next_cnid; | 135 | u32 next_cnid; |
| 131 | u32 file_count; | 136 | u32 file_count; |
| 132 | u32 folder_count; | 137 | u32 folder_count; |
| 133 | u32 data_clump_blocks, rsrc_clump_blocks; | 138 | struct mutex vh_mutex; |
| 134 | 139 | ||
| 135 | /* Config options */ | 140 | /* Config options */ |
| 136 | u32 creator; | 141 | u32 creator; |
| @@ -143,40 +148,50 @@ struct hfsplus_sb_info { | |||
| 143 | int part, session; | 148 | int part, session; |
| 144 | 149 | ||
| 145 | unsigned long flags; | 150 | unsigned long flags; |
| 146 | |||
| 147 | struct hlist_head rsrc_inodes; | ||
| 148 | }; | 151 | }; |
| 149 | 152 | ||
| 150 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 | 153 | #define HFSPLUS_SB_WRITEBACKUP 0 |
| 151 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 | 154 | #define HFSPLUS_SB_NODECOMPOSE 1 |
| 152 | #define HFSPLUS_SB_FORCE 0x0004 | 155 | #define HFSPLUS_SB_FORCE 2 |
| 153 | #define HFSPLUS_SB_HFSX 0x0008 | 156 | #define HFSPLUS_SB_HFSX 3 |
| 154 | #define HFSPLUS_SB_CASEFOLD 0x0010 | 157 | #define HFSPLUS_SB_CASEFOLD 4 |
| 155 | 158 | ||
| 156 | 159 | ||
| 157 | struct hfsplus_inode_info { | 160 | struct hfsplus_inode_info { |
| 158 | struct mutex extents_lock; | ||
| 159 | u32 clump_blocks, alloc_blocks; | ||
| 160 | sector_t fs_blocks; | ||
| 161 | /* Allocation extents from catalog record or volume header */ | ||
| 162 | hfsplus_extent_rec first_extents; | ||
| 163 | u32 first_blocks; | ||
| 164 | hfsplus_extent_rec cached_extents; | ||
| 165 | u32 cached_start, cached_blocks; | ||
| 166 | atomic_t opencnt; | 161 | atomic_t opencnt; |
| 167 | 162 | ||
| 168 | struct inode *rsrc_inode; | 163 | /* |
| 164 | * Extent allocation information, protected by extents_lock. | ||
| 165 | */ | ||
| 166 | u32 first_blocks; | ||
| 167 | u32 clump_blocks; | ||
| 168 | u32 alloc_blocks; | ||
| 169 | u32 cached_start; | ||
| 170 | u32 cached_blocks; | ||
| 171 | hfsplus_extent_rec first_extents; | ||
| 172 | hfsplus_extent_rec cached_extents; | ||
| 169 | unsigned long flags; | 173 | unsigned long flags; |
| 174 | struct mutex extents_lock; | ||
| 170 | 175 | ||
| 176 | /* | ||
| 177 | * Immutable data. | ||
| 178 | */ | ||
| 179 | struct inode *rsrc_inode; | ||
| 171 | __be32 create_date; | 180 | __be32 create_date; |
| 172 | /* Device number in hfsplus_permissions in catalog */ | ||
| 173 | u32 dev; | ||
| 174 | /* BSD system and user file flags */ | ||
| 175 | u8 rootflags; | ||
| 176 | u8 userflags; | ||
| 177 | 181 | ||
| 182 | /* | ||
| 183 | * Protected by sbi->vh_mutex. | ||
| 184 | */ | ||
| 185 | u32 linkid; | ||
| 186 | |||
| 187 | /* | ||
| 188 | * Protected by i_mutex. | ||
| 189 | */ | ||
| 190 | sector_t fs_blocks; | ||
| 191 | u8 userflags; /* BSD user file flags */ | ||
| 178 | struct list_head open_dir_list; | 192 | struct list_head open_dir_list; |
| 179 | loff_t phys_size; | 193 | loff_t phys_size; |
| 194 | |||
| 180 | struct inode vfs_inode; | 195 | struct inode vfs_inode; |
| 181 | }; | 196 | }; |
| 182 | 197 | ||
| @@ -184,8 +199,8 @@ struct hfsplus_inode_info { | |||
| 184 | #define HFSPLUS_FLG_EXT_DIRTY 0x0002 | 199 | #define HFSPLUS_FLG_EXT_DIRTY 0x0002 |
| 185 | #define HFSPLUS_FLG_EXT_NEW 0x0004 | 200 | #define HFSPLUS_FLG_EXT_NEW 0x0004 |
| 186 | 201 | ||
| 187 | #define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)) | 202 | #define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC)) |
| 188 | #define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC) | 203 | #define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC) |
| 189 | 204 | ||
| 190 | struct hfs_find_data { | 205 | struct hfs_find_data { |
| 191 | /* filled by caller */ | 206 | /* filled by caller */ |
| @@ -311,6 +326,7 @@ int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); | |||
| 311 | int hfsplus_delete_cat(u32, struct inode *, struct qstr *); | 326 | int hfsplus_delete_cat(u32, struct inode *, struct qstr *); |
| 312 | int hfsplus_rename_cat(u32, struct inode *, struct qstr *, | 327 | int hfsplus_rename_cat(u32, struct inode *, struct qstr *, |
| 313 | struct inode *, struct qstr *); | 328 | struct inode *, struct qstr *); |
| 329 | void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms); | ||
| 314 | 330 | ||
| 315 | /* dir.c */ | 331 | /* dir.c */ |
| 316 | extern const struct inode_operations hfsplus_dir_inode_operations; | 332 | extern const struct inode_operations hfsplus_dir_inode_operations; |
| @@ -372,26 +388,15 @@ int hfsplus_read_wrapper(struct super_block *); | |||
| 372 | int hfs_part_find(struct super_block *, sector_t *, sector_t *); | 388 | int hfs_part_find(struct super_block *, sector_t *, sector_t *); |
| 373 | 389 | ||
| 374 | /* access macros */ | 390 | /* access macros */ |
| 375 | /* | ||
| 376 | static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) | 391 | static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) |
| 377 | { | 392 | { |
| 378 | return sb->s_fs_info; | 393 | return sb->s_fs_info; |
| 379 | } | 394 | } |
| 395 | |||
| 380 | static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) | 396 | static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) |
| 381 | { | 397 | { |
| 382 | return list_entry(inode, struct hfsplus_inode_info, vfs_inode); | 398 | return list_entry(inode, struct hfsplus_inode_info, vfs_inode); |
| 383 | } | 399 | } |
| 384 | */ | ||
| 385 | #define HFSPLUS_SB(super) (*(struct hfsplus_sb_info *)(super)->s_fs_info) | ||
| 386 | #define HFSPLUS_I(inode) (*list_entry(inode, struct hfsplus_inode_info, vfs_inode)) | ||
| 387 | |||
| 388 | #if 1 | ||
| 389 | #define hfsplus_kmap(p) ({ struct page *__p = (p); kmap(__p); }) | ||
| 390 | #define hfsplus_kunmap(p) ({ struct page *__p = (p); kunmap(__p); __p; }) | ||
| 391 | #else | ||
| 392 | #define hfsplus_kmap(p) kmap(p) | ||
| 393 | #define hfsplus_kunmap(p) kunmap(p) | ||
| 394 | #endif | ||
| 395 | 400 | ||
| 396 | #define sb_bread512(sb, sec, data) ({ \ | 401 | #define sb_bread512(sb, sec, data) ({ \ |
| 397 | struct buffer_head *__bh; \ | 402 | struct buffer_head *__bh; \ |
| @@ -419,6 +424,4 @@ static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) | |||
| 419 | #define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec) | 424 | #define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec) |
| 420 | #define hfsp_now2mt() __hfsp_ut2mt(get_seconds()) | 425 | #define hfsp_now2mt() __hfsp_ut2mt(get_seconds()) |
| 421 | 426 | ||
| 422 | #define kdev_t_to_nr(x) (x) | ||
| 423 | |||
| 424 | #endif | 427 | #endif |
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index fe99fe8db61a..6892899fd6fb 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h | |||
| @@ -200,6 +200,7 @@ struct hfsplus_cat_key { | |||
| 200 | struct hfsplus_unistr name; | 200 | struct hfsplus_unistr name; |
| 201 | } __packed; | 201 | } __packed; |
| 202 | 202 | ||
| 203 | #define HFSPLUS_CAT_KEYLEN (sizeof(struct hfsplus_cat_key)) | ||
| 203 | 204 | ||
| 204 | /* Structs from hfs.h */ | 205 | /* Structs from hfs.h */ |
| 205 | struct hfsp_point { | 206 | struct hfsp_point { |
| @@ -323,7 +324,7 @@ struct hfsplus_ext_key { | |||
| 323 | __be32 start_block; | 324 | __be32 start_block; |
| 324 | } __packed; | 325 | } __packed; |
| 325 | 326 | ||
| 326 | #define HFSPLUS_EXT_KEYLEN 12 | 327 | #define HFSPLUS_EXT_KEYLEN sizeof(struct hfsplus_ext_key) |
| 327 | 328 | ||
| 328 | /* HFS+ generic BTree key */ | 329 | /* HFS+ generic BTree key */ |
| 329 | typedef union { | 330 | typedef union { |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index c5a979d62c65..78449280dae0 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
| @@ -36,7 +36,7 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping, | |||
| 36 | *pagep = NULL; | 36 | *pagep = NULL; |
| 37 | ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 37 | ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
| 38 | hfsplus_get_block, | 38 | hfsplus_get_block, |
| 39 | &HFSPLUS_I(mapping->host).phys_size); | 39 | &HFSPLUS_I(mapping->host)->phys_size); |
| 40 | if (unlikely(ret)) { | 40 | if (unlikely(ret)) { |
| 41 | loff_t isize = mapping->host->i_size; | 41 | loff_t isize = mapping->host->i_size; |
| 42 | if (pos + len > isize) | 42 | if (pos + len > isize) |
| @@ -62,13 +62,13 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask) | |||
| 62 | 62 | ||
| 63 | switch (inode->i_ino) { | 63 | switch (inode->i_ino) { |
| 64 | case HFSPLUS_EXT_CNID: | 64 | case HFSPLUS_EXT_CNID: |
| 65 | tree = HFSPLUS_SB(sb).ext_tree; | 65 | tree = HFSPLUS_SB(sb)->ext_tree; |
| 66 | break; | 66 | break; |
| 67 | case HFSPLUS_CAT_CNID: | 67 | case HFSPLUS_CAT_CNID: |
| 68 | tree = HFSPLUS_SB(sb).cat_tree; | 68 | tree = HFSPLUS_SB(sb)->cat_tree; |
| 69 | break; | 69 | break; |
| 70 | case HFSPLUS_ATTR_CNID: | 70 | case HFSPLUS_ATTR_CNID: |
| 71 | tree = HFSPLUS_SB(sb).attr_tree; | 71 | tree = HFSPLUS_SB(sb)->attr_tree; |
| 72 | break; | 72 | break; |
| 73 | default: | 73 | default: |
| 74 | BUG(); | 74 | BUG(); |
| @@ -172,12 +172,13 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
| 172 | struct hfs_find_data fd; | 172 | struct hfs_find_data fd; |
| 173 | struct super_block *sb = dir->i_sb; | 173 | struct super_block *sb = dir->i_sb; |
| 174 | struct inode *inode = NULL; | 174 | struct inode *inode = NULL; |
| 175 | struct hfsplus_inode_info *hip; | ||
| 175 | int err; | 176 | int err; |
| 176 | 177 | ||
| 177 | if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) | 178 | if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) |
| 178 | goto out; | 179 | goto out; |
| 179 | 180 | ||
| 180 | inode = HFSPLUS_I(dir).rsrc_inode; | 181 | inode = HFSPLUS_I(dir)->rsrc_inode; |
| 181 | if (inode) | 182 | if (inode) |
| 182 | goto out; | 183 | goto out; |
| 183 | 184 | ||
| @@ -185,12 +186,13 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
| 185 | if (!inode) | 186 | if (!inode) |
| 186 | return ERR_PTR(-ENOMEM); | 187 | return ERR_PTR(-ENOMEM); |
| 187 | 188 | ||
| 189 | hip = HFSPLUS_I(inode); | ||
| 188 | inode->i_ino = dir->i_ino; | 190 | inode->i_ino = dir->i_ino; |
| 189 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 191 | INIT_LIST_HEAD(&hip->open_dir_list); |
| 190 | mutex_init(&HFSPLUS_I(inode).extents_lock); | 192 | mutex_init(&hip->extents_lock); |
| 191 | HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; | 193 | hip->flags = HFSPLUS_FLG_RSRC; |
| 192 | 194 | ||
| 193 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 195 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
| 194 | err = hfsplus_find_cat(sb, dir->i_ino, &fd); | 196 | err = hfsplus_find_cat(sb, dir->i_ino, &fd); |
| 195 | if (!err) | 197 | if (!err) |
| 196 | err = hfsplus_cat_read_inode(inode, &fd); | 198 | err = hfsplus_cat_read_inode(inode, &fd); |
| @@ -199,10 +201,18 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
| 199 | iput(inode); | 201 | iput(inode); |
| 200 | return ERR_PTR(err); | 202 | return ERR_PTR(err); |
| 201 | } | 203 | } |
| 202 | HFSPLUS_I(inode).rsrc_inode = dir; | 204 | hip->rsrc_inode = dir; |
| 203 | HFSPLUS_I(dir).rsrc_inode = inode; | 205 | HFSPLUS_I(dir)->rsrc_inode = inode; |
| 204 | igrab(dir); | 206 | igrab(dir); |
| 205 | hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); | 207 | |
| 208 | /* | ||
| 209 | * __mark_inode_dirty expects inodes to be hashed. Since we don't | ||
| 210 | * want resource fork inodes in the regular inode space, we make them | ||
| 211 | * appear hashed, but do not put on any lists. hlist_del() | ||
| 212 | * will work fine and require no locking. | ||
| 213 | */ | ||
| 214 | inode->i_hash.pprev = &inode->i_hash.next; | ||
| 215 | |||
| 206 | mark_inode_dirty(inode); | 216 | mark_inode_dirty(inode); |
| 207 | out: | 217 | out: |
| 208 | d_add(dentry, inode); | 218 | d_add(dentry, inode); |
| @@ -211,30 +221,27 @@ out: | |||
| 211 | 221 | ||
| 212 | static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) | 222 | static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) |
| 213 | { | 223 | { |
| 214 | struct super_block *sb = inode->i_sb; | 224 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); |
| 215 | u16 mode; | 225 | u16 mode; |
| 216 | 226 | ||
| 217 | mode = be16_to_cpu(perms->mode); | 227 | mode = be16_to_cpu(perms->mode); |
| 218 | 228 | ||
| 219 | inode->i_uid = be32_to_cpu(perms->owner); | 229 | inode->i_uid = be32_to_cpu(perms->owner); |
| 220 | if (!inode->i_uid && !mode) | 230 | if (!inode->i_uid && !mode) |
| 221 | inode->i_uid = HFSPLUS_SB(sb).uid; | 231 | inode->i_uid = sbi->uid; |
| 222 | 232 | ||
| 223 | inode->i_gid = be32_to_cpu(perms->group); | 233 | inode->i_gid = be32_to_cpu(perms->group); |
| 224 | if (!inode->i_gid && !mode) | 234 | if (!inode->i_gid && !mode) |
| 225 | inode->i_gid = HFSPLUS_SB(sb).gid; | 235 | inode->i_gid = sbi->gid; |
| 226 | 236 | ||
| 227 | if (dir) { | 237 | if (dir) { |
| 228 | mode = mode ? (mode & S_IALLUGO) : | 238 | mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask)); |
| 229 | (S_IRWXUGO & ~(HFSPLUS_SB(sb).umask)); | ||
| 230 | mode |= S_IFDIR; | 239 | mode |= S_IFDIR; |
| 231 | } else if (!mode) | 240 | } else if (!mode) |
| 232 | mode = S_IFREG | ((S_IRUGO|S_IWUGO) & | 241 | mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask)); |
| 233 | ~(HFSPLUS_SB(sb).umask)); | ||
| 234 | inode->i_mode = mode; | 242 | inode->i_mode = mode; |
| 235 | 243 | ||
| 236 | HFSPLUS_I(inode).rootflags = perms->rootflags; | 244 | HFSPLUS_I(inode)->userflags = perms->userflags; |
| 237 | HFSPLUS_I(inode).userflags = perms->userflags; | ||
| 238 | if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) | 245 | if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) |
| 239 | inode->i_flags |= S_IMMUTABLE; | 246 | inode->i_flags |= S_IMMUTABLE; |
| 240 | else | 247 | else |
| @@ -245,30 +252,13 @@ static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, i | |||
| 245 | inode->i_flags &= ~S_APPEND; | 252 | inode->i_flags &= ~S_APPEND; |
| 246 | } | 253 | } |
| 247 | 254 | ||
| 248 | static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | ||
| 249 | { | ||
| 250 | if (inode->i_flags & S_IMMUTABLE) | ||
| 251 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; | ||
| 252 | else | ||
| 253 | perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | ||
| 254 | if (inode->i_flags & S_APPEND) | ||
| 255 | perms->rootflags |= HFSPLUS_FLG_APPEND; | ||
| 256 | else | ||
| 257 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; | ||
| 258 | perms->userflags = HFSPLUS_I(inode).userflags; | ||
| 259 | perms->mode = cpu_to_be16(inode->i_mode); | ||
| 260 | perms->owner = cpu_to_be32(inode->i_uid); | ||
| 261 | perms->group = cpu_to_be32(inode->i_gid); | ||
| 262 | perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev); | ||
| 263 | } | ||
| 264 | |||
| 265 | static int hfsplus_file_open(struct inode *inode, struct file *file) | 255 | static int hfsplus_file_open(struct inode *inode, struct file *file) |
| 266 | { | 256 | { |
| 267 | if (HFSPLUS_IS_RSRC(inode)) | 257 | if (HFSPLUS_IS_RSRC(inode)) |
| 268 | inode = HFSPLUS_I(inode).rsrc_inode; | 258 | inode = HFSPLUS_I(inode)->rsrc_inode; |
| 269 | if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) | 259 | if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) |
| 270 | return -EOVERFLOW; | 260 | return -EOVERFLOW; |
| 271 | atomic_inc(&HFSPLUS_I(inode).opencnt); | 261 | atomic_inc(&HFSPLUS_I(inode)->opencnt); |
| 272 | return 0; | 262 | return 0; |
| 273 | } | 263 | } |
| 274 | 264 | ||
| @@ -277,12 +267,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) | |||
| 277 | struct super_block *sb = inode->i_sb; | 267 | struct super_block *sb = inode->i_sb; |
| 278 | 268 | ||
| 279 | if (HFSPLUS_IS_RSRC(inode)) | 269 | if (HFSPLUS_IS_RSRC(inode)) |
| 280 | inode = HFSPLUS_I(inode).rsrc_inode; | 270 | inode = HFSPLUS_I(inode)->rsrc_inode; |
| 281 | if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { | 271 | if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) { |
| 282 | mutex_lock(&inode->i_mutex); | 272 | mutex_lock(&inode->i_mutex); |
| 283 | hfsplus_file_truncate(inode); | 273 | hfsplus_file_truncate(inode); |
| 284 | if (inode->i_flags & S_DEAD) { | 274 | if (inode->i_flags & S_DEAD) { |
| 285 | hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); | 275 | hfsplus_delete_cat(inode->i_ino, |
| 276 | HFSPLUS_SB(sb)->hidden_dir, NULL); | ||
| 286 | hfsplus_delete_inode(inode); | 277 | hfsplus_delete_inode(inode); |
| 287 | } | 278 | } |
| 288 | mutex_unlock(&inode->i_mutex); | 279 | mutex_unlock(&inode->i_mutex); |
| @@ -361,47 +352,52 @@ static const struct file_operations hfsplus_file_operations = { | |||
| 361 | 352 | ||
| 362 | struct inode *hfsplus_new_inode(struct super_block *sb, int mode) | 353 | struct inode *hfsplus_new_inode(struct super_block *sb, int mode) |
| 363 | { | 354 | { |
| 355 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 364 | struct inode *inode = new_inode(sb); | 356 | struct inode *inode = new_inode(sb); |
| 357 | struct hfsplus_inode_info *hip; | ||
| 358 | |||
| 365 | if (!inode) | 359 | if (!inode) |
| 366 | return NULL; | 360 | return NULL; |
| 367 | 361 | ||
| 368 | inode->i_ino = HFSPLUS_SB(sb).next_cnid++; | 362 | inode->i_ino = sbi->next_cnid++; |
| 369 | inode->i_mode = mode; | 363 | inode->i_mode = mode; |
| 370 | inode->i_uid = current_fsuid(); | 364 | inode->i_uid = current_fsuid(); |
| 371 | inode->i_gid = current_fsgid(); | 365 | inode->i_gid = current_fsgid(); |
| 372 | inode->i_nlink = 1; | 366 | inode->i_nlink = 1; |
| 373 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 367 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
| 374 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 368 | |
| 375 | mutex_init(&HFSPLUS_I(inode).extents_lock); | 369 | hip = HFSPLUS_I(inode); |
| 376 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | 370 | INIT_LIST_HEAD(&hip->open_dir_list); |
| 377 | HFSPLUS_I(inode).flags = 0; | 371 | mutex_init(&hip->extents_lock); |
| 378 | memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec)); | 372 | atomic_set(&hip->opencnt, 0); |
| 379 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | 373 | hip->flags = 0; |
| 380 | HFSPLUS_I(inode).alloc_blocks = 0; | 374 | memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); |
| 381 | HFSPLUS_I(inode).first_blocks = 0; | 375 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); |
| 382 | HFSPLUS_I(inode).cached_start = 0; | 376 | hip->alloc_blocks = 0; |
| 383 | HFSPLUS_I(inode).cached_blocks = 0; | 377 | hip->first_blocks = 0; |
| 384 | HFSPLUS_I(inode).phys_size = 0; | 378 | hip->cached_start = 0; |
| 385 | HFSPLUS_I(inode).fs_blocks = 0; | 379 | hip->cached_blocks = 0; |
| 386 | HFSPLUS_I(inode).rsrc_inode = NULL; | 380 | hip->phys_size = 0; |
| 381 | hip->fs_blocks = 0; | ||
| 382 | hip->rsrc_inode = NULL; | ||
| 387 | if (S_ISDIR(inode->i_mode)) { | 383 | if (S_ISDIR(inode->i_mode)) { |
| 388 | inode->i_size = 2; | 384 | inode->i_size = 2; |
| 389 | HFSPLUS_SB(sb).folder_count++; | 385 | sbi->folder_count++; |
| 390 | inode->i_op = &hfsplus_dir_inode_operations; | 386 | inode->i_op = &hfsplus_dir_inode_operations; |
| 391 | inode->i_fop = &hfsplus_dir_operations; | 387 | inode->i_fop = &hfsplus_dir_operations; |
| 392 | } else if (S_ISREG(inode->i_mode)) { | 388 | } else if (S_ISREG(inode->i_mode)) { |
| 393 | HFSPLUS_SB(sb).file_count++; | 389 | sbi->file_count++; |
| 394 | inode->i_op = &hfsplus_file_inode_operations; | 390 | inode->i_op = &hfsplus_file_inode_operations; |
| 395 | inode->i_fop = &hfsplus_file_operations; | 391 | inode->i_fop = &hfsplus_file_operations; |
| 396 | inode->i_mapping->a_ops = &hfsplus_aops; | 392 | inode->i_mapping->a_ops = &hfsplus_aops; |
| 397 | HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks; | 393 | hip->clump_blocks = sbi->data_clump_blocks; |
| 398 | } else if (S_ISLNK(inode->i_mode)) { | 394 | } else if (S_ISLNK(inode->i_mode)) { |
| 399 | HFSPLUS_SB(sb).file_count++; | 395 | sbi->file_count++; |
| 400 | inode->i_op = &page_symlink_inode_operations; | 396 | inode->i_op = &page_symlink_inode_operations; |
| 401 | inode->i_mapping->a_ops = &hfsplus_aops; | 397 | inode->i_mapping->a_ops = &hfsplus_aops; |
| 402 | HFSPLUS_I(inode).clump_blocks = 1; | 398 | hip->clump_blocks = 1; |
| 403 | } else | 399 | } else |
| 404 | HFSPLUS_SB(sb).file_count++; | 400 | sbi->file_count++; |
| 405 | insert_inode_hash(inode); | 401 | insert_inode_hash(inode); |
| 406 | mark_inode_dirty(inode); | 402 | mark_inode_dirty(inode); |
| 407 | sb->s_dirt = 1; | 403 | sb->s_dirt = 1; |
| @@ -414,11 +410,11 @@ void hfsplus_delete_inode(struct inode *inode) | |||
| 414 | struct super_block *sb = inode->i_sb; | 410 | struct super_block *sb = inode->i_sb; |
| 415 | 411 | ||
| 416 | if (S_ISDIR(inode->i_mode)) { | 412 | if (S_ISDIR(inode->i_mode)) { |
| 417 | HFSPLUS_SB(sb).folder_count--; | 413 | HFSPLUS_SB(sb)->folder_count--; |
| 418 | sb->s_dirt = 1; | 414 | sb->s_dirt = 1; |
| 419 | return; | 415 | return; |
| 420 | } | 416 | } |
| 421 | HFSPLUS_SB(sb).file_count--; | 417 | HFSPLUS_SB(sb)->file_count--; |
| 422 | if (S_ISREG(inode->i_mode)) { | 418 | if (S_ISREG(inode->i_mode)) { |
| 423 | if (!inode->i_nlink) { | 419 | if (!inode->i_nlink) { |
| 424 | inode->i_size = 0; | 420 | inode->i_size = 0; |
| @@ -434,34 +430,39 @@ void hfsplus_delete_inode(struct inode *inode) | |||
| 434 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | 430 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) |
| 435 | { | 431 | { |
| 436 | struct super_block *sb = inode->i_sb; | 432 | struct super_block *sb = inode->i_sb; |
| 433 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 434 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 437 | u32 count; | 435 | u32 count; |
| 438 | int i; | 436 | int i; |
| 439 | 437 | ||
| 440 | memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents, | 438 | memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec)); |
| 441 | sizeof(hfsplus_extent_rec)); | ||
| 442 | for (count = 0, i = 0; i < 8; i++) | 439 | for (count = 0, i = 0; i < 8; i++) |
| 443 | count += be32_to_cpu(fork->extents[i].block_count); | 440 | count += be32_to_cpu(fork->extents[i].block_count); |
| 444 | HFSPLUS_I(inode).first_blocks = count; | 441 | hip->first_blocks = count; |
| 445 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | 442 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); |
| 446 | HFSPLUS_I(inode).cached_start = 0; | 443 | hip->cached_start = 0; |
| 447 | HFSPLUS_I(inode).cached_blocks = 0; | 444 | hip->cached_blocks = 0; |
| 448 | 445 | ||
| 449 | HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks); | 446 | hip->alloc_blocks = be32_to_cpu(fork->total_blocks); |
| 450 | inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size); | 447 | hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size); |
| 451 | HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; | 448 | hip->fs_blocks = |
| 452 | inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); | 449 | (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; |
| 453 | HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 450 | inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); |
| 454 | if (!HFSPLUS_I(inode).clump_blocks) | 451 | hip->clump_blocks = |
| 455 | HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks : | 452 | be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift; |
| 456 | HFSPLUS_SB(sb).data_clump_blocks; | 453 | if (!hip->clump_blocks) { |
| 454 | hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ? | ||
| 455 | sbi->rsrc_clump_blocks : | ||
| 456 | sbi->data_clump_blocks; | ||
| 457 | } | ||
| 457 | } | 458 | } |
| 458 | 459 | ||
| 459 | void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | 460 | void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) |
| 460 | { | 461 | { |
| 461 | memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents, | 462 | memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents, |
| 462 | sizeof(hfsplus_extent_rec)); | 463 | sizeof(hfsplus_extent_rec)); |
| 463 | fork->total_size = cpu_to_be64(inode->i_size); | 464 | fork->total_size = cpu_to_be64(inode->i_size); |
| 464 | fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks); | 465 | fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks); |
| 465 | } | 466 | } |
| 466 | 467 | ||
| 467 | int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | 468 | int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) |
| @@ -472,7 +473,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
| 472 | 473 | ||
| 473 | type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); | 474 | type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); |
| 474 | 475 | ||
| 475 | HFSPLUS_I(inode).dev = 0; | 476 | HFSPLUS_I(inode)->linkid = 0; |
| 476 | if (type == HFSPLUS_FOLDER) { | 477 | if (type == HFSPLUS_FOLDER) { |
| 477 | struct hfsplus_cat_folder *folder = &entry.folder; | 478 | struct hfsplus_cat_folder *folder = &entry.folder; |
| 478 | 479 | ||
| @@ -486,8 +487,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
| 486 | inode->i_atime = hfsp_mt2ut(folder->access_date); | 487 | inode->i_atime = hfsp_mt2ut(folder->access_date); |
| 487 | inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); | 488 | inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); |
| 488 | inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); | 489 | inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); |
| 489 | HFSPLUS_I(inode).create_date = folder->create_date; | 490 | HFSPLUS_I(inode)->create_date = folder->create_date; |
| 490 | HFSPLUS_I(inode).fs_blocks = 0; | 491 | HFSPLUS_I(inode)->fs_blocks = 0; |
| 491 | inode->i_op = &hfsplus_dir_inode_operations; | 492 | inode->i_op = &hfsplus_dir_inode_operations; |
| 492 | inode->i_fop = &hfsplus_dir_operations; | 493 | inode->i_fop = &hfsplus_dir_operations; |
| 493 | } else if (type == HFSPLUS_FILE) { | 494 | } else if (type == HFSPLUS_FILE) { |
| @@ -518,7 +519,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
| 518 | inode->i_atime = hfsp_mt2ut(file->access_date); | 519 | inode->i_atime = hfsp_mt2ut(file->access_date); |
| 519 | inode->i_mtime = hfsp_mt2ut(file->content_mod_date); | 520 | inode->i_mtime = hfsp_mt2ut(file->content_mod_date); |
| 520 | inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); | 521 | inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); |
| 521 | HFSPLUS_I(inode).create_date = file->create_date; | 522 | HFSPLUS_I(inode)->create_date = file->create_date; |
| 522 | } else { | 523 | } else { |
| 523 | printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); | 524 | printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); |
| 524 | res = -EIO; | 525 | res = -EIO; |
| @@ -533,12 +534,12 @@ int hfsplus_cat_write_inode(struct inode *inode) | |||
| 533 | hfsplus_cat_entry entry; | 534 | hfsplus_cat_entry entry; |
| 534 | 535 | ||
| 535 | if (HFSPLUS_IS_RSRC(inode)) | 536 | if (HFSPLUS_IS_RSRC(inode)) |
| 536 | main_inode = HFSPLUS_I(inode).rsrc_inode; | 537 | main_inode = HFSPLUS_I(inode)->rsrc_inode; |
| 537 | 538 | ||
| 538 | if (!main_inode->i_nlink) | 539 | if (!main_inode->i_nlink) |
| 539 | return 0; | 540 | return 0; |
| 540 | 541 | ||
| 541 | if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd)) | 542 | if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd)) |
| 542 | /* panic? */ | 543 | /* panic? */ |
| 543 | return -EIO; | 544 | return -EIO; |
| 544 | 545 | ||
| @@ -554,7 +555,7 @@ int hfsplus_cat_write_inode(struct inode *inode) | |||
| 554 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | 555 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
| 555 | sizeof(struct hfsplus_cat_folder)); | 556 | sizeof(struct hfsplus_cat_folder)); |
| 556 | /* simple node checks? */ | 557 | /* simple node checks? */ |
| 557 | hfsplus_set_perms(inode, &folder->permissions); | 558 | hfsplus_cat_set_perms(inode, &folder->permissions); |
| 558 | folder->access_date = hfsp_ut2mt(inode->i_atime); | 559 | folder->access_date = hfsp_ut2mt(inode->i_atime); |
| 559 | folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); | 560 | folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); |
| 560 | folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); | 561 | folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); |
| @@ -576,11 +577,7 @@ int hfsplus_cat_write_inode(struct inode *inode) | |||
| 576 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | 577 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
| 577 | sizeof(struct hfsplus_cat_file)); | 578 | sizeof(struct hfsplus_cat_file)); |
| 578 | hfsplus_inode_write_fork(inode, &file->data_fork); | 579 | hfsplus_inode_write_fork(inode, &file->data_fork); |
| 579 | if (S_ISREG(inode->i_mode)) | 580 | hfsplus_cat_set_perms(inode, &file->permissions); |
| 580 | HFSPLUS_I(inode).dev = inode->i_nlink; | ||
| 581 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) | ||
| 582 | HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev); | ||
| 583 | hfsplus_set_perms(inode, &file->permissions); | ||
| 584 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) | 581 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) |
| 585 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); | 582 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); |
| 586 | else | 583 | else |
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index ac405f099026..5b4667e08ef7 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c | |||
| @@ -17,83 +17,98 @@ | |||
| 17 | #include <linux/mount.h> | 17 | #include <linux/mount.h> |
| 18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 19 | #include <linux/xattr.h> | 19 | #include <linux/xattr.h> |
| 20 | #include <linux/smp_lock.h> | ||
| 21 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
| 22 | #include "hfsplus_fs.h" | 21 | #include "hfsplus_fs.h" |
| 23 | 22 | ||
| 24 | long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 23 | static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags) |
| 25 | { | 24 | { |
| 26 | struct inode *inode = filp->f_path.dentry->d_inode; | 25 | struct inode *inode = file->f_path.dentry->d_inode; |
| 26 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 27 | unsigned int flags = 0; | ||
| 28 | |||
| 29 | if (inode->i_flags & S_IMMUTABLE) | ||
| 30 | flags |= FS_IMMUTABLE_FL; | ||
| 31 | if (inode->i_flags |= S_APPEND) | ||
| 32 | flags |= FS_APPEND_FL; | ||
| 33 | if (hip->userflags & HFSPLUS_FLG_NODUMP) | ||
| 34 | flags |= FS_NODUMP_FL; | ||
| 35 | |||
| 36 | return put_user(flags, user_flags); | ||
| 37 | } | ||
| 38 | |||
| 39 | static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags) | ||
| 40 | { | ||
| 41 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 42 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
| 27 | unsigned int flags; | 43 | unsigned int flags; |
| 44 | int err = 0; | ||
| 28 | 45 | ||
| 29 | lock_kernel(); | 46 | err = mnt_want_write(file->f_path.mnt); |
| 30 | switch (cmd) { | 47 | if (err) |
| 31 | case HFSPLUS_IOC_EXT2_GETFLAGS: | 48 | goto out; |
| 32 | flags = 0; | ||
| 33 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE) | ||
| 34 | flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */ | ||
| 35 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND) | ||
| 36 | flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */ | ||
| 37 | if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP) | ||
| 38 | flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */ | ||
| 39 | return put_user(flags, (int __user *)arg); | ||
| 40 | case HFSPLUS_IOC_EXT2_SETFLAGS: { | ||
| 41 | int err = 0; | ||
| 42 | err = mnt_want_write(filp->f_path.mnt); | ||
| 43 | if (err) { | ||
| 44 | unlock_kernel(); | ||
| 45 | return err; | ||
| 46 | } | ||
| 47 | 49 | ||
| 48 | if (!is_owner_or_cap(inode)) { | 50 | if (!is_owner_or_cap(inode)) { |
| 49 | err = -EACCES; | 51 | err = -EACCES; |
| 50 | goto setflags_out; | 52 | goto out_drop_write; |
| 51 | } | 53 | } |
| 52 | if (get_user(flags, (int __user *)arg)) { | ||
| 53 | err = -EFAULT; | ||
| 54 | goto setflags_out; | ||
| 55 | } | ||
| 56 | if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) || | ||
| 57 | HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { | ||
| 58 | if (!capable(CAP_LINUX_IMMUTABLE)) { | ||
| 59 | err = -EPERM; | ||
| 60 | goto setflags_out; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | 54 | ||
| 64 | /* don't silently ignore unsupported ext2 flags */ | 55 | if (get_user(flags, user_flags)) { |
| 65 | if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) { | 56 | err = -EFAULT; |
| 66 | err = -EOPNOTSUPP; | 57 | goto out_drop_write; |
| 67 | goto setflags_out; | 58 | } |
| 68 | } | 59 | |
| 69 | if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */ | 60 | mutex_lock(&inode->i_mutex); |
| 70 | inode->i_flags |= S_IMMUTABLE; | 61 | |
| 71 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; | 62 | if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) || |
| 72 | } else { | 63 | inode->i_flags & (S_IMMUTABLE|S_APPEND)) { |
| 73 | inode->i_flags &= ~S_IMMUTABLE; | 64 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
| 74 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | 65 | err = -EPERM; |
| 75 | } | 66 | goto out_unlock_inode; |
| 76 | if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */ | ||
| 77 | inode->i_flags |= S_APPEND; | ||
| 78 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND; | ||
| 79 | } else { | ||
| 80 | inode->i_flags &= ~S_APPEND; | ||
| 81 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND; | ||
| 82 | } | 67 | } |
| 83 | if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */ | ||
| 84 | HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP; | ||
| 85 | else | ||
| 86 | HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP; | ||
| 87 | |||
| 88 | inode->i_ctime = CURRENT_TIME_SEC; | ||
| 89 | mark_inode_dirty(inode); | ||
| 90 | setflags_out: | ||
| 91 | mnt_drop_write(filp->f_path.mnt); | ||
| 92 | unlock_kernel(); | ||
| 93 | return err; | ||
| 94 | } | 68 | } |
| 69 | |||
| 70 | /* don't silently ignore unsupported ext2 flags */ | ||
| 71 | if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) { | ||
| 72 | err = -EOPNOTSUPP; | ||
| 73 | goto out_unlock_inode; | ||
| 74 | } | ||
| 75 | |||
| 76 | if (flags & FS_IMMUTABLE_FL) | ||
| 77 | inode->i_flags |= S_IMMUTABLE; | ||
| 78 | else | ||
| 79 | inode->i_flags &= ~S_IMMUTABLE; | ||
| 80 | |||
| 81 | if (flags & FS_APPEND_FL) | ||
| 82 | inode->i_flags |= S_APPEND; | ||
| 83 | else | ||
| 84 | inode->i_flags &= ~S_APPEND; | ||
| 85 | |||
| 86 | if (flags & FS_NODUMP_FL) | ||
| 87 | hip->userflags |= HFSPLUS_FLG_NODUMP; | ||
| 88 | else | ||
| 89 | hip->userflags &= ~HFSPLUS_FLG_NODUMP; | ||
| 90 | |||
| 91 | inode->i_ctime = CURRENT_TIME_SEC; | ||
| 92 | mark_inode_dirty(inode); | ||
| 93 | |||
| 94 | out_unlock_inode: | ||
| 95 | mutex_lock(&inode->i_mutex); | ||
| 96 | out_drop_write: | ||
| 97 | mnt_drop_write(file->f_path.mnt); | ||
| 98 | out: | ||
| 99 | return err; | ||
| 100 | } | ||
| 101 | |||
| 102 | long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 103 | { | ||
| 104 | void __user *argp = (void __user *)arg; | ||
| 105 | |||
| 106 | switch (cmd) { | ||
| 107 | case HFSPLUS_IOC_EXT2_GETFLAGS: | ||
| 108 | return hfsplus_ioctl_getflags(file, argp); | ||
| 109 | case HFSPLUS_IOC_EXT2_SETFLAGS: | ||
| 110 | return hfsplus_ioctl_setflags(file, argp); | ||
| 95 | default: | 111 | default: |
| 96 | unlock_kernel(); | ||
| 97 | return -ENOTTY; | 112 | return -ENOTTY; |
| 98 | } | 113 | } |
| 99 | } | 114 | } |
| @@ -110,7 +125,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name, | |||
| 110 | if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) | 125 | if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) |
| 111 | return -EOPNOTSUPP; | 126 | return -EOPNOTSUPP; |
| 112 | 127 | ||
| 113 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | 128 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); |
| 114 | if (res) | 129 | if (res) |
| 115 | return res; | 130 | return res; |
| 116 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | 131 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); |
| @@ -153,7 +168,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, | |||
| 153 | return -EOPNOTSUPP; | 168 | return -EOPNOTSUPP; |
| 154 | 169 | ||
| 155 | if (size) { | 170 | if (size) { |
| 156 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | 171 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); |
| 157 | if (res) | 172 | if (res) |
| 158 | return res; | 173 | return res; |
| 159 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | 174 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); |
| @@ -177,7 +192,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, | |||
| 177 | } else | 192 | } else |
| 178 | res = size ? -ERANGE : 4; | 193 | res = size ? -ERANGE : 4; |
| 179 | } else | 194 | } else |
| 180 | res = -ENODATA; | 195 | res = -EOPNOTSUPP; |
| 181 | out: | 196 | out: |
| 182 | if (size) | 197 | if (size) |
| 183 | hfs_find_exit(&fd); | 198 | hfs_find_exit(&fd); |
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index 572628b4b07d..f9ab276a4d8d 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c | |||
| @@ -143,13 +143,13 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) | |||
| 143 | kfree(p); | 143 | kfree(p); |
| 144 | break; | 144 | break; |
| 145 | case opt_decompose: | 145 | case opt_decompose: |
| 146 | sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE; | 146 | clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); |
| 147 | break; | 147 | break; |
| 148 | case opt_nodecompose: | 148 | case opt_nodecompose: |
| 149 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; | 149 | set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); |
| 150 | break; | 150 | break; |
| 151 | case opt_force: | 151 | case opt_force: |
| 152 | sbi->flags |= HFSPLUS_SB_FORCE; | 152 | set_bit(HFSPLUS_SB_FORCE, &sbi->flags); |
| 153 | break; | 153 | break; |
| 154 | default: | 154 | default: |
| 155 | return 0; | 155 | return 0; |
| @@ -171,7 +171,7 @@ done: | |||
| 171 | 171 | ||
| 172 | int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) | 172 | int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) |
| 173 | { | 173 | { |
| 174 | struct hfsplus_sb_info *sbi = &HFSPLUS_SB(mnt->mnt_sb); | 174 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(mnt->mnt_sb); |
| 175 | 175 | ||
| 176 | if (sbi->creator != HFSPLUS_DEF_CR_TYPE) | 176 | if (sbi->creator != HFSPLUS_DEF_CR_TYPE) |
| 177 | seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator); | 177 | seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator); |
| @@ -184,7 +184,7 @@ int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) | |||
| 184 | seq_printf(seq, ",session=%u", sbi->session); | 184 | seq_printf(seq, ",session=%u", sbi->session); |
| 185 | if (sbi->nls) | 185 | if (sbi->nls) |
| 186 | seq_printf(seq, ",nls=%s", sbi->nls->charset); | 186 | seq_printf(seq, ",nls=%s", sbi->nls->charset); |
| 187 | if (sbi->flags & HFSPLUS_SB_NODECOMPOSE) | 187 | if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags)) |
| 188 | seq_printf(seq, ",nodecompose"); | 188 | seq_printf(seq, ",nodecompose"); |
| 189 | return 0; | 189 | return 0; |
| 190 | } | 190 | } |
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c index 1528a6fd0299..208b16c645cc 100644 --- a/fs/hfsplus/part_tbl.c +++ b/fs/hfsplus/part_tbl.c | |||
| @@ -74,6 +74,7 @@ struct old_pmap { | |||
| 74 | int hfs_part_find(struct super_block *sb, | 74 | int hfs_part_find(struct super_block *sb, |
| 75 | sector_t *part_start, sector_t *part_size) | 75 | sector_t *part_start, sector_t *part_size) |
| 76 | { | 76 | { |
| 77 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 77 | struct buffer_head *bh; | 78 | struct buffer_head *bh; |
| 78 | __be16 *data; | 79 | __be16 *data; |
| 79 | int i, size, res; | 80 | int i, size, res; |
| @@ -95,7 +96,7 @@ int hfs_part_find(struct super_block *sb, | |||
| 95 | for (i = 0; i < size; p++, i++) { | 96 | for (i = 0; i < size; p++, i++) { |
| 96 | if (p->pdStart && p->pdSize && | 97 | if (p->pdStart && p->pdSize && |
| 97 | p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && | 98 | p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && |
| 98 | (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { | 99 | (sbi->part < 0 || sbi->part == i)) { |
| 99 | *part_start += be32_to_cpu(p->pdStart); | 100 | *part_start += be32_to_cpu(p->pdStart); |
| 100 | *part_size = be32_to_cpu(p->pdSize); | 101 | *part_size = be32_to_cpu(p->pdSize); |
| 101 | res = 0; | 102 | res = 0; |
| @@ -111,7 +112,7 @@ int hfs_part_find(struct super_block *sb, | |||
| 111 | size = be32_to_cpu(pm->pmMapBlkCnt); | 112 | size = be32_to_cpu(pm->pmMapBlkCnt); |
| 112 | for (i = 0; i < size;) { | 113 | for (i = 0; i < size;) { |
| 113 | if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && | 114 | if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && |
| 114 | (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { | 115 | (sbi->part < 0 || sbi->part == i)) { |
| 115 | *part_start += be32_to_cpu(pm->pmPyPartStart); | 116 | *part_start += be32_to_cpu(pm->pmPyPartStart); |
| 116 | *part_size = be32_to_cpu(pm->pmPartBlkCnt); | 117 | *part_size = be32_to_cpu(pm->pmPartBlkCnt); |
| 117 | res = 0; | 118 | res = 0; |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 3b55c050c742..9a88d7536103 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/smp_lock.h> | ||
| 16 | #include <linux/vfs.h> | 15 | #include <linux/vfs.h> |
| 17 | #include <linux/nls.h> | 16 | #include <linux/nls.h> |
| 18 | 17 | ||
| @@ -21,40 +20,11 @@ static void hfsplus_destroy_inode(struct inode *inode); | |||
| 21 | 20 | ||
| 22 | #include "hfsplus_fs.h" | 21 | #include "hfsplus_fs.h" |
| 23 | 22 | ||
| 24 | struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) | 23 | static int hfsplus_system_read_inode(struct inode *inode) |
| 25 | { | 24 | { |
| 26 | struct hfs_find_data fd; | 25 | struct hfsplus_vh *vhdr = HFSPLUS_SB(inode->i_sb)->s_vhdr; |
| 27 | struct hfsplus_vh *vhdr; | ||
| 28 | struct inode *inode; | ||
| 29 | long err = -EIO; | ||
| 30 | |||
| 31 | inode = iget_locked(sb, ino); | ||
| 32 | if (!inode) | ||
| 33 | return ERR_PTR(-ENOMEM); | ||
| 34 | if (!(inode->i_state & I_NEW)) | ||
| 35 | return inode; | ||
| 36 | 26 | ||
| 37 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 27 | switch (inode->i_ino) { |
| 38 | mutex_init(&HFSPLUS_I(inode).extents_lock); | ||
| 39 | HFSPLUS_I(inode).flags = 0; | ||
| 40 | HFSPLUS_I(inode).rsrc_inode = NULL; | ||
| 41 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | ||
| 42 | |||
| 43 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { | ||
| 44 | read_inode: | ||
| 45 | hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | ||
| 46 | err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | ||
| 47 | if (!err) | ||
| 48 | err = hfsplus_cat_read_inode(inode, &fd); | ||
| 49 | hfs_find_exit(&fd); | ||
| 50 | if (err) | ||
| 51 | goto bad_inode; | ||
| 52 | goto done; | ||
| 53 | } | ||
| 54 | vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; | ||
| 55 | switch(inode->i_ino) { | ||
| 56 | case HFSPLUS_ROOT_CNID: | ||
| 57 | goto read_inode; | ||
| 58 | case HFSPLUS_EXT_CNID: | 28 | case HFSPLUS_EXT_CNID: |
| 59 | hfsplus_inode_read_fork(inode, &vhdr->ext_file); | 29 | hfsplus_inode_read_fork(inode, &vhdr->ext_file); |
| 60 | inode->i_mapping->a_ops = &hfsplus_btree_aops; | 30 | inode->i_mapping->a_ops = &hfsplus_btree_aops; |
| @@ -75,74 +45,101 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) | |||
| 75 | inode->i_mapping->a_ops = &hfsplus_btree_aops; | 45 | inode->i_mapping->a_ops = &hfsplus_btree_aops; |
| 76 | break; | 46 | break; |
| 77 | default: | 47 | default: |
| 78 | goto bad_inode; | 48 | return -EIO; |
| 49 | } | ||
| 50 | |||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) | ||
| 55 | { | ||
| 56 | struct hfs_find_data fd; | ||
| 57 | struct inode *inode; | ||
| 58 | int err; | ||
| 59 | |||
| 60 | inode = iget_locked(sb, ino); | ||
| 61 | if (!inode) | ||
| 62 | return ERR_PTR(-ENOMEM); | ||
| 63 | if (!(inode->i_state & I_NEW)) | ||
| 64 | return inode; | ||
| 65 | |||
| 66 | INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list); | ||
| 67 | mutex_init(&HFSPLUS_I(inode)->extents_lock); | ||
| 68 | HFSPLUS_I(inode)->flags = 0; | ||
| 69 | HFSPLUS_I(inode)->rsrc_inode = NULL; | ||
| 70 | atomic_set(&HFSPLUS_I(inode)->opencnt, 0); | ||
| 71 | |||
| 72 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || | ||
| 73 | inode->i_ino == HFSPLUS_ROOT_CNID) { | ||
| 74 | hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); | ||
| 75 | err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | ||
| 76 | if (!err) | ||
| 77 | err = hfsplus_cat_read_inode(inode, &fd); | ||
| 78 | hfs_find_exit(&fd); | ||
| 79 | } else { | ||
| 80 | err = hfsplus_system_read_inode(inode); | ||
| 81 | } | ||
| 82 | |||
| 83 | if (err) { | ||
| 84 | iget_failed(inode); | ||
| 85 | return ERR_PTR(err); | ||
| 79 | } | 86 | } |
| 80 | 87 | ||
| 81 | done: | ||
| 82 | unlock_new_inode(inode); | 88 | unlock_new_inode(inode); |
| 83 | return inode; | 89 | return inode; |
| 84 | |||
| 85 | bad_inode: | ||
| 86 | iget_failed(inode); | ||
| 87 | return ERR_PTR(err); | ||
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | static int hfsplus_write_inode(struct inode *inode, | 92 | static int hfsplus_system_write_inode(struct inode *inode) |
| 91 | struct writeback_control *wbc) | ||
| 92 | { | 93 | { |
| 93 | struct hfsplus_vh *vhdr; | 94 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); |
| 94 | int ret = 0; | 95 | struct hfsplus_vh *vhdr = sbi->s_vhdr; |
| 96 | struct hfsplus_fork_raw *fork; | ||
| 97 | struct hfs_btree *tree = NULL; | ||
| 95 | 98 | ||
| 96 | dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino); | ||
| 97 | hfsplus_ext_write_extent(inode); | ||
| 98 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { | ||
| 99 | return hfsplus_cat_write_inode(inode); | ||
| 100 | } | ||
| 101 | vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; | ||
| 102 | switch (inode->i_ino) { | 99 | switch (inode->i_ino) { |
| 103 | case HFSPLUS_ROOT_CNID: | ||
| 104 | ret = hfsplus_cat_write_inode(inode); | ||
| 105 | break; | ||
| 106 | case HFSPLUS_EXT_CNID: | 100 | case HFSPLUS_EXT_CNID: |
| 107 | if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) { | 101 | fork = &vhdr->ext_file; |
| 108 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | 102 | tree = sbi->ext_tree; |
| 109 | inode->i_sb->s_dirt = 1; | ||
| 110 | } | ||
| 111 | hfsplus_inode_write_fork(inode, &vhdr->ext_file); | ||
| 112 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).ext_tree); | ||
| 113 | break; | 103 | break; |
| 114 | case HFSPLUS_CAT_CNID: | 104 | case HFSPLUS_CAT_CNID: |
| 115 | if (vhdr->cat_file.total_size != cpu_to_be64(inode->i_size)) { | 105 | fork = &vhdr->cat_file; |
| 116 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | 106 | tree = sbi->cat_tree; |
| 117 | inode->i_sb->s_dirt = 1; | ||
| 118 | } | ||
| 119 | hfsplus_inode_write_fork(inode, &vhdr->cat_file); | ||
| 120 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).cat_tree); | ||
| 121 | break; | 107 | break; |
| 122 | case HFSPLUS_ALLOC_CNID: | 108 | case HFSPLUS_ALLOC_CNID: |
| 123 | if (vhdr->alloc_file.total_size != cpu_to_be64(inode->i_size)) { | 109 | fork = &vhdr->alloc_file; |
| 124 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
| 125 | inode->i_sb->s_dirt = 1; | ||
| 126 | } | ||
| 127 | hfsplus_inode_write_fork(inode, &vhdr->alloc_file); | ||
| 128 | break; | 110 | break; |
| 129 | case HFSPLUS_START_CNID: | 111 | case HFSPLUS_START_CNID: |
| 130 | if (vhdr->start_file.total_size != cpu_to_be64(inode->i_size)) { | 112 | fork = &vhdr->start_file; |
| 131 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
| 132 | inode->i_sb->s_dirt = 1; | ||
| 133 | } | ||
| 134 | hfsplus_inode_write_fork(inode, &vhdr->start_file); | ||
| 135 | break; | 113 | break; |
| 136 | case HFSPLUS_ATTR_CNID: | 114 | case HFSPLUS_ATTR_CNID: |
| 137 | if (vhdr->attr_file.total_size != cpu_to_be64(inode->i_size)) { | 115 | fork = &vhdr->attr_file; |
| 138 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | 116 | tree = sbi->attr_tree; |
| 139 | inode->i_sb->s_dirt = 1; | 117 | default: |
| 140 | } | 118 | return -EIO; |
| 141 | hfsplus_inode_write_fork(inode, &vhdr->attr_file); | 119 | } |
| 142 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree); | 120 | |
| 143 | break; | 121 | if (fork->total_size != cpu_to_be64(inode->i_size)) { |
| 122 | set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); | ||
| 123 | inode->i_sb->s_dirt = 1; | ||
| 144 | } | 124 | } |
| 145 | return ret; | 125 | hfsplus_inode_write_fork(inode, fork); |
| 126 | if (tree) | ||
| 127 | hfs_btree_write(tree); | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int hfsplus_write_inode(struct inode *inode, | ||
| 132 | struct writeback_control *wbc) | ||
| 133 | { | ||
| 134 | dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino); | ||
| 135 | |||
| 136 | hfsplus_ext_write_extent(inode); | ||
| 137 | |||
| 138 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || | ||
| 139 | inode->i_ino == HFSPLUS_ROOT_CNID) | ||
| 140 | return hfsplus_cat_write_inode(inode); | ||
| 141 | else | ||
| 142 | return hfsplus_system_write_inode(inode); | ||
| 146 | } | 143 | } |
| 147 | 144 | ||
| 148 | static void hfsplus_evict_inode(struct inode *inode) | 145 | static void hfsplus_evict_inode(struct inode *inode) |
| @@ -151,51 +148,53 @@ static void hfsplus_evict_inode(struct inode *inode) | |||
| 151 | truncate_inode_pages(&inode->i_data, 0); | 148 | truncate_inode_pages(&inode->i_data, 0); |
| 152 | end_writeback(inode); | 149 | end_writeback(inode); |
| 153 | if (HFSPLUS_IS_RSRC(inode)) { | 150 | if (HFSPLUS_IS_RSRC(inode)) { |
| 154 | HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; | 151 | HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL; |
| 155 | iput(HFSPLUS_I(inode).rsrc_inode); | 152 | iput(HFSPLUS_I(inode)->rsrc_inode); |
| 156 | } | 153 | } |
| 157 | } | 154 | } |
| 158 | 155 | ||
| 159 | int hfsplus_sync_fs(struct super_block *sb, int wait) | 156 | int hfsplus_sync_fs(struct super_block *sb, int wait) |
| 160 | { | 157 | { |
| 161 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 158 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); |
| 159 | struct hfsplus_vh *vhdr = sbi->s_vhdr; | ||
| 162 | 160 | ||
| 163 | dprint(DBG_SUPER, "hfsplus_write_super\n"); | 161 | dprint(DBG_SUPER, "hfsplus_write_super\n"); |
| 164 | 162 | ||
| 165 | lock_super(sb); | 163 | mutex_lock(&sbi->vh_mutex); |
| 164 | mutex_lock(&sbi->alloc_mutex); | ||
| 166 | sb->s_dirt = 0; | 165 | sb->s_dirt = 0; |
| 167 | 166 | ||
| 168 | vhdr->free_blocks = cpu_to_be32(HFSPLUS_SB(sb).free_blocks); | 167 | vhdr->free_blocks = cpu_to_be32(sbi->free_blocks); |
| 169 | vhdr->next_alloc = cpu_to_be32(HFSPLUS_SB(sb).next_alloc); | 168 | vhdr->next_cnid = cpu_to_be32(sbi->next_cnid); |
| 170 | vhdr->next_cnid = cpu_to_be32(HFSPLUS_SB(sb).next_cnid); | 169 | vhdr->folder_count = cpu_to_be32(sbi->folder_count); |
| 171 | vhdr->folder_count = cpu_to_be32(HFSPLUS_SB(sb).folder_count); | 170 | vhdr->file_count = cpu_to_be32(sbi->file_count); |
| 172 | vhdr->file_count = cpu_to_be32(HFSPLUS_SB(sb).file_count); | ||
| 173 | 171 | ||
| 174 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | 172 | mark_buffer_dirty(sbi->s_vhbh); |
| 175 | if (HFSPLUS_SB(sb).flags & HFSPLUS_SB_WRITEBACKUP) { | 173 | if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) { |
| 176 | if (HFSPLUS_SB(sb).sect_count) { | 174 | if (sbi->sect_count) { |
| 177 | struct buffer_head *bh; | 175 | struct buffer_head *bh; |
| 178 | u32 block, offset; | 176 | u32 block, offset; |
| 179 | 177 | ||
| 180 | block = HFSPLUS_SB(sb).blockoffset; | 178 | block = sbi->blockoffset; |
| 181 | block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); | 179 | block += (sbi->sect_count - 2) >> (sb->s_blocksize_bits - 9); |
| 182 | offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); | 180 | offset = ((sbi->sect_count - 2) << 9) & (sb->s_blocksize - 1); |
| 183 | printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, | 181 | printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", |
| 184 | HFSPLUS_SB(sb).sect_count, block, offset); | 182 | sbi->blockoffset, sbi->sect_count, |
| 183 | block, offset); | ||
| 185 | bh = sb_bread(sb, block); | 184 | bh = sb_bread(sb, block); |
| 186 | if (bh) { | 185 | if (bh) { |
| 187 | vhdr = (struct hfsplus_vh *)(bh->b_data + offset); | 186 | vhdr = (struct hfsplus_vh *)(bh->b_data + offset); |
| 188 | if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) { | 187 | if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) { |
| 189 | memcpy(vhdr, HFSPLUS_SB(sb).s_vhdr, sizeof(*vhdr)); | 188 | memcpy(vhdr, sbi->s_vhdr, sizeof(*vhdr)); |
| 190 | mark_buffer_dirty(bh); | 189 | mark_buffer_dirty(bh); |
| 191 | brelse(bh); | 190 | brelse(bh); |
| 192 | } else | 191 | } else |
| 193 | printk(KERN_WARNING "hfs: backup not found!\n"); | 192 | printk(KERN_WARNING "hfs: backup not found!\n"); |
| 194 | } | 193 | } |
| 195 | } | 194 | } |
| 196 | HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; | ||
| 197 | } | 195 | } |
| 198 | unlock_super(sb); | 196 | mutex_unlock(&sbi->alloc_mutex); |
| 197 | mutex_unlock(&sbi->vh_mutex); | ||
| 199 | return 0; | 198 | return 0; |
| 200 | } | 199 | } |
| 201 | 200 | ||
| @@ -209,48 +208,48 @@ static void hfsplus_write_super(struct super_block *sb) | |||
| 209 | 208 | ||
| 210 | static void hfsplus_put_super(struct super_block *sb) | 209 | static void hfsplus_put_super(struct super_block *sb) |
| 211 | { | 210 | { |
| 211 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 212 | |||
| 212 | dprint(DBG_SUPER, "hfsplus_put_super\n"); | 213 | dprint(DBG_SUPER, "hfsplus_put_super\n"); |
| 214 | |||
| 213 | if (!sb->s_fs_info) | 215 | if (!sb->s_fs_info) |
| 214 | return; | 216 | return; |
| 215 | 217 | ||
| 216 | lock_kernel(); | ||
| 217 | |||
| 218 | if (sb->s_dirt) | 218 | if (sb->s_dirt) |
| 219 | hfsplus_write_super(sb); | 219 | hfsplus_write_super(sb); |
| 220 | if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) { | 220 | if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { |
| 221 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 221 | struct hfsplus_vh *vhdr = sbi->s_vhdr; |
| 222 | 222 | ||
| 223 | vhdr->modify_date = hfsp_now2mt(); | 223 | vhdr->modify_date = hfsp_now2mt(); |
| 224 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); | 224 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); |
| 225 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); | 225 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); |
| 226 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | 226 | mark_buffer_dirty(sbi->s_vhbh); |
| 227 | sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); | 227 | sync_dirty_buffer(sbi->s_vhbh); |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | hfs_btree_close(HFSPLUS_SB(sb).cat_tree); | 230 | hfs_btree_close(sbi->cat_tree); |
| 231 | hfs_btree_close(HFSPLUS_SB(sb).ext_tree); | 231 | hfs_btree_close(sbi->ext_tree); |
| 232 | iput(HFSPLUS_SB(sb).alloc_file); | 232 | iput(sbi->alloc_file); |
| 233 | iput(HFSPLUS_SB(sb).hidden_dir); | 233 | iput(sbi->hidden_dir); |
| 234 | brelse(HFSPLUS_SB(sb).s_vhbh); | 234 | brelse(sbi->s_vhbh); |
| 235 | unload_nls(HFSPLUS_SB(sb).nls); | 235 | unload_nls(sbi->nls); |
| 236 | kfree(sb->s_fs_info); | 236 | kfree(sb->s_fs_info); |
| 237 | sb->s_fs_info = NULL; | 237 | sb->s_fs_info = NULL; |
| 238 | |||
| 239 | unlock_kernel(); | ||
| 240 | } | 238 | } |
| 241 | 239 | ||
| 242 | static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) | 240 | static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) |
| 243 | { | 241 | { |
| 244 | struct super_block *sb = dentry->d_sb; | 242 | struct super_block *sb = dentry->d_sb; |
| 243 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 245 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); | 244 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
| 246 | 245 | ||
| 247 | buf->f_type = HFSPLUS_SUPER_MAGIC; | 246 | buf->f_type = HFSPLUS_SUPER_MAGIC; |
| 248 | buf->f_bsize = sb->s_blocksize; | 247 | buf->f_bsize = sb->s_blocksize; |
| 249 | buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; | 248 | buf->f_blocks = sbi->total_blocks << sbi->fs_shift; |
| 250 | buf->f_bfree = HFSPLUS_SB(sb).free_blocks << HFSPLUS_SB(sb).fs_shift; | 249 | buf->f_bfree = sbi->free_blocks << sbi->fs_shift; |
| 251 | buf->f_bavail = buf->f_bfree; | 250 | buf->f_bavail = buf->f_bfree; |
| 252 | buf->f_files = 0xFFFFFFFF; | 251 | buf->f_files = 0xFFFFFFFF; |
| 253 | buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid; | 252 | buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid; |
| 254 | buf->f_fsid.val[0] = (u32)id; | 253 | buf->f_fsid.val[0] = (u32)id; |
| 255 | buf->f_fsid.val[1] = (u32)(id >> 32); | 254 | buf->f_fsid.val[1] = (u32)(id >> 32); |
| 256 | buf->f_namelen = HFSPLUS_MAX_STRLEN; | 255 | buf->f_namelen = HFSPLUS_MAX_STRLEN; |
| @@ -263,11 +262,11 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
| 263 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 262 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
| 264 | return 0; | 263 | return 0; |
| 265 | if (!(*flags & MS_RDONLY)) { | 264 | if (!(*flags & MS_RDONLY)) { |
| 266 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 265 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; |
| 267 | struct hfsplus_sb_info sbi; | 266 | struct hfsplus_sb_info sbi; |
| 268 | 267 | ||
| 269 | memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); | 268 | memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); |
| 270 | sbi.nls = HFSPLUS_SB(sb).nls; | 269 | sbi.nls = HFSPLUS_SB(sb)->nls; |
| 271 | if (!hfsplus_parse_options(data, &sbi)) | 270 | if (!hfsplus_parse_options(data, &sbi)) |
| 272 | return -EINVAL; | 271 | return -EINVAL; |
| 273 | 272 | ||
| @@ -276,7 +275,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
| 276 | "running fsck.hfsplus is recommended. leaving read-only.\n"); | 275 | "running fsck.hfsplus is recommended. leaving read-only.\n"); |
| 277 | sb->s_flags |= MS_RDONLY; | 276 | sb->s_flags |= MS_RDONLY; |
| 278 | *flags |= MS_RDONLY; | 277 | *flags |= MS_RDONLY; |
| 279 | } else if (sbi.flags & HFSPLUS_SB_FORCE) { | 278 | } else if (test_bit(HFSPLUS_SB_FORCE, &sbi.flags)) { |
| 280 | /* nothing */ | 279 | /* nothing */ |
| 281 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 280 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
| 282 | printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); | 281 | printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); |
| @@ -320,7 +319,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 320 | return -ENOMEM; | 319 | return -ENOMEM; |
| 321 | 320 | ||
| 322 | sb->s_fs_info = sbi; | 321 | sb->s_fs_info = sbi; |
| 323 | INIT_HLIST_HEAD(&sbi->rsrc_inodes); | 322 | mutex_init(&sbi->alloc_mutex); |
| 323 | mutex_init(&sbi->vh_mutex); | ||
| 324 | hfsplus_fill_defaults(sbi); | 324 | hfsplus_fill_defaults(sbi); |
| 325 | if (!hfsplus_parse_options(data, sbi)) { | 325 | if (!hfsplus_parse_options(data, sbi)) { |
| 326 | printk(KERN_ERR "hfs: unable to parse mount options\n"); | 326 | printk(KERN_ERR "hfs: unable to parse mount options\n"); |
| @@ -344,7 +344,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 344 | err = -EINVAL; | 344 | err = -EINVAL; |
| 345 | goto cleanup; | 345 | goto cleanup; |
| 346 | } | 346 | } |
| 347 | vhdr = HFSPLUS_SB(sb).s_vhdr; | 347 | vhdr = sbi->s_vhdr; |
| 348 | 348 | ||
| 349 | /* Copy parts of the volume header into the superblock */ | 349 | /* Copy parts of the volume header into the superblock */ |
| 350 | sb->s_magic = HFSPLUS_VOLHEAD_SIG; | 350 | sb->s_magic = HFSPLUS_VOLHEAD_SIG; |
| @@ -353,18 +353,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 353 | printk(KERN_ERR "hfs: wrong filesystem version\n"); | 353 | printk(KERN_ERR "hfs: wrong filesystem version\n"); |
| 354 | goto cleanup; | 354 | goto cleanup; |
| 355 | } | 355 | } |
| 356 | HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); | 356 | sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); |
| 357 | HFSPLUS_SB(sb).free_blocks = be32_to_cpu(vhdr->free_blocks); | 357 | sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); |
| 358 | HFSPLUS_SB(sb).next_alloc = be32_to_cpu(vhdr->next_alloc); | 358 | sbi->next_cnid = be32_to_cpu(vhdr->next_cnid); |
| 359 | HFSPLUS_SB(sb).next_cnid = be32_to_cpu(vhdr->next_cnid); | 359 | sbi->file_count = be32_to_cpu(vhdr->file_count); |
| 360 | HFSPLUS_SB(sb).file_count = be32_to_cpu(vhdr->file_count); | 360 | sbi->folder_count = be32_to_cpu(vhdr->folder_count); |
| 361 | HFSPLUS_SB(sb).folder_count = be32_to_cpu(vhdr->folder_count); | 361 | sbi->data_clump_blocks = |
| 362 | HFSPLUS_SB(sb).data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 362 | be32_to_cpu(vhdr->data_clump_sz) >> sbi->alloc_blksz_shift; |
| 363 | if (!HFSPLUS_SB(sb).data_clump_blocks) | 363 | if (!sbi->data_clump_blocks) |
| 364 | HFSPLUS_SB(sb).data_clump_blocks = 1; | 364 | sbi->data_clump_blocks = 1; |
| 365 | HFSPLUS_SB(sb).rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 365 | sbi->rsrc_clump_blocks = |
| 366 | if (!HFSPLUS_SB(sb).rsrc_clump_blocks) | 366 | be32_to_cpu(vhdr->rsrc_clump_sz) >> sbi->alloc_blksz_shift; |
| 367 | HFSPLUS_SB(sb).rsrc_clump_blocks = 1; | 367 | if (!sbi->rsrc_clump_blocks) |
| 368 | sbi->rsrc_clump_blocks = 1; | ||
| 368 | 369 | ||
| 369 | /* Set up operations so we can load metadata */ | 370 | /* Set up operations so we can load metadata */ |
| 370 | sb->s_op = &hfsplus_sops; | 371 | sb->s_op = &hfsplus_sops; |
| @@ -374,7 +375,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 374 | printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, " | 375 | printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, " |
| 375 | "running fsck.hfsplus is recommended. mounting read-only.\n"); | 376 | "running fsck.hfsplus is recommended. mounting read-only.\n"); |
| 376 | sb->s_flags |= MS_RDONLY; | 377 | sb->s_flags |= MS_RDONLY; |
| 377 | } else if (sbi->flags & HFSPLUS_SB_FORCE) { | 378 | } else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) { |
| 378 | /* nothing */ | 379 | /* nothing */ |
| 379 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 380 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
| 380 | printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n"); | 381 | printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n"); |
| @@ -384,16 +385,15 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 384 | "use the force option at your own risk, mounting read-only.\n"); | 385 | "use the force option at your own risk, mounting read-only.\n"); |
| 385 | sb->s_flags |= MS_RDONLY; | 386 | sb->s_flags |= MS_RDONLY; |
| 386 | } | 387 | } |
| 387 | sbi->flags &= ~HFSPLUS_SB_FORCE; | ||
| 388 | 388 | ||
| 389 | /* Load metadata objects (B*Trees) */ | 389 | /* Load metadata objects (B*Trees) */ |
| 390 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); | 390 | sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); |
| 391 | if (!HFSPLUS_SB(sb).ext_tree) { | 391 | if (!sbi->ext_tree) { |
| 392 | printk(KERN_ERR "hfs: failed to load extents file\n"); | 392 | printk(KERN_ERR "hfs: failed to load extents file\n"); |
| 393 | goto cleanup; | 393 | goto cleanup; |
| 394 | } | 394 | } |
| 395 | HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); | 395 | sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); |
| 396 | if (!HFSPLUS_SB(sb).cat_tree) { | 396 | if (!sbi->cat_tree) { |
| 397 | printk(KERN_ERR "hfs: failed to load catalog file\n"); | 397 | printk(KERN_ERR "hfs: failed to load catalog file\n"); |
| 398 | goto cleanup; | 398 | goto cleanup; |
| 399 | } | 399 | } |
| @@ -404,7 +404,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 404 | err = PTR_ERR(inode); | 404 | err = PTR_ERR(inode); |
| 405 | goto cleanup; | 405 | goto cleanup; |
| 406 | } | 406 | } |
| 407 | HFSPLUS_SB(sb).alloc_file = inode; | 407 | sbi->alloc_file = inode; |
| 408 | 408 | ||
| 409 | /* Load the root directory */ | 409 | /* Load the root directory */ |
| 410 | root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID); | 410 | root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID); |
| @@ -423,7 +423,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 423 | 423 | ||
| 424 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; | 424 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; |
| 425 | str.name = HFSP_HIDDENDIR_NAME; | 425 | str.name = HFSP_HIDDENDIR_NAME; |
| 426 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 426 | hfs_find_init(sbi->cat_tree, &fd); |
| 427 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); | 427 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); |
| 428 | if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { | 428 | if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { |
| 429 | hfs_find_exit(&fd); | 429 | hfs_find_exit(&fd); |
| @@ -434,7 +434,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 434 | err = PTR_ERR(inode); | 434 | err = PTR_ERR(inode); |
| 435 | goto cleanup; | 435 | goto cleanup; |
| 436 | } | 436 | } |
| 437 | HFSPLUS_SB(sb).hidden_dir = inode; | 437 | sbi->hidden_dir = inode; |
| 438 | } else | 438 | } else |
| 439 | hfs_find_exit(&fd); | 439 | hfs_find_exit(&fd); |
| 440 | 440 | ||
| @@ -449,15 +449,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 449 | be32_add_cpu(&vhdr->write_count, 1); | 449 | be32_add_cpu(&vhdr->write_count, 1); |
| 450 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); | 450 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); |
| 451 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); | 451 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); |
| 452 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | 452 | mark_buffer_dirty(sbi->s_vhbh); |
| 453 | sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); | 453 | sync_dirty_buffer(sbi->s_vhbh); |
| 454 | 454 | ||
| 455 | if (!HFSPLUS_SB(sb).hidden_dir) { | 455 | if (!sbi->hidden_dir) { |
| 456 | printk(KERN_DEBUG "hfs: create hidden dir...\n"); | 456 | printk(KERN_DEBUG "hfs: create hidden dir...\n"); |
| 457 | HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); | 457 | |
| 458 | hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, | 458 | mutex_lock(&sbi->vh_mutex); |
| 459 | &str, HFSPLUS_SB(sb).hidden_dir); | 459 | sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); |
| 460 | mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir); | 460 | hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode, |
| 461 | &str, sbi->hidden_dir); | ||
| 462 | mutex_unlock(&sbi->vh_mutex); | ||
| 463 | |||
| 464 | mark_inode_dirty(sbi->hidden_dir); | ||
| 461 | } | 465 | } |
| 462 | out: | 466 | out: |
| 463 | unload_nls(sbi->nls); | 467 | unload_nls(sbi->nls); |
| @@ -486,7 +490,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb) | |||
| 486 | 490 | ||
| 487 | static void hfsplus_destroy_inode(struct inode *inode) | 491 | static void hfsplus_destroy_inode(struct inode *inode) |
| 488 | { | 492 | { |
| 489 | kmem_cache_free(hfsplus_inode_cachep, &HFSPLUS_I(inode)); | 493 | kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode)); |
| 490 | } | 494 | } |
| 491 | 495 | ||
| 492 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) | 496 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) |
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index 628ccf6fa402..b66d67de882c 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c | |||
| @@ -121,7 +121,7 @@ static u16 *hfsplus_compose_lookup(u16 *p, u16 cc) | |||
| 121 | int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p) | 121 | int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p) |
| 122 | { | 122 | { |
| 123 | const hfsplus_unichr *ip; | 123 | const hfsplus_unichr *ip; |
| 124 | struct nls_table *nls = HFSPLUS_SB(sb).nls; | 124 | struct nls_table *nls = HFSPLUS_SB(sb)->nls; |
| 125 | u8 *op; | 125 | u8 *op; |
| 126 | u16 cc, c0, c1; | 126 | u16 cc, c0, c1; |
| 127 | u16 *ce1, *ce2; | 127 | u16 *ce1, *ce2; |
| @@ -132,7 +132,7 @@ int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, c | |||
| 132 | ustrlen = be16_to_cpu(ustr->length); | 132 | ustrlen = be16_to_cpu(ustr->length); |
| 133 | len = *len_p; | 133 | len = *len_p; |
| 134 | ce1 = NULL; | 134 | ce1 = NULL; |
| 135 | compose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 135 | compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
| 136 | 136 | ||
| 137 | while (ustrlen > 0) { | 137 | while (ustrlen > 0) { |
| 138 | c0 = be16_to_cpu(*ip++); | 138 | c0 = be16_to_cpu(*ip++); |
| @@ -246,7 +246,7 @@ out: | |||
| 246 | static inline int asc2unichar(struct super_block *sb, const char *astr, int len, | 246 | static inline int asc2unichar(struct super_block *sb, const char *astr, int len, |
| 247 | wchar_t *uc) | 247 | wchar_t *uc) |
| 248 | { | 248 | { |
| 249 | int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc); | 249 | int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc); |
| 250 | if (size <= 0) { | 250 | if (size <= 0) { |
| 251 | *uc = '?'; | 251 | *uc = '?'; |
| 252 | size = 1; | 252 | size = 1; |
| @@ -293,7 +293,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, | |||
| 293 | u16 *dstr, outlen = 0; | 293 | u16 *dstr, outlen = 0; |
| 294 | wchar_t c; | 294 | wchar_t c; |
| 295 | 295 | ||
| 296 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 296 | decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
| 297 | while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { | 297 | while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { |
| 298 | size = asc2unichar(sb, astr, len, &c); | 298 | size = asc2unichar(sb, astr, len, &c); |
| 299 | 299 | ||
| @@ -330,8 +330,8 @@ int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str) | |||
| 330 | wchar_t c; | 330 | wchar_t c; |
| 331 | u16 c2; | 331 | u16 c2; |
| 332 | 332 | ||
| 333 | casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); | 333 | casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); |
| 334 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 334 | decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
| 335 | hash = init_name_hash(); | 335 | hash = init_name_hash(); |
| 336 | astr = str->name; | 336 | astr = str->name; |
| 337 | len = str->len; | 337 | len = str->len; |
| @@ -373,8 +373,8 @@ int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr * | |||
| 373 | u16 c1, c2; | 373 | u16 c1, c2; |
| 374 | wchar_t c; | 374 | wchar_t c; |
| 375 | 375 | ||
| 376 | casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); | 376 | casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); |
| 377 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 377 | decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
| 378 | astr1 = s1->name; | 378 | astr1 = s1->name; |
| 379 | len1 = s1->len; | 379 | len1 = s1->len; |
| 380 | astr2 = s2->name; | 380 | astr2 = s2->name; |
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index bed78ac8f6d1..8972c20b3216 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c | |||
| @@ -65,8 +65,8 @@ static int hfsplus_get_last_session(struct super_block *sb, | |||
| 65 | *start = 0; | 65 | *start = 0; |
| 66 | *size = sb->s_bdev->bd_inode->i_size >> 9; | 66 | *size = sb->s_bdev->bd_inode->i_size >> 9; |
| 67 | 67 | ||
| 68 | if (HFSPLUS_SB(sb).session >= 0) { | 68 | if (HFSPLUS_SB(sb)->session >= 0) { |
| 69 | te.cdte_track = HFSPLUS_SB(sb).session; | 69 | te.cdte_track = HFSPLUS_SB(sb)->session; |
| 70 | te.cdte_format = CDROM_LBA; | 70 | te.cdte_format = CDROM_LBA; |
| 71 | res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te); | 71 | res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te); |
| 72 | if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) { | 72 | if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) { |
| @@ -87,6 +87,7 @@ static int hfsplus_get_last_session(struct super_block *sb, | |||
| 87 | /* Takes in super block, returns true if good data read */ | 87 | /* Takes in super block, returns true if good data read */ |
| 88 | int hfsplus_read_wrapper(struct super_block *sb) | 88 | int hfsplus_read_wrapper(struct super_block *sb) |
| 89 | { | 89 | { |
| 90 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
| 90 | struct buffer_head *bh; | 91 | struct buffer_head *bh; |
| 91 | struct hfsplus_vh *vhdr; | 92 | struct hfsplus_vh *vhdr; |
| 92 | struct hfsplus_wd wd; | 93 | struct hfsplus_wd wd; |
| @@ -122,7 +123,7 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
| 122 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) | 123 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) |
| 123 | break; | 124 | break; |
| 124 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) { | 125 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) { |
| 125 | HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX; | 126 | set_bit(HFSPLUS_SB_HFSX, &sbi->flags); |
| 126 | break; | 127 | break; |
| 127 | } | 128 | } |
| 128 | brelse(bh); | 129 | brelse(bh); |
| @@ -143,11 +144,11 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
| 143 | if (blocksize < HFSPLUS_SECTOR_SIZE || | 144 | if (blocksize < HFSPLUS_SECTOR_SIZE || |
| 144 | ((blocksize - 1) & blocksize)) | 145 | ((blocksize - 1) & blocksize)) |
| 145 | return -EINVAL; | 146 | return -EINVAL; |
| 146 | HFSPLUS_SB(sb).alloc_blksz = blocksize; | 147 | sbi->alloc_blksz = blocksize; |
| 147 | HFSPLUS_SB(sb).alloc_blksz_shift = 0; | 148 | sbi->alloc_blksz_shift = 0; |
| 148 | while ((blocksize >>= 1) != 0) | 149 | while ((blocksize >>= 1) != 0) |
| 149 | HFSPLUS_SB(sb).alloc_blksz_shift++; | 150 | sbi->alloc_blksz_shift++; |
| 150 | blocksize = min(HFSPLUS_SB(sb).alloc_blksz, (u32)PAGE_SIZE); | 151 | blocksize = min(sbi->alloc_blksz, (u32)PAGE_SIZE); |
| 151 | 152 | ||
| 152 | /* align block size to block offset */ | 153 | /* align block size to block offset */ |
| 153 | while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1)) | 154 | while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1)) |
| @@ -158,23 +159,26 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
| 158 | return -EINVAL; | 159 | return -EINVAL; |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | HFSPLUS_SB(sb).blockoffset = part_start >> | 162 | sbi->blockoffset = |
| 162 | (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT); | 163 | part_start >> (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT); |
| 163 | HFSPLUS_SB(sb).sect_count = part_size; | 164 | sbi->sect_count = part_size; |
| 164 | HFSPLUS_SB(sb).fs_shift = HFSPLUS_SB(sb).alloc_blksz_shift - | 165 | sbi->fs_shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits; |
| 165 | sb->s_blocksize_bits; | ||
| 166 | 166 | ||
| 167 | bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); | 167 | bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); |
| 168 | if (!bh) | 168 | if (!bh) |
| 169 | return -EIO; | 169 | return -EIO; |
| 170 | 170 | ||
| 171 | /* should still be the same... */ | 171 | /* should still be the same... */ |
| 172 | if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ? | 172 | if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) { |
| 173 | cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) : | 173 | if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) |
| 174 | cpu_to_be16(HFSPLUS_VOLHEAD_SIG))) | 174 | goto error; |
| 175 | goto error; | 175 | } else { |
| 176 | HFSPLUS_SB(sb).s_vhbh = bh; | 176 | if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) |
| 177 | HFSPLUS_SB(sb).s_vhdr = vhdr; | 177 | goto error; |
| 178 | } | ||
| 179 | |||
| 180 | sbi->s_vhbh = bh; | ||
| 181 | sbi->s_vhdr = vhdr; | ||
| 178 | 182 | ||
| 179 | return 0; | 183 | return 0; |
| 180 | error: | 184 | error: |
