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

Commit 9f1ad094 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus: (29 commits)
  hfsplus: fix getxattr return value
  hfsplus: remove the unused hfsplus_kmap/hfsplus_kunmap helpers
  hfsplus: create correct initial catalog entries for device files
  hfsplus: remove superflous rootflags field in hfsplus_inode_info
  hfsplus: fix link corruption
  hfsplus: validate btree flags
  hfsplus: handle more on-disk corruptions without oopsing
  hfsplus: hfs_bnode_find() can fail, resulting in hfs_bnode_split() breakage
  hfsplus: fix oops on mount with corrupted btree extent records
  hfsplus: fix rename over directories
  hfsplus: convert tree_lock to mutex
  hfsplus: add missing extent locking in hfsplus_write_inode
  hfsplus: protect readdir against removals from open_dir_list
  hfsplus: use atomic bitops for the superblock flags
  hfsplus: add per-superblock lock for volume header updates
  hfsplus: remove the rsrc_inodes list
  hfsplus: do not cache and write next_alloc
  hfsplus: fix error handling in hfsplus_symlink
  hfsplus: merge mknod/mkdir/creat
  hfsplus: clean up hfsplus_write_inode
  ...
parents f6f94e2a 46bf36ec
Loading
Loading
Loading
Loading
+15 −2
Original line number Original line Diff line number Diff line
@@ -23,7 +23,7 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
	fd->search_key = ptr;
	fd->search_key = ptr;
	fd->key = ptr + tree->max_key_len + 2;
	fd->key = ptr + tree->max_key_len + 2;
	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
	down(&tree->tree_lock);
	mutex_lock(&tree->tree_lock);
	return 0;
	return 0;
}
}


@@ -32,7 +32,7 @@ void hfs_find_exit(struct hfs_find_data *fd)
	hfs_bnode_put(fd->bnode);
	hfs_bnode_put(fd->bnode);
	kfree(fd->search_key);
	kfree(fd->search_key);
	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
	up(&fd->tree->tree_lock);
	mutex_unlock(&fd->tree->tree_lock);
	fd->tree = NULL;
	fd->tree = NULL;
}
}


@@ -52,6 +52,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
		rec = (e + b) / 2;
		rec = (e + b) / 2;
		len = hfs_brec_lenoff(bnode, rec, &off);
		len = hfs_brec_lenoff(bnode, rec, &off);
		keylen = hfs_brec_keylen(bnode, rec);
		keylen = hfs_brec_keylen(bnode, rec);
		if (keylen == 0) {
			res = -EINVAL;
			goto fail;
		}
		hfs_bnode_read(bnode, fd->key, off, keylen);
		hfs_bnode_read(bnode, fd->key, off, keylen);
		cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
		cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
		if (!cmpval) {
		if (!cmpval) {
@@ -67,6 +71,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
	if (rec != e && e >= 0) {
	if (rec != e && e >= 0) {
		len = hfs_brec_lenoff(bnode, e, &off);
		len = hfs_brec_lenoff(bnode, e, &off);
		keylen = hfs_brec_keylen(bnode, e);
		keylen = hfs_brec_keylen(bnode, e);
		if (keylen == 0) {
			res = -EINVAL;
			goto fail;
		}
		hfs_bnode_read(bnode, fd->key, off, keylen);
		hfs_bnode_read(bnode, fd->key, off, keylen);
	}
	}
done:
done:
@@ -75,6 +83,7 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
	fd->keylength = keylen;
	fd->keylength = keylen;
	fd->entryoffset = off + keylen;
	fd->entryoffset = off + keylen;
	fd->entrylength = len - keylen;
	fd->entrylength = len - keylen;
fail:
	return res;
	return res;
}
}


