aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/inode.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/hfsplus/inode.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/hfsplus/inode.c')
-rw-r--r--fs/hfsplus/inode.c274
1 files changed, 147 insertions, 127 deletions
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index c5a979d62c65..b248a6cfcad9 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -8,6 +8,7 @@
8 * Inode handling routines 8 * Inode handling routines
9 */ 9 */
10 10
11#include <linux/blkdev.h>
11#include <linux/mm.h> 12#include <linux/mm.h>
12#include <linux/fs.h> 13#include <linux/fs.h>
13#include <linux/pagemap.h> 14#include <linux/pagemap.h>
@@ -36,7 +37,7 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping,
36 *pagep = NULL; 37 *pagep = NULL;
37 ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 38 ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
38 hfsplus_get_block, 39 hfsplus_get_block,
39 &HFSPLUS_I(mapping->host).phys_size); 40 &HFSPLUS_I(mapping->host)->phys_size);
40 if (unlikely(ret)) { 41 if (unlikely(ret)) {
41 loff_t isize = mapping->host->i_size; 42 loff_t isize = mapping->host->i_size;
42 if (pos + len > isize) 43 if (pos + len > isize)
@@ -62,13 +63,13 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
62 63
63 switch (inode->i_ino) { 64 switch (inode->i_ino) {
64 case HFSPLUS_EXT_CNID: 65 case HFSPLUS_EXT_CNID:
65 tree = HFSPLUS_SB(sb).ext_tree; 66 tree = HFSPLUS_SB(sb)->ext_tree;
66 break; 67 break;
67 case HFSPLUS_CAT_CNID: 68 case HFSPLUS_CAT_CNID:
68 tree = HFSPLUS_SB(sb).cat_tree; 69 tree = HFSPLUS_SB(sb)->cat_tree;
69 break; 70 break;
70 case HFSPLUS_ATTR_CNID: 71 case HFSPLUS_ATTR_CNID:
71 tree = HFSPLUS_SB(sb).attr_tree; 72 tree = HFSPLUS_SB(sb)->attr_tree;
72 break; 73 break;
73 default: 74 default:
74 BUG(); 75 BUG();
@@ -77,7 +78,8 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
77 if (!tree) 78 if (!tree)
78 return 0; 79 return 0;
79 if (tree->node_size >= PAGE_CACHE_SIZE) { 80 if (tree->node_size >= PAGE_CACHE_SIZE) {
80 nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT); 81 nidx = page->index >>
82 (tree->node_size_shift - PAGE_CACHE_SHIFT);
81 spin_lock(&tree->hash_lock); 83 spin_lock(&tree->hash_lock);
82 node = hfs_bnode_findhash(tree, nidx); 84 node = hfs_bnode_findhash(tree, nidx);
83 if (!node) 85 if (!node)
@@ -90,7 +92,8 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
90 } 92 }
91 spin_unlock(&tree->hash_lock); 93 spin_unlock(&tree->hash_lock);
92 } else { 94 } else {
93 nidx = page->index << (PAGE_CACHE_SHIFT - tree->node_size_shift); 95 nidx = page->index <<
96 (PAGE_CACHE_SHIFT - tree->node_size_shift);
94 i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift); 97 i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift);
95 spin_lock(&tree->hash_lock); 98 spin_lock(&tree->hash_lock);
96 do { 99 do {
@@ -143,7 +146,6 @@ static int hfsplus_writepages(struct address_space *mapping,
143const struct address_space_operations hfsplus_btree_aops = { 146const struct address_space_operations hfsplus_btree_aops = {
144 .readpage = hfsplus_readpage, 147 .readpage = hfsplus_readpage,
145 .writepage = hfsplus_writepage, 148 .writepage = hfsplus_writepage,
146 .sync_page = block_sync_page,
147 .write_begin = hfsplus_write_begin, 149 .write_begin = hfsplus_write_begin,
148 .write_end = generic_write_end, 150 .write_end = generic_write_end,
149 .bmap = hfsplus_bmap, 151 .bmap = hfsplus_bmap,
@@ -153,7 +155,6 @@ const struct address_space_operations hfsplus_btree_aops = {
153const struct address_space_operations hfsplus_aops = { 155const struct address_space_operations hfsplus_aops = {
154 .readpage = hfsplus_readpage, 156 .readpage = hfsplus_readpage,
155 .writepage = hfsplus_writepage, 157 .writepage = hfsplus_writepage,
156 .sync_page = block_sync_page,
157 .write_begin = hfsplus_write_begin, 158 .write_begin = hfsplus_write_begin,
158 .write_end = generic_write_end, 159 .write_end = generic_write_end,
159 .bmap = hfsplus_bmap, 160 .bmap = hfsplus_bmap,
@@ -166,18 +167,19 @@ const struct dentry_operations hfsplus_dentry_operations = {
166 .d_compare = hfsplus_compare_dentry, 167 .d_compare = hfsplus_compare_dentry,
167}; 168};
168 169
169static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry, 170static struct dentry *hfsplus_file_lookup(struct inode *dir,
170 struct nameidata *nd) 171 struct dentry *dentry, struct nameidata *nd)
171{ 172{
172 struct hfs_find_data fd; 173 struct hfs_find_data fd;
173 struct super_block *sb = dir->i_sb; 174 struct super_block *sb = dir->i_sb;
174 struct inode *inode = NULL; 175 struct inode *inode = NULL;
176 struct hfsplus_inode_info *hip;
175 int err; 177 int err;
176 178
177 if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) 179 if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
178 goto out; 180 goto out;
179 181
180 inode = HFSPLUS_I(dir).rsrc_inode; 182 inode = HFSPLUS_I(dir)->rsrc_inode;
181 if (inode) 183 if (inode)
182 goto out; 184 goto out;
183 185
@@ -185,12 +187,15 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
185 if (!inode) 187 if (!inode)
186 return ERR_PTR(-ENOMEM); 188 return ERR_PTR(-ENOMEM);
187 189
190 hip = HFSPLUS_I(inode);
188 inode->i_ino = dir->i_ino; 191 inode->i_ino = dir->i_ino;
189 INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); 192 INIT_LIST_HEAD(&hip->open_dir_list);
190 mutex_init(&HFSPLUS_I(inode).extents_lock); 193 mutex_init(&hip->extents_lock);
191 HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; 194 hip->extent_state = 0;
195 hip->flags = 0;
196 set_bit(HFSPLUS_I_RSRC, &hip->flags);
192 197
193 hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); 198 hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
194 err = hfsplus_find_cat(sb, dir->i_ino, &fd); 199 err = hfsplus_find_cat(sb, dir->i_ino, &fd);
195 if (!err) 200 if (!err)
196 err = hfsplus_cat_read_inode(inode, &fd); 201 err = hfsplus_cat_read_inode(inode, &fd);
@@ -199,42 +204,48 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
199 iput(inode); 204 iput(inode);
200 return ERR_PTR(err); 205 return ERR_PTR(err);
201 } 206 }
202 HFSPLUS_I(inode).rsrc_inode = dir; 207 hip->rsrc_inode = dir;
203 HFSPLUS_I(dir).rsrc_inode = inode; 208 HFSPLUS_I(dir)->rsrc_inode = inode;
204 igrab(dir); 209 igrab(dir);
205 hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); 210
211 /*
212 * __mark_inode_dirty expects inodes to be hashed. Since we don't
213 * want resource fork inodes in the regular inode space, we make them
214 * appear hashed, but do not put on any lists. hlist_del()
215 * will work fine and require no locking.
216 */
217 hlist_add_fake(&inode->i_hash);
218
206 mark_inode_dirty(inode); 219 mark_inode_dirty(inode);
207out: 220out:
208 d_add(dentry, inode); 221 d_add(dentry, inode);
209 return NULL; 222 return NULL;
210} 223}
211 224
212static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) 225static void hfsplus_get_perms(struct inode *inode,
226 struct hfsplus_perm *perms, int dir)
213{ 227{
214 struct super_block *sb = inode->i_sb; 228 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
215 u16 mode; 229 u16 mode;
216 230
217 mode = be16_to_cpu(perms->mode); 231 mode = be16_to_cpu(perms->mode);
218 232
219 inode->i_uid = be32_to_cpu(perms->owner); 233 inode->i_uid = be32_to_cpu(perms->owner);
220 if (!inode->i_uid && !mode) 234 if (!inode->i_uid && !mode)
221 inode->i_uid = HFSPLUS_SB(sb).uid; 235 inode->i_uid = sbi->uid;
222 236
223 inode->i_gid = be32_to_cpu(perms->group); 237 inode->i_gid = be32_to_cpu(perms->group);
224 if (!inode->i_gid && !mode) 238 if (!inode->i_gid && !mode)
225 inode->i_gid = HFSPLUS_SB(sb).gid; 239 inode->i_gid = sbi->gid;
226 240
227 if (dir) { 241 if (dir) {
228 mode = mode ? (mode & S_IALLUGO) : 242 mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask));
229 (S_IRWXUGO & ~(HFSPLUS_SB(sb).umask));
230 mode |= S_IFDIR; 243 mode |= S_IFDIR;
231 } else if (!mode) 244 } else if (!mode)
232 mode = S_IFREG | ((S_IRUGO|S_IWUGO) & 245 mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask));
233 ~(HFSPLUS_SB(sb).umask));
234 inode->i_mode = mode; 246 inode->i_mode = mode;
235 247
236 HFSPLUS_I(inode).rootflags = perms->rootflags; 248 HFSPLUS_I(inode)->userflags = perms->userflags;
237 HFSPLUS_I(inode).userflags = perms->userflags;
238 if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) 249 if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE)
239 inode->i_flags |= S_IMMUTABLE; 250 inode->i_flags |= S_IMMUTABLE;
240 else 251 else
@@ -245,30 +256,13 @@ static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, i
245 inode->i_flags &= ~S_APPEND; 256 inode->i_flags &= ~S_APPEND;
246} 257}
247 258
248static 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
265static int hfsplus_file_open(struct inode *inode, struct file *file) 259static int hfsplus_file_open(struct inode *inode, struct file *file)
266{ 260{
267 if (HFSPLUS_IS_RSRC(inode)) 261 if (HFSPLUS_IS_RSRC(inode))
268 inode = HFSPLUS_I(inode).rsrc_inode; 262 inode = HFSPLUS_I(inode)->rsrc_inode;
269 if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) 263 if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
270 return -EOVERFLOW; 264 return -EOVERFLOW;
271 atomic_inc(&HFSPLUS_I(inode).opencnt); 265 atomic_inc(&HFSPLUS_I(inode)->opencnt);
272 return 0; 266 return 0;
273} 267}
274 268
@@ -277,12 +271,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
277 struct super_block *sb = inode->i_sb; 271 struct super_block *sb = inode->i_sb;
278 272
279 if (HFSPLUS_IS_RSRC(inode)) 273 if (HFSPLUS_IS_RSRC(inode))
280 inode = HFSPLUS_I(inode).rsrc_inode; 274 inode = HFSPLUS_I(inode)->rsrc_inode;
281 if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { 275 if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) {
282 mutex_lock(&inode->i_mutex); 276 mutex_lock(&inode->i_mutex);
283 hfsplus_file_truncate(inode); 277 hfsplus_file_truncate(inode);
284 if (inode->i_flags & S_DEAD) { 278 if (inode->i_flags & S_DEAD) {
285 hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); 279 hfsplus_delete_cat(inode->i_ino,
280 HFSPLUS_SB(sb)->hidden_dir, NULL);
286 hfsplus_delete_inode(inode); 281 hfsplus_delete_inode(inode);
287 } 282 }
288 mutex_unlock(&inode->i_mutex); 283 mutex_unlock(&inode->i_mutex);
@@ -311,29 +306,41 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
311 return 0; 306 return 0;
312} 307}
313 308
314static int hfsplus_file_fsync(struct file *filp, int datasync) 309int hfsplus_file_fsync(struct file *file, int datasync)
315{ 310{
316 struct inode *inode = filp->f_mapping->host; 311 struct inode *inode = file->f_mapping->host;
317 struct super_block * sb; 312 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
318 int ret, err; 313 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
319 314 int error = 0, error2;
320 /* sync the inode to buffers */ 315
321 ret = write_inode_now(inode, 0); 316 /*
322 317 * Sync inode metadata into the catalog and extent trees.
323 /* sync the superblock to buffers */ 318 */
324 sb = inode->i_sb; 319 sync_inode_metadata(inode, 1);
325 if (sb->s_dirt) { 320
326 if (!(sb->s_flags & MS_RDONLY)) 321 /*
327 hfsplus_sync_fs(sb, 1); 322 * And explicitly write out the btrees.
328 else 323 */
329 sb->s_dirt = 0; 324 if (test_and_clear_bit(HFSPLUS_I_CAT_DIRTY, &hip->flags))
325 error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
326
327 if (test_and_clear_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags)) {
328 error2 =
329 filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
330 if (!error)
331 error = error2;
330 } 332 }
331 333
332 /* .. finally sync the buffers to disk */ 334 if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags)) {
333 err = sync_blockdev(sb->s_bdev); 335 error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
334 if (!ret) 336 if (!error)
335 ret = err; 337 error = error2;
336 return ret; 338 }
339
340 if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
341 blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
342
343 return error;
337} 344}
338 345
339static const struct inode_operations hfsplus_file_inode_operations = { 346static const struct inode_operations hfsplus_file_inode_operations = {
@@ -346,7 +353,7 @@ static const struct inode_operations hfsplus_file_inode_operations = {
346}; 353};
347 354
348static const struct file_operations hfsplus_file_operations = { 355static const struct file_operations hfsplus_file_operations = {
349 .llseek = generic_file_llseek, 356 .llseek = generic_file_llseek,
350 .read = do_sync_read, 357 .read = do_sync_read,
351 .aio_read = generic_file_aio_read, 358 .aio_read = generic_file_aio_read,
352 .write = do_sync_write, 359 .write = do_sync_write,
@@ -361,47 +368,53 @@ static const struct file_operations hfsplus_file_operations = {
361 368
362struct inode *hfsplus_new_inode(struct super_block *sb, int mode) 369struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
363{ 370{
371 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
364 struct inode *inode = new_inode(sb); 372 struct inode *inode = new_inode(sb);
373 struct hfsplus_inode_info *hip;
374
365 if (!inode) 375 if (!inode)
366 return NULL; 376 return NULL;
367 377
368 inode->i_ino = HFSPLUS_SB(sb).next_cnid++; 378 inode->i_ino = sbi->next_cnid++;
369 inode->i_mode = mode; 379 inode->i_mode = mode;
370 inode->i_uid = current_fsuid(); 380 inode->i_uid = current_fsuid();
371 inode->i_gid = current_fsgid(); 381 inode->i_gid = current_fsgid();
372 inode->i_nlink = 1; 382 inode->i_nlink = 1;
373 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; 383 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
374 INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); 384
375 mutex_init(&HFSPLUS_I(inode).extents_lock); 385 hip = HFSPLUS_I(inode);
376 atomic_set(&HFSPLUS_I(inode).opencnt, 0); 386 INIT_LIST_HEAD(&hip->open_dir_list);
377 HFSPLUS_I(inode).flags = 0; 387 mutex_init(&hip->extents_lock);
378 memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec)); 388 atomic_set(&hip->opencnt, 0);
379 memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); 389 hip->extent_state = 0;
380 HFSPLUS_I(inode).alloc_blocks = 0; 390 hip->flags = 0;
381 HFSPLUS_I(inode).first_blocks = 0; 391 memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
382 HFSPLUS_I(inode).cached_start = 0; 392 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
383 HFSPLUS_I(inode).cached_blocks = 0; 393 hip->alloc_blocks = 0;
384 HFSPLUS_I(inode).phys_size = 0; 394 hip->first_blocks = 0;
385 HFSPLUS_I(inode).fs_blocks = 0; 395 hip->cached_start = 0;
386 HFSPLUS_I(inode).rsrc_inode = NULL; 396 hip->cached_blocks = 0;
397 hip->phys_size = 0;
398 hip->fs_blocks = 0;
399 hip->rsrc_inode = NULL;
387 if (S_ISDIR(inode->i_mode)) { 400 if (S_ISDIR(inode->i_mode)) {
388 inode->i_size = 2; 401 inode->i_size = 2;
389 HFSPLUS_SB(sb).folder_count++; 402 sbi->folder_count++;
390 inode->i_op = &hfsplus_dir_inode_operations; 403 inode->i_op = &hfsplus_dir_inode_operations;
391 inode->i_fop = &hfsplus_dir_operations; 404 inode->i_fop = &hfsplus_dir_operations;
392 } else if (S_ISREG(inode->i_mode)) { 405 } else if (S_ISREG(inode->i_mode)) {
393 HFSPLUS_SB(sb).file_count++; 406 sbi->file_count++;
394 inode->i_op = &hfsplus_file_inode_operations; 407 inode->i_op = &hfsplus_file_inode_operations;
395 inode->i_fop = &hfsplus_file_operations; 408 inode->i_fop = &hfsplus_file_operations;
396 inode->i_mapping->a_ops = &hfsplus_aops; 409 inode->i_mapping->a_ops = &hfsplus_aops;
397 HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks; 410 hip->clump_blocks = sbi->data_clump_blocks;
398 } else if (S_ISLNK(inode->i_mode)) { 411 } else if (S_ISLNK(inode->i_mode)) {
399 HFSPLUS_SB(sb).file_count++; 412 sbi->file_count++;
400 inode->i_op = &page_symlink_inode_operations; 413 inode->i_op = &page_symlink_inode_operations;
401 inode->i_mapping->a_ops = &hfsplus_aops; 414 inode->i_mapping->a_ops = &hfsplus_aops;
402 HFSPLUS_I(inode).clump_blocks = 1; 415 hip->clump_blocks = 1;
403 } else 416 } else
404 HFSPLUS_SB(sb).file_count++; 417 sbi->file_count++;
405 insert_inode_hash(inode); 418 insert_inode_hash(inode);
406 mark_inode_dirty(inode); 419 mark_inode_dirty(inode);
407 sb->s_dirt = 1; 420 sb->s_dirt = 1;
@@ -414,11 +427,11 @@ void hfsplus_delete_inode(struct inode *inode)
414 struct super_block *sb = inode->i_sb; 427 struct super_block *sb = inode->i_sb;
415 428
416 if (S_ISDIR(inode->i_mode)) { 429 if (S_ISDIR(inode->i_mode)) {
417 HFSPLUS_SB(sb).folder_count--; 430 HFSPLUS_SB(sb)->folder_count--;
418 sb->s_dirt = 1; 431 sb->s_dirt = 1;
419 return; 432 return;
420 } 433 }
421 HFSPLUS_SB(sb).file_count--; 434 HFSPLUS_SB(sb)->file_count--;
422 if (S_ISREG(inode->i_mode)) { 435 if (S_ISREG(inode->i_mode)) {
423 if (!inode->i_nlink) { 436 if (!inode->i_nlink) {
424 inode->i_size = 0; 437 inode->i_size = 0;
@@ -434,34 +447,40 @@ void hfsplus_delete_inode(struct inode *inode)
434void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) 447void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
435{ 448{
436 struct super_block *sb = inode->i_sb; 449 struct super_block *sb = inode->i_sb;
450 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
451 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
437 u32 count; 452 u32 count;
438 int i; 453 int i;
439 454
440 memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents, 455 memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec));
441 sizeof(hfsplus_extent_rec));
442 for (count = 0, i = 0; i < 8; i++) 456 for (count = 0, i = 0; i < 8; i++)
443 count += be32_to_cpu(fork->extents[i].block_count); 457 count += be32_to_cpu(fork->extents[i].block_count);
444 HFSPLUS_I(inode).first_blocks = count; 458 hip->first_blocks = count;
445 memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); 459 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
446 HFSPLUS_I(inode).cached_start = 0; 460 hip->cached_start = 0;
447 HFSPLUS_I(inode).cached_blocks = 0; 461 hip->cached_blocks = 0;
448 462
449 HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks); 463 hip->alloc_blocks = be32_to_cpu(fork->total_blocks);
450 inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size); 464 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; 465 hip->fs_blocks =
452 inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); 466 (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; 467 inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
454 if (!HFSPLUS_I(inode).clump_blocks) 468 hip->clump_blocks =
455 HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks : 469 be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift;
456 HFSPLUS_SB(sb).data_clump_blocks; 470 if (!hip->clump_blocks) {
471 hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ?
472 sbi->rsrc_clump_blocks :
473 sbi->data_clump_blocks;
474 }
457} 475}
458 476
459void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) 477void hfsplus_inode_write_fork(struct inode *inode,
478 struct hfsplus_fork_raw *fork)
460{ 479{
461 memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents, 480 memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents,
462 sizeof(hfsplus_extent_rec)); 481 sizeof(hfsplus_extent_rec));
463 fork->total_size = cpu_to_be64(inode->i_size); 482 fork->total_size = cpu_to_be64(inode->i_size);
464 fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks); 483 fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks);
465} 484}
466 485
467int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) 486int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
@@ -472,7 +491,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
472 491
473 type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); 492 type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
474 493
475 HFSPLUS_I(inode).dev = 0; 494 HFSPLUS_I(inode)->linkid = 0;
476 if (type == HFSPLUS_FOLDER) { 495 if (type == HFSPLUS_FOLDER) {
477 struct hfsplus_cat_folder *folder = &entry.folder; 496 struct hfsplus_cat_folder *folder = &entry.folder;
478 497
@@ -486,8 +505,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
486 inode->i_atime = hfsp_mt2ut(folder->access_date); 505 inode->i_atime = hfsp_mt2ut(folder->access_date);
487 inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); 506 inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
488 inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); 507 inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
489 HFSPLUS_I(inode).create_date = folder->create_date; 508 HFSPLUS_I(inode)->create_date = folder->create_date;
490 HFSPLUS_I(inode).fs_blocks = 0; 509 HFSPLUS_I(inode)->fs_blocks = 0;
491 inode->i_op = &hfsplus_dir_inode_operations; 510 inode->i_op = &hfsplus_dir_inode_operations;
492 inode->i_fop = &hfsplus_dir_operations; 511 inode->i_fop = &hfsplus_dir_operations;
493 } else if (type == HFSPLUS_FILE) { 512 } else if (type == HFSPLUS_FILE) {
@@ -498,13 +517,14 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
498 hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, 517 hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
499 sizeof(struct hfsplus_cat_file)); 518 sizeof(struct hfsplus_cat_file));
500 519
501 hfsplus_inode_read_fork(inode, HFSPLUS_IS_DATA(inode) ? 520 hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
502 &file->data_fork : &file->rsrc_fork); 521 &file->rsrc_fork : &file->data_fork);
503 hfsplus_get_perms(inode, &file->permissions, 0); 522 hfsplus_get_perms(inode, &file->permissions, 0);
504 inode->i_nlink = 1; 523 inode->i_nlink = 1;
505 if (S_ISREG(inode->i_mode)) { 524 if (S_ISREG(inode->i_mode)) {
506 if (file->permissions.dev) 525 if (file->permissions.dev)
507 inode->i_nlink = be32_to_cpu(file->permissions.dev); 526 inode->i_nlink =
527 be32_to_cpu(file->permissions.dev);
508 inode->i_op = &hfsplus_file_inode_operations; 528 inode->i_op = &hfsplus_file_inode_operations;
509 inode->i_fop = &hfsplus_file_operations; 529 inode->i_fop = &hfsplus_file_operations;
510 inode->i_mapping->a_ops = &hfsplus_aops; 530 inode->i_mapping->a_ops = &hfsplus_aops;
@@ -518,7 +538,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
518 inode->i_atime = hfsp_mt2ut(file->access_date); 538 inode->i_atime = hfsp_mt2ut(file->access_date);
519 inode->i_mtime = hfsp_mt2ut(file->content_mod_date); 539 inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
520 inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); 540 inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
521 HFSPLUS_I(inode).create_date = file->create_date; 541 HFSPLUS_I(inode)->create_date = file->create_date;
522 } else { 542 } else {
523 printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); 543 printk(KERN_ERR "hfs: bad catalog entry used to create inode\n");
524 res = -EIO; 544 res = -EIO;
@@ -533,12 +553,12 @@ int hfsplus_cat_write_inode(struct inode *inode)
533 hfsplus_cat_entry entry; 553 hfsplus_cat_entry entry;
534 554
535 if (HFSPLUS_IS_RSRC(inode)) 555 if (HFSPLUS_IS_RSRC(inode))
536 main_inode = HFSPLUS_I(inode).rsrc_inode; 556 main_inode = HFSPLUS_I(inode)->rsrc_inode;
537 557
538 if (!main_inode->i_nlink) 558 if (!main_inode->i_nlink)
539 return 0; 559 return 0;
540 560
541 if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd)) 561 if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd))
542 /* panic? */ 562 /* panic? */
543 return -EIO; 563 return -EIO;
544 564
@@ -554,7 +574,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
554 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, 574 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
555 sizeof(struct hfsplus_cat_folder)); 575 sizeof(struct hfsplus_cat_folder));
556 /* simple node checks? */ 576 /* simple node checks? */
557 hfsplus_set_perms(inode, &folder->permissions); 577 hfsplus_cat_set_perms(inode, &folder->permissions);
558 folder->access_date = hfsp_ut2mt(inode->i_atime); 578 folder->access_date = hfsp_ut2mt(inode->i_atime);
559 folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); 579 folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
560 folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); 580 folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
@@ -576,12 +596,10 @@ int hfsplus_cat_write_inode(struct inode *inode)
576 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, 596 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
577 sizeof(struct hfsplus_cat_file)); 597 sizeof(struct hfsplus_cat_file));
578 hfsplus_inode_write_fork(inode, &file->data_fork); 598 hfsplus_inode_write_fork(inode, &file->data_fork);
579 if (S_ISREG(inode->i_mode)) 599 hfsplus_cat_set_perms(inode, &file->permissions);
580 HFSPLUS_I(inode).dev = inode->i_nlink; 600 if (HFSPLUS_FLG_IMMUTABLE &
581 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 601 (file->permissions.rootflags |
582 HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev); 602 file->permissions.userflags))
583 hfsplus_set_perms(inode, &file->permissions);
584 if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
585 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); 603 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
586 else 604 else
587 file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED); 605 file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED);
@@ -591,6 +609,8 @@ int hfsplus_cat_write_inode(struct inode *inode)
591 hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, 609 hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
592 sizeof(struct hfsplus_cat_file)); 610 sizeof(struct hfsplus_cat_file));
593 } 611 }
612
613 set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
594out: 614out:
595 hfs_find_exit(&fd); 615 hfs_find_exit(&fd);
596 return 0; 616 return 0;