From: Robert Yang <liezhi.yang@windriver.com>
To: Robert Yang <liezhi.yang@windriver.com>, <tytso@mit.edu>,
<dvhart@linux.intel.com>
Cc: <linux-ext4@vger.kernel.org>
Subject: Re: [PATCH V2 09/11] misc/create_inode.c: handle hardlinks
Date: Wed, 25 Dec 2013 11:14:05 +0800 [thread overview]
Message-ID: <52BA4D7D.1020803@windriver.com> (raw)
In-Reply-To: <1387874847-4922-10-git-send-email-liezhi.yang@windriver.com>
Sorry, this patch should be updated a little, please see my comments inline ...
On 12/24/2013 04:47 PM, Robert Yang wrote:
> Create the inode and save the native inode number when we meet the hard
> link (st_nlink > 1) at the first time, use ext2fs_link() to link the
> name to the target inode number when we meet the same native inode
> number again.
>
> This algorithm is referred this from the genext2fs.
>
> Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> ---
> misc/create_inode.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
> misc/create_inode.h | 18 +++++++++++
> misc/mke2fs.c | 12 +++++++
> 3 files changed, 117 insertions(+)
>
> diff --git a/misc/create_inode.c b/misc/create_inode.c
> index f1af6a9..7462413 100644
> --- a/misc/create_inode.c
> +++ b/misc/create_inode.c
> @@ -10,6 +10,44 @@
> #define S_BLKSIZE 512
> #endif
>
> +/* For saving the hard links */
> +int hdlink_cnt = HDLINK_CNT;
> +
> +/* Link an inode number to a directory */
> +static errcode_t add_link(ext2_ino_t parent_ino, ext2_ino_t ino, const char *name)
> +{
> + struct ext2_inode inode;
> + errcode_t retval;
> +
> + retval = ext2fs_read_inode(current_fs, ino, &inode);
> + if (retval) {
> + com_err(__FUNCTION__, retval, "while reading inode %u", ino);
> + return retval;
> + }
> +
> + retval = ext2fs_link(current_fs, parent_ino, name, ino, inode.i_flags);
> + if (retval == EXT2_ET_DIR_NO_SPACE) {
> + retval = ext2fs_expand_dir(current_fs, parent_ino);
> + if (retval) {
> + com_err(__FUNCTION__, retval, "while expanding directory");
> + return retval;
> + }
> + retval = ext2fs_link(current_fs, parent_ino, name, ino, inode.i_flags);
> + }
> + if (retval) {
> + com_err(__FUNCTION__, retval, "while linking %s", name);
> + return retval;
> + }
> +
> + inode.i_links_count++;
> +
> + retval = ext2fs_write_inode(current_fs, ino, &inode);
> + if (retval)
> + com_err(__FUNCTION__, retval, "while writing inode %u", ino);
> +
> + return retval;
> +}
> +
> /* Fill the uid, gid, mode and time for the inode */
> static void fill_inode(struct ext2_inode *inode, struct stat *st)
> {
> @@ -270,6 +308,17 @@ fail:
> return retval;
> }
>
> +int is_hardlink(ext2_ino_t ino)
> +{
> + int i;
> +
> + for(i = 0; i < hdlinks.count; i++) {
> + if(hdlinks.hdl[i].src_ino == ino)
> + return i;
> + }
> + return -1;
> +}
> +
> /* Copy the native file to the fs */
> errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest)
> {
> @@ -380,9 +429,11 @@ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir)
> struct dirent *dent;
> struct stat st;
> char ln_target[PATH_MAX];
> + unsigned int save_inode = 0;
The save_inode = 0 should be set before read each file (inside the while
loop), otherwise it will be 1 for other files after we meet the first
hardlink.
// Robert
> ext2_ino_t ino;
> errcode_t retval;
> int read_cnt;
> + int hdlink;
>
> root = EXT2_ROOT_INO;
>
> @@ -404,6 +455,21 @@ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir)
> lstat(dent->d_name, &st);
> name = dent->d_name;
>
> + /* Check for hardlinks */
> + if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && st.st_nlink > 1) {
> + hdlink = is_hardlink(st.st_ino);
> + if (hdlink >= 0) {
> + retval = add_link(parent_ino,
> + hdlinks.hdl[hdlink].dst_ino, name);
> + if (retval) {
> + com_err(__FUNCTION__, retval, "while linking %s", name);
> + return retval;
> + }
> + continue;
> + } else
> + save_inode = 1;
> + }
> +
> switch(st.st_mode & S_IFMT) {
> case S_IFCHR:
> case S_IFBLK:
> @@ -472,6 +538,27 @@ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir)
> _("while setting inode for \"%s\""), name);
> return retval;
> }
> +
> + /* Save the hardlink ino */
> + if (save_inode) {
> + /*
> + * Check whether need more memory, and we don't need
> + * free() since the lifespan will be over after the fs
> + * populated.
> + */
> + if (hdlinks.count == hdlink_cnt) {
> + if ((hdlinks.hdl = realloc (hdlinks.hdl,
> + (hdlink_cnt + HDLINK_CNT) *
> + sizeof (struct hdlink_s))) == NULL) {
> + com_err(name, errno, "Not enough memory");
> + return errno;
> + }
> + hdlink_cnt += HDLINK_CNT;
> + }
> + hdlinks.hdl[hdlinks.count].src_ino = st.st_ino;
> + hdlinks.hdl[hdlinks.count].dst_ino = ino;
> + hdlinks.count++;
> + }
> }
> closedir(dh);
> return retval;
> diff --git a/misc/create_inode.h b/misc/create_inode.h
> index 9fc97fa..2b6d429 100644
> --- a/misc/create_inode.h
> +++ b/misc/create_inode.h
> @@ -6,9 +6,27 @@
> #include "ext2fs/ext2fs.h"
> #include "nls-enable.h"
>
> +struct hdlink_s
> +{
> + ext2_ino_t src_ino;
> + ext2_ino_t dst_ino;
> +};
> +
> +struct hdlinks_s
> +{
> + int count;
> + struct hdlink_s *hdl;
> +};
> +
> +struct hdlinks_s hdlinks;
> +
> ext2_filsys current_fs;
> ext2_ino_t root;
>
> +/* For saving the hard links */
> +#define HDLINK_CNT 4
> +extern int hdlink_cnt;
> +
> /* For populating the filesystem */
> extern errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir);
> extern errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st);
> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> index eab5463..10cdfd2 100644
> --- a/misc/mke2fs.c
> +++ b/misc/mke2fs.c
> @@ -2802,6 +2802,18 @@ no_journal:
> if (!quiet)
> printf("%s", _("Copying files into the device: "));
>
> + /*
> + * Allocate memory for the hardlinks, we don't need free()
> + * since the lifespan will be over after the fs populated.
> + */
> + if ((hdlinks.hdl = (struct hdlink_s *)
> + malloc(hdlink_cnt * sizeof(struct hdlink_s))) == NULL) {
> + fprintf(stderr, "%s", _("\nNot enough memory\n"));
> + retval = ext2fs_close(fs);
> + return retval;
> + }
> +
> + hdlinks.count = 0;
> current_fs = fs;
> root = EXT2_ROOT_INO;
> retval = populate_fs(root, root_dir);
>
next prev parent reply other threads:[~2013-12-25 3:14 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-24 8:47 [PATCH V2 00/11] e2fsprogs/mke2fs: add an option: -d root-directory Robert Yang
2013-12-24 8:47 ` [PATCH V2 01/11] mke2fs: add the ability to copy files from a given directory Robert Yang
2013-12-24 8:47 ` [PATCH V2 02/11] misc/create_inode.c: copy files recursively Robert Yang
2013-12-24 8:47 ` [PATCH V2 03/11] misc/create_inode.c: create special file Robert Yang
2013-12-24 8:47 ` [PATCH V2 04/11] misc/create_inode.c: create symlink Robert Yang
2013-12-24 8:47 ` [PATCH V2 05/11] misc/create_inode.c: copy regular file Robert Yang
2013-12-24 8:47 ` [PATCH V2 06/11] misc/create_inode.c: create directory Robert Yang
2013-12-24 8:47 ` [PATCH V2 07/11] misc/create_inode.c: set owner/mode/time for the inode Robert Yang
2013-12-24 8:47 ` [PATCH V2 08/11] mke2fs.c: add an option: -d root-directory Robert Yang
2013-12-24 8:47 ` [PATCH V2 09/11] misc/create_inode.c: handle hardlinks Robert Yang
2013-12-25 3:14 ` Robert Yang [this message]
2013-12-25 3:21 ` [PATCH V3 " Robert Yang
2013-12-24 8:47 ` [PATCH V2 10/11] debugfs: use the functions in misc/create_inode.c Robert Yang
2013-12-24 8:47 ` [PATCH V2 11/11] mke2fs.8.in: update the manual for the -d option Robert Yang
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=52BA4D7D.1020803@windriver.com \
--to=liezhi.yang@windriver.com \
--cc=dvhart@linux.intel.com \
--cc=linux-ext4@vger.kernel.org \
--cc=tytso@mit.edu \
/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.