@@ -198,6 +207,10 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt)


	len = hfs_brec_lenoff(bnode, fd->record, &off);
	len = hfs_brec_lenoff(bnode, fd->record, &off);
	keylen = hfs_brec_keylen(bnode, fd->record);
	keylen = hfs_brec_keylen(bnode, fd->record);
	if (keylen == 0) {
		res = -EINVAL;
		goto out;
	}
	fd->keyoffset = off;
	fd->keyoffset = off;
	fd->keylength = keylen;
	fd->keylength = keylen;
	fd->entryoffset = off + keylen;
	fd->entryoffset = off + keylen;
+11 −9
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@


int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
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 page *page;
	struct address_space *mapping;
	struct address_space *mapping;
	__be32 *pptr, *curr, *end;
	__be32 *pptr, *curr, *end;
@@ -29,8 +30,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
		return size;
		return size;


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


int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
{
{
	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
	struct page *page;
	struct page *page;
	struct address_space *mapping;
	struct address_space *mapping;
	__be32 *pptr, *curr, *end;
	__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);
	dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
	/* are all of the bits in range? */
	/* are all of the bits in range? */
	if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
	if ((offset + count) > sbi->total_blocks)
		return -2;
		return -2;


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


	return 0;
	return 0;
}
}
+22 −7
Original line number Original line Diff line number Diff line
@@ -42,10 +42,13 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
		recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
		recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
		if (!recoff)
		if (!recoff)
			return 0;
			return 0;
		if (node->tree->attributes & HFS_TREE_BIGKEYS)

		retval = hfs_bnode_read_u16(node, recoff) + 2;
		retval = hfs_bnode_read_u16(node, recoff) + 2;
		else
		if (retval > node->tree->max_key_len + 2) {
			retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1;
			printk(KERN_ERR "hfs: keylen %d too large\n",
				retval);
			retval = 0;
		}
	}
	}
	return retval;
	return retval;
}
}
@@ -216,7 +219,7 @@ int hfs_brec_remove(struct hfs_find_data *fd)
static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
{
{
	struct hfs_btree *tree;
	struct hfs_btree *tree;
	struct hfs_bnode *node, *new_node;
	struct hfs_bnode *node, *new_node, *next_node;
	struct hfs_bnode_desc node_desc;
	struct hfs_bnode_desc node_desc;
	int num_recs, new_rec_off, new_off, old_rec_off;
	int num_recs, new_rec_off, new_off, old_rec_off;
	int data_start, data_end, size;
	int data_start, data_end, size;
@@ -235,6 +238,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
	new_node->type = node->type;
	new_node->type = node->type;
	new_node->height = node->height;
	new_node->height = node->height;


	if (node->next)
		next_node = hfs_bnode_find(tree, node->next);
	else
		next_node = NULL;

	if (IS_ERR(next_node)) {
		hfs_bnode_put(node);
		hfs_bnode_put(new_node);
		return next_node;
	}

	size = tree->node_size / 2 - node->num_recs * 2 - 14;
	size = tree->node_size / 2 - node->num_recs * 2 - 14;
	old_rec_off = tree->node_size - 4;
	old_rec_off = tree->node_size - 4;
	num_recs = 1;
	num_recs = 1;
@@ -248,6 +262,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
		/* panic? */
		/* panic? */
		hfs_bnode_put(node);
		hfs_bnode_put(node);
		hfs_bnode_put(new_node);
		hfs_bnode_put(new_node);
		if (next_node)
			hfs_bnode_put(next_node);
		return ERR_PTR(-ENOSPC);
		return ERR_PTR(-ENOSPC);
	}
	}


