Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160151256
D11210.id29784.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D11210.id29784.diff
View Options
Index: sys/fs/ext2fs/ext2_dir.h
===================================================================
--- sys/fs/ext2fs/ext2_dir.h
+++ sys/fs/ext2fs/ext2_dir.h
@@ -74,6 +74,7 @@
* Maximal count of links to a file
*/
#define EXT2_LINK_MAX 32000
+#define EXT4_LINK_MAX 65000
/*
* Ext2 directory file types. Only the low 3 bits are used. The
Index: sys/fs/ext2fs/ext2_vnops.c
===================================================================
--- sys/fs/ext2fs/ext2_vnops.c
+++ sys/fs/ext2fs/ext2_vnops.c
@@ -672,6 +672,19 @@
return (error);
}
+static int
+ext2_max_nlink(struct inode *ip)
+{
+ struct m_ext2fs *fs;
+
+ fs = ip->i_e2fs;
+
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_EXTENTS))
+ return (EXT4_LINK_MAX);
+ else
+ return (EXT2_LINK_MAX);
+}
+
/*
* link vnode call
*/
@@ -689,7 +702,7 @@
panic("ext2_link: no name");
#endif
ip = VTOI(vp);
- if ((nlink_t)ip->i_nlink >= EXT2_LINK_MAX) {
+ if ((nlink_t)ip->i_nlink >= ext2_max_nlink(ip)) {
error = EMLINK;
goto out;
}
@@ -710,6 +723,31 @@
return (error);
}
+static int
+ext2_inc_nlink(struct inode *ip)
+{
+
+ ip->i_nlink++;
+
+ if (ext2_htree_has_idx(ip) && ip->i_nlink > 1) {
+ if (ip->i_nlink >= ext2_max_nlink(ip) || ip->i_nlink == 2)
+ ip->i_nlink = 1;
+ } else if (ip->i_nlink > ext2_max_nlink(ip)) {
+ ip->i_nlink--;
+ return (EMLINK);
+ }
+
+ return (0);
+}
+
+static void
+ext2_dec_nlink(struct inode *ip)
+{
+
+ if (!S_ISDIR(ip->i_mode) || ip->i_nlink > 2)
+ ip->i_nlink--;
+}
+
/*
* Rename system call.
* rename("foo", "bar");
@@ -792,7 +830,7 @@
goto abortit;
dp = VTOI(fdvp);
ip = VTOI(fvp);
- if (ip->i_nlink >= EXT2_LINK_MAX) {
+ if (ip->i_nlink >= ext2_max_nlink(ip) && !ext2_htree_has_idx(ip)) {
VOP_UNLOCK(fvp, 0);
error = EMLINK;
goto abortit;
@@ -835,7 +873,7 @@
* completing our work, the link count
* may be wrong, but correctable.
*/
- ip->i_nlink++;
+ ext2_inc_nlink(ip);
ip->i_flag |= IN_CHANGE;
if ((error = ext2_update(fvp, !DOINGASYNC(fvp))) != 0) {
VOP_UNLOCK(fvp, 0);
@@ -890,11 +928,10 @@
* parent we don't fool with the link count.
*/
if (doingdirectory && newparent) {
- if ((nlink_t)dp->i_nlink >= EXT2_LINK_MAX) {
- error = EMLINK;
+ error = ext2_inc_nlink(dp);
+ if (error)
goto bad;
- }
- dp->i_nlink++;
+
dp->i_flag |= IN_CHANGE;
error = ext2_update(tdvp, !DOINGASYNC(tdvp));
if (error)
@@ -903,7 +940,7 @@
error = ext2_direnter(ip, tdvp, tcnp);
if (error) {
if (doingdirectory && newparent) {
- dp->i_nlink--;
+ ext2_dec_nlink(dp);
dp->i_flag |= IN_CHANGE;
(void)ext2_update(tdvp, 1);
}
@@ -936,8 +973,7 @@
* (both directories, or both not directories).
*/
if ((xp->i_mode & IFMT) == IFDIR) {
- if (!ext2_dirempty(xp, dp->i_number, tcnp->cn_cred) ||
- xp->i_nlink > 2) {
+ if (!ext2_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
error = ENOTEMPTY;
goto bad;
}
@@ -960,7 +996,7 @@
* of the target directory.
*/
if (doingdirectory && !newparent) {
- dp->i_nlink--;
+ ext2_dec_nlink(dp);
dp->i_flag |= IN_CHANGE;
}
vput(tdvp);
@@ -974,7 +1010,7 @@
* it above, as the remaining link would point to
* a directory without "." or ".." entries.
*/
- xp->i_nlink--;
+ ext2_dec_nlink(xp);
if (doingdirectory) {
if (--xp->i_nlink != 0)
panic("ext2_rename: linked directory");
@@ -1031,7 +1067,7 @@
* and ".." set to point to the new parent.
*/
if (doingdirectory && newparent) {
- dp->i_nlink--;
+ ext2_dec_nlink(dp);
dp->i_flag |= IN_CHANGE;
error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
sizeof(struct dirtemplate), (off_t)0,
@@ -1060,7 +1096,7 @@
}
error = ext2_dirremove(fdvp, fcnp);
if (!error) {
- xp->i_nlink--;
+ ext2_dec_nlink(xp);
xp->i_flag |= IN_CHANGE;
}
xp->i_flag &= ~IN_RENAME;
@@ -1080,7 +1116,7 @@
if (doingdirectory)
ip->i_flag &= ~IN_RENAME;
if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
- ip->i_nlink--;
+ ext2_dec_nlink(ip);
ip->i_flag |= IN_CHANGE;
ip->i_flag &= ~IN_RENAME;
vput(fvp);
@@ -1255,7 +1291,8 @@
panic("ext2_mkdir: no name");
#endif
dp = VTOI(dvp);
- if ((nlink_t)dp->i_nlink >= EXT2_LINK_MAX) {
+ if ((nlink_t)dp->i_nlink >= ext2_max_nlink(dp) &&
+ !ext2_htree_has_idx(dp)) {
error = EMLINK;
goto out;
}
@@ -1306,7 +1343,7 @@
* be done before reference is created
* so reparation is possible if we crash.
*/
- dp->i_nlink++;
+ ext2_inc_nlink(dp);
dp->i_flag |= IN_CHANGE;
error = ext2_update(dvp, !DOINGASYNC(dvp));
if (error)
@@ -1333,7 +1370,7 @@
IO_NODELOCKED | IO_SYNC | IO_NOMACCHECK, cnp->cn_cred, NOCRED,
NULL, NULL);
if (error) {
- dp->i_nlink--;
+ ext2_dec_nlink(dp);
dp->i_flag |= IN_CHANGE;
goto bad;
}
@@ -1358,7 +1395,7 @@
/* Directory set up, now install its entry in the parent directory. */
error = ext2_direnter(ip, dvp, cnp);
if (error) {
- dp->i_nlink--;
+ ext2_dec_nlink(dp);
dp->i_flag |= IN_CHANGE;
}
bad:
@@ -1400,7 +1437,7 @@
* the current directory and thus be
* non-empty.)
*/
- if (ip->i_nlink != 2 || !ext2_dirempty(ip, dp->i_number, cnp->cn_cred)) {
+ if (!ext2_dirempty(ip, dp->i_number, cnp->cn_cred)) {
error = ENOTEMPTY;
goto out;
}
@@ -1417,22 +1454,15 @@
error = ext2_dirremove(dvp, cnp);
if (error)
goto out;
- dp->i_nlink--;
+ ext2_dec_nlink(dp);
dp->i_flag |= IN_CHANGE;
cache_purge(dvp);
VOP_UNLOCK(dvp, 0);
/*
* Truncate inode. The only stuff left
- * in the directory is "." and "..". The
- * "." reference is inconsequential since
- * we're quashing it. The ".." reference
- * has already been adjusted above. We've
- * removed the "." reference and the reference
- * in the parent directory, but there may be
- * other hard links so decrement by 2 and
- * worry about them later.
+ * in the directory is "." and "..".
*/
- ip->i_nlink -= 2;
+ ip->i_nlink = 0;
error = ext2_truncate(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
cnp->cn_thread);
cache_purge(ITOV(ip));
@@ -1592,7 +1622,10 @@
switch (ap->a_name) {
case _PC_LINK_MAX:
- *ap->a_retval = EXT2_LINK_MAX;
+ if (ext2_htree_has_idx(VTOI(ap->a_vp)))
+ *ap->a_retval = INT_MAX;
+ else
+ *ap->a_retval = ext2_max_nlink(VTOI(ap->a_vp));
break;
case _PC_NAME_MAX:
*ap->a_retval = NAME_MAX;
Index: sys/fs/ext2fs/ext2fs.h
===================================================================
--- sys/fs/ext2fs/ext2fs.h
+++ sys/fs/ext2fs/ext2fs.h
@@ -259,6 +259,7 @@
#define EXT2F_COMPAT_SUPP EXT2F_COMPAT_DIRHASHINDEX
#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER | \
EXT2F_ROCOMPAT_LARGEFILE | \
+ EXT2F_ROCOMPAT_DIR_NLINK | \
EXT2F_ROCOMPAT_EXTRA_ISIZE)
#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
#define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_EXTENTS | \
Index: sys/fs/ext2fs/inode.h
===================================================================
--- sys/fs/ext2fs/inode.h
+++ sys/fs/ext2fs/inode.h
@@ -91,7 +91,7 @@
/* Fields from struct dinode in UFS. */
uint16_t i_mode; /* IFMT, permissions; see below. */
- int16_t i_nlink; /* File link count. */
+ int32_t i_nlink; /* File link count. */
uint32_t i_uid; /* File owner. */
uint32_t i_gid; /* File group. */
uint64_t i_size; /* File byte count. */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jun 22, 7:19 PM (6 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34206394
Default Alt Text
D11210.id29784.diff (7 KB)
Attached To
Mode
D11210: ext2fs: Add dir_nlink feature support
Attached
Detach File
Event Timeline
Log In to Comment