Page MenuHomeFreeBSD

ext2fs: Add dir_nlink feature support
ClosedPublic

Authored by fsu on Jun 15 2017, 8:21 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sat, Nov 23, 1:39 PM
Unknown Object (File)
Tue, Nov 19, 11:19 PM
Unknown Object (File)
Sun, Nov 3, 11:01 PM
Unknown Object (File)
Sun, Nov 3, 11:00 PM
Unknown Object (File)
Sun, Nov 3, 11:00 PM
Unknown Object (File)
Sun, Nov 3, 11:00 PM
Unknown Object (File)
Sun, Nov 3, 11:00 PM
Unknown Object (File)
Sun, Nov 3, 11:00 PM
Subscribers

Details

Test Plan

The script from attachment could be uses{F1418347}.

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

This patch doesn't implement dir_nlink: by enabling dir_nlink you should be able to set up more than 65000 links. (linux extends the number of links somewhere, don't remember).

65000 should be supported for the base ext4, however we don't for a simple reason:

http://src.illumos.org/source/xref/freebsd-head/sys/fs/ext2fs/ext2_vnops.c#344

va_nlink is of type short.

sys/fs/ext2fs/ext2_dir.h
76

This is actually EXT4_LINK_MAX.
For EXT2 the limit is still 32000

But we able to set 65000. I tested it on x86_64, but I can see the same for 32 bit platforms _types.h:
typedef uint64_t nlink_t; /* link count */

In case of linux, if n_link > 65000, the n_link count is immediately set to 1. The same logic is represented in the patch.

sys/fs/ext2fs/ext2_dir.h
76

Yep, if it needed I can make:
#define EXT2_LINK_MAX 32000
#define EXT4_LINK_MAX 65000

In D11210#231998, @thisisadrgreenthumb_gmail.com wrote:

But we able to set 65000. I tested it on x86_64, but I can see the same for 32 bit platforms _types.h:
typedef uint64_t nlink_t; /* link count */

Actually: va_nlink is now nlink_t, this was a change for INO64, but the illumos' opengrok hasn't caught up.
The change is fine, but only on -current.

In case of linux, if n_link > 65000, the n_link count is immediately set to 1. The same logic is represented in the patch.

OK. Still we have to enforce the 32000 limit on ext2.

Restrict LINK_MAX to 32k

I don't see EXT4_LINK_MAX (?):

in the case where we are using EXT4 (extents), without the EXT2F_ROCOMPAT_DIR_NLINK feature, we should enforce the 54000 limit.

Use _NLINK_MAX limit depending of extfs version.

For the case where EXT2F_ROCOMPAT_DIR_NLINK is defined, should be able to handle more that 65000 links.
This code doesn't support that case so we are not really supporting the feature.

I suspect the feature is not really usable on ext2.

sys/fs/ext2fs/ext2_vnops.c
676

Note that this function never returns a number bigger that 65000.

In D11210#233013, @pfg wrote:

For the case where EXT2F_ROCOMPAT_DIR_NLINK is defined, should be able to handle more that 65000 links.
This code doesn't support that case so we are not really supporting the feature.

I suspect the feature is not really usable on ext2.

In D11210#233013, @pfg wrote:

For the case where EXT2F_ROCOMPAT_DIR_NLINK is defined, should be able to handle more that 65000 links.
This code doesn't support that case so we are not really supporting the feature.

No, we should not. You can see it here:https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout

0x20 Indicates that the old ext3 32,000 subdirectory limit no longer applies (RO_COMPAT_DIR_NLINK).

The case when > 65000 is supported is when dir_index feature applied. It could be checked on linux:
root@user:~ # mkfs.ext2 -O ^dir_index -O dir_nlink /dev/md1
mke2fs 1.43.4 (31-Jan-2017)
Creating filesystem with 4194304 4k blocks and 1048576 inodes
Filesystem UUID: 832ff2e8-b1c2-42f1-838a-2e64daf151ab
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000

Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done

root@user:~ # dumpe2fs /dev/md1 | head -20
dumpe2fs 1.43.4 (31-Jan-2017)
Filesystem volume name: <none>
Last mounted on: <not available>
Filesystem UUID: 832ff2e8-b1c2-42f1-838a-2e64daf151ab
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: ext_attr resize_inode filetype sparse_super large_file dir_nlink

...

root@user:/mnt/TEST_DIR# for i in {1..70000}; do mkdir dir_$i; done
mkdir: cannot create directory ‘dir_64999’: Too many links

I suspect the feature is not really usable on ext2.

And, unfortunately it is usable too.

Fix ext2_max_nlink() function.

Approved with a sidenote:
The helpers to increment and decrement i_nlink involve a deviation to how it's done in UFS.
I don't see any way around it, it's just the way ext4 works.

This revision is now accepted and ready to land.Jun 19 2017, 4:37 PM
pfg requested changes to this revision.Jun 19 2017, 5:14 PM

There is something wrong still, we cannot just bump i_nlink without considering how the information is stored on disk,

http://src.illumos.org/source/xref/freebsd-head/sys/fs/ext2fs/ext2_inode_cnv.c#89

In particular, e2di_nlink is still uint16_t (see ext2_dinode.h). The higher bits must be stored somewhere.

This revision now requires changes to proceed.Jun 19 2017, 5:14 PM
In D11210#233240, @pfg wrote:

There is something wrong still, we cannot just bump i_nlink without considering how the information is stored on disk,

http://src.illumos.org/source/xref/freebsd-head/sys/fs/ext2fs/ext2_inode_cnv.c#89

In particular, e2di_nlink is still uint16_t (see ext2_dinode.h). The higher bits must be stored somewhere.

Nevermind ... I forgot we never get to write when dir_nlink is set.

The 65000 of course does fit in e2di_nlink.

This revision is now accepted and ready to land.Jun 19 2017, 5:35 PM
This revision was automatically updated to reflect the committed changes.