Well, I'll be damned.  I'd never run into that trick.  My apologies.

Tim Conway
[EMAIL PROTECTED]
303.682.4917
Philips Semiconductor - Longmont TC
1880 Industrial Circle, Suite D
Longmont, CO 80501
Available via SameTime Connect within Philips, n9hmg on AIM
perl -e 'print pack(nnnnnnnnnnnn, 
19061,29556,8289,28271,29800,25970,8304,25970,27680,26721,25451,25970), 
".\n" '
"There are some who call me.... Tim?"




Martin Pool <[EMAIL PROTECTED]>
12/12/2001 03:27 PM

 
        To:     Tim Conway/LMT/SC/PHILIPS@AMEC
        cc:     [EMAIL PROTECTED]
Dave Dykstra <[EMAIL PROTECTED]>
[EMAIL PROTECTED]
        Subject:        Re: Problems with rsync 2.5.1pre1 and hardlinks
        Classification: 



On 12 Dec 2001, [EMAIL PROTECTED] wrote:

> An additional hard link to an existing file takes only directory
> space, which, if it's not enough of an addition to that directories
> existing data to cause the filesystem driver to add another
> allocation to the directories data space, takes up no more disk
> space.  A symlink, however, has the same effect in the directory,
> but, in addition, gets its own data space, and inode, as well.

Actually on Linux (and some others?) the content of a symlink is
normally stored *inside* the inode, in the space that would otherwise
be used for pointers to the data and indirect blocks.  This only helps
if the target of the symlink as a string is short enough to fit in
this uint32[15] field, in other words 60 bytes.  These are called
"fast symlinks", and you can see them listed separately in the output
of e2fsck.  Of course as well as not occupying blocks they have the
advantage of being read faster, and not using any time in modifying
block allocation maps, etc.

If the symlink is longer, data blocks are allocated as on classic
Unix.

>From linux-2.4.16/fs/ext2/namei.c:ext2_symlink:

                 if (l > sizeof (inode->u.ext2_i.i_data)) {
                                 /* slow symlink */
                                 inode->i_op = 
&page_symlink_inode_operations;
                                 inode->i_mapping->a_ops = &ext2_aops;
                                 err = block_symlink(inode, symname, l);
                                 if (err)
                                                 goto out_fail;
                 } else {
                                 /* fast symlink */
                                 inode->i_op = 
&ext2_fast_symlink_inode_operations;
 memcpy((char*)&inode->u.ext2_i.i_data,symname,l);
                                 inode->i_size = l-1;
                 }

So since most ext2 filesystems have more inodes allocated than they
can use and most symlinks are short, symlinks are usually no more
likely to make you run low on space than hardlinks.

The big problem in rsync is that using -H doubles the amount of space
used to store the file list:

hlink.c:57
                 if (!(hlink_list = 
                       (struct file_struct 
*)malloc(sizeof(hlink_list[0])*flist->count)))
                                 out_of_memory("init_hard_links");

There are certainly better ways to do this.  To start with, hlink.c
only needs to even *think* about non-directories which have nlinks>1.

-- 
Martin




Reply via email to