All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zheng Liu <gnehzuil.liu@gmail.com>
To: "Darrick J. Wong" <darrick.wong@oracle.com>
Cc: linux-ext4@vger.kernel.org, Theodore Ts'o <tytso@mit.edu>,
	Zheng Liu <wenqing.lz@taobao.com>
Subject: Re: [PATCH v2 17/28] libext2fs: handle inline data in read/write function
Date: Wed, 4 Dec 2013 11:47:58 +0800	[thread overview]
Message-ID: <20131204034757.GC20409@gmail.com> (raw)
In-Reply-To: <20131204030242.GJ9535@birch.djwong.org>

On Tue, Dec 03, 2013 at 07:02:42PM -0800, Darrick J. Wong wrote:
[...]
> > +static errcode_t
> > +ext2fs_file_read_inline_data(ext2_file_t file, void *buf,
> > +			     unsigned int wanted, unsigned int *got)
> > +{
> > +	ext2_filsys fs;
> > +	errcode_t retval;
> > +	unsigned int start, count = 0;
> > +	size_t size;
> > +
> > +	fs = file->fs;
> > +	retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
> > +					file->buf, &size);
> > +	if (retval)
> > +		return retval;
> > +
> > +	if (file->pos >= size)
> > +		goto out;
> > +
> > +	start = file->pos % size;
> 
> If file->pos can never be larger than size, this is unnecessary.

Good catch!  I will fix it soon.

Thanks,
                                                - Zheng

