X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fhfsplus%2Fsuper.c;h=d55ad67b8e4238e3625f2139b78b353858337657;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=4ff176a0bb58380bfe38f83bfc16a39bc63390ee;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 4ff176a0b..d55ad67b8 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -16,6 +16,7 @@ #include #include #include +#include static struct inode *hfsplus_alloc_inode(struct super_block *sb); static void hfsplus_destroy_inode(struct inode *inode); @@ -94,7 +95,7 @@ static void hfsplus_read_inode(struct inode *inode) make_bad_inode(inode); } -int hfsplus_write_inode(struct inode *inode, int unused) +static int hfsplus_write_inode(struct inode *inode, int unused) { struct hfsplus_vh *vhdr; int ret = 0; @@ -207,7 +208,9 @@ static void hfsplus_write_super(struct super_block *sb) static void hfsplus_put_super(struct super_block *sb) { dprint(DBG_SUPER, "hfsplus_put_super\n"); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb->s_fs_info) + return; + if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) { struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; vhdr->modify_date = hfsp_now2mt(); @@ -223,6 +226,10 @@ static void hfsplus_put_super(struct super_block *sb) iput(HFSPLUS_SB(sb).alloc_file); iput(HFSPLUS_SB(sb).hidden_dir); brelse(HFSPLUS_SB(sb).s_vhbh); + if (HFSPLUS_SB(sb).nls) + unload_nls(HFSPLUS_SB(sb).nls); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; } static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) @@ -239,15 +246,14 @@ static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) return 0; } -int hfsplus_remount(struct super_block *sb, int *flags, char *data) +static int hfsplus_remount(struct super_block *sb, int *flags, char *data) { if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0; if (!(*flags & MS_RDONLY)) { struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; - if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) || - !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { + if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " "running fsck.hfsplus is recommended. leaving read-only.\n"); sb->s_flags |= MS_RDONLY; @@ -281,13 +287,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) struct hfs_find_data fd; struct inode *root; struct qstr str; + struct nls_table *nls = NULL; int err = -EINVAL; sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL); - if (!sbi) { - err = -ENOMEM; - goto out2; - } + if (!sbi) + return -ENOMEM; + memset(sbi, 0, sizeof(HFSPLUS_SB(sb))); sb->s_fs_info = sbi; INIT_HLIST_HEAD(&sbi->rsrc_inodes); @@ -296,7 +302,16 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) if (!silent) printk("HFS+-fs: unable to parse mount options\n"); err = -EINVAL; - goto out2; + goto cleanup; + } + + /* temporarily use utf8 to correctly find the hidden dir below */ + nls = sbi->nls; + sbi->nls = load_nls("utf8"); + if (!nls) { + printk("HFS+: unable to load nls for utf8\n"); + err = -EINVAL; + goto cleanup; } /* Grab the volume header */ @@ -304,7 +319,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) if (!silent) printk("HFS+-fs: unable to find HFS+ superblock\n"); err = -EINVAL; - goto out2; + goto cleanup; } vhdr = HFSPLUS_SB(sb).s_vhdr; @@ -332,8 +347,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &hfsplus_sops; sb->s_maxbytes = MAX_LFS_FILESIZE; - if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) || - !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { + if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { if (!silent) printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " "running fsck.hfsplus is recommended. mounting read-only.\n"); @@ -378,7 +392,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; str.name = HFSP_HIDDENDIR_NAME; hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); - hfsplus_cat_build_key(fd.search_key, HFSPLUS_ROOT_CNID, &str); + hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { hfs_find_exit(&fd); if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) @@ -412,11 +426,14 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir); } out: + unload_nls(sbi->nls); + sbi->nls = nls; return 0; cleanup: hfsplus_put_super(sb); -out2: + if (nls) + unload_nls(nls); return err; }