aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hfsplus/inode.c')
-rw-r--r--fs/hfsplus/inode.c89
1 files changed, 57 insertions, 32 deletions
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 8afd7e84f98d..a8df651747f0 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>
@@ -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 {
@@ -166,8 +169,8 @@ const struct dentry_operations hfsplus_dentry_operations = {
166 .d_compare = hfsplus_compare_dentry, 169 .d_compare = hfsplus_compare_dentry,
167}; 170};
168 171
169static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry, 172static struct dentry *hfsplus_file_lookup(struct inode *dir,
170 struct nameidata *nd) 173 struct dentry *dentry, struct nameidata *nd)
171{ 174{
172 struct hfs_find_data fd; 175 struct hfs_find_data fd;
173 struct super_block *sb = dir->i_sb; 176 struct super_block *sb = dir->i_sb;
@@ -190,7 +193,9 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
190 inode->i_ino = dir->i_ino; 193 inode->i_ino = dir->i_ino;
191 INIT_LIST_HEAD(&hip->open_dir_list); 194 INIT_LIST_HEAD(&hip->open_dir_list);
192 mutex_init(&hip->extents_lock); 195 mutex_init(&hip->extents_lock);
193 hip->flags = HFSPLUS_FLG_RSRC; 196 hip->extent_state = 0;
197 hip->flags = 0;
198 set_bit(HFSPLUS_I_RSRC, &hip->flags);
194 199
195 hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); 200 hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
196 err = hfsplus_find_cat(sb, dir->i_ino, &fd); 201 err = hfsplus_find_cat(sb, dir->i_ino, &fd);
@@ -219,7 +224,8 @@ out:
219 return NULL; 224 return NULL;
220} 225}
221 226
222static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) 227static void hfsplus_get_perms(struct inode *inode,
228 struct hfsplus_perm *perms, int dir)
223{ 229{
224 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); 230 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
225 u16 mode; 231 u16 mode;
@@ -302,29 +308,41 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
302 return 0; 308 return 0;
303} 309}
304 310
305static int hfsplus_file_fsync(struct file *filp, int datasync) 311int hfsplus_file_fsync(struct file *file, int datasync)
306{ 312{
307 struct inode *inode = filp->f_mapping->host; 313 struct inode *inode = file->f_mapping->host;
308 struct super_block * sb; 314 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
309 int ret, err; 315 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
310 316 int error = 0, error2;
311 /* sync the inode to buffers */ 317
312 ret = write_inode_now(inode, 0); 318 /*
313 319 * Sync inode metadata into the catalog and extent trees.
314 /* sync the superblock to buffers */ 320 */
315 sb = inode->i_sb; 321 sync_inode_metadata(inode, 1);
316 if (sb->s_dirt) { 322
317 if (!(sb->s_flags & MS_RDONLY)) 323 /*
318 hfsplus_sync_fs(sb, 1); 324 * And explicitly write out the btrees.
319 else 325 */
320 sb->s_dirt = 0; 326 if (test_and_clear_bit(HFSPLUS_I_CAT_DIRTY, &hip->flags))
327 error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
328
329 if (test_and_clear_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags)) {
330 error2 =
331 filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
332 if (!error)
333 error = error2;
321 } 334 }
322 335
323 /* .. finally sync the buffers to disk */ 336 if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags)) {
324 err = sync_blockdev(sb->s_bdev); 337 error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
325 if (!ret) 338 if (!error)
326 ret = err; 339 error = error2;
327 return ret; 340 }
341
342 if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
343 blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
344
345 return error;
328} 346}
329 347
330static const struct inode_operations hfsplus_file_inode_operations = { 348static const struct inode_operations hfsplus_file_inode_operations = {
@@ -337,7 +355,7 @@ static const struct inode_operations hfsplus_file_inode_operations = {
337}; 355};
338 356
339static const struct file_operations hfsplus_file_operations = { 357static const struct file_operations hfsplus_file_operations = {
340 .llseek = generic_file_llseek, 358 .llseek = generic_file_llseek,
341 .read = do_sync_read, 359 .read = do_sync_read,
342 .aio_read = generic_file_aio_read, 360 .aio_read = generic_file_aio_read,
343 .write = do_sync_write, 361 .write = do_sync_write,
@@ -370,6 +388,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
370 INIT_LIST_HEAD(&hip->open_dir_list); 388 INIT_LIST_HEAD(&hip->open_dir_list);
371 mutex_init(&hip->extents_lock); 389 mutex_init(&hip->extents_lock);
372 atomic_set(&hip->opencnt, 0); 390 atomic_set(&hip->opencnt, 0);
391 hip->extent_state = 0;
373 hip->flags = 0; 392 hip->flags = 0;
374 memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); 393 memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
375 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); 394 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
@@ -457,7 +476,8 @@ void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
457 } 476 }
458} 477}
459 478
460void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) 479void hfsplus_inode_write_fork(struct inode *inode,
480 struct hfsplus_fork_raw *fork)
461{ 481{
462 memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents, 482 memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents,
463 sizeof(hfsplus_extent_rec)); 483 sizeof(hfsplus_extent_rec));
@@ -499,13 +519,14 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
499 hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, 519 hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
500 sizeof(struct hfsplus_cat_file)); 520 sizeof(struct hfsplus_cat_file));
501 521
502 hfsplus_inode_read_fork(inode, HFSPLUS_IS_DATA(inode) ? 522 hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
503 &file->data_fork : &file->rsrc_fork); 523 &file->rsrc_fork : &file->data_fork);
504 hfsplus_get_perms(inode, &file->permissions, 0); 524 hfsplus_get_perms(inode, &file->permissions, 0);
505 inode->i_nlink = 1; 525 inode->i_nlink = 1;
506 if (S_ISREG(inode->i_mode)) { 526 if (S_ISREG(inode->i_mode)) {
507 if (file->permissions.dev) 527 if (file->permissions.dev)
508 inode->i_nlink = be32_to_cpu(file->permissions.dev); 528 inode->i_nlink =
529 be32_to_cpu(file->permissions.dev);
509 inode->i_op = &hfsplus_file_inode_operations; 530 inode->i_op = &hfsplus_file_inode_operations;
510 inode->i_fop = &hfsplus_file_operations; 531 inode->i_fop = &hfsplus_file_operations;
511 inode->i_mapping->a_ops = &hfsplus_aops; 532 inode->i_mapping->a_ops = &hfsplus_aops;
@@ -578,7 +599,9 @@ int hfsplus_cat_write_inode(struct inode *inode)
578 sizeof(struct hfsplus_cat_file)); 599 sizeof(struct hfsplus_cat_file));
579 hfsplus_inode_write_fork(inode, &file->data_fork); 600 hfsplus_inode_write_fork(inode, &file->data_fork);
580 hfsplus_cat_set_perms(inode, &file->permissions); 601 hfsplus_cat_set_perms(inode, &file->permissions);
581 if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) 602 if (HFSPLUS_FLG_IMMUTABLE &
603 (file->permissions.rootflags |
604 file->permissions.userflags))
582 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); 605 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
583 else 606 else
584 file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED); 607 file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED);
@@ -588,6 +611,8 @@ int hfsplus_cat_write_inode(struct inode *inode)
588 hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, 611 hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
589 sizeof(struct hfsplus_cat_file)); 612 sizeof(struct hfsplus_cat_file));
590 } 613 }
614
615 set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
591out: 616out:
592 hfs_find_exit(&fd); 617 hfs_find_exit(&fd);
593 return 0; 618 return 0;