@@ -302,8 +318,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
	hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
	hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));


	/* update next bnode header */
	/* update next bnode header */
	if (new_node->next) {
	if (next_node) {
		struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
		next_node->prev = new_node->this;
		next_node->prev = new_node->this;
		hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
		hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
		node_desc.prev = cpu_to_be32(next_node->prev);
		node_desc.prev = cpu_to_be32(next_node->prev);
+52 −15
Original line number Original line Diff line number Diff line
@@ -30,7 +30,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
	if (!tree)
	if (!tree)
		return NULL;
		return NULL;


	init_MUTEX(&tree->tree_lock);
	mutex_init(&tree->tree_lock);
	spin_lock_init(&tree->hash_lock);
	spin_lock_init(&tree->hash_lock);
	tree->sb = sb;
	tree->sb = sb;
	tree->cnid = id;
	tree->cnid = id;
@@ -39,10 +39,16 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
		goto free_tree;
		goto free_tree;
	tree->inode = inode;
	tree->inode = inode;


	if (!HFSPLUS_I(tree->inode)->first_blocks) {
		printk(KERN_ERR
		       "hfs: invalid btree extent records (0 size).\n");
		goto free_inode;
	}

	mapping = tree->inode->i_mapping;
	mapping = tree->inode->i_mapping;
	page = read_mapping_page(mapping, 0, NULL);
	page = read_mapping_page(mapping, 0, NULL);
	if (IS_ERR(page))
	if (IS_ERR(page))
		goto free_tree;
		goto free_inode;


	/* Load the header */
	/* Load the header */
	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
@@ -57,27 +63,56 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
	tree->max_key_len = be16_to_cpu(head->max_key_len);
	tree->max_key_len = be16_to_cpu(head->max_key_len);
	tree->depth = be16_to_cpu(head->depth);
	tree->depth = be16_to_cpu(head->depth);


	/* Set the correct compare function */
	/* Verify the tree and set the correct compare function */
	if (id == HFSPLUS_EXT_CNID) {
	switch (id) {
	case HFSPLUS_EXT_CNID:
		if (tree->max_key_len != HFSPLUS_EXT_KEYLEN - sizeof(u16)) {
			printk(KERN_ERR "hfs: invalid extent max_key_len %d\n",
				tree->max_key_len);
			goto fail_page;
		}
		if (tree->attributes & HFS_TREE_VARIDXKEYS) {
			printk(KERN_ERR "hfs: invalid extent btree flag\n");
			goto fail_page;
		}

		tree->keycmp = hfsplus_ext_cmp_key;
		tree->keycmp = hfsplus_ext_cmp_key;
	} else if (id == HFSPLUS_CAT_CNID) {
		break;
		if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
	case HFSPLUS_CAT_CNID:
		if (tree->max_key_len != HFSPLUS_CAT_KEYLEN - sizeof(u16)) {
			printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n",
				tree->max_key_len);
			goto fail_page;
		}
		if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) {
			printk(KERN_ERR "hfs: invalid catalog btree flag\n");
			goto fail_page;
		}

		if (test_bit(HFSPLUS_SB_HFSX, &HFSPLUS_SB(sb)->flags) &&
		    (head->key_type == HFSPLUS_KEY_BINARY))
		    (head->key_type == HFSPLUS_KEY_BINARY))
			tree->keycmp = hfsplus_cat_bin_cmp_key;
			tree->keycmp = hfsplus_cat_bin_cmp_key;
		else {
		else {
			tree->keycmp = hfsplus_cat_case_cmp_key;
			tree->keycmp = hfsplus_cat_case_cmp_key;
			HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD;
			set_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
		}
		}
	} else {
		break;
	default:
		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
		goto fail_page;
		goto fail_page;
	}
	}


	if (!(tree->attributes & HFS_TREE_BIGKEYS)) {
		printk(KERN_ERR "hfs: invalid btree flag\n");
		goto fail_page;
	}

	size = tree->node_size;
	size = tree->node_size;
	if (!is_power_of_2(size))
	if (!is_power_of_2(size))
		goto fail_page;
		goto fail_page;
	if (!tree->node_count)
	if (!tree->node_count)
		goto fail_page;
		goto fail_page;

	tree->node_size_shift = ffs(size) - 1;
	tree->node_size_shift = ffs(size) - 1;


	tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
@@ -87,10 +122,11 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
	return tree;
	return tree;


 fail_page:
 fail_page:
	tree->inode->i_mapping->a_ops = &hfsplus_aops;
	page_cache_release(page);
	page_cache_release(page);
 free_tree:
 free_inode:
	tree->inode->i_mapping->a_ops = &hfsplus_aops;
	iput(tree->inode);
	iput(tree->inode);
 free_tree:
	kfree(tree);
	kfree(tree);
	return NULL;
	return NULL;
}
}
@@ -192,17 +228,18 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)


	while (!tree->free_nodes) {
	while (!tree->free_nodes) {
		struct inode *inode = tree->inode;
		struct inode *inode = tree->inode;
		struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
		u32 count;
		u32 count;
		int res;
		int res;


		res = hfsplus_file_extend(inode);
		res = hfsplus_file_extend(inode);
		if (res)
		if (res)
			return ERR_PTR(res);
			return ERR_PTR(res);
		HFSPLUS_I(inode).phys_size = inode->i_size =
		hip->phys_size = inode->i_size =
				(loff_t)HFSPLUS_I(inode).alloc_blocks <<
			(loff_t)hip->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 <<
		hip->fs_blocks =
					     HFSPLUS_SB(tree->sb).fs_shift;
			hip->alloc_blocks << HFSPLUS_SB(tree->sb)->fs_shift;
		inode_set_bytes(inode, inode->i_size);
		inode_set_bytes(inode, inode->i_size);
		count = inode->i_size >> tree->node_size_shift;
		count = inode->i_size >> tree->node_size_shift;
		tree->free_nodes = count - tree->node_count;
		tree->free_nodes = count - tree->node_count;
+28 −22
Original line number Original line Diff line number Diff line
@@ -67,7 +67,7 @@ static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent,
	key->key_len = cpu_to_be16(6 + ustrlen);
	key->key_len = cpu_to_be16(6 + ustrlen);
}
}


static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms)
{
{
	if (inode->i_flags & S_IMMUTABLE)
	if (inode->i_flags & S_IMMUTABLE)
		perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
		perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
@@ -77,15 +77,24 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
		perms->rootflags |= HFSPLUS_FLG_APPEND;
		perms->rootflags |= HFSPLUS_FLG_APPEND;
	else
	else
		perms->rootflags &= ~HFSPLUS_FLG_APPEND;
		perms->rootflags &= ~HFSPLUS_FLG_APPEND;
	HFSPLUS_I(inode).rootflags = perms->rootflags;

	HFSPLUS_I(inode).userflags = perms->userflags;
	perms->userflags = HFSPLUS_I(inode)->userflags;
	perms->mode = cpu_to_be16(inode->i_mode);
	perms->mode = cpu_to_be16(inode->i_mode);
	perms->owner = cpu_to_be32(inode->i_uid);
	perms->owner = cpu_to_be32(inode->i_uid);
	perms->group = cpu_to_be32(inode->i_gid);
	perms->group = cpu_to_be32(inode->i_gid);

	if (S_ISREG(inode->i_mode))
		perms->dev = cpu_to_be32(inode->i_nlink);
	else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode))
		perms->dev = cpu_to_be32(inode->i_rdev);
	else
		perms->dev = 0;
}
}


