Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd73a01a authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Christoph Hellwig
Browse files

hfsplus: fix HFSPLUS_SB calling convention



HFSPLUS_SB doesn't return a pointer to the hfsplus-specific superblock
information like all other FOO_SB macros, but dereference the pointer in a way
that made it look like a direct struct derefence.  This only works as long
as the HFSPLUS_SB macro is used directly and prevents us from keepig a local
hfsplus_sb_info pointer.  Fix the calling convention and introduce a local
sbi variable in all functions that use it constantly.

Signed-off-by: default avatarChristoph Hellwig <hch@tuxera.com>
parent e753a621
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
{
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
	struct page *page;
	struct address_space *mapping;
	__be32 *pptr, *curr, *end;
@@ -29,8 +30,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
		return size;

	dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
	mutex_lock(&HFSPLUS_SB(sb).alloc_mutex);
	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
	mutex_lock(&sbi->alloc_mutex);
	mapping = sbi->alloc_file->i_mapping;
	page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
	if (IS_ERR(page)) {
		start = size;
@@ -150,16 +151,17 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
	set_page_dirty(page);
	kunmap(page);
	*max = offset + (curr - pptr) * 32 + i - start;
	HFSPLUS_SB(sb).free_blocks -= *max;
	sbi->free_blocks -= *max;
	sb->s_dirt = 1;
	dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
out:
	mutex_unlock(&HFSPLUS_SB(sb).alloc_mutex);
	mutex_unlock(&sbi->alloc_mutex);
	return start;
}

int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
{
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
	struct page *page;
	struct address_space *mapping;
	__be32 *pptr, *curr, *end;
@@ -172,11 +174,11 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)

	dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
	/* are all of the bits in range? */
	if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
	if ((offset + count) > sbi->total_blocks)
		return -2;

	mutex_lock(&HFSPLUS_SB(sb).alloc_mutex);
	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
	mutex_lock(&sbi->alloc_mutex);
	mapping = sbi->alloc_file->i_mapping;
	pnr = offset / PAGE_CACHE_BITS;
	page = read_mapping_page(mapping, pnr, NULL);
	pptr = kmap(page);
@@ -224,9 +226,9 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
out:
	set_page_dirty(page);
	kunmap(page);
	HFSPLUS_SB(sb).free_blocks += len;
	sbi->free_blocks += len;
	sb->s_dirt = 1;
	mutex_unlock(&HFSPLUS_SB(sb).alloc_mutex);
	mutex_unlock(&sbi->alloc_mutex);

	return 0;
}
+4 −4
Original line number Diff line number Diff line
@@ -61,12 +61,12 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
	if (id == HFSPLUS_EXT_CNID) {
		tree->keycmp = hfsplus_ext_cmp_key;
	} else if (id == HFSPLUS_CAT_CNID) {
		if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
		if ((HFSPLUS_SB(sb)->flags & HFSPLUS_SB_HFSX) &&
		    (head->key_type == HFSPLUS_KEY_BINARY))
			tree->keycmp = hfsplus_cat_bin_cmp_key;
		else {
			tree->keycmp = hfsplus_cat_case_cmp_key;
			HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD;
			HFSPLUS_SB(sb)->flags |= HFSPLUS_SB_CASEFOLD;
		}
	} else {
		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
@@ -200,9 +200,9 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
			return ERR_PTR(res);
		HFSPLUS_I(inode).phys_size = inode->i_size =
				(loff_t)HFSPLUS_I(inode).alloc_blocks <<
				HFSPLUS_SB(tree->sb).alloc_blksz_shift;
				HFSPLUS_SB(tree->sb)->alloc_blksz_shift;
		HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks <<
					     HFSPLUS_SB(tree->sb).fs_shift;
					     HFSPLUS_SB(tree->sb)->fs_shift;
		inode_set_bytes(inode, inode->i_size);
		count = inode->i_size >> tree->node_size_shift;
		tree->free_nodes = count - tree->node_count;
+12 −13
Original line number Diff line number Diff line
@@ -86,6 +86,8 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)

static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode)
{
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);

	if (S_ISDIR(inode->i_mode)) {
		struct hfsplus_cat_folder *folder;

@@ -99,7 +101,7 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
			folder->attribute_mod_date =
			folder->access_date = hfsp_now2mt();
		hfsplus_set_perms(inode, &folder->permissions);
		if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
		if (inode == sbi->hidden_dir)
			/* invisible and namelocked */
			folder->user_info.frFlags = cpu_to_be16(0x5000);
		return sizeof(*folder);
@@ -122,8 +124,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
				file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
				file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
			} else {
				file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
				file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
				file->user_info.fdType = cpu_to_be32(sbi->type);
				file->user_info.fdCreator = cpu_to_be32(sbi->creator);
			}
			if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
				file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
