hfsplus: add support of manipulation by attributes file
Add support of manipulation by attributes file. Signed-off-by: Vyacheslav Dubeyko <slava@dubeyko.com> Reported-by: Hin-Tak Leung <htl10@users.sourceforge.net> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Cc: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
127e5f5ae5
commit
324ef39a8a
@@ -20,6 +20,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb);
|
||||
static void hfsplus_destroy_inode(struct inode *inode);
|
||||
|
||||
#include "hfsplus_fs.h"
|
||||
#include "xattr.h"
|
||||
|
||||
static int hfsplus_system_read_inode(struct inode *inode)
|
||||
{
|
||||
@@ -118,6 +119,7 @@ static int hfsplus_system_write_inode(struct inode *inode)
|
||||
case HFSPLUS_ATTR_CNID:
|
||||
fork = &vhdr->attr_file;
|
||||
tree = sbi->attr_tree;
|
||||
break;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
@@ -191,6 +193,12 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait)
|
||||
error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
|
||||
if (!error)
|
||||
error = error2;
|
||||
if (sbi->attr_tree) {
|
||||
error2 =
|
||||
filemap_write_and_wait(sbi->attr_tree->inode->i_mapping);
|
||||
if (!error)
|
||||
error = error2;
|
||||
}
|
||||
error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
|
||||
if (!error)
|
||||
error = error2;
|
||||
@@ -281,6 +289,7 @@ static void hfsplus_put_super(struct super_block *sb)
|
||||
hfsplus_sync_fs(sb, 1);
|
||||
}
|
||||
|
||||
hfs_btree_close(sbi->attr_tree);
|
||||
hfs_btree_close(sbi->cat_tree);
|
||||
hfs_btree_close(sbi->ext_tree);
|
||||
iput(sbi->alloc_file);
|
||||
@@ -477,12 +486,20 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
|
||||
printk(KERN_ERR "hfs: failed to load catalog file\n");
|
||||
goto out_close_ext_tree;
|
||||
}
|
||||
if (vhdr->attr_file.total_blocks != 0) {
|
||||
sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
|
||||
if (!sbi->attr_tree) {
|
||||
printk(KERN_ERR "hfs: failed to load attributes file\n");
|
||||
goto out_close_cat_tree;
|
||||
}
|
||||
}
|
||||
sb->s_xattr = hfsplus_xattr_handlers;
|
||||
|
||||
inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID);
|
||||
if (IS_ERR(inode)) {
|
||||
printk(KERN_ERR "hfs: failed to load allocation file\n");
|
||||
err = PTR_ERR(inode);
|
||||
goto out_close_cat_tree;
|
||||
goto out_close_attr_tree;
|
||||
}
|
||||
sbi->alloc_file = inode;
|
||||
|
||||
@@ -542,10 +559,27 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
|
||||
}
|
||||
err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root,
|
||||
&str, sbi->hidden_dir);
|
||||
mutex_unlock(&sbi->vh_mutex);
|
||||
if (err)
|
||||
if (err) {
|
||||
mutex_unlock(&sbi->vh_mutex);
|
||||
goto out_put_hidden_dir;
|
||||
}
|
||||
|
||||
err = hfsplus_init_inode_security(sbi->hidden_dir,
|
||||
root, &str);
|
||||
if (err == -EOPNOTSUPP)
|
||||
err = 0; /* Operation is not supported. */
|
||||
else if (err) {
|
||||
/*
|
||||
* Try to delete anyway without
|
||||
* error analysis.
|
||||
*/
|
||||
hfsplus_delete_cat(sbi->hidden_dir->i_ino,
|
||||
root, &str);
|
||||
mutex_unlock(&sbi->vh_mutex);
|
||||
goto out_put_hidden_dir;
|
||||
}
|
||||
|
||||
mutex_unlock(&sbi->vh_mutex);
|
||||
hfsplus_mark_inode_dirty(sbi->hidden_dir,
|
||||
HFSPLUS_I_CAT_DIRTY);
|
||||
}
|
||||
@@ -562,6 +596,8 @@ out_put_root:
|
||||
sb->s_root = NULL;
|
||||
out_put_alloc_file:
|
||||
iput(sbi->alloc_file);
|
||||
out_close_attr_tree:
|
||||
hfs_btree_close(sbi->attr_tree);
|
||||
out_close_cat_tree:
|
||||
hfs_btree_close(sbi->cat_tree);
|
||||
out_close_ext_tree:
|
||||
@@ -635,9 +671,20 @@ static int __init init_hfsplus_fs(void)
|
||||
hfsplus_init_once);
|
||||
if (!hfsplus_inode_cachep)
|
||||
return -ENOMEM;
|
||||
err = hfsplus_create_attr_tree_cache();
|
||||
if (err)
|
||||
goto destroy_inode_cache;
|
||||
err = register_filesystem(&hfsplus_fs_type);
|
||||
if (err)
|
||||
kmem_cache_destroy(hfsplus_inode_cachep);
|
||||
goto destroy_attr_tree_cache;
|
||||
return 0;
|
||||
|
||||
destroy_attr_tree_cache:
|
||||
hfsplus_destroy_attr_tree_cache();
|
||||
|
||||
destroy_inode_cache:
|
||||
kmem_cache_destroy(hfsplus_inode_cachep);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -650,6 +697,7 @@ static void __exit exit_hfsplus_fs(void)
|
||||
* destroy cache.
|
||||
*/
|
||||
rcu_barrier();
|
||||
hfsplus_destroy_attr_tree_cache();
|
||||
kmem_cache_destroy(hfsplus_inode_cachep);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user