All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tao Ma <tm@tao.ma>
To: Andreas Dilger <adilger@dilger.ca>
Cc: linux-ext4@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH V4 03/22] ext4: Add the basic function for inline data support.
Date: Fri, 13 Apr 2012 10:59:20 +0800	[thread overview]
Message-ID: <4F879688.3030908@tao.ma> (raw)
In-Reply-To: <68133D01-6191-40F4-87DD-E73918FDBEAA@dilger.ca>

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@taobao.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@taobao.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@taobao.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@vger.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@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


  reply	other threads:[~2012-04-13  2:59 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-20  7:00 [PATCH V4 00/22] ext4: Add inline data support Tao Ma
2012-02-20  7:01 ` [PATCH V4 01/22] ext4: Move extra inode read to a new function Tao Ma
2012-02-20  7:01   ` [PATCH V4 02/22] ext4: export inline xattr functions Tao Ma
2012-02-21 22:45     ` Andreas Dilger
2012-02-20  7:01   ` [PATCH V4 03/22] ext4: Add the basic function for inline data support Tao Ma
2012-04-07  0:21     ` Andreas Dilger
2012-04-13  2:59       ` Tao Ma [this message]
2012-02-20  7:01   ` [PATCH V4 04/22] ext4: Add read support for inline data Tao Ma
2012-02-20  7:01   ` [PATCH V4 05/22] ext4: Add normal write " Tao Ma
2012-02-20  7:01   ` [PATCH V4 06/22] ext4: Add journalled " Tao Ma
2012-02-20  7:01   ` [PATCH V4 07/22] ext4: Add delalloc " Tao Ma
2012-02-20  7:01   ` [PATCH V4 08/22] ext4: Create a new function ext4_init_new_dir Tao Ma
2012-02-20  7:01   ` [PATCH V4 09/22] ext4: Refactor __ext4_check_dir_entry to accepts start and size Tao Ma
2012-02-20  7:01   ` [PATCH V4 10/22] ext4: Create __ext4_insert_dentry for dir entry insertion Tao Ma
2012-02-20  7:01   ` [PATCH V4 11/22] ext4: let add_dir_entry handle inline data properly Tao Ma
2012-02-20  7:01   ` [PATCH V4 12/22] ext4: Let ext4_readdir handle inline data Tao Ma
2012-02-20  7:01   ` [PATCH V4 13/22] ext4: Create a new function search_dir Tao Ma
2012-02-20  7:01   ` [PATCH V4 14/22] ext4: let ext4_find_entry handle inline data Tao Ma
2012-02-20  7:01   ` [PATCH V4 15/22] ext4: make ext4_delete_entry generic Tao Ma
2012-02-20  7:01   ` [PATCH V4 16/22] ext4: let ext4_delete_entry handle inline data Tao Ma
2012-02-20  7:01   ` [PATCH V4 17/22] ext4: let empty_dir handle inline dir Tao Ma
2012-04-07  0:21     ` Andreas Dilger
2012-04-17  3:55       ` Tao Ma
2012-02-20  7:01   ` [PATCH V4 18/22] ext4: let ext4_rename " Tao Ma
2012-02-20  7:01   ` [PATCH V4 19/22] ext4: Let fiemap work with inline data Tao Ma
2012-02-20  7:01   ` [PATCH V4 20/22] ext4: Evict inline data out if we needs to strore xattr in inode Tao Ma
2012-02-20  7:01   ` [PATCH V4 21/22] ext4: let ext4_truncate handle inline data correctly Tao Ma
2012-02-20  7:01   ` [PATCH V4 22/22] ext4: Enable ext4 inline support Tao Ma
2012-02-21  6:51   ` [PATCH V4 01/22] ext4: Move extra inode read to a new function Andreas Dilger
2012-02-21  8:13     ` Tao Ma
2012-02-21 23:44 ` [PATCH V4 00/22] ext4: Add inline data support Andreas Dilger
2012-02-22  1:34   ` Tao Ma

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F879688.3030908@tao.ma \
    --to=tm@tao.ma \
    --cc=adilger@dilger.ca \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.