lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 13 Apr 2012 10:59:20 +0800
From:	Tao Ma <tm@....ma>
To:	Andreas Dilger <adilger@...ger.ca>
CC:	linux-ext4@...r.kernel.org, linux-fsdevel@...r.kernel.org
Subject: Re: [PATCH V4 03/22] ext4: Add the basic function for inline data
 support.

Hi Andreas,
	thanks for the detailed review and sorry for the delay. I will
integrate all the advices you gave to my next post.

Thanks
Tao
On 04/07/2012 08:21 AM, Andreas Dilger wrote:
> On 2012-02-20, at 12:01 AM, Tao Ma wrote:
> 
>> From: Tao Ma <boyu.mt@...bao.com>
>>
>> Implement inline data with xattr. This idea is inspired by Andreas.
>> So now we use "system.data" to store xattr.
>> For inode_size = 256, currently we uses all the space between i_extra_isize
>> and inode_size. For inode_size > 256, we use half of that space.
>>
>> Signed-off-by: Tao Ma <boyu.mt@...bao.com>
>> ---
>> fs/ext4/Makefile |    2 +-
>> fs/ext4/ext4.h   |    7 +
>> fs/ext4/inline.c |  456 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> fs/ext4/inode.c  |    5 +-
>> fs/ext4/xattr.c  |   24 ---
>> fs/ext4/xattr.h  |   60 +++++++-
>> 6 files changed, 525 insertions(+), 29 deletions(-)
>> create mode 100644 fs/ext4/inline.c
>>
>> diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
>> index 56fd8f8..e88b7a6 100644
>> --- a/fs/ext4/Makefile
>> +++ b/fs/ext4/Makefile
>> @@ -9,6 +9,6 @@ ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
>> 		ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
>> 		mmp.o indirect.o
>>
>> -ext4-$(CONFIG_EXT4_FS_XATTR)		+= xattr.o xattr_user.o xattr_trusted.o
>> +ext4-$(CONFIG_EXT4_FS_XATTR)		+= xattr.o xattr_user.o xattr_trusted.o inline.o
>> ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
>> ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
>> index 513004f..18254c0 100644
>> --- a/fs/ext4/ext4.h
>> +++ b/fs/ext4/ext4.h
>> @@ -371,6 +371,7 @@ struct flex_groups {
>> #define EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
>> #define EXT4_EA_INODE_FL	        0x00200000 /* Inode used for large EA */
>> #define EXT4_EOFBLOCKS_FL		0x00400000 /* Blocks allocated beyond EOF */
>> +#define EXT4_INLINE_DATA_FL		0x00800000 /* Inode has inline data. */
> 
> This patch defines EXT4_INLINE_DATA_FL here, but it isn't used anywhere in
> the code.  This would make the code a lot more efficient if this flag were
> checked at the start of ext4_find_inline_data() and skip searching all of
> the xattrs if no INLINE_DATA_FL is set.  That avoids overhead for reading
> every regular inode that does not have inline data.
> 
>> #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
>>
>> #define EXT4_FL_USER_VISIBLE		0x004BDFFF /* User visible flags */
>> @@ -427,6 +428,7 @@ enum {
>> 	EXT4_INODE_EXTENTS	= 19,	/* Inode uses extents */
>> 	EXT4_INODE_EA_INODE	= 21,	/* Inode used for large EA */
>> 	EXT4_INODE_EOFBLOCKS	= 22,	/* Blocks allocated beyond EOF */
>> +	EXT4_INODE_INLINE_DATA	= 23,	/* Data in inode. */
>> 	EXT4_INODE_RESERVED	= 31,	/* reserved for ext4 lib */
>> };
>>
>> @@ -878,6 +880,10 @@ struct ext4_inode_info {
>> 	/* on-disk additional length */
>> 	__u16 i_extra_isize;
>>
>> +	/* Indicate the inline data space. */
>> +	u16 i_inline_off;
>> +	u16 i_inline_size;
>> +
>> #ifdef CONFIG_QUOTA
>> 	/* quota space reservation, managed internally by quota code */
>> 	qsize_t i_reserved_quota;
>> @@ -1307,6 +1313,7 @@ enum {
>> 	EXT4_STATE_DIO_UNWRITTEN,	/* need convert on dio done*/
>> 	EXT4_STATE_NEWENTRY,		/* File just added to dir */
>> 	EXT4_STATE_DELALLOC_RESERVED,	/* blks already reserved for delalloc */
>> +	EXT4_STATE_MAY_INLINE_DATA,	/* may have in-inode data */
>> };
>>
>> #define EXT4_INODE_BIT_FNS(name, field, offset)				\
>> diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
>> new file mode 100644
>> index 0000000..77cedd2
>> --- /dev/null
>> +++ b/fs/ext4/inline.c
>> @@ -0,0 +1,456 @@
>> +/*
>> + * Copyright (c) 2011 Taobao.
>> + * Written by Tao Ma <boyu.mt@...bao.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of version 2.1 of the GNU Lesser General Public License
>> + * as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +#include "ext4_jbd2.h"
>> +#include "ext4.h"
>> +#include "xattr.h"
>> +
>> +#define EXT4_XATTR_SYSTEM_DATA_NAME	"data"
> 
> If this constant name was shorter it would be easier to use, like:
> 
> #define EXT4_XATTR_SYSTEM_DATA "data"
> 
>> +#define EXT4_MIN_INLINE_DATA_SIZE	((sizeof(__le32) * EXT4_N_BLOCKS))
>> +
>> +int ext4_get_inline_size(struct inode *inode)
>> +{
>> +	if (EXT4_I(inode)->i_inline_off)
>> +		return EXT4_I(inode)->i_inline_size;
>> +
>> +	return 0;
>> +}
>> +
>> +static int get_max_inline_xattr_value_size(struct inode *inode,
>> +					   struct ext4_iloc *iloc)
>> +{
>> +	struct ext4_xattr_ibody_header *header;
>> +	struct ext4_xattr_entry *entry;
>> +	struct ext4_inode *raw_inode;
>> +	int free, min_offs;
>> +
>> +	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
>> +		return EXT4_XATTR_SIZE(EXT4_SB(inode->i_sb)->s_inode_size -
>> +			EXT4_GOOD_OLD_INODE_SIZE -
>> +			EXT4_I(inode)->i_extra_isize -
>> +			sizeof(struct ext4_xattr_ibody_header) -
>> +			EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA_NAME)) -
>> +			EXT4_XATTR_ROUND - sizeof(__u32));
> 
> Most of this calculation is common with min_offs below.  It would be nice
> to compute it once instead of twice, since this calculation here is
> pretty complex to read and would be simplified with an intermediate value.
> 
> 	min_offs = EXT4_SB(inode->i_sb)->s_inode_size -
> 			EXT4_GOOD_OLD_INODE_SIZE -
> 			EXT4_I(inode)->i_extra_isize -
> 			sizeof(struct ext4_xattr_ibody_header) -
> 			EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA));
> 
> 	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
> 		return EXT4_XATTR_SIZE(min_offs -
> 				       EXT4_XATTR_ROUND - sizeof(__u32));
> 
> It isn't obvious what the sizeof(__u32) represents here.  The EXT4_XATTR_ROUND
> is to compensate for the "round_up" factor used in EXT4_XATTR_SIZE(), but it would be useful to document this.
> 
>> +	down_read(&EXT4_I(inode)->xattr_sem);
>> +	raw_inode = ext4_raw_inode(iloc);
>> +	header = IHDR(inode, raw_inode);
>> +	entry = IFIRST(header);
>> +	min_offs = EXT4_SB(inode->i_sb)->s_inode_size -
>> +			EXT4_GOOD_OLD_INODE_SIZE -
>> +			EXT4_I(inode)->i_extra_isize -
>> +			sizeof(struct ext4_xattr_ibody_header);
> 
>> +
>> +	/* Compute min_offs. */
>> +	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
>> +		if (!entry->e_value_block && entry->e_value_size) {
>> +			size_t offs = le16_to_cpu(entry->e_value_offs);
>> +			if (offs < min_offs)
>> +				min_offs = offs;
>> +		}
>> +	}
>> +	free = min_offs -
>> +		((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);
>> +
>> +	if (EXT4_I(inode)->i_inline_off) {
>> +		entry = (struct ext4_xattr_entry *)
>> +			((void *)raw_inode + EXT4_I(inode)->i_inline_off);
>> +
>> +		free += le32_to_cpu(entry->e_value_size);
>> +		goto out;
>> +	}
>> +
>> +	free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA_NAME));
>> +
>> +	if (free > EXT4_XATTR_ROUND)
>> +		free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND);
>> +	else
>> +		free = 0;
>> +
>> +out:
>> +	up_read(&EXT4_I(inode)->xattr_sem);
>> +	return free;
>> +}
>> +
>> +/*
>> + * Get the maximum size we now can store in an inode.
>> + * If we can't find the space for a xattr entry, don't use the space
>> + * of the extents since we have no space to indicate the inline data.
>> + */
>> +int ext4_get_max_inline_size(struct inode *inode)
>> +{
>> +	int error, max_inline_size;
>> +	struct ext4_iloc iloc;
>> +
>> +	if (EXT4_I(inode)->i_extra_isize == 0)
>> +		return 0;
>> +
>> +	error = ext4_get_inode_loc(inode, &iloc);
>> +	if (error) {
>> +		ext4_error_inode(inode, __func__, __LINE__, 0,
>> +				 "can't get inode location %lu",
>> +				 inode->i_ino);
>> +		return 0;
>> +	}
>> +
>> +	max_inline_size = get_max_inline_xattr_value_size(inode, &iloc);
>> +
>> +	brelse(iloc.bh);
>> +
>> +	if (!max_inline_size)
>> +		return 0;
>> +
>> +	return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE;
>> +}
>> +
>> +int ext4_has_inline_data(struct inode *inode)
>> +{
>> +	return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
>> +	       EXT4_I(inode)->i_inline_off;
>> +}
>> +
>> +int ext4_find_inline_data(struct inode *inode)
>> +{
>> +	struct ext4_xattr_ibody_find is = {
>> +		.s = { .not_found = -ENODATA, },
>> +	};
>> +	struct ext4_xattr_info i = {
>> +		.name_index = EXT4_XATTR_INDEX_SYSTEM_DATA,
>> +		.name = EXT4_XATTR_SYSTEM_DATA_NAME,
>> +	};
>> +	int error;
>> +
>> +	if (EXT4_I(inode)->i_extra_isize == 0)
>> +		return 0;
>> +
>> +	error = ext4_get_inode_loc(inode, &is.iloc);
>> +	if (error)
>> +		return error;
>> +
>> +	error = ext4_xattr_ibody_find(inode, &i, &is);
>> +	if (error)
>> +		goto out;
>> +
>> +	if (!is.s.not_found) {
>> +		EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
>> +					(void *)ext4_raw_inode(&is.iloc));
>> +		EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
>> +				le32_to_cpu(is.s.here->e_value_size);
>> +		ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
>> +	}
>> +out:
>> +	brelse(is.iloc.bh);
>> +	return error;
>> +}
>> +
>> +static int ext4_read_inline_data(struct inode *inode, void *buffer, unsigned int len,
>> +				 struct ext4_iloc *iloc)
>> +{
>> +	struct ext4_xattr_entry *entry;
>> +	struct ext4_xattr_ibody_header *header;
>> +	int cp_len = 0;
>> +	struct ext4_inode *raw_inode;
>> +
>> +	if (!len)
>> +		return 0;
>> +
>> +	BUG_ON(len > EXT4_I(inode)->i_inline_size);
>> +
>> +	cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ?
>> +			len : EXT4_MIN_INLINE_DATA_SIZE;
>> +
>> +	raw_inode = ext4_raw_inode(iloc);
>> +	memcpy(buffer, (void *)(raw_inode->i_block), cp_len);
>> +
>> +	len -= cp_len;
>> +	buffer += cp_len;
>> +
>> +	if (!len)
>> +		goto out;
>> +
>> +	header = IHDR(inode, raw_inode);
>> +	entry = (struct ext4_xattr_entry *)((void *)raw_inode +
>> +					    EXT4_I(inode)->i_inline_off);
>> +	len = min_t(unsigned int, len,
>> +		    (unsigned int)le32_to_cpu(entry->e_value_size));
>> +
>> +	memcpy(buffer,
>> +	       (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len);
>> +	cp_len += len;
>> +
>> +out:
>> +	return cp_len;
>> +}
>> +
>> +/*
>> + * write the buffer to the inline inode.
>> + * If 'create' is set, we don't need to do the extra copy in the xattr
>> + * value since it is already handled by ext4_xattr_ibody_set. That saves
>> + * us one memcpy.
>> + */
>> +void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
>> +			    void *buffer, loff_t pos, unsigned int len)
>> +{
>> +	struct ext4_xattr_entry *entry;
>> +	struct ext4_xattr_ibody_header *header;
>> +	struct ext4_inode *raw_inode;
>> +	int cp_len = 0;
>> +
>> +	BUG_ON(!EXT4_I(inode)->i_inline_off);
>> +	BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);
>> +
>> +	raw_inode = ext4_raw_inode(iloc);
>> +	buffer += pos;
>> +
>> +	if (pos < EXT4_MIN_INLINE_DATA_SIZE) {
>> +		cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ?
>> +			 EXT4_MIN_INLINE_DATA_SIZE - pos : len;
>> +		memcpy((void *)raw_inode->i_block + pos, buffer, cp_len);
>> +
>> +		len -= cp_len;
>> +		buffer += cp_len;
>> +		pos += cp_len;
>> +	}
>> +
>> +	if (!len)
>> +		return;
>> +
>> +	pos -= EXT4_MIN_INLINE_DATA_SIZE;
>> +	header = IHDR(inode, raw_inode);
>> +	entry = (struct ext4_xattr_entry *)((void *)raw_inode +
>> +					    EXT4_I(inode)->i_inline_off);
>> +
>> +	memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos,
>> +	       buffer, len);
>> +}
>> +
>> +static int ext4_create_inline_data(handle_t *handle,
>> +				   struct inode *inode, unsigned len)
>> +{
>> +	int error;
>> +	void *value = NULL;
>> +	struct ext4_xattr_ibody_find is = {
>> +		.s = { .not_found = -ENODATA, },
>> +	};
>> +	struct ext4_xattr_info i = {
>> +		.name_index = EXT4_XATTR_INDEX_SYSTEM_DATA,
>> +		.name = EXT4_XATTR_SYSTEM_DATA_NAME,
>> +	};
>> +
>> +	error = ext4_get_inode_loc(inode, &is.iloc);
>> +	if (error)
>> +		return error;
>> +
>> +	error = ext4_journal_get_write_access(handle, is.iloc.bh);
>> +	if (error)
>> +		goto out;
>> +
>> +	if (len > EXT4_MIN_INLINE_DATA_SIZE) {
>> +		value = (void *)empty_zero_page;
>> +		len -= EXT4_MIN_INLINE_DATA_SIZE;
>> +	} else {
>> +		value = "";
>> +		len = 0;
>> +	}
>> +
>> +	/* Insert the the xttr entry. */
>> +	i.value = value;
>> +	i.value_len = len;
>> +
>> +	error = ext4_xattr_ibody_find(inode, &i, &is);
>> +	if (error)
>> +		goto out;
>> +
>> +	BUG_ON(!is.s.not_found);
>> +
>> +	error = ext4_xattr_ibody_set(handle, inode, &i, &is);
>> +	if (error) {
>> +		if (error == -ENOSPC)
>> +			ext4_clear_inode_state(inode,
>> +					       EXT4_STATE_MAY_INLINE_DATA);
>> +		goto out;
>> +	}
>> +
>> +	memset((void *)ext4_raw_inode(&is.iloc)->i_block,
>> +		0, EXT4_MIN_INLINE_DATA_SIZE);
>> +
>> +	EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
>> +				      (void *)ext4_raw_inode(&is.iloc));
>> +	EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE;
>> +	ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
>> +	ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA);
>> +	get_bh(is.iloc.bh);
>> +	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
>> +
>> +out:
>> +	brelse(is.iloc.bh);
>> +	return error;
>> +}
>> +
>> +static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
>> +				   unsigned int len)
>> +{
>> +	int error;
>> +	void *value = NULL;
>> +	struct ext4_xattr_ibody_find is = {
>> +		.s = { .not_found = -ENODATA, },
>> +	};
>> +	struct ext4_xattr_info i = {
>> +		.name_index = EXT4_XATTR_INDEX_SYSTEM_DATA,
>> +		.name = EXT4_XATTR_SYSTEM_DATA_NAME,
>> +	};
>> +
>> +	/* If the old space is ok, write the data directly. */
>> +	if (len <= EXT4_I(inode)->i_inline_size)
>> +		return 0;
>> +
>> +	error = ext4_get_inode_loc(inode, &is.iloc);
>> +	if (error)
>> +		return error;
>> +
>> +	error = ext4_xattr_ibody_find(inode, &i, &is);
>> +	if (error)
>> +		goto out;
>> +
>> +	BUG_ON(is.s.not_found);
>> +
>> +	len -= EXT4_MIN_INLINE_DATA_SIZE;
>> +	value = kzalloc(len, GFP_NOFS);
>> +	if (!value)
>> +		goto out;
>> +
>> +	error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
>> +				     value, len);
>> +	if (error == -ENODATA)
>> +		goto out;
>> +
>> +	error = ext4_journal_get_write_access(handle, is.iloc.bh);
>> +	if (error)
>> +		goto out;
>> +
>> +	/* Update the xttr entry. */
>> +	i.value = value;
>> +	i.value_len = len;
>> +
>> +	error = ext4_xattr_ibody_set(handle, inode, &i, &is);
>> +	if (error)
>> +		goto out;
>> +
>> +	EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
>> +				      (void *)ext4_raw_inode(&is.iloc));
>> +	EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
>> +				le32_to_cpu(is.s.here->e_value_size);
>> +	ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
>> +	get_bh(is.iloc.bh);
>> +	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
>> +
>> +out:
>> +	kfree(value);
>> +	brelse(is.iloc.bh);
>> +	return error;
>> +}
>> +
>> +int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
>> +			     unsigned int len)
>> +{
>> +	int ret, size;
>> +	struct ext4_inode_info *ei = EXT4_I(inode);
>> +
>> +	if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))
>> +		return -ENOSPC;
>> +
>> +	size = ext4_get_max_inline_size(inode);
>> +	if (size < len)
>> +		return -ENOSPC;
>> +
>> +	down_write(&EXT4_I(inode)->xattr_sem);
>> +
>> +	if (ei->i_inline_off)
>> +		ret = ext4_update_inline_data(handle, inode, len);
>> +	else
>> +		ret = ext4_create_inline_data(handle, inode, len);
>> +
>> +	up_write(&EXT4_I(inode)->xattr_sem);
>> +
>> +	return ret;
>> +}
>> +
>> +static int ext4_destroy_inline_data_nolock(handle_t *handle, struct inode *inode)
>> +{
>> +	struct ext4_inode_info *ei = EXT4_I(inode);
>> +	struct ext4_xattr_ibody_find is = {
>> +		.s = { .not_found = 0, },
>> +	};
>> +	struct ext4_xattr_info i = {
>> +		.name_index = EXT4_XATTR_INDEX_SYSTEM_DATA,
>> +		.name = EXT4_XATTR_SYSTEM_DATA_NAME,
>> +		.value = NULL,
>> +		.value_len = 0,
>> +	};
>> +	int error;
>> +
>> +	if (!ei->i_inline_off)
>> +		return 0;
>> +
>> +	error = ext4_get_inode_loc(inode, &is.iloc);
>> +	if (error)
>> +		return error;
>> +
>> +	error = ext4_xattr_ibody_find(inode, &i, &is);
>> +	if (error)
>> +		goto out;
>> +
>> +	error = ext4_journal_get_write_access(handle, is.iloc.bh);
>> +	if (error)
>> +		goto out;
>> +
>> +	error = ext4_xattr_ibody_set(handle, inode, &i, &is);
>> +	if (error)
>> +		goto out;
>> +
>> +	memset((void *)ext4_raw_inode(&is.iloc)->i_block,
>> +		0, EXT4_MIN_INLINE_DATA_SIZE);
>> +
>> +	if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
>> +				      EXT4_FEATURE_INCOMPAT_EXTENTS)) {
>> +		if (S_ISDIR(inode->i_mode) ||
>> +		    S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) {
>> +			ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);
>> +			ext4_ext_tree_init(handle, inode);
>> +		}
>> +	}
>> +	ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
>> +
>> +	get_bh(is.iloc.bh);
>> +	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
>> +
>> +	EXT4_I(inode)->i_inline_off = 0;
>> +	EXT4_I(inode)->i_inline_size = 0;
>> +	ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
>> +out:
>> +	brelse(is.iloc.bh);
>> +	if (error == -ENODATA)
>> +		error = 0;
>> +	return error;
>> +}
>> +
>> +int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
>> +{
>> +	int ret;
>> +
>> +	down_write(&EXT4_I(inode)->xattr_sem);
>> +	ret = ext4_destroy_inline_data_nolock(handle, inode);
>> +	up_write(&EXT4_I(inode)->xattr_sem);
>> +
>> +	return ret;
>> +}
>> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
>> index 0b2d6c1..b94a388 100644
>> --- a/fs/ext4/inode.c
>> +++ b/fs/ext4/inode.c
>> @@ -3616,8 +3616,10 @@ static inline void ext4_iget_extra_inode(struct inode *inode,
>> {
>> 	__le32 *magic = (void *)raw_inode +
>> 			EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize;
>> -	if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
>> +	if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
>> 		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
>> +		ext4_find_inline_data(inode);
>> +	}
>> }
>>
>> struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
>> @@ -3653,6 +3655,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
>> 	set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
>>
>> 	ext4_clear_state_flags(ei);	/* Only relevant on 32-bit archs */
>> +	ei->i_inline_off = 0;
>> 	ei->i_dir_start_lookup = 0;
>> 	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
>> 	/* We now have enough fields to check if the inode was active or not.
>> diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
>> index 07eeaf3..71ef45e 100644
>> --- a/fs/ext4/xattr.c
>> +++ b/fs/ext4/xattr.c
>> @@ -899,30 +899,6 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
>> 	return 0;
>> }
>>
>> -int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
>> -				struct ext4_xattr_info *i,
>> -				struct ext4_xattr_ibody_find *is)
>> -{
>> -	struct ext4_xattr_ibody_header *header;
>> -	struct ext4_xattr_search *s = &is->s;
>> -	int error;
>> -
>> -	if (EXT4_I(inode)->i_extra_isize == 0)
>> -		return -ENOSPC;
>> -	error = ext4_xattr_set_entry(i, s);
>> -	if (error)
>> -		return error;
>> -	header = IHDR(inode, ext4_raw_inode(&is->iloc));
>> -	if (!IS_LAST_ENTRY(s->first)) {
>> -		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
>> -		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
>> -	} else {
>> -		header->h_magic = cpu_to_le32(0);
>> -		ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
>> -	}
>> -	return 0;
>> -}
> 
> On further review, this function was added in [PATCH 02/22] without any
> users, and is being deleted here immediately.  It should just be removed
> from 02/22 entirely.
> 
>> int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
>> 			 struct ext4_xattr_info *i,
>> 			 struct ext4_xattr_ibody_find *is)
>> diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
>> index 2879761..2fe373f 100644
>> --- a/fs/ext4/xattr.h
>> +++ b/fs/ext4/xattr.h
>> @@ -21,6 +21,7 @@
>>  #define EXT4_XATTR_INDEX_TRUSTED		4
>>  #define	EXT4_XATTR_INDEX_LUSTRE			5
>>  #define EXT4_XATTR_INDEX_SECURITY	        6
>> +#define EXT4_XATTR_INDEX_SYSTEM_DATA		7
> 
> Is this intended for all "system.*" uses?  Then it should be changed to be
> named "SYSTEM" instead of "SYSTEM_DATA":
> 
> #define EXT4_XATTR_INDEX_SYSTEM			7
> 
> 
>> struct ext4_xattr_header {
>> 	__le32	h_magic;	/* magic number for identification */
>> @@ -116,13 +117,26 @@ extern const struct xattr_handler *ext4_xattr_handlers[];
>>
>> extern int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
>> 				 struct ext4_xattr_ibody_find *is);
>> -extern int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
>> -				       struct ext4_xattr_info *i,
>> -				       struct ext4_xattr_ibody_find *is);
>> +extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
>> +			        struct ext4_xattr_info *i,
>> +			        struct ext4_xattr_ibody_find *is);
>> extern int ext4_xattr_ibody_get(struct inode *inode, int name_index,
>> 				const char *name,
>> 				void *buffer, size_t buffer_size);
>>
>> +extern int ext4_has_inline_data(struct inode *inode);
>> +extern int ext4_get_inline_size(struct inode *inode);
>> +extern int ext4_get_max_inline_size(struct inode *inode);
>> +extern int ext4_find_inline_data(struct inode *inode);
>> +extern void ext4_write_inline_data(struct inode *inode,
>> +				   struct ext4_iloc *iloc,
>> +				   void *buffer, loff_t pos,
>> +				   unsigned int len);
>> +extern int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
>> +				    unsigned int len);
>> +extern int ext4_init_inline_data(handle_t *handle, struct inode *inode,
>> +				 unsigned int len);
>> +extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
>> # else  /* CONFIG_EXT4_FS_XATTR */
>>
>> static inline int
>> @@ -198,6 +212,46 @@ extern int ext4_xattr_ibody_get(struct inode *inode, int name_index,
>> 	return -EOPNOTSUPP;
>> }
>>
>> +static inline int ext4_find_inline_data(struct inode *inode)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int ext4_has_inline_data(struct inode *inode)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int ext4_get_inline_size(struct inode *inode)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int ext4_get_max_inline_size(struct inode *inode)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline void ext4_write_inline_data(struct inode *inode,
>> +					  struct ext4_iloc *iloc,
>> +					  void *buffer, loff_t pos,
>> +					  unsigned int len)
>> +{
>> +	return;
>> +}
>> +
>> +static inline int ext4_init_inline_data(handle_t *handle,
>> +					struct inode *inode,
>> +					unsigned int len)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int ext4_destroy_inline_data(handle_t *handle,
>> +					   struct inode *inode)
>> +{
>> +	return 0;
>> +}
>> # endif  /* CONFIG_EXT4_FS_XATTR */
>>
>> #ifdef CONFIG_EXT4_FS_SECURITY
>> -- 
>> 1.7.0.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
>> the body of a message to majordomo@...r.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> Cheers, Andreas
> 
> 
> 
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists