Re: [e2fsprogs] initdir: Writing inode after the initial write?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/01/2012 11:31 AM, Andreas Dilger wrote:
> On 2012-11-30, at 10:08 PM, Darren Hart wrote:
>> On 11/30/2012 08:23 PM, Andreas Dilger wrote:
>>> On 2012-11-30, at 7:13 PM, Darren Hart wrote:
>>>> I am working on creating some files after creating a filesystem in
>>>> mke2fs. This is part of a larger project to add initial directory
>>>> support to mke2fs.
>>>
>>> Maybe some background on what you are trying to do would help us to
>>> understand the problem?
>>
>> Sure, a few are already aware, but I suppose some extra detail for
>> the first post to this list is in order.
>>
>> I work on the Yocto Project, and this particular effort is part of
>> improving our deployment tooling. Specifically, the part of the build
>> process that creates the root filesystem.
>>
>> Most all filesystems have some mechanism to create prepopulated
>> images without the need for root permissions. Many do this through
>> a -r parameter to their corresponding mkfs.* tool. The exceptions to
>> this are ext3 and ext4. Our current tooling relies on genext2fs and
>> flipping some bits to "convert" the ext2 filesystem to ext3 and 4.
>> Not ideal.
>>
>> After exploring options like libguestfs and finding them to be
>> considerably heavy weight for what we are trying to accomplish, I
>> discussed the possibility of adding an argument to mke2fs which would
>> populate a newly formatted filesystem from a specified directory. Ted
>> suggested a clean set of patches implementing this were likely to be
>> accepted.
>
> Hmm, I wonder if libext2fs can itself create extent-mapped files,
> or if these files will be block-mapped?  If they are small (< 1MB),
> it is probably not a huge problem, but if your files are large it
> may be that libext2fs also creates "ext2" files internally?
>
> Maybe Ted can confirm whether that is true or not.  At least I recall
> that the block allocator inside libext2fs was horrible, and creating
> large files was problematic.


Ted, can you confirm?


> I guess the other question is why you don't use debugfs to create
> the directory tree and copy the files into your new filesystem?
> It already has "mkdir", "mknod" and "write" commands for use, and
> it is a one-line patch to alias "write" to "cp" for easier use[*].


I just didn't know about it and it didn't come up in my polling :-)
(which would have been more fruitful had I done some of that here).


> Then, it just needs a debugfs script to build your directory tree
> and copy files over.  Possibly enhancing "cp" to call do_mknod() for
> pipe/block/char devices would make this easier to use.
>
> Something like the following, though it seems there isn't an "ln -s"
> or "symlink" command for debugfs yet, that would need to be written.
>
> #!/bin/bash
> SRCDIR=$1
> DEVICE=$2
>
> {
> 	find $SRCDIR | while read FILE; do
> 		TGT=${FILE#$SRCDIR}
> 		case $(stat -c "%F" $FILE) in
> 		"directory")
> 			echo "mkdir $TGT"
> 			;;
> 		"regular file")
> 			echo "write $FILE $TGT"
> 			;;
> 		"symbolic link")
> 			LINK_TGT=$(ls -l $FILE | sed -e 's/.*-> //')
> 			echo "symlink $TGT $LINK_TGT"
> 			;;
> 		"block special file")
> 			DEVNO=$(stat -c "%t %T" $FILE)
> 			echo "mknod $F $DEVNO $TGT
> 			;;
> 		"character special file")
> 			DEVNO=$(stat -c "%t %T" $FILE)
> 			echo "mknod $TYPE $DEVNO $TGT
> 			;;
> 		*)
> 			echo "Unknown file $FILE" 1>&2
> 			;;
> 		done
> 	done
> } | debugfs -w -f /dev/stdin $device


