From 6f80dfe55fcbde1e588bc2cfa1273403b710872d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Nov 2010 23:01:17 +0100 Subject: hfsplus: fix option parsing during remount hfsplus only actually uses the force option during remount, but it uses the full option parser with a fake superblock to do so. This means remount will fail if any nls option is set (which happens frequently with older mount tools), even if it is the same. Fix this by adding a simpler version of the parser that only parses the force option for remount. Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index cb3653efb57a..f07aa640c27d 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -362,6 +362,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size); /* options.c */ int hfsplus_parse_options(char *, struct hfsplus_sb_info *); +int hfsplus_parse_options_remount(char *input, int *force); void hfsplus_fill_defaults(struct hfsplus_sb_info *); int hfsplus_show_options(struct seq_file *, struct vfsmount *); -- cgit v1.2.1 From 52399b171dfaea02b6944cd6feba49b624147126 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 23 Nov 2010 14:37:47 +0100 Subject: hfsplus: use raw bio access for the volume headers The hfsplus backup volume header is located two blocks from the end of the device. In case of device sizes that are not 4k aligned this means we can't access it using buffer_heads when using the default 4k block size. Switch to using raw bios to read/write all buffer headers. We were not relying on any caching behaviour of the buffer heads anyway. Additionally always read in the backup volume header during mount to verify that we can actually read it. Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index f07aa640c27d..276ddb0fd0fd 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -107,8 +107,8 @@ struct hfsplus_vh; struct hfs_btree; struct hfsplus_sb_info { - struct buffer_head *s_vhbh; struct hfsplus_vh *s_vhdr; + struct hfsplus_vh *s_backup_vhdr; struct hfs_btree *ext_tree; struct hfs_btree *cat_tree; struct hfs_btree *attr_tree; @@ -118,7 +118,8 @@ struct hfsplus_sb_info { /* Runtime variables */ u32 blockoffset; - u32 sect_count; + sector_t part_start; + sector_t sect_count; int fs_shift; /* immutable data from the volume header */ @@ -385,8 +386,9 @@ int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr * /* wrapper.c */ int hfsplus_read_wrapper(struct super_block *); - int hfs_part_find(struct super_block *, sector_t *, sector_t *); +int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, + void *data, int rw); /* access macros */ static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) -- cgit v1.2.1 From 358f26d52680cb150907302d4334359de7dd2d59 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 23 Nov 2010 14:37:51 +0100 Subject: hfsplus: use raw bio access for partition tables Switch the hfsplus partition table reding for cdroms to use our bio helpers. Again we don't rely on any caching in the buffer_heads, and this gets rid of the last buffer_head use in hfsplus. Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 276ddb0fd0fd..0d8532d96694 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -401,23 +401,6 @@ static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) return list_entry(inode, struct hfsplus_inode_info, vfs_inode); } -#define sb_bread512(sb, sec, data) ({ \ - struct buffer_head *__bh; \ - sector_t __block; \ - loff_t __start; \ - int __offset; \ - \ - __start = (loff_t)(sec) << HFSPLUS_SECTOR_SHIFT;\ - __block = __start >> (sb)->s_blocksize_bits; \ - __offset = __start & ((sb)->s_blocksize - 1); \ - __bh = sb_bread((sb), __block); \ - if (likely(__bh != NULL)) \ - data = (void *)(__bh->b_data + __offset);\ - else \ - data = NULL; \ - __bh; \ -}) - /* time macros */ #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) #define __hfsp_ut2mt(t) (cpu_to_be32(t + 2082844800U)) -- cgit v1.2.1 From eb29d66d4f2dc98a81ae590bbdddc8cfa8964d73 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 23 Nov 2010 14:38:10 +0100 Subject: hfsplus: write up fsync for directories fsync is supposed to not just work on regular files, but also on directories. Fortunately enough hfsplus_file_fsync works just fine for directories, so we can just wire it up. Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 0d8532d96694..625549579e9e 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -352,6 +352,7 @@ int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *); int hfsplus_cat_write_inode(struct inode *); struct inode *hfsplus_new_inode(struct super_block *, int); void hfsplus_delete_inode(struct inode *); +int hfsplus_file_fsync(struct file *file, int datasync); /* ioctl.c */ long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -- cgit v1.2.1 From b33b7921db14abcd10c30d0ccfc68e364f5ef7fe Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 23 Nov 2010 14:38:13 +0100 Subject: hfsplus: split up inode flags Split the flags field in the hfsplus inode into an extent_state flag that is locked by the extent_lock, and a new flags field that uses atomic bitops. The second will grow more flags in the next patch. Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 625549579e9e..9889d0033b8f 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -171,7 +171,7 @@ struct hfsplus_inode_info { u32 cached_blocks; hfsplus_extent_rec first_extents; hfsplus_extent_rec cached_extents; - unsigned long flags; + unsigned int extent_state; struct mutex extents_lock; /* @@ -185,6 +185,11 @@ struct hfsplus_inode_info { */ u32 linkid; + /* + * Accessed using atomic bitops. + */ + unsigned long flags; + /* * Protected by i_mutex. */ @@ -196,12 +201,13 @@ struct hfsplus_inode_info { struct inode vfs_inode; }; -#define HFSPLUS_FLG_RSRC 0x0001 -#define HFSPLUS_FLG_EXT_DIRTY 0x0002 -#define HFSPLUS_FLG_EXT_NEW 0x0004 +#define HFSPLUS_EXT_DIRTY 0x0001 +#define HFSPLUS_EXT_NEW 0x0002 + +#define HFSPLUS_I_RSRC 0 /* represents a resource fork */ -#define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC)) -#define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC) +#define HFSPLUS_IS_RSRC(inode) \ + test_bit(HFSPLUS_I_RSRC, &HFSPLUS_I(inode)->flags) struct hfs_find_data { /* filled by caller */ -- cgit v1.2.1 From e34947056076ca5467ee8256d2d9cbc594a79b37 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 23 Nov 2010 14:38:15 +0100 Subject: hfsplus: optimize fsync Avoid doing unessecary work in fsync. Do nothing unless the inode was marked dirty, and only write the various metadata inodes out if they contain any dirty state from this inode. This is archived by adding three new dirty bits to the hfsplus-specific inode which are set in the correct places. Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 9889d0033b8f..65c698f78ef7 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -157,6 +157,11 @@ struct hfsplus_sb_info { #define HFSPLUS_SB_HFSX 3 #define HFSPLUS_SB_CASEFOLD 4 +static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + struct hfsplus_inode_info { atomic_t opencnt; @@ -205,10 +210,31 @@ struct hfsplus_inode_info { #define HFSPLUS_EXT_NEW 0x0002 #define HFSPLUS_I_RSRC 0 /* represents a resource fork */ +#define HFSPLUS_I_CAT_DIRTY 1 /* has changes in the catalog tree */ +#define HFSPLUS_I_EXT_DIRTY 2 /* has changes in the extent tree */ +#define HFSPLUS_I_ALLOC_DIRTY 3 /* has changes in the allocation file */ #define HFSPLUS_IS_RSRC(inode) \ test_bit(HFSPLUS_I_RSRC, &HFSPLUS_I(inode)->flags) +static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) +{ + return list_entry(inode, struct hfsplus_inode_info, vfs_inode); +} + +/* + * Mark an inode dirty, and also mark the btree in which the + * specific type of metadata is stored. + * For data or metadata that gets written back by into the catalog btree + * by hfsplus_write_inode a plain mark_inode_dirty call is enough. + */ +static inline void hfsplus_mark_inode_dirty(struct inode *inode, + unsigned int flag) +{ + set_bit(flag, &HFSPLUS_I(inode)->flags); + mark_inode_dirty(inode); +} + struct hfs_find_data { /* filled by caller */ hfsplus_btree_key *search_key; @@ -397,17 +423,6 @@ int hfs_part_find(struct super_block *, sector_t *, sector_t *); int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, void *data, int rw); -/* access macros */ -static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} - -static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) -{ - return list_entry(inode, struct hfsplus_inode_info, vfs_inode); -} - /* time macros */ #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) #define __hfsp_ut2mt(t) (cpu_to_be32(t + 2082844800U)) -- cgit v1.2.1 From 34a2d313c51f47cae50ccb89f4196462665f2c48 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 23 Nov 2010 14:38:21 +0100 Subject: hfsplus: flush disk caches in sync and fsync Flush the disk cache in fsync and sync to make sure data actually is on disk on completion of these system calls. There is a nobarrier mount option to disable this behaviour. It's slightly misnamed now that barrier actually are gone, but it matches the name used by all major filesystems. Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 65c698f78ef7..17ac254e72cb 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -156,6 +156,7 @@ struct hfsplus_sb_info { #define HFSPLUS_SB_FORCE 2 #define HFSPLUS_SB_HFSX 3 #define HFSPLUS_SB_CASEFOLD 4 +#define HFSPLUS_SB_NOBARRIER 5 static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) { -- cgit v1.2.1 From 2753cc281c9a0e8a0a45ee2b8110866a9fe63bdd Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Thu, 16 Dec 2010 18:08:38 +0200 Subject: hfsplus: over 80 character lines clean-up Match coding style line length limitation where checkpatch.pl reported over-80-character-line warnings. Signed-off-by: Anton Salikhmetov Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 17ac254e72cb..c4abec167826 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -37,7 +37,8 @@ #define HFSPLUS_TYPE_DATA 0x00 #define HFSPLUS_TYPE_RSRC 0xFF -typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *); +typedef int (*btree_keycmp)(const hfsplus_btree_key *, + const hfsplus_btree_key *); #define NODE_HASH_SIZE 256 @@ -352,9 +353,12 @@ int hfs_brec_read(struct hfs_find_data *, void *, int); int hfs_brec_goto(struct hfs_find_data *, int); /* catalog.c */ -int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); -int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); -void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *); +int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, + const hfsplus_btree_key *); +int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, + const hfsplus_btree_key *); +void hfsplus_cat_build_key(struct super_block *sb, + hfsplus_btree_key *, u32, struct qstr *); int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *); int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); int hfsplus_delete_cat(u32, struct inode *, struct qstr *); @@ -370,7 +374,8 @@ extern const struct file_operations hfsplus_dir_operations; int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); void hfsplus_ext_write_extent(struct inode *); int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); -int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int); +int hfsplus_free_fork(struct super_block *, u32, + struct hfsplus_fork_raw *, int); int hfsplus_file_extend(struct inode *); void hfsplus_file_truncate(struct inode *); @@ -411,12 +416,17 @@ extern u16 hfsplus_decompose_table[]; extern u16 hfsplus_compose_table[]; /* unicode.c */ -int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); -int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); -int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); -int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); +int hfsplus_strcasecmp(const struct hfsplus_unistr *, + const struct hfsplus_unistr *); +int hfsplus_strcmp(const struct hfsplus_unistr *, + const struct hfsplus_unistr *); +int hfsplus_uni2asc(struct super_block *, + const struct hfsplus_unistr *, char *, int *); +int hfsplus_asc2uni(struct super_block *, + struct hfsplus_unistr *, const char *, int); int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str); -int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2); +int hfsplus_compare_dentry(struct dentry *dentry, + struct qstr *s1, struct qstr *s2); /* wrapper.c */ int hfsplus_read_wrapper(struct super_block *); -- cgit v1.2.1 From 21f2296a598c4089e0a9bdf54634269ac913a693 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Thu, 16 Dec 2010 18:08:39 +0200 Subject: hfsplus: C99 comments clean-up Match coding style restriction against C99 comments where checkpatch.pl reported errors about their usage. Signed-off-by: Anton Salikhmetov Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index c4abec167826..a15e1c11e820 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -23,9 +23,11 @@ #define DBG_EXTENT 0x00000020 #define DBG_BITMAP 0x00000040 -//#define DBG_MASK (DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD) -//#define DBG_MASK (DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE) -//#define DBG_MASK (DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT) +#if 0 +#define DBG_MASK (DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD) +#define DBG_MASK (DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE) +#define DBG_MASK (DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT) +#endif #define DBG_MASK (0) #define dprint(flg, fmt, args...) \ @@ -62,7 +64,6 @@ struct hfs_btree { unsigned int max_key_len; unsigned int depth; - //unsigned int map1_size, map_size; struct mutex tree_lock; unsigned int pages_per_bnode; -- cgit v1.2.1 From b2837fcf4994e699a4def002e26f274d95b387c1 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Thu, 16 Dec 2010 18:08:41 +0200 Subject: hfsplus: %L-to-%ll, macro correction, and remove unneeded braces Clean-up based on checkpatch.pl report against unnecessary braces (`{' and `}'), non-standard format option %Lu (%llu recommended) as well as one trailing statement in a macro definition which should have been on the next line. Signed-off-by: Anton Salikhmetov Signed-off-by: Christoph Hellwig --- fs/hfsplus/hfsplus_fs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/hfsplus/hfsplus_fs.h') diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index a15e1c11e820..f7cbdf89ac9b 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -31,7 +31,8 @@ #define DBG_MASK (0) #define dprint(flg, fmt, args...) \ - if (flg & DBG_MASK) printk(fmt , ## args) + if (flg & DBG_MASK) \ + printk(fmt , ## args) /* Runtime config options */ #define HFSPLUS_DEF_CR_TYPE 0x3F3F3F3F /* '????' */ -- cgit v1.2.1