> 
> > +	count = size - start;
> > +	if (count > wanted)
> > +		count = wanted;
> > +	memcpy(buf, file->buf + start, count);
> > +	file->pos += count;
> > +	buf += count;
> > +
> > +out:
> > +	if (got)
> > +		*got = count;
> > +	return retval;
> > +}
> > +
> > +
> >  errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
> >  			   unsigned int wanted, unsigned int *got)
> >  {
> > @@ -236,6 +269,10 @@ errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
> >  	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
> >  	fs = file->fs;
> >  
> > +	/* If an inode has inline data, things get complicated. */
> > +	if (file->inode.i_flags & EXT4_INLINE_DATA_FL)
> > +		return ext2fs_file_read_inline_data(file, buf, wanted, got);
> > +
> >  	while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
> >  		retval = sync_buffer_position(file);
> >  		if (retval)
> > @@ -266,6 +303,67 @@ fail:
> >  }
> >  
> >  
> > +static errcode_t
> > +ext2fs_file_write_inline_data(ext2_file_t file, const void *buf,
> > +			      unsigned int nbytes, unsigned int *written)
> > +{
> > +	ext2_filsys fs;
> > +	errcode_t retval;
> > +	unsigned int start, count = 0;
> > +	size_t size;
> > +
> > +	fs = file->fs;
> > +	retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
> > +					file->buf, &size);
> > +	if (retval)
> > +		return retval;
> > +
> > +	if (file->pos < size) {
> > +		start = file->pos % fs->blocksize;
> 
> Since we're not dealing with blocks, I don't think you need to '%' with the
> block size.
> 
> --D
> 
> > +		count = nbytes - start;
> > +		memcpy(file->buf + start, buf, count);
> > +
> > +		retval = ext2fs_inline_data_set(fs, file->ino, &file->inode,
> > +						file->buf, count);
> > +		if (retval == EXT2_ET_INLINE_DATA_NO_SPACE)
> > +			goto expand;
> > +		if (retval)
> > +			return retval;
> > +
> > +		file->pos += count;
> > +
> > +		/* Update inode size */
> > +		if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) {
> > +			errcode_t	rc;
> > +
> > +			rc = ext2fs_file_set_size2(file, file->pos);
> > +			if (retval == 0)
> > +				retval = rc;
> > +		}
> > +
> > +		if (written)
> > +			*written = count;
> > +		return 0;
> > +	}
> > +
> > +expand:
> > +	retval = ext2fs_inline_data_expand(fs, file->ino);
> > +	if (retval)
> > +		return retval;
> > +	/*
> > +	 * reload inode and return no space error
> > +	 *
> > +	 * XXX: file->inode could be copied from the outside
> > +	 * in ext2fs_file_open2().  We have no way to modify
> > +	 * the outside inode.
> > +	 */
> > +	retval = ext2fs_read_inode(fs, file->ino, &file->inode);
> > +	if (retval)
> > +		return retval;
> > +	return EXT2_ET_INLINE_DATA_NO_SPACE;
> > +}
> > +
> > +
> >  errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
> >  			    unsigned int nbytes, unsigned int *written)
> >  {
> > @@ -280,6 +378,16 @@ errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
> >  	if (!(file->flags & EXT2_FILE_WRITE))
> >  		return EXT2_ET_FILE_RO;
> >  
> > +	/* If an inode has inline data, things get complicated. */
> > +	if (file->inode.i_flags & EXT4_INLINE_DATA_FL) {
> > +		retval = ext2fs_file_write_inline_data(file, buf, nbytes,
> > +						       written);
> > +		if (retval != EXT2_ET_INLINE_DATA_NO_SPACE)
> > +			return retval;
> > +		/* fall through to read data from the block */
> > +		retval = 0;
> > +	}
> > +
> >  	while (nbytes > 0) {
> >  		retval = sync_buffer_position(file);
> >  		if (retval)
> > diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
> > index 16af814..4a35209 100644
> > --- a/lib/ext2fs/inline_data.c
> > +++ b/lib/ext2fs/inline_data.c
> > @@ -309,6 +309,7 @@ errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino)
> >  	struct ext2_inline_data data;
> >  	errcode_t retval;
> >  	blk64_t blk;
> > +	size_t inline_size;
> >  	char *inline_buf = 0;
> >  	char *blk_buf = 0;
> >  
> > @@ -327,8 +328,8 @@ errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino)
> >  	retval = ext2fs_inline_data_ea_get(&data);
> >  	if (retval)
> >  		return retval;
> > -	retval = ext2fs_get_mem(EXT4_MIN_INLINE_DATA_SIZE + data.ea_size,
> > -				&inline_buf);
> > +	inline_size = data.ea_size + EXT4_MIN_INLINE_DATA_SIZE;
> > +	retval = ext2fs_get_mem(inline_size, &inline_buf);
> >  	if (retval)
> >  		goto errout;
> >  
> > @@ -347,10 +348,14 @@ errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino)
> >  	if (retval)
> >  		goto errout;
> >  
> > -	/* Adjust the rec_len */
> > -	retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, inline_buf,
> > -						EXT4_MIN_INLINE_DATA_SIZE +
> > -							data.ea_size);
> > +	if (LINUX_S_ISDIR(inode.i_mode)) {
> > +		/* Adjust the rec_len */
> > +		retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf,
> > +							inline_buf, inline_size);
> > +	} else {
> > +		/* Copy data for a regular inode */
> > +		memcpy(blk_buf, inline_buf, inline_size);
> > +	}
> >  	if (retval)
> >  		goto errout;
> >  
> > @@ -389,3 +394,76 @@ errout:
> >  	ext2fs_free_mem(&data.ea_data);
> >  	return retval;
> >  }
> > +
> > +/*
> > + * When caller uses this function to retrieve the inline data, it must
> > + * allocate a buffer which has the size of inline data.  The size of
> > + * inline data can be know by ext2fs_inline_data_get_size().
> > + */
> > +errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino,
> > +				 struct ext2_inode *inode,
> > +				 void *buf, size_t *size)
> > +{
> > +	struct ext2_inode inode_buf;
> > +	struct ext2_inline_data data;
> > +	errcode_t retval;
> > +
> > +	if (!inode) {
> > +		retval = ext2fs_read_inode(fs, ino, &inode_buf);
> > +		if (retval)
> > +			return retval;
> > +		inode = &inode_buf;
> > +	}
> > +
> > +	data.fs = fs;
> > +	data.ino = ino;
> > +	retval = ext2fs_inline_data_ea_get(&data);
> > +	if (retval)
> > +		return retval;
> > +
> > +	memcpy(buf, (void *)inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
> > +	if (data.ea_size > 0)
> > +		memcpy(buf + EXT4_MIN_INLINE_DATA_SIZE,
> > +		       data.ea_data, data.ea_size);
> > +
> > +	if (size)
> > +		*size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size;
> > +	ext2fs_free_mem(&data.ea_data);
> > +	return 0;
> > +}
> > +
> > +errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
> > +				 struct ext2_inode *inode,
> > +				 void *buf, size_t size)
> > +{
> > +	struct ext2_inode inode_buf;
> > +	struct ext2_inline_data data;
> > +	unsigned int max_size = 0;
> > +	errcode_t retval;
> > +
> > +	if (!inode) {
> > +		retval = ext2fs_read_inode(fs, ino, &inode_buf);
> > +		if (retval)
> > +			return retval;
> > +		inode = &inode_buf;
> > +	}
> > +
> > +	/* simple case */
> > +	if (size <= EXT4_MIN_INLINE_DATA_SIZE) {
> > +		memcpy((void *)inode->i_block, buf, size);
> > +		return ext2fs_write_inode(fs, ino, inode);
> > +	}
> > +
> > +	/*
> > +	 * complicated case
> > +	 */
> > +	memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
> > +	retval = ext2fs_write_inode(fs, ino, inode);
> > +	if (retval)
> > +		return retval;
> > +	data.fs = fs;
> > +	data.ino = ino;
> > +	data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
> > +	data.ea_data = buf + EXT4_MIN_INLINE_DATA_SIZE;
> > +	return ext2fs_inline_data_ea_set(&data);
> > +}
> > -- 
> > 1.7.9.7
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-ext4" 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:[~2013-12-04  3:45 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-03 12:11 [PATCH v2 00/28] e2fsprogs: inline data refinement patch set Zheng Liu
2013-12-03 12:11 ` [PATCH v2 01/28] libext2fs: support modifying arbitrary extended attributes Zheng Liu
2013-12-03 19:54   ` Darrick J. Wong
2013-12-04  3:20     ` Zheng Liu
2013-12-04  3:21       ` Darrick J. Wong
2013-12-04 14:53     ` Theodore Ts'o
2013-12-04 20:30       ` Darrick J. Wong
2013-12-04 22:43         ` Theodore Ts'o
2013-12-04 22:55           ` Darrick J. Wong
2013-12-03 12:11 ` [PATCH v2 02/28] libext2fs: various tweaks to the xattr editor APIs Zheng Liu
2013-12-03 12:11 ` [PATCH v2 03/28] libext2fs: extend xattr api to query number of attrs Zheng Liu
2013-12-03 12:11 ` [PATCH v2 04/28] libext2fs: fix memory leaks in extended attribute code Zheng Liu
2013-12-03 12:11 ` [PATCH v2 05/28] libext2fs: fix block leak when releasing xattr block Zheng Liu
2013-12-03 12:11 ` [PATCH v2 06/28] libext2fs: remove redundant code Zheng Liu
2013-12-03 12:11 ` [PATCH v2 07/28] libext2fs: free key/value pairs before reading Zheng Liu
2013-12-03 12:11 ` [PATCH v2 08/28] debugfs: dump all extended attributes Zheng Liu
2013-12-03 12:11 ` [PATCH v2 09/28] libext2fs: handle inline data in dir iterator function Zheng Liu
2013-12-03 22:13   ` Darrick J. Wong
2013-12-04  4:57     ` Zheng Liu
2013-12-04  5:10       ` Darrick J. Wong
2013-12-04  5:26         ` Zheng Liu
2013-12-04  6:07           ` Darrick J. Wong
2013-12-04  6:21             ` Zheng Liu
2013-12-04  7:33               ` Darrick J. Wong
2013-12-03 12:11 ` [PATCH v2 10/28] libext2fs: handle inline_data in block " Zheng Liu
2013-12-03 12:11 ` [PATCH v2 11/28] debugfs: make stat command support inline data Zheng Liu
2013-12-03 12:11 ` [PATCH v2 12/28] debugfs: make expand " Zheng Liu
2013-12-03 21:19   ` Darrick J. Wong
2013-12-04  3:42     ` Zheng Liu
2013-12-03 12:11 ` [PATCH v2 13/28] debugfs: make mkdir " Zheng Liu
2013-12-03 12:11 ` [PATCH v2 14/28] debugfs: make lsdel " Zheng Liu
2013-12-03 12:11 ` [PATCH v2 15/28] debugfs: handle inline_data feature in bmap command Zheng Liu
2013-12-04  3:11   ` Darrick J. Wong
2013-12-04  3:46     ` Zheng Liu
2013-12-03 12:11 ` [PATCH v2 16/28] debugfs: handle inline data feature in punch command Zheng Liu
2013-12-03 12:11 ` [PATCH v2 17/28] libext2fs: handle inline data in read/write function Zheng Liu
2013-12-04  3:02   ` Darrick J. Wong
2013-12-04  3:47     ` Zheng Liu [this message]
2013-12-03 12:11 ` [PATCH v2 18/28] libext2fs: add inline_data feature into EXT2_LIB_FEATURE_INCOMPAT_SUPP Zheng Liu
2013-12-03 12:11 ` [PATCH v2 19/28] mke2fs: add inline_data support in mke2fs Zheng Liu
2013-12-03 22:30   ` Darrick J. Wong
2013-12-04  3:27     ` Zheng Liu
2013-12-04  4:08       ` Darrick J. Wong
2013-12-04  5:21         ` Zheng Liu
2013-12-04  5:26           ` Darrick J. Wong
2013-12-04  5:50             ` Zheng Liu
2013-12-04  6:02               ` Darrick J. Wong
2013-12-04  6:18                 ` Zheng Liu
2013-12-03 12:11 ` [PATCH v2 20/28] tune2fs: add inline_data feature in tune2fs Zheng Liu
2013-12-03 22:29   ` Darrick J. Wong
2013-12-04  3:55     ` Zheng Liu
2013-12-04  4:03       ` Darrick J. Wong
2013-12-04  5:27         ` Zheng Liu
2013-12-03 12:11 ` [PATCH v2 21/28] e2fsck: add problem descriptions and check inline data feature Zheng Liu
2013-12-03 12:11 ` [PATCH v2 22/28] e2fsck: check inline_data in pass1 Zheng Liu
2013-12-03 12:11 ` [PATCH v2 23/28] e2fsck: check inline_data in pass2 Zheng Liu
2013-12-03 12:11 ` [PATCH v2 24/28] e2fsck: check inline_data in pass3 Zheng Liu
2013-12-03 12:11 ` [PATCH v2 25/28] tests: change result in f_bad_disconnected_inode Zheng Liu
2013-12-03 12:11 ` [PATCH v2 26/28] mke2fs: enable inline_data feature on ext4dev filesystem Zheng Liu
2013-12-03 12:11 ` [PATCH v2 27/28] libext2fs: export inode cahce creation function Zheng Liu
2013-12-03 22:22   ` Darrick J. Wong
2013-12-04  3:56     ` Zheng Liu
2013-12-03 12:11 ` [PATCH v2 28/28] libext2fs: add a unit test for inline data Zheng Liu

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=20131204034757.GC20409@gmail.com \
    --to=gnehzuil.liu@gmail.com \
    --cc=darrick.wong@oracle.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    --cc=wenqing.lz@taobao.com \
    /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.