@@ -131,7 +133,7 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
			file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
			file->user_info.fdFlags = cpu_to_be16(0x100);
			file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date;
			file->create_date = HFSPLUS_I(sbi->hidden_dir).create_date;
			file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
		}
		return sizeof(*file);
@@ -180,15 +182,14 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,

int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode)
{
	struct super_block *sb = dir->i_sb;
	struct hfs_find_data fd;
	struct super_block *sb;
	hfsplus_cat_entry entry;
	int entry_size;
	int err;

	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink);
	sb = dir->i_sb;
	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);

	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
	entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
@@ -234,7 +235,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct ino

int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
{
	struct super_block *sb;
	struct super_block *sb = dir->i_sb;
	struct hfs_find_data fd;
	struct hfsplus_fork_raw fork;
	struct list_head *pos;
@@ -242,8 +243,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
	u16 type;

	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
	sb = dir->i_sb;
	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);

	if (!str) {
		int len;
@@ -312,7 +312,7 @@ int hfsplus_rename_cat(u32 cnid,
		       struct inode *src_dir, struct qstr *src_name,
		       struct inode *dst_dir, struct qstr *dst_name)
{
	struct super_block *sb;
	struct super_block *sb = src_dir->i_sb;
	struct hfs_find_data src_fd, dst_fd;
	hfsplus_cat_entry entry;
	int entry_size, type;
@@ -320,8 +320,7 @@ int hfsplus_rename_cat(u32 cnid,

	dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name,
		dst_dir->i_ino, dst_name->name);
	sb = src_dir->i_sb;
	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd);
	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd);
	dst_fd = src_fd;

	/* find the old dir entry and read the data */
+21 −19
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,

	dentry->d_op = &hfsplus_dentry_operations;
	dentry->d_fsdata = NULL;
	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
again:
	err = hfs_brec_read(&fd, &entry, sizeof(entry));
@@ -68,9 +68,9 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
		cnid = be32_to_cpu(entry.file.id);
		if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
		    entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
		    (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
		    (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir).create_date ||
		     entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
		    HFSPLUS_SB(sb).hidden_dir) {
		    HFSPLUS_SB(sb)->hidden_dir) {
			struct qstr str;
			char name[32];

@@ -86,7 +86,8 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
				linkid = be32_to_cpu(entry.file.permissions.dev);
				str.len = sprintf(name, "iNode%d", linkid);
				str.name = name;
				hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
				hfsplus_cat_build_key(sb, fd.search_key,
					HFSPLUS_SB(sb)->hidden_dir->i_ino, &str);
				goto again;
			}
		} else if (!dentry->d_fsdata)
@@ -124,7 +125,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
	if (filp->f_pos >= inode->i_size)
		return 0;

	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
	hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
	err = hfs_brec_find(&fd);
	if (err)
@@ -180,8 +181,9 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
				err = -EIO;
				goto out;
			}
			if (HFSPLUS_SB(sb).hidden_dir &&
			    HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id))
			if (HFSPLUS_SB(sb)->hidden_dir &&
			    HFSPLUS_SB(sb)->hidden_dir->i_ino ==
					be32_to_cpu(entry.folder.id))
				goto next;
			if (filldir(dirent, strbuf, len, filp->f_pos,
				    be32_to_cpu(entry.folder.id), DT_DIR))
@@ -260,7 +262,7 @@ static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
			struct dentry *dst_dentry)
{
	struct super_block *sb = dst_dir->i_sb;
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb);
	struct inode *inode = src_dentry->d_inode;
	struct inode *src_dir = src_dentry->d_parent->d_inode;
	struct qstr str;
@@ -279,22 +281,22 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
			str.len = sprintf(name, "iNode%d", id);
			res = hfsplus_rename_cat(inode->i_ino,
						 src_dir, &src_dentry->d_name,
						 HFSPLUS_SB(sb).hidden_dir, &str);
						 sbi->hidden_dir, &str);
			if (!res)
				break;
			if (res != -EEXIST)
				return res;
		}
		HFSPLUS_I(inode).dev = id;
		cnid = HFSPLUS_SB(sb).next_cnid++;
		cnid = sbi->next_cnid++;
		src_dentry->d_fsdata = (void *)(unsigned long)cnid;
		res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode);
		if (res)
			/* panic? */
			return res;
		HFSPLUS_SB(sb).file_count++;
		sbi->file_count++;
	}
	cnid = HFSPLUS_SB(sb).next_cnid++;
	cnid = sbi->next_cnid++;
	res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode);
	if (res)
		return res;
@@ -304,15 +306,15 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
	atomic_inc(&inode->i_count);
	inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(inode);
	HFSPLUS_SB(sb).file_count++;
	sb->s_dirt = 1;
	sbi->file_count++;
	dst_dir->i_sb->s_dirt = 1;

	return 0;
}

