Module Name: src Committed By: jdolecek Date: Mon Aug 15 18:38:10 UTC 2016
Modified Files: src/sys/ufs/ext2fs: ext2fs.h ext2fs_rename.c ext2fs_vnops.c Log Message: bump link limit to 65000 for files, and add support for EXT2F_ROCOMPAT_DIR_NLINK to make link count unlimited for directories To generate a diff of this commit: cvs rdiff -u -r1.45 -r1.46 src/sys/ufs/ext2fs/ext2fs.h cvs rdiff -u -r1.10 -r1.11 src/sys/ufs/ext2fs/ext2fs_rename.c cvs rdiff -u -r1.124 -r1.125 src/sys/ufs/ext2fs/ext2fs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/ufs/ext2fs/ext2fs.h diff -u src/sys/ufs/ext2fs/ext2fs.h:1.45 src/sys/ufs/ext2fs/ext2fs.h:1.46 --- src/sys/ufs/ext2fs/ext2fs.h:1.45 Sun Aug 14 11:42:50 2016 +++ src/sys/ufs/ext2fs/ext2fs.h Mon Aug 15 18:38:10 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs.h,v 1.45 2016/08/14 11:42:50 jdolecek Exp $ */ +/* $NetBSD: ext2fs.h,v 1.46 2016/08/15 18:38:10 jdolecek Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -128,6 +128,13 @@ #define MINFREE 5 /* + * This is maximum amount of links allowed for files. For directories, + * going over this means setting DIR_NLINK feature. + */ +#define EXT2FS_LINK_MAX 65000 +#define EXT2FS_LINK_INF 1 /* link count unknown */ + +/* * Super block for an ext2fs file system. */ struct ext2fs { @@ -358,7 +365,8 @@ struct m_ext2fs { #define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \ | EXT2F_ROCOMPAT_LARGEFILE \ | EXT2F_ROCOMPAT_HUGE_FILE \ - | EXT2F_ROCOMPAT_EXTRA_ISIZE) + | EXT2F_ROCOMPAT_EXTRA_ISIZE \ + | EXT2F_ROCOMPAT_DIR_NLINK) #define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE \ | EXT2F_INCOMPAT_EXTENTS) Index: src/sys/ufs/ext2fs/ext2fs_rename.c diff -u src/sys/ufs/ext2fs/ext2fs_rename.c:1.10 src/sys/ufs/ext2fs/ext2fs_rename.c:1.11 --- src/sys/ufs/ext2fs/ext2fs_rename.c:1.10 Sat Aug 13 07:40:10 2016 +++ src/sys/ufs/ext2fs/ext2fs_rename.c Mon Aug 15 18:38:10 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_rename.c,v 1.10 2016/08/13 07:40:10 christos Exp $ */ +/* $NetBSD: ext2fs_rename.c,v 1.11 2016/08/15 18:38:10 jdolecek Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_rename.c,v 1.10 2016/08/13 07:40:10 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_rename.c,v 1.11 2016/08/15 18:38:10 jdolecek Exp $"); #include <sys/param.h> #include <sys/buf.h> @@ -307,7 +307,7 @@ ext2fs_gro_rename(struct mount *mp, kaut * We shall need to temporarily bump the link count, so make * sure there is room to do so. */ - if ((nlink_t)VTOI(fvp)->i_e2fs_nlink >= LINK_MAX) + if ((nlink_t)VTOI(fvp)->i_e2fs_nlink >= EXT2FS_LINK_MAX) return EMLINK; directory_p = (fvp->v_type == VDIR); @@ -330,7 +330,7 @@ ext2fs_gro_rename(struct mount *mp, kaut * may be wrong, but correctable. */ - KASSERT((nlink_t)VTOI(fvp)->i_e2fs_nlink < LINK_MAX); + KASSERT((nlink_t)VTOI(fvp)->i_e2fs_nlink < EXT2FS_LINK_MAX); VTOI(fvp)->i_e2fs_nlink++; VTOI(fvp)->i_flag |= IN_CHANGE; error = ext2fs_update(fvp, NULL, NULL, UPDATE_WAIT); @@ -352,11 +352,11 @@ ext2fs_gro_rename(struct mount *mp, kaut * parent we don't fool with the link count. */ if (directory_p && reparent_p) { - if ((nlink_t)VTOI(tdvp)->i_e2fs_nlink >= LINK_MAX) { + if ((nlink_t)VTOI(tdvp)->i_e2fs_nlink >= EXT2FS_LINK_MAX) { error = EMLINK; goto whymustithurtsomuch; } - KASSERT((nlink_t)VTOI(tdvp)->i_e2fs_nlink < LINK_MAX); + KASSERT((nlink_t)VTOI(tdvp)->i_e2fs_nlink < EXT2FS_LINK_MAX); VTOI(tdvp)->i_e2fs_nlink++; VTOI(tdvp)->i_flag |= IN_CHANGE; error = ext2fs_update(tdvp, NULL, NULL, UPDATE_WAIT); Index: src/sys/ufs/ext2fs/ext2fs_vnops.c diff -u src/sys/ufs/ext2fs/ext2fs_vnops.c:1.124 src/sys/ufs/ext2fs/ext2fs_vnops.c:1.125 --- src/sys/ufs/ext2fs/ext2fs_vnops.c:1.124 Mon Aug 15 18:29:34 2016 +++ src/sys/ufs/ext2fs/ext2fs_vnops.c Mon Aug 15 18:38:10 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vnops.c,v 1.124 2016/08/15 18:29:34 jdolecek Exp $ */ +/* $NetBSD: ext2fs_vnops.c,v 1.125 2016/08/15 18:38:10 jdolecek Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.124 2016/08/15 18:29:34 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.125 2016/08/15 18:38:10 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -626,7 +626,7 @@ ext2fs_link(void *v) goto out2; } ip = VTOI(vp); - if ((nlink_t)ip->i_e2fs_nlink >= LINK_MAX) { + if ((nlink_t)ip->i_e2fs_nlink >= EXT2FS_LINK_MAX) { VOP_ABORTOP(dvp, cnp); error = EMLINK; goto out1; @@ -677,11 +677,6 @@ ext2fs_mkdir(void *v) ulr = &VTOI(dvp)->i_crap; UFS_CHECK_CRAPCOUNTER(VTOI(dvp)); - if ((nlink_t)dp->i_e2fs_nlink >= LINK_MAX) { - error = EMLINK; - goto out; - } - /* * Acquire the inode, but don't sync/direnter it just yet */ @@ -700,7 +695,24 @@ ext2fs_mkdir(void *v) * be done before reference is created * so reparation is possible if we crash. */ - dp->i_e2fs_nlink++; + if (dp->i_e2fs_nlink != EXT2FS_LINK_INF) + dp->i_e2fs_nlink++; + + /* + * If we hit the link limit, for directories just set the nlink + * to special value 1, which means the link count is bigger + * than EXT2FS_LINK_MAX. + */ + if ((nlink_t)dp->i_e2fs_nlink >= EXT2FS_LINK_MAX) { + dp->i_e2fs_nlink = EXT2FS_LINK_INF; + + /* set the feature flag DIR_NLINK if not set already */ + if (!EXT2F_HAS_ROCOMPAT_FEATURE(dp->i_e2fs, EXT2F_ROCOMPAT_DIR_NLINK)) { + dp->i_e2fs->e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_DIR_NLINK; + dp->i_e2fs->e2fs_fmod = 1; + } + } + dp->i_flag |= IN_CHANGE; if ((error = ext2fs_update(dvp, NULL, NULL, UPDATE_DIROP)) != 0) goto bad; @@ -725,7 +737,8 @@ ext2fs_mkdir(void *v) sizeof (dirtemplate), (off_t)0, IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (size_t *)0, NULL); if (error) { - dp->i_e2fs_nlink--; + if (dp->i_e2fs_nlink != EXT2FS_LINK_INF) + dp->i_e2fs_nlink--; dp->i_flag |= IN_CHANGE; goto bad; } @@ -734,7 +747,8 @@ ext2fs_mkdir(void *v) else { error = ext2fs_setsize(ip, VTOI(dvp)->i_e2fs->e2fs_bsize); if (error) { - dp->i_e2fs_nlink--; + if (dp->i_e2fs_nlink != EXT2FS_LINK_INF) + dp->i_e2fs_nlink--; dp->i_flag |= IN_CHANGE; goto bad; } @@ -745,7 +759,8 @@ ext2fs_mkdir(void *v) /* Directory set up, now install its entry in the parent directory. */ error = ext2fs_direnter(ip, dvp, ulr, cnp); if (error != 0) { - dp->i_e2fs_nlink--; + if (dp->i_e2fs_nlink != EXT2FS_LINK_INF) + dp->i_e2fs_nlink--; dp->i_flag |= IN_CHANGE; } bad: @@ -807,7 +822,7 @@ ext2fs_rmdir(void *v) * non-empty.) */ error = 0; - if (ip->i_e2fs_nlink != 2 || + if ((ip->i_e2fs_nlink != 2 && ip->i_e2fs_nlink != EXT2FS_LINK_INF) || !ext2fs_dirempty(ip, dp->i_number, cnp->cn_cred)) { error = ENOTEMPTY; goto out; @@ -825,7 +840,8 @@ ext2fs_rmdir(void *v) error = ext2fs_dirremove(dvp, ulr, cnp); if (error != 0) goto out; - dp->i_e2fs_nlink--; + if (dp->i_e2fs_nlink != EXT2FS_LINK_INF) + dp->i_e2fs_nlink--; dp->i_flag |= IN_CHANGE; VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); cache_purge(dvp);