static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode)
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)) {
	if (S_ISDIR(inode->i_mode)) {
		struct hfsplus_cat_folder *folder;
		struct hfsplus_cat_folder *folder;


@@ -93,13 +102,13 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
		memset(folder, 0, sizeof(*folder));
		memset(folder, 0, sizeof(*folder));
		folder->type = cpu_to_be16(HFSPLUS_FOLDER);
		folder->type = cpu_to_be16(HFSPLUS_FOLDER);
		folder->id = cpu_to_be32(inode->i_ino);
		folder->id = cpu_to_be32(inode->i_ino);
		HFSPLUS_I(inode).create_date =
		HFSPLUS_I(inode)->create_date =
			folder->create_date =
			folder->create_date =
			folder->content_mod_date =
			folder->content_mod_date =
			folder->attribute_mod_date =
			folder->attribute_mod_date =
			folder->access_date = hfsp_now2mt();
			folder->access_date = hfsp_now2mt();
		hfsplus_set_perms(inode, &folder->permissions);
		hfsplus_cat_set_perms(inode, &folder->permissions);
		if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
		if (inode == sbi->hidden_dir)
			/* invisible and namelocked */
			/* invisible and namelocked */
			folder->user_info.frFlags = cpu_to_be16(0x5000);
			folder->user_info.frFlags = cpu_to_be16(0x5000);
		return sizeof(*folder);
		return sizeof(*folder);
@@ -111,19 +120,19 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
		file->type = cpu_to_be16(HFSPLUS_FILE);
		file->type = cpu_to_be16(HFSPLUS_FILE);
		file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
		file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
		file->id = cpu_to_be32(cnid);
		file->id = cpu_to_be32(cnid);
		HFSPLUS_I(inode).create_date =
		HFSPLUS_I(inode)->create_date =
			file->create_date =
			file->create_date =
			file->content_mod_date =
			file->content_mod_date =
			file->attribute_mod_date =
			file->attribute_mod_date =
			file->access_date = hfsp_now2mt();
			file->access_date = hfsp_now2mt();
		if (cnid == inode->i_ino) {
		if (cnid == inode->i_ino) {
			hfsplus_set_perms(inode, &file->permissions);
			hfsplus_cat_set_perms(inode, &file->permissions);
			if (S_ISLNK(inode->i_mode)) {
			if (S_ISLNK(inode->i_mode)) {
				file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
				file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
				file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
				file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
			} else {
			} else {
				file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
				file->user_info.fdType = cpu_to_be32(sbi->type);
				file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
				file->user_info.fdCreator = cpu_to_be32(sbi->creator);
			}
			}
			if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
			if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
				file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
				file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
@@ -131,8 +140,8 @@ 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.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
			file->user_info.fdFlags = cpu_to_be16(0x100);
			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);
			file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode)->linkid);
		}
		}
		return sizeof(*file);
		return sizeof(*file);
	}
	}
@@ -180,15 +189,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)
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 hfs_find_data fd;
	struct super_block *sb;
	hfsplus_cat_entry entry;
	hfsplus_cat_entry entry;
	int entry_size;
	int entry_size;
	int err;
	int err;


	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink);
	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);
	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
	entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
	entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
@@ -234,7 +242,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)
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 hfs_find_data fd;
	struct hfsplus_fork_raw fork;
	struct hfsplus_fork_raw fork;
	struct list_head *pos;
	struct list_head *pos;
@@ -242,8 +250,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
	u16 type;
	u16 type;


	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
	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) {
	if (!str) {
		int len;
		int len;
@@ -279,7 +286,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
	}
	}


	list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) {
	list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) {
		struct hfsplus_readdir_data *rd =
		struct hfsplus_readdir_data *rd =
			list_entry(pos, struct hfsplus_readdir_data, list);
			list_entry(pos, struct hfsplus_readdir_data, list);
		if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
		if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
@@ -312,7 +319,7 @@ int hfsplus_rename_cat(u32 cnid,
		       struct inode *src_dir, struct qstr *src_name,
		       struct inode *src_dir, struct qstr *src_name,
		       struct inode *dst_dir, struct qstr *dst_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;
	struct hfs_find_data src_fd, dst_fd;
	hfsplus_cat_entry entry;
	hfsplus_cat_entry entry;
	int entry_size, type;
	int entry_size, type;
@@ -320,8 +327,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,
	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);
		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;
	dst_fd = src_fd;


	/* find the old dir entry and read the data */
	/* find the old dir entry and read the data */
Loading