static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
{
	struct super_block *sb = dir->i_sb;
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
	struct inode *inode = dentry->d_inode;
	struct qstr str;
	char name[32];
@@ -329,7 +331,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
		str.len = sprintf(name, "temp%lu", inode->i_ino);
		res = hfsplus_rename_cat(inode->i_ino,
					 dir, &dentry->d_name,
					 HFSPLUS_SB(sb).hidden_dir, &str);
					 sbi->hidden_dir, &str);
		if (!res)
			inode->i_flags |= S_DEAD;
		return res;
@@ -344,10 +346,10 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
		clear_nlink(inode);
	if (!inode->i_nlink) {
		if (inode->i_ino != cnid) {
			HFSPLUS_SB(sb).file_count--;
			sbi->file_count--;
			if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
				res = hfsplus_delete_cat(inode->i_ino,
							 HFSPLUS_SB(sb).hidden_dir,
							 sbi->hidden_dir,
							 NULL);
				if (!res)
					hfsplus_delete_inode(inode);
@@ -356,7 +358,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
		} else
			hfsplus_delete_inode(inode);
	} else
		HFSPLUS_SB(sb).file_count--;
		sbi->file_count--;
	inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(inode);

+20 −17
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ void hfsplus_ext_write_extent(struct inode *inode)
	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) {
		struct hfs_find_data fd;

		hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
		hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
		__hfsplus_ext_write_extent(inode, &fd);
		hfs_find_exit(&fd);
	}
@@ -162,7 +162,7 @@ static int hfsplus_ext_read_extent(struct inode *inode, u32 block)
	    block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks)
		return 0;

	hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
	hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
	res = __hfsplus_ext_cache_extent(&fd, inode, block);
	hfs_find_exit(&fd);
	return res;
@@ -172,16 +172,15 @@ static int hfsplus_ext_read_extent(struct inode *inode, u32 block)
int hfsplus_get_block(struct inode *inode, sector_t iblock,
		      struct buffer_head *bh_result, int create)
{
	struct super_block *sb;
	struct super_block *sb = inode->i_sb;
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
	int res = -EIO;
	u32 ablock, dblock, mask;
	int shift;

	sb = inode->i_sb;

	/* Convert inode block to disk allocation block */
	shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits;
	ablock = iblock >> HFSPLUS_SB(sb).fs_shift;
	shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits;
	ablock = iblock >> sbi->fs_shift;

	if (iblock >= HFSPLUS_I(inode).fs_blocks) {
		if (iblock > HFSPLUS_I(inode).fs_blocks || !create)
@@ -215,8 +214,8 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,

done:
	dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock);
	mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1;
	map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask));
	mask = (1 << sbi->fs_shift) - 1;
	map_bh(bh_result, sb, (dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask));
	if (create) {
		set_buffer_new(bh_result);
		HFSPLUS_I(inode).phys_size += sb->s_blocksize;
@@ -327,7 +326,7 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw
	if (total_blocks == blocks)
		return 0;

	hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
	hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
	do {
		res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid,
						total_blocks, type);
@@ -348,13 +347,16 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw
int hfsplus_file_extend(struct inode *inode)
{
	struct super_block *sb = inode->i_sb;
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
	u32 start, len, goal;
	int res;

	if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
	if (sbi->alloc_file->i_size * 8 <
	    sbi->total_blocks - sbi->free_blocks + 8) {
		// extend alloc file
		printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
			HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
		printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n",
				sbi->alloc_file->i_size * 8,
				sbi->total_blocks, sbi->free_blocks);
		return -ENOSPC;
	}

@@ -369,8 +371,8 @@ int hfsplus_file_extend(struct inode *inode)
	}

	len = HFSPLUS_I(inode).clump_blocks;
	start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len);
	if (start >= HFSPLUS_SB(sb).total_blocks) {
	start = hfsplus_block_allocate(sb, sbi->total_blocks, goal, &len);
	if (start >= sbi->total_blocks) {
		start = hfsplus_block_allocate(sb, goal, 0, &len);
		if (start >= goal) {
			res = -ENOSPC;
@@ -463,13 +465,14 @@ void hfsplus_file_truncate(struct inode *inode)
	} else if (inode->i_size == HFSPLUS_I(inode).phys_size)
		return;

	blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift;
	blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >>
			HFSPLUS_SB(sb)->alloc_blksz_shift;
	alloc_cnt = HFSPLUS_I(inode).alloc_blocks;
	if (blk_cnt == alloc_cnt)
		goto out;

	mutex_lock(&HFSPLUS_I(inode).extents_lock);
	hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
	hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
	while (1) {
		if (alloc_cnt == HFSPLUS_I(inode).first_blocks) {
			hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents,
Loading