This is really promising. I've tweaked it a bit to use the basename and
cd into the directories as they are traversed by find so it doesn't try
and create filenames like "/dir1/hello.txt" in the root directory.

	#!/bin/sh
	SRCDIR=$1
	DEVICE=$2
	
	{
		find $SRCDIR | while read FILE; do
			#TGT=${FILE#$SRCDIR}
			TGT=$(basename ${FILE#$SRCDIR})
	
			# Skip the root dir
			if [ -z "$TGT" ]; then
				continue
			fi
	
			case $(stat -c "%F" $FILE) in
			"directory")
				echo "mkdir $TGT"
				echo "cd $TGT"
				;;
			"regular file")
				echo "write $FILE $TGT"
				;;
			"symbolic link")
				LINK_TGT=$(ls -l $FILE | sed -e 's/.*-> //')
				echo "symlink $TGT $LINK_TGT"
				;;
			"block special file")
				DEVNO=$(stat -c "%t %T" $FILE)
				echo "mknod $TGT b $DEVNO"
				;;
			"character special file")
				DEVNO=$(stat -c "%t %T" $FILE)
				echo "mknod $TGT c $DEVNO"
				;;
			*)
				echo "Unknown file $FILE" 1>&2
				;;
			esac
		done
	} | debugfs -w -f /dev/stdin $DEVICE


> I would guess that implementing "symlink" support in debugfs will
> be orders of magnitude less work, maintenance, and bugs than your
> current patch.


It needs symlink as you said, but I can relatively easily migrate my
code for that in mke2fs to debugfs.

Still needs permissions and such. Is that done with "modify_inode" ? If
so, how do I specify the new contents?

I need to look into how to detect and support hard links.


> This might be turned inside-out and just run a "find $SRCDIR" and
> have the inner loop check the file type and call the appropriate
> operation for it (mkdir, write/cp, mknod, symlink).  Note that
> "find" will return the directories first, so this should be OK to
> just consume the lines as they are output by find.


Yes, this seems to work just fine.


>> I don't have much filesystem experience - most of my experience is
>> with core kernel mechanisms, ipc, locking, etc. - so I'm mostly
>> hacking my way to some basic functionality before refactoring. The
>> libext2fs library documentation gave me a good start, but I
>> occasionally trip over things like the problem described below as
>> there is no documentation for what I'm trying to do specifically
>> (of course) and many of the required functions are only minimally
>> documented, and sometimes only listed in the index.
>
> Definitely, if the documentation is lacking and you've spent cycles
> figuring something out, then a patch to improve the documentation is
> most welcome.


I plan to update this as I go... although I'm going to have much less to
do if I use the debugfs approach. ;-)

I wonder if it would make sense to integrate the debugfs functionality
into libext2fs and enable both debugfs and mke2fs to use the same common
code. I think the "-r initialdir" option would still be nice to have for
mke2fs, and does make it more consistent with other FSs in this feature.


>
>> The specific instance below is the result of me trying to format and
>> populate a filesystem image (in a file) from a root directory that looks like this:
>>
>> $ tree rootdir/
>> rootdir/
>> |-- dir1
>> |   |-- hello.lnk -> /hello.txt
>> |   `-- world.txt
>> |-- hello.lnk -> /hello.txt
>> |-- hello.txt
>> |-- sda
>> `-- ttyS0
>>
>> $ cat rootdir/hello.txt
>> hello
>>
>> In mke2fs.c I setup the new getopt argument and call nftw() with a
>> callback called init_dir_cb() which checks the file type and takes
>> the appropriate action to duplicate each entry. The exact code is at:
>
> To be honest, ntfw() will drag a bunch of bloat into e2fsprogs that
> doesn't exist today, and isn't really portable.


OK, well it could also be done with ftw to be more portable, but I guess
it's still marked obsolete in POSIX.1-2008 :/

Similar functionality could be implemented relatively easily.


>
>> http://git.infradead.org/users/dvhart/e2fsprogs/blob/refs/heads/initialdir:/misc/mke2fs.c#l2319
>>
>> As described below, when I update the inode.i_size after the initial
>> write and copying of the file content, the above cat command fails to
>> output anything when run on the loop mounted filesystem. If I just
>> hack in the i_size prior to writing the inode for the first time and
>> don't update it after copying the file content, then the cat command
>> succeeds as above on the loop mounted image.
>
> It probably makes sense to understand what is broken here, whether
> it is the library or the program.  We definitely want to make sure
> the API is usable and working correctly in any case.


I should be able to compare with debugfs "write" and see what the
difference is.


>
>> The commented out inode write is noted here:
>>
>> http://git.infradead.org/users/dvhart/e2fsprogs/blob/refs/heads/initialdir:/misc/mke2fs.c#l2462
>>
>> Does that help clarify the situation?
>>
>> What I'm looking for is some insight into what it is I am not
>> understanding about the filesystem structures that causes this behavior.
>
> I hate to put a downer on your current work, but I think that you
> are adding something overly complex that only has a very limited
> usefulness, and your time could be better spent elsewhere.

Not at all! I appreciate the tip. And it hasn't been wasted time, I've
learned quite a bit, and as I said above, perhaps the debugfs copies and
such can be pushed into libext2fs and used in both. ext2fs_mkdir()
exists after all, why not ext2fs_mksymlink(), ext2fs_mknod() and
ext2fs_writefile() ?

Thanks a lot for the insight, exactly what I needed!

--
Darren

>
> [*] add debugfs "cp" command as an alias to "write":
>
> diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct
> index a799dd7..3789dcd 100644
> --- a/debugfs/debug_cmds.ct
> +++ b/debugfs/debug_cmds.ct
> @@ -119,7 +119,7 @@ request do_undel, "Undelete file",
>         undelete, undel;
>
>  request do_write, "Copy a file from your native filesystem",
> -       write;
> +       write, cp;
>
>  request do_dump, "Dump an inode out to a file",
>         dump_inode, dump;
>
>> Thanks,
>>
>> Darren
>>
>>>
>>> Cheers, Andreas
>>>
>>>> To make it easy for people to see what I'm working
>>>> on, I've pushed my dev tree here:
>>>>
>>>> http://git.infradead.org/users/dvhart/e2fsprogs/shortlog/refs/heads/initialdir
>>>>
>>>> Note: the code is still just in the prototyping state. It is inelegant
>>>> to say the least. The git tree will most definitely rebase. I'm trying
>>>> to get it functional, once that is understand, I will refactor
>>>> appropriately.
>>>>
>>>> I can create a simple directory structure and link in files and fast
>>>> symlinks. I'm currently working on copying content from files in the
>>>> initial directory. The process I'm using is as follows:
>>>>
>>>>
>>>> ext2fs_new_inode(&ino)
>>>> ext2fs_link()
>>>>
>>>> ext2fs_read_inode(ino, &inode)
>>>> /* some initial inode setup */
>>>> ext2fs_write_new_inode(ino, &inode)
>>>>
>>>> ext2fs_file_open2(&inode)
>>>> ext2fs_write_file()
>>>> ext2fs_file_close()
>>>>
>>>> inode.i_size = bytes_written
>>>> ext2fs_write_inode()
>>>>
>>>> ext2fs_inode_alloc_stats2(ino)
>>>>
>>>>
>>>> When I mount the image, the size for the file is correct, by catting it
>>>> returns nothing. If I instead hack in the known size during the initial
>>>> inode setup and drop the last ext2fs_write_inode() call, then the size
>>>> is right and catting the file works as expected.
>>>>
>>>> Is it incorrect to write the inode more than once? If not, am I doing
>>>> something that is somehow decoupling the block where the data was
>>>> written from the inode associated with the file?
>>>>
>>>> Thanks,
>>>>
>>>> --
>>>> Darren Hart
>>>> Intel Open Source Technology Center
>>>> Yocto Project - Technical Lead - Linux Kernel
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
>>>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>> Cheers, Andreas
>>>
>>>
>>>
>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
>>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>>> 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@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
> Cheers, Andreas
>
>
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> 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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux