diff --git a/libexec/lfs_cleanerd/cleaner.h b/libexec/lfs_cleanerd/cleaner.h index b10a52aa2b72..268e6beaf3bd 100644 --- a/libexec/lfs_cleanerd/cleaner.h +++ b/libexec/lfs_cleanerd/cleaner.h @@ -21,7 +21,8 @@ struct clfs { struct dlfs64 u_64; } lfs_dlfs_u; unsigned lfs_is64 : 1, - lfs_dobyteswap : 1; + lfs_dobyteswap : 1, + lfs_hasolddirfmt : 1; /* Ifile */ int clfs_ifilefd; /* Ifile file descriptor */ diff --git a/libexec/lfs_cleanerd/lfs_cleanerd.c b/libexec/lfs_cleanerd/lfs_cleanerd.c index a6bffd642700..c400b1ba3cd4 100644 --- a/libexec/lfs_cleanerd/lfs_cleanerd.c +++ b/libexec/lfs_cleanerd/lfs_cleanerd.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_cleanerd.c,v 1.52 2015/09/01 06:12:04 dholland Exp $ */ +/* $NetBSD: lfs_cleanerd.c,v 1.53 2015/09/01 06:16:58 dholland Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -270,6 +270,8 @@ init_fs(struct clfs *fs, char *fsname) } fs->lfs_is64 = 0; /* XXX notyet */ fs->lfs_dobyteswap = 0; /* XXX notyet */ + /* XXX: can this ever need to be set? does the cleaner even care? */ + fs->lfs_hasolddirfmt = 0; /* If this is not a version 2 filesystem, complain and exit */ if (lfs_sb_getversion(fs) != 2) { diff --git a/sbin/fsck_lfs/dir.c b/sbin/fsck_lfs/dir.c index 5f606d61f61c..a8669c340432 100644 --- a/sbin/fsck_lfs/dir.c +++ b/sbin/fsck_lfs/dir.c @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.37 2015/09/01 06:08:37 dholland Exp $ */ +/* $NetBSD: dir.c,v 1.38 2015/09/01 06:16:58 dholland Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -70,6 +70,7 @@ struct lfs_dirtemplate dirhead = { .dotdot_namlen = 2, .dotdot_name = ".." }; +#if 0 struct lfs_odirtemplate odirhead = { .dot_ino = 0, .dot_reclen = 12, @@ -80,6 +81,7 @@ struct lfs_odirtemplate odirhead = { .dotdot_namlen = 2, .dotdot_name = ".." }; +#endif static int expanddir(struct uvnode *, union lfs_dinode *, char *); static void freedir(ino_t, ino_t); @@ -193,8 +195,8 @@ fsck_readdir(struct uvnode *vp, struct inodesc *idesc) dp = (struct lfs_direct *) (bp->b_data + idesc->id_loc); dp->d_reclen = LFS_DIRBLKSIZ; dp->d_ino = 0; - dp->d_type = 0; - dp->d_namlen = 0; + lfs_dir_settype(fs, dp, LFS_DT_UNKNOWN); + lfs_dir_setnamlen(fs, dp, 0); dp->d_name[0] = '\0'; if (fix) VOP_BWRITE(bp); @@ -266,9 +268,9 @@ dircheck(struct inodesc *idesc, struct lfs_direct *dp) } if (dp->d_ino == 0) return (1); - size = LFS_DIRSIZ(0, dp, 0); - namlen = dp->d_namlen; - type = dp->d_type; + size = LFS_DIRSIZ(fs, dp); + namlen = lfs_dir_getnamlen(fs, dp); + type = lfs_dir_gettype(fs, dp); if (dp->d_reclen < size || idesc->id_filesize < size || /* namlen > MAXNAMLEN || */ @@ -366,12 +368,14 @@ mkentry(struct inodesc *idesc) { struct lfs_direct *dirp = idesc->id_dirp; struct lfs_direct newent; + unsigned namlen; int newlen, oldlen; - newent.d_namlen = strlen(idesc->id_name); - newlen = LFS_DIRSIZ(0, &newent, 0); + namlen = strlen(idesc->id_name); + lfs_dir_setnamlen(fs, &newent, namlen); + newlen = LFS_DIRSIZ(fs, &newent); if (dirp->d_ino != 0) - oldlen = LFS_DIRSIZ(0, dirp, 0); + oldlen = LFS_DIRSIZ(fs, dirp); else oldlen = 0; if (dirp->d_reclen - oldlen < newlen) @@ -381,9 +385,9 @@ mkentry(struct inodesc *idesc) dirp = (struct lfs_direct *) (((char *) dirp) + oldlen); dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ dirp->d_reclen = newent.d_reclen; - dirp->d_type = typemap[idesc->id_parent]; - dirp->d_namlen = newent.d_namlen; - memcpy(dirp->d_name, idesc->id_name, (size_t) dirp->d_namlen + 1); + lfs_dir_settype(fs, dirp, typemap[idesc->id_parent]); + lfs_dir_setnamlen(fs, dirp, namlen); + memcpy(dirp->d_name, idesc->id_name, (size_t)namlen + 1); return (ALTERED | STOP); } @@ -391,11 +395,13 @@ static int chgino(struct inodesc *idesc) { struct lfs_direct *dirp = idesc->id_dirp; + int namlen; - if (memcmp(dirp->d_name, idesc->id_name, (int) dirp->d_namlen + 1)) + namlen = lfs_dir_getnamlen(fs, dirp); + if (memcmp(dirp->d_name, idesc->id_name, namlen + 1)) return (KEEPON); dirp->d_ino = idesc->id_parent; - dirp->d_type = typemap[idesc->id_parent]; + lfs_dir_settype(fs, dirp, typemap[idesc->id_parent]); return (ALTERED | STOP); } diff --git a/sbin/fsck_lfs/inode.c b/sbin/fsck_lfs/inode.c index dc4b5600c03d..f020b051e70c 100644 --- a/sbin/fsck_lfs/inode.c +++ b/sbin/fsck_lfs/inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: inode.c,v 1.62 2015/09/01 06:15:02 dholland Exp $ */ +/* $NetBSD: inode.c,v 1.63 2015/09/01 06:16:58 dholland Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. @@ -507,8 +507,11 @@ findname(struct inodesc * idesc) if (dirp->d_ino != idesc->id_parent) return (KEEPON); - if ((len = dirp->d_namlen + 1) > MAXPATHLEN) { + len = lfs_dir_getnamlen(fs, dirp) + 1; + /* XXX this is wrong: namlen+1 can be up to MAXPATHLEN+1 */ + if (len > MAXPATHLEN) { /* Truncate it but don't overflow the buffer */ + /* XXX: this case doesn't null-terminate the result */ len = MAXPATHLEN; } /* this is namebuf with utils.h */ diff --git a/sbin/fsck_lfs/pass2.c b/sbin/fsck_lfs/pass2.c index 47173328faee..32fa71a28e23 100644 --- a/sbin/fsck_lfs/pass2.c +++ b/sbin/fsck_lfs/pass2.c @@ -1,4 +1,4 @@ -/* $NetBSD: pass2.c,v 1.26 2015/08/12 18:28:00 dholland Exp $ */ +/* $NetBSD: pass2.c,v 1.27 2015/09/01 06:16:58 dholland Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -229,24 +229,26 @@ pass2check(struct inodesc * idesc) if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { if (dirp->d_ino != idesc->id_number) { direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); - dirp->d_ino = idesc->id_number; - if (reply("FIX") == 1) + if (reply("FIX") == 1) { + dirp->d_ino = idesc->id_number; ret |= ALTERED; + } } - if (dirp->d_type != LFS_DT_DIR) { + if (lfs_dir_gettype(fs, dirp) != LFS_DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); - dirp->d_type = LFS_DT_DIR; - if (reply("FIX") == 1) + if (reply("FIX") == 1) { + lfs_dir_settype(fs, dirp, LFS_DT_DIR); ret |= ALTERED; + } } goto chk1; } direrror(idesc->id_number, "MISSING '.'"); proto.d_ino = idesc->id_number; - proto.d_type = LFS_DT_DIR; - proto.d_namlen = 1; + lfs_dir_settype(fs, &proto, LFS_DT_DIR); + lfs_dir_setnamlen(fs, &proto, 1); (void) strlcpy(proto.d_name, ".", sizeof(proto.d_name)); - entrysize = LFS_DIRSIZ(0, &proto, 0); + entrysize = LFS_DIRSIZ(fs, &proto); if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); @@ -274,12 +276,12 @@ chk1: goto chk2; inp = getinoinfo(idesc->id_number); proto.d_ino = inp->i_parent; - proto.d_type = LFS_DT_DIR; - proto.d_namlen = 2; + lfs_dir_settype(fs, &proto, LFS_DT_DIR); + lfs_dir_setnamlen(fs, &proto, 2); (void) strlcpy(proto.d_name, "..", sizeof(proto.d_name)); - entrysize = LFS_DIRSIZ(0, &proto, 0); + entrysize = LFS_DIRSIZ(fs, &proto); if (idesc->id_entryno == 0) { - n = LFS_DIRSIZ(0, dirp, 0); + n = LFS_DIRSIZ(fs, dirp); if (dirp->d_reclen < n + entrysize) goto chk2; proto.d_reclen = dirp->d_reclen - n; @@ -292,9 +294,9 @@ chk1: } if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { inp->i_dotdot = dirp->d_ino; - if (dirp->d_type != LFS_DT_DIR) { + if (lfs_dir_gettype(fs, dirp) != LFS_DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); - dirp->d_type = LFS_DT_DIR; + lfs_dir_settype(fs, dirp, LFS_DT_DIR); if (reply("FIX") == 1) ret |= ALTERED; } @@ -327,21 +329,23 @@ chk1: chk2: if (dirp->d_ino == 0) return (ret | KEEPON); - if (dirp->d_namlen <= 2 && + if (lfs_dir_getnamlen(fs, dirp) <= 2 && dirp->d_name[0] == '.' && idesc->id_entryno >= 2) { - if (dirp->d_namlen == 1) { + if (lfs_dir_getnamlen(fs, dirp) == 1) { direrror(idesc->id_number, "EXTRA '.' ENTRY"); - dirp->d_ino = 0; - if (reply("FIX") == 1) + if (reply("FIX") == 1) { + dirp->d_ino = 0; ret |= ALTERED; + } return (KEEPON | ret); } if (dirp->d_name[1] == '.') { direrror(idesc->id_number, "EXTRA '..' ENTRY"); - dirp->d_ino = 0; - if (reply("FIX") == 1) + if (reply("FIX") == 1) { + dirp->d_ino = 0; ret |= ALTERED; + } return (KEEPON | ret); } } @@ -352,20 +356,22 @@ chk2: n = reply("REMOVE"); } else if (dirp->d_ino == LFS_IFILE_INUM && idesc->id_number == ULFS_ROOTINO) { - if (dirp->d_type != LFS_DT_REG) { + if (lfs_dir_gettype(fs, dirp) != LFS_DT_REG) { fileerror(idesc->id_number, dirp->d_ino, "BAD TYPE FOR IFILE"); - dirp->d_type = LFS_DT_REG; - if (reply("FIX") == 1) + if (reply("FIX") == 1) { + lfs_dir_settype(fs, dirp, LFS_DT_REG); ret |= ALTERED; + } } - } else if (((dirp->d_ino == ULFS_WINO && (dirp->d_type != LFS_DT_WHT)) || - (dirp->d_ino != ULFS_WINO && dirp->d_type == LFS_DT_WHT))) { + } else if (((dirp->d_ino == ULFS_WINO && lfs_dir_gettype(fs, dirp) != LFS_DT_WHT) || + (dirp->d_ino != ULFS_WINO && lfs_dir_gettype(fs, dirp) == LFS_DT_WHT))) { fileerror(idesc->id_number, dirp->d_ino, "BAD WHITEOUT ENTRY"); dirp->d_ino = ULFS_WINO; - dirp->d_type = LFS_DT_WHT; - if (reply("FIX") == 1) + if (reply("FIX") == 1) { + lfs_dir_settype(fs, dirp, LFS_DT_WHT); ret |= ALTERED; + } } else { again: switch (statemap[dirp->d_ino]) { @@ -418,13 +424,13 @@ again: /* fall through */ case FSTATE: - if (dirp->d_type != typemap[dirp->d_ino]) { + if (lfs_dir_gettype(fs, dirp) != typemap[dirp->d_ino]) { fileerror(idesc->id_number, dirp->d_ino, "BAD TYPE VALUE"); if (debug) pwarn("dir has %d, typemap has %d\n", - dirp->d_type, typemap[dirp->d_ino]); - dirp->d_type = typemap[dirp->d_ino]; + lfs_dir_gettype(fs, dirp), typemap[dirp->d_ino]); + lfs_dir_settype(fs, dirp, typemap[dirp->d_ino]); if (reply("FIX") == 1) ret |= ALTERED; } diff --git a/sbin/newfs_lfs/make_lfs.c b/sbin/newfs_lfs/make_lfs.c index c65937d52426..971f4e6856f4 100644 --- a/sbin/newfs_lfs/make_lfs.c +++ b/sbin/newfs_lfs/make_lfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: make_lfs.c,v 1.48 2015/09/01 06:15:02 dholland Exp $ */ +/* $NetBSD: make_lfs.c,v 1.49 2015/09/01 06:16:58 dholland Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ #if 0 static char sccsid[] = "@(#)lfs.c 8.5 (Berkeley) 5/24/95"; #else -__RCSID("$NetBSD: make_lfs.c,v 1.48 2015/09/01 06:15:02 dholland Exp $"); +__RCSID("$NetBSD: make_lfs.c,v 1.49 2015/09/01 06:16:58 dholland Exp $"); #endif #endif /* not lint */ @@ -243,24 +243,62 @@ static const struct lfs lfs_default; #define UMASK 0755 struct lfs_direct lfs_root_dir[] = { - { ULFS_ROOTINO, sizeof(struct lfs_direct), LFS_DT_DIR, 1, "."}, - { ULFS_ROOTINO, sizeof(struct lfs_direct), LFS_DT_DIR, 2, ".."}, - /* { LFS_IFILE_INUM, sizeof(struct lfs_direct), LFS_DT_REG, 5, "ifile"}, */ + { + .d_ino = ULFS_ROOTINO, + .d_reclen = sizeof(struct lfs_direct), + .d_type = LFS_DT_DIR, + .d_namlen = 1, + .d_name = "." + }, + { + .d_ino = ULFS_ROOTINO, + .d_reclen = sizeof(struct lfs_direct), + .d_type = LFS_DT_DIR, + .d_namlen = 2, + .d_name = ".." + }, +/* + { + .d_ino = LFS_IFILE_INUM, + .d_reclen = sizeof(struct lfs_direct), + .d_type = LFS_DT_REG, + .d_namlen = 5, + .d_name = "ifile" + }, +*/ #ifdef MAKE_LF_DIR - { LOSTFOUNDINO, sizeof(struct lfs_direct), LFS_DT_DIR, 10, "lost+found"}, + { + .d_ino = LOSTFOUNDINO, + .d_reclen = sizeof(struct lfs_direct), + .d_type = LFS_DT_DIR, + .d_namlen = 10, + .d_name = "lost+found" + }, #endif }; #ifdef MAKE_LF_DIR struct lfs_direct lfs_lf_dir[] = { - { LOSTFOUNDINO, sizeof(struct lfs_direct), LFS_DT_DIR, 1, "." }, - { ULFS_ROOTINO, sizeof(struct lfs_direct), LFS_DT_DIR, 2, ".." }, + { + .d_ino = LOSTFOUNDINO, + .d_reclen = sizeof(struct lfs_direct), + .d_type = LFS_DT_DIR, + .d_reclen = 1, + .d_name = "." + }, + { + .d_ino = ULFS_ROOTINO, + .d_reclen = sizeof(struct lfs_direct), + .d_type = LFS_DT_DIR, + .d_reclen = 2, + .d_name = ".." + }, }; #endif void pwarn(const char *, ...); static void make_dinode(ino_t, union lfs_dinode *, int, struct lfs *); -static void make_dir( void *, struct lfs_direct *, int); +static void make_dir(struct lfs *, void *, struct lfs_direct *, int); static uint64_t maxfilesize(int); /* @@ -347,21 +385,21 @@ make_dinode(ino_t ino, union lfs_dinode *dip, int nfrags, struct lfs *fs) * entries in protodir fit in the first DIRBLKSIZ. */ static void -make_dir(void *bufp, struct lfs_direct *protodir, int entries) +make_dir(struct lfs *fs, void *bufp, struct lfs_direct *protodir, int entries) { char *cp; int i, spcleft; spcleft = LFS_DIRBLKSIZ; for (cp = bufp, i = 0; i < entries - 1; i++) { - protodir[i].d_reclen = LFS_DIRSIZ(LFS_NEWDIRFMT, &protodir[i], 0); + protodir[i].d_reclen = LFS_DIRSIZ(fs, &protodir[i]); memmove(cp, &protodir[i], protodir[i].d_reclen); cp += protodir[i].d_reclen; if ((spcleft -= protodir[i].d_reclen) < 0) fatal("%s: %s", special, "directory too big"); } protodir[i].d_reclen = spcleft; - memmove(cp, &protodir[i], LFS_DIRSIZ(LFS_NEWDIRFMT, &protodir[i], 0)); + memmove(cp, &protodir[i], LFS_DIRSIZ(fs, &protodir[i])); } int @@ -423,6 +461,7 @@ make_lfs(int devfd, uint secsize, struct dkwedge_info *dkw, int minfree, } fs->lfs_is64 = is64; fs->lfs_dobyteswap = dobyteswap; + fs->lfs_hasolddirfmt = false; fs->lfs_ivnode = vp; fs->lfs_devvp = save_devvp; @@ -797,7 +836,7 @@ make_lfs(int devfd, uint secsize, struct dkwedge_info *dkw, int minfree, VTOI(vp)->i_lfs_fragsize[i - 1] = roundup(LFS_DIRBLKSIZ, lfs_sb_getfsize(fs)); bread(vp, 0, lfs_sb_getfsize(fs), 0, &bp); - make_dir(bp->b_data, lfs_root_dir, + make_dir(fs, bp->b_data, lfs_root_dir, sizeof(lfs_root_dir) / sizeof(struct lfs_direct)); VOP_BWRITE(bp); @@ -817,7 +856,7 @@ make_lfs(int devfd, uint secsize, struct dkwedge_info *dkw, int minfree, VTOI(vp)->i_lfs_fragsize[i - 1] = roundup(DIRBLKSIZ,fs->lfs_fsize); bread(vp, 0, fs->lfs_fsize, 0, &bp); - make_dir(bp->b_data, lfs_lf_dir, + make_dir(fs, bp->b_data, lfs_lf_dir, sizeof(lfs_lf_dir) / sizeof(struct lfs_direct)); VOP_BWRITE(bp); #endif /* MAKE_LF_DIR */ diff --git a/sys/lib/libsa/ufs.c b/sys/lib/libsa/ufs.c index 271bc36c9353..0f5d092236ba 100644 --- a/sys/lib/libsa/ufs.c +++ b/sys/lib/libsa/ufs.c @@ -1,4 +1,4 @@ -/* $NetBSD: ufs.c,v 1.73 2015/09/01 06:12:04 dholland Exp $ */ +/* $NetBSD: ufs.c,v 1.74 2015/09/01 06:16:58 dholland Exp $ */ /*- * Copyright (c) 1993 @@ -108,7 +108,9 @@ struct salfs { struct dlfs u_32; struct dlfs64 u_64; } lfs_dlfs_u; - unsigned lfs_is64 : 1; + unsigned lfs_is64 : 1, + lfs_dobyteswap : 1, + lfs_hasolddirfmt : 1; }; /* Get lfs accessors that use struct salfs. */ #define STRUCT_LFS struct salfs @@ -598,6 +600,8 @@ ufs_open(const char *path, struct open_file *f) #endif #if defined(LIBSA_LFS) fs->lfs_is64 = 0; + fs->lfs_dobyteswap = 0; + fs->lfs_hasolddirfmt = (fs->fs_maxsymlinklen <= 0); #endif #endif diff --git a/sys/ufs/lfs/lfs.h b/sys/ufs/lfs/lfs.h index 18baae34a1c3..dea59e735eab 100644 --- a/sys/ufs/lfs/lfs.h +++ b/sys/ufs/lfs/lfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.h,v 1.184 2015/09/01 06:15:46 dholland Exp $ */ +/* $NetBSD: lfs.h,v 1.185 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp */ /* from NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp */ @@ -340,29 +340,6 @@ #define LFS_IFTODT(mode) (((mode) & 0170000) >> 12) #define LFS_DTTOIF(dirtype) ((dirtype) << 12) -/* - * The LFS_DIRSIZ macro gives the minimum record length which will hold - * the directory entry. This requires the amount of space in struct lfs_direct - * without the d_name field, plus enough space for the name with a terminating - * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. - */ -#define LFS_DIRECTSIZ(namlen) \ - ((sizeof(struct lfs_direct) - (LFS_MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3)) - -#if (BYTE_ORDER == LITTLE_ENDIAN) -#define LFS_DIRSIZ(oldfmt, dp, needswap) \ - (((oldfmt) && !(needswap)) ? \ - LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) -#else -#define LFS_DIRSIZ(oldfmt, dp, needswap) \ - (((oldfmt) && (needswap)) ? \ - LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) -#endif - -/* Constants for the first argument of LFS_DIRSIZ */ -#define LFS_OLDDIRFMT 1 -#define LFS_NEWDIRFMT 0 - /* * Theoretically, directories can be more than 2Gb in length; however, in * practice this seems unlikely. So, we define the type doff_t as a 32-bit @@ -960,7 +937,8 @@ struct lfs { /* These fields are set at mount time and are meaningless on disk. */ unsigned lfs_is64 : 1, /* are we lfs64 or lfs32? */ - lfs_dobyteswap : 1; /* are we opposite-endian? */ + lfs_dobyteswap : 1, /* are we opposite-endian? */ + lfs_hasolddirfmt : 1; /* dir entries have no d_type */ struct segment *lfs_sp; /* current segment being written */ struct vnode *lfs_ivnode; /* vnode for the ifile */ diff --git a/sys/ufs/lfs/lfs_accessors.h b/sys/ufs/lfs/lfs_accessors.h index b99772746575..caefc6af3d58 100644 --- a/sys/ufs/lfs/lfs_accessors.h +++ b/sys/ufs/lfs/lfs_accessors.h @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_accessors.h,v 1.21 2015/09/01 06:13:09 dholland Exp $ */ +/* $NetBSD: lfs_accessors.h,v 1.22 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp */ /* from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp */ @@ -201,6 +201,157 @@ ((fs)->lfs_dobyteswap ? bswap64(val) : (val)) #endif +/* + * For handling directories we will need to know if the volume is + * little-endian. + */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define LFS_LITTLE_ENDIAN_ONDISK(fs) (!(fs)->lfs_dobyteswap) +#else +#define LFS_LITTLE_ENDIAN_ONDISK(fs) ((fs)->lfs_dobyteswap) +#endif + + +/* + * directories + */ + +/* + * The LFS_DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct lfs_direct + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#define LFS_DIRECTSIZ(namlen) \ + ((sizeof(struct lfs_direct) - (LFS_MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3)) + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define LFS_OLDDIRSIZ(oldfmt, dp, needswap) \ + (((oldfmt) && !(needswap)) ? \ + LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) +#else +#define LFS_OLDDIRSIZ(oldfmt, dp, needswap) \ + (((oldfmt) && (needswap)) ? \ + LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) +#endif + +#define LFS_DIRSIZ(fs, dp) LFS_DIRECTSIZ(lfs_dir_getnamlen(fs, dp)) + +/* Constants for the first argument of LFS_OLDDIRSIZ */ +#define LFS_OLDDIRFMT 1 +#define LFS_NEWDIRFMT 0 + +static __unused inline uint8_t +lfs_dir_gettype(const STRUCT_LFS *fs, const struct lfs_direct *dp) +{ + if (fs->lfs_hasolddirfmt) { + return LFS_DT_UNKNOWN; + } + return dp->d_type; +} + +static __unused inline uint8_t +lfs_dir_getnamlen(const STRUCT_LFS *fs, const struct lfs_direct *dp) +{ + if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { + /* low-order byte of old 16-bit namlen field */ + return dp->d_type; + } + return dp->d_namlen; +} + +static __unused inline void +lfs_dir_settype(const STRUCT_LFS *fs, struct lfs_direct *dp, uint8_t type) +{ + if (fs->lfs_hasolddirfmt) { + /* do nothing */ + return; + } + dp->d_type = type; +} + +static __unused inline void +lfs_dir_setnamlen(const STRUCT_LFS *fs, struct lfs_direct *dp, uint8_t namlen) +{ + if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { + /* low-order byte of old 16-bit namlen field */ + dp->d_type = namlen; + } + dp->d_namlen = namlen; +} + +/* + * These are called "dirt" because they ought to be cleaned up. + */ + +static __unused inline uint8_t +lfs_dirt_getdottype(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) +{ + if (fs->lfs_hasolddirfmt) { + return LFS_DT_UNKNOWN; + } + return dp->dot_type; +} + +static __unused inline uint8_t +lfs_dirt_getdotnamlen(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) +{ + if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { + /* low-order byte of old 16-bit namlen field */ + return dp->dot_type; + } + return dp->dot_namlen; +} + +static __unused inline uint8_t +lfs_dirt_getdotdottype(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) +{ + if (fs->lfs_hasolddirfmt) { + return LFS_DT_UNKNOWN; + } + return dp->dotdot_type; +} + +static __unused inline uint8_t +lfs_dirt_getdotdotnamlen(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) +{ + if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { + /* low-order byte of old 16-bit namlen field */ + return dp->dotdot_type; + } + return dp->dotdot_namlen; +} + +static __unused inline void +lfs_dirt_settypes(const STRUCT_LFS *fs, struct lfs_dirtemplate *dtp, + unsigned dt1, unsigned dt2) +{ + if (fs->lfs_hasolddirfmt) { + /* do nothing */ + return; + } + dtp->dot_type = dt1; + dtp->dotdot_type = dt2; +} + +static __unused inline void +lfs_dirt_setnamlens(const STRUCT_LFS *fs, struct lfs_dirtemplate *dtp, + unsigned len1, unsigned len2) +{ + if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { + /* low-order bytes of old 16-bit namlen field */ + dtp->dot_type = len1; + dtp->dotdot_type = len2; + /* clear the high-order bytes */ + dtp->dot_namlen = 0; + dtp->dotdot_namlen = 0; + return; + } + dtp->dot_namlen = len1; + dtp->dotdot_namlen = len2; +} + + /* * dinodes */ diff --git a/sys/ufs/lfs/lfs_rename.c b/sys/ufs/lfs/lfs_rename.c index aa6b4200eb9c..e6d02b46af42 100644 --- a/sys/ufs/lfs/lfs_rename.c +++ b/sys/ufs/lfs/lfs_rename.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_rename.c,v 1.8 2015/03/27 17:27:56 riastradh Exp $ */ +/* $NetBSD: lfs_rename.c,v 1.9 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: ufs_rename.c,v 1.6 2013/01/22 09:39:18 dholland Exp */ /*- @@ -89,7 +89,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_rename.c,v 1.8 2015/03/27 17:27:56 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_rename.c,v 1.9 2015/09/01 06:16:59 dholland Exp $"); #include #include @@ -124,6 +124,7 @@ __KERNEL_RCSID(0, "$NetBSD: lfs_rename.c,v 1.8 2015/03/27 17:27:56 riastradh Exp #include #include +#include #include /* @@ -329,20 +330,16 @@ ulfs_rename_ulr_overlap_p(const struct ulfs_lookup_results *fulr, static int /* XXX int? uint8_t? */ ulfs_direct_namlen(const struct lfs_direct *ep, const struct vnode *vp) { - bool swap; + struct lfs *fs; KASSERT(ep != NULL); KASSERT(vp != NULL); KASSERT(VTOI(vp) != NULL); KASSERT(VTOI(vp)->i_ump != NULL); + KASSERT(VTOI(vp)->i_lfs != NULL); + fs = VTOI(vp)->i_lfs; -#if (BYTE_ORDER == LITTLE_ENDIAN) - swap = (ULFS_IPNEEDSWAP(VTOI(vp)) == 0); -#else - swap = (ULFS_IPNEEDSWAP(VTOI(vp)) != 0); -#endif - - return ((FSFMT(vp) && swap)? ep->d_type : ep->d_namlen); + return lfs_dir_getnamlen(fs, ep); } /* @@ -598,21 +595,16 @@ static int /* XXX int? uint8_t? */ ulfs_dirbuf_dotdot_namlen(const struct lfs_dirtemplate *dirbuf, const struct vnode *vp) { - bool swap; + struct lfs *fs; KASSERT(dirbuf != NULL); KASSERT(vp != NULL); KASSERT(VTOI(vp) != NULL); KASSERT(VTOI(vp)->i_ump != NULL); + KASSERT(VTOI(vp)->i_lfs != NULL); + fs = VTOI(vp)->i_lfs; -#if (BYTE_ORDER == LITTLE_ENDIAN) - swap = (ULFS_IPNEEDSWAP(VTOI(vp)) == 0); -#else - swap = (ULFS_IPNEEDSWAP(VTOI(vp)) != 0); -#endif - - return ((FSFMT(vp) && swap)? - dirbuf->dotdot_type : dirbuf->dotdot_namlen); + return lfs_dirt_getdotdotnamlen(fs, dirbuf); } /* diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c index 78f1f3d32989..f5aeba074073 100644 --- a/sys/ufs/lfs/lfs_vfsops.c +++ b/sys/ufs/lfs/lfs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vfsops.c,v 1.344 2015/09/01 06:11:06 dholland Exp $ */ +/* $NetBSD: lfs_vfsops.c,v 1.345 2015/09/01 06:16:59 dholland Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007 @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.344 2015/09/01 06:11:06 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.345 2015/09/01 06:16:59 dholland Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -958,6 +958,7 @@ lfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) memcpy(&fs->lfs_dlfs_u.u_32, tdfs, sizeof(struct dlfs)); fs->lfs_is64 = false; /* XXX notyet */ fs->lfs_dobyteswap = false; /* XXX notyet */ + fs->lfs_hasolddirfmt = false; /* set for real below */ /* Compatibility */ if (lfs_sb_getversion(fs) < 2) { @@ -1065,6 +1066,8 @@ lfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) mp->mnt_fs_bshift = lfs_sb_getbshift(fs); if (fs->um_maxsymlinklen > 0) mp->mnt_iflag |= IMNT_DTYPE; + else + fs->lfs_hasolddirfmt = true; ump->um_mountp = mp; ump->um_dev = dev; diff --git a/sys/ufs/lfs/lfs_vnops.c b/sys/ufs/lfs/lfs_vnops.c index 84ca944c82e6..74ca36d833dd 100644 --- a/sys/ufs/lfs/lfs_vnops.c +++ b/sys/ufs/lfs/lfs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vnops.c,v 1.288 2015/09/01 06:08:37 dholland Exp $ */ +/* $NetBSD: lfs_vnops.c,v 1.289 2015/09/01 06:16:59 dholland Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -125,7 +125,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.288 2015/09/01 06:08:37 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.289 2015/09/01 06:16:59 dholland Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -944,19 +944,8 @@ lfs_mkdir(void *v) ULFS_MPNEEDSWAP(fs)); dirtemplate.dotdot_reclen = ulfs_rw16(dirtemplate.dotdot_reclen, ULFS_MPNEEDSWAP(fs)); - if (fs->um_maxsymlinklen <= 0) { -#if BYTE_ORDER == LITTLE_ENDIAN - if (ULFS_MPNEEDSWAP(fs) == 0) -#else - if (ULFS_MPNEEDSWAP(fs) != 0) -#endif - { - dirtemplate.dot_type = dirtemplate.dot_namlen; - dirtemplate.dotdot_type = dirtemplate.dotdot_namlen; - dirtemplate.dot_namlen = dirtemplate.dotdot_namlen = 0; - } else - dirtemplate.dot_type = dirtemplate.dotdot_type = 0; - } + lfs_dirt_settypes(fs, &dirtemplate, LFS_DT_DIR, LFS_DT_DIR); + lfs_dirt_setnamlens(fs, &dirtemplate, 1, 2); if ((error = lfs_balloc(tvp, (off_t)0, dirblksiz, cnp->cn_cred, B_CLRBUF, &bp)) != 0) goto bad; diff --git a/sys/ufs/lfs/ulfs_dirhash.c b/sys/ufs/lfs/ulfs_dirhash.c index 276eb84deda0..a46cd5cae3a0 100644 --- a/sys/ufs/lfs/ulfs_dirhash.c +++ b/sys/ufs/lfs/ulfs_dirhash.c @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_dirhash.c,v 1.8 2014/02/25 18:30:13 pooka Exp $ */ +/* $NetBSD: ulfs_dirhash.c,v 1.9 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: ufs_dirhash.c,v 1.34 2009/10/05 23:48:08 rmind Exp */ /* @@ -29,7 +29,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ulfs_dirhash.c,v 1.8 2014/02/25 18:30:13 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_dirhash.c,v 1.9 2015/09/01 06:16:59 dholland Exp $"); /* * This implements a hash-based lookup scheme for ULFS directories. @@ -49,6 +49,8 @@ __KERNEL_RCSID(0, "$NetBSD: ulfs_dirhash.c,v 1.8 2014/02/25 18:30:13 pooka Exp $ #include #include +#include +#include #include #include #include @@ -112,13 +114,13 @@ static struct sysctllog *ulfsdirhash_sysctl_log; int ulfsdirhash_build(struct inode *ip) { + struct lfs *fs = ip->i_lfs; struct dirhash *dh; struct buf *bp = NULL; struct lfs_direct *ep; struct vnode *vp; doff_t bmask, pos; int dirblocks, i, j, memreqd, nblocks, narrays, nslots, slot; - const int needswap = ULFS_IPNEEDSWAP(ip); int dirblksiz = ip->i_lfs->um_dirblksiz; /* Check if we can/should use dirhash. */ @@ -234,12 +236,13 @@ ulfsdirhash_build(struct inode *ip) } if (ep->d_ino != 0) { /* Add the entry (simplified ulfsdirhash_add). */ - slot = ulfsdirhash_hash(dh, ep->d_name, ep->d_namlen); + slot = ulfsdirhash_hash(dh, ep->d_name, + lfs_dir_getnamlen(fs, ep)); while (DH_ENTRY(dh, slot) != DIRHASH_EMPTY) slot = WRAPINCR(slot, dh->dh_hlen); dh->dh_hused++; DH_ENTRY(dh, slot) = pos; - ulfsdirhash_adjfree(dh, pos, -LFS_DIRSIZ(0, ep, needswap), + ulfsdirhash_adjfree(dh, pos, -LFS_DIRSIZ(fs, ep), dirblksiz); } pos += ep->d_reclen; @@ -323,13 +326,13 @@ int ulfsdirhash_lookup(struct inode *ip, const char *name, int namelen, doff_t *offp, struct buf **bpp, doff_t *prevoffp) { + struct lfs *fs = ip->i_lfs; struct dirhash *dh, *dh_next; struct lfs_direct *dp; struct vnode *vp; struct buf *bp; doff_t blkoff, bmask, offset, prevoff; int i, slot; - const int needswap = ULFS_IPNEEDSWAP(ip); int dirblksiz = ip->i_lfs->um_dirblksiz; if ((dh = ip->i_dirhash) == NULL) @@ -429,7 +432,7 @@ restart: brelse(bp, 0); return (EJUSTRETURN); } - if (dp->d_namlen == namelen && + if (lfs_dir_getnamlen(fs, dp) == namelen && memcmp(dp->d_name, name, namelen) == 0) { /* Found. Get the prev offset if needed. */ if (prevoffp != NULL) { @@ -448,7 +451,7 @@ restart: /* Check for sequential access, and update offset. */ if (dh->dh_seqopt == 0 && dh->dh_seqoff == offset) dh->dh_seqopt = 1; - dh->dh_seqoff = offset + LFS_DIRSIZ(0, dp, needswap); + dh->dh_seqoff = offset + LFS_DIRSIZ(fs, dp); DIRHASH_UNLOCK(dh); *bpp = bp; @@ -497,12 +500,12 @@ restart: doff_t ulfsdirhash_findfree(struct inode *ip, int slotneeded, int *slotsize) { + struct lfs *fs = ip->i_lfs; struct lfs_direct *dp; struct dirhash *dh; struct buf *bp; doff_t pos, slotstart; int dirblock, error, freebytes, i; - const int needswap = ULFS_IPNEEDSWAP(ip); int dirblksiz = ip->i_lfs->um_dirblksiz; if ((dh = ip->i_dirhash) == NULL) @@ -540,7 +543,7 @@ ulfsdirhash_findfree(struct inode *ip, int slotneeded, int *slotsize) brelse(bp, 0); return (-1); } - if (dp->d_ino == 0 || dp->d_reclen > LFS_DIRSIZ(0, dp, needswap)) + if (dp->d_ino == 0 || dp->d_reclen > LFS_DIRSIZ(fs, dp)) break; i += dp->d_reclen; dp = (struct lfs_direct *)((char *)dp + dp->d_reclen); @@ -557,7 +560,7 @@ ulfsdirhash_findfree(struct inode *ip, int slotneeded, int *slotsize) while (i < dirblksiz && freebytes < slotneeded) { freebytes += dp->d_reclen; if (dp->d_ino != 0) - freebytes -= LFS_DIRSIZ(0, dp, needswap); + freebytes -= LFS_DIRSIZ(fs, dp); if (dp->d_reclen == 0) { DIRHASH_UNLOCK(dh); brelse(bp, 0); @@ -620,9 +623,9 @@ ulfsdirhash_enduseful(struct inode *ip) void ulfsdirhash_add(struct inode *ip, struct lfs_direct *dirp, doff_t offset) { + struct lfs *fs = ip->i_lfs; struct dirhash *dh; int slot; - const int needswap = ULFS_IPNEEDSWAP(ip); int dirblksiz = ip->i_lfs->um_dirblksiz; if ((dh = ip->i_dirhash) == NULL) @@ -647,7 +650,7 @@ ulfsdirhash_add(struct inode *ip, struct lfs_direct *dirp, doff_t offset) } /* Find a free hash slot (empty or deleted), and add the entry. */ - slot = ulfsdirhash_hash(dh, dirp->d_name, dirp->d_namlen); + slot = ulfsdirhash_hash(dh, dirp->d_name, lfs_dir_getnamlen(fs, dirp)); while (DH_ENTRY(dh, slot) >= 0) slot = WRAPINCR(slot, dh->dh_hlen); if (DH_ENTRY(dh, slot) == DIRHASH_EMPTY) @@ -655,7 +658,7 @@ ulfsdirhash_add(struct inode *ip, struct lfs_direct *dirp, doff_t offset) DH_ENTRY(dh, slot) = offset; /* Update the per-block summary info. */ - ulfsdirhash_adjfree(dh, offset, -LFS_DIRSIZ(0, dirp, needswap), dirblksiz); + ulfsdirhash_adjfree(dh, offset, -LFS_DIRSIZ(fs, dirp), dirblksiz); DIRHASH_UNLOCK(dh); } @@ -667,9 +670,9 @@ ulfsdirhash_add(struct inode *ip, struct lfs_direct *dirp, doff_t offset) void ulfsdirhash_remove(struct inode *ip, struct lfs_direct *dirp, doff_t offset) { + struct lfs *fs = ip->i_lfs; struct dirhash *dh; int slot; - const int needswap = ULFS_IPNEEDSWAP(ip); int dirblksiz = ip->i_lfs->um_dirblksiz; if ((dh = ip->i_dirhash) == NULL) @@ -684,13 +687,14 @@ ulfsdirhash_remove(struct inode *ip, struct lfs_direct *dirp, doff_t offset) KASSERT(offset < dh->dh_dirblks * dirblksiz); /* Find the entry */ - slot = ulfsdirhash_findslot(dh, dirp->d_name, dirp->d_namlen, offset); + slot = ulfsdirhash_findslot(dh, dirp->d_name, + lfs_dir_getnamlen(fs, dirp), offset); /* Remove the hash entry. */ ulfsdirhash_delslot(dh, slot); /* Update the per-block summary info. */ - ulfsdirhash_adjfree(dh, offset, LFS_DIRSIZ(0, dirp, needswap), dirblksiz); + ulfsdirhash_adjfree(dh, offset, LFS_DIRSIZ(fs, dirp), dirblksiz); DIRHASH_UNLOCK(dh); } @@ -702,6 +706,7 @@ void ulfsdirhash_move(struct inode *ip, struct lfs_direct *dirp, doff_t oldoff, doff_t newoff) { + struct lfs *fs = ip->i_lfs; struct dirhash *dh; int slot; @@ -717,7 +722,8 @@ ulfsdirhash_move(struct inode *ip, struct lfs_direct *dirp, doff_t oldoff, KASSERT(oldoff < dh->dh_dirblks * ip->i_lfs->um_dirblksiz && newoff < dh->dh_dirblks * ip->i_lfs->um_dirblksiz); /* Find the entry, and update the offset. */ - slot = ulfsdirhash_findslot(dh, dirp->d_name, dirp->d_namlen, oldoff); + slot = ulfsdirhash_findslot(dh, dirp->d_name, + lfs_dir_getnamlen(fs, dirp), oldoff); DH_ENTRY(dh, slot) = newoff; DIRHASH_UNLOCK(dh); } @@ -822,10 +828,10 @@ ulfsdirhash_dirtrunc(struct inode *ip, doff_t offset) void ulfsdirhash_checkblock(struct inode *ip, char *sbuf, doff_t offset) { + struct lfs *fs = ip->i_lfs; struct dirhash *dh; struct lfs_direct *dp; int block, ffslot, i, nfree; - const int needswap = ULFS_IPNEEDSWAP(ip); int dirblksiz = ip->i_lfs->um_dirblksiz; if (!ulfs_dirhashcheck) @@ -866,9 +872,10 @@ ulfsdirhash_checkblock(struct inode *ip, char *sbuf, doff_t offset) } /* Check that the entry exists (will panic if it doesn't). */ - ulfsdirhash_findslot(dh, dp->d_name, dp->d_namlen, offset + i); + ulfsdirhash_findslot(dh, dp->d_name, lfs_dir_getnamlen(fs, dp), + offset + i); - nfree += dp->d_reclen - LFS_DIRSIZ(0, dp, needswap); + nfree += dp->d_reclen - LFS_DIRSIZ(fs, dp); } if (i != dirblksiz) panic("ulfsdirhash_checkblock: bad dir end"); diff --git a/sys/ufs/lfs/ulfs_extern.h b/sys/ufs/lfs/ulfs_extern.h index 862139804316..75b46b8b32ee 100644 --- a/sys/ufs/lfs/ulfs_extern.h +++ b/sys/ufs/lfs/ulfs_extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_extern.h,v 1.15 2015/05/31 15:48:03 hannken Exp $ */ +/* $NetBSD: ulfs_extern.h,v 1.16 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: ufs_extern.h,v 1.72 2012/05/09 00:21:18 riastradh Exp */ /*- @@ -114,6 +114,8 @@ void ulfs_dirbad(struct inode *, doff_t, const char *); int ulfs_dirbadentry(struct vnode *, struct lfs_direct *, int); void ulfs_makedirentry(struct inode *, struct componentname *, struct lfs_direct *); +void ulfs_makedirentry_bytype(struct lfs *, struct componentname *, + ino_t, unsigned /*dtype*/, struct lfs_direct *); int ulfs_direnter(struct vnode *, const struct ulfs_lookup_results *, struct vnode *, struct lfs_direct *, struct componentname *, struct buf *); diff --git a/sys/ufs/lfs/ulfs_inode.c b/sys/ufs/lfs/ulfs_inode.c index 34e99a91c44a..d220a7dc5148 100644 --- a/sys/ufs/lfs/ulfs_inode.c +++ b/sys/ufs/lfs/ulfs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_inode.c,v 1.10 2015/05/31 15:48:03 hannken Exp $ */ +/* $NetBSD: ulfs_inode.c,v 1.11 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: ufs_inode.c,v 1.89 2013/01/22 09:39:18 dholland Exp */ /* @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ulfs_inode.c,v 1.10 2015/05/31 15:48:03 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_inode.c,v 1.11 2015/09/01 06:16:59 dholland Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -58,6 +58,8 @@ __KERNEL_RCSID(0, "$NetBSD: ulfs_inode.c,v 1.10 2015/05/31 15:48:03 hannken Exp #include #include +#include +#include #include #include diff --git a/sys/ufs/lfs/ulfs_lookup.c b/sys/ufs/lfs/ulfs_lookup.c index 0e6176a4c102..c256f2ce693b 100644 --- a/sys/ufs/lfs/ulfs_lookup.c +++ b/sys/ufs/lfs/ulfs_lookup.c @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_lookup.c,v 1.25 2015/07/11 11:04:48 mlelstv Exp $ */ +/* $NetBSD: ulfs_lookup.c,v 1.26 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: ufs_lookup.c,v 1.122 2013/01/22 09:39:18 dholland Exp */ /* @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.25 2015/07/11 11:04:48 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.26 2015/09/01 06:16:59 dholland Exp $"); #ifdef _KERNEL_OPT #include "opt_lfs.h" @@ -59,6 +59,8 @@ __KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.25 2015/07/11 11:04:48 mlelstv Exp #include #include +#include +#include #include #include @@ -348,7 +350,7 @@ searchloop: int size = ulfs_rw16(ep->d_reclen, needswap); if (ep->d_ino != 0) - size -= LFS_DIRSIZ(FSFMT(vdp), ep, needswap); + size -= LFS_DIRSIZ(fs, ep); if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; @@ -376,17 +378,7 @@ searchloop: if (ep->d_ino) { int namlen; -#if (BYTE_ORDER == LITTLE_ENDIAN) - if (FSFMT(vdp) && needswap == 0) - namlen = ep->d_type; - else - namlen = ep->d_namlen; -#else - if (FSFMT(vdp) && needswap != 0) - namlen = ep->d_type; - else - namlen = ep->d_namlen; -#endif + namlen = lfs_dir_getnamlen(fs, ep); if (namlen == cnp->cn_namelen && !memcmp(cnp->cn_nameptr, ep->d_name, (unsigned)namlen)) { @@ -397,7 +389,7 @@ foundentry: * Save directory entry's inode number and * reclen, and release directory buffer. */ - if (!FSFMT(vdp) && ep->d_type == LFS_DT_WHT) { + if (!FSFMT(vdp) && lfs_dir_gettype(fs, ep) == LFS_DT_WHT) { slotstatus = FOUND; slotoffset = results->ulr_offset; slotsize = ulfs_rw16(ep->d_reclen, @@ -528,10 +520,10 @@ found: * Check that directory length properly reflects presence * of this entry. */ - if (results->ulr_offset + LFS_DIRSIZ(FSFMT(vdp), ep, needswap) > dp->i_size) { + if (results->ulr_offset + LFS_DIRSIZ(fs, ep) > dp->i_size) { ulfs_dirbad(dp, results->ulr_offset, "i_size too small"); dp->i_size = - results->ulr_offset + LFS_DIRSIZ(FSFMT(vdp), ep, needswap); + results->ulr_offset + LFS_DIRSIZ(fs, ep); DIP_ASSIGN(dp, size, dp->i_size); dp->i_flag |= IN_CHANGE | IN_UPDATE; } @@ -679,28 +671,17 @@ ulfs_dirbadentry(struct vnode *dp, struct lfs_direct *ep, int entryoffsetinblock const int needswap = ULFS_MPNEEDSWAP(fs); int dirblksiz = fs->um_dirblksiz; -#if (BYTE_ORDER == LITTLE_ENDIAN) - if (FSFMT(dp) && needswap == 0) - namlen = ep->d_type; - else - namlen = ep->d_namlen; -#else - if (FSFMT(dp) && needswap != 0) - namlen = ep->d_type; - else - namlen = ep->d_namlen; -#endif + namlen = lfs_dir_getnamlen(fs, ep); if ((ulfs_rw16(ep->d_reclen, needswap) & 0x3) != 0 || ulfs_rw16(ep->d_reclen, needswap) > dirblksiz - (entryoffsetinblock & (dirblksiz - 1)) || - ulfs_rw16(ep->d_reclen, needswap) < - LFS_DIRSIZ(FSFMT(dp), ep, needswap) || + ulfs_rw16(ep->d_reclen, needswap) < LFS_DIRSIZ(fs, ep) || namlen > LFS_MAXNAMLEN) { /*return (1); */ printf("First bad, reclen=%#x, DIRSIZ=%lu, namlen=%d, " "flags=%#x, entryoffsetinblock=%d, dirblksiz = %d\n", ulfs_rw16(ep->d_reclen, needswap), - (u_long)LFS_DIRSIZ(FSFMT(dp), ep, needswap), + (u_long)LFS_DIRSIZ(fs, ep), namlen, dp->v_mount->mnt_flag, entryoffsetinblock, dirblksiz); goto bad; @@ -724,19 +705,34 @@ bad: * Construct a new directory entry after a call to namei, using the * name in the componentname argument cnp. The argument ip is the * inode to which the new directory entry will refer. + * + * Does not set d_reclen. */ void ulfs_makedirentry(struct inode *ip, struct componentname *cnp, struct lfs_direct *newdirp) { + struct lfs *fs = ip->i_lfs; + newdirp->d_ino = ip->i_number; - newdirp->d_namlen = cnp->cn_namelen; memcpy(newdirp->d_name, cnp->cn_nameptr, (size_t)cnp->cn_namelen); newdirp->d_name[cnp->cn_namelen] = '\0'; - if (FSFMT(ITOV(ip))) - newdirp->d_type = 0; - else - newdirp->d_type = LFS_IFTODT(ip->i_mode); + lfs_dir_setnamlen(fs, newdirp, cnp->cn_namelen); + lfs_dir_settype(fs, newdirp, LFS_IFTODT(ip->i_mode)); +} + +/* + * Similar but for special inodes. + */ +void +ulfs_makedirentry_bytype(struct lfs *fs, struct componentname *cnp, + ino_t inum, unsigned dtype, struct lfs_direct *newdirp) +{ + newdirp->d_ino = inum; + memcpy(newdirp->d_name, cnp->cn_nameptr, (size_t)cnp->cn_namelen); + newdirp->d_name[cnp->cn_namelen] = '\0'; + lfs_dir_setnamlen(fs, newdirp, cnp->cn_namelen); + lfs_dir_settype(fs, newdirp, dtype); } /* @@ -754,6 +750,12 @@ ulfs_makedirentry(struct inode *ip, struct componentname *cnp, * The link count of the target inode is *not* incremented; the * caller does that. * + * DIRP should have been filled in by ulfs_makedirentry(). Manual + * initialization should be avoided, but if needed should be + * equivalent to ulfs_makedirentry in byteswapping, use of accessor + * functions, etc.; otherwise we might byteswap too many times or not + * enough. + * * If ulr->ulr_count is 0, ulfs_lookup did not find space to insert the * directory entry. ulr_offset, which is the place to put the entry, * should be on a block boundary (and should be at the end of the @@ -791,7 +793,7 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr, cr = cnp->cn_cred; dp = VTOI(dvp); - newentrysize = LFS_DIRSIZ(0, dirp, 0); + newentrysize = LFS_DIRSIZ(fs, dirp); if (ulr->ulr_count == 0) { /* @@ -812,17 +814,7 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr, uvm_vnp_setsize(dvp, dp->i_size); dirp->d_reclen = ulfs_rw16(dirblksiz, needswap); dirp->d_ino = ulfs_rw32(dirp->d_ino, needswap); - if (FSFMT(dvp)) { -#if (BYTE_ORDER == LITTLE_ENDIAN) - if (needswap == 0) { -#else - if (needswap != 0) { -#endif - u_char tmp = dirp->d_namlen; - dirp->d_namlen = dirp->d_type; - dirp->d_type = tmp; - } - } + /* d_type/d_namlen are handled in ulfs_makedirentry */ lfs_blkoff = ulr->ulr_offset & (ump->um_mountp->mnt_stat.f_iosize - 1); memcpy((char *)bp->b_data + lfs_blkoff, dirp, newentrysize); #ifdef LFS_DIRHASH @@ -880,7 +872,7 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr, * ulr_offset + ulr_count would yield the space. */ ep = (struct lfs_direct *)dirbuf; - dsize = (ep->d_ino != 0) ? LFS_DIRSIZ(FSFMT(dvp), ep, needswap) : 0; + dsize = (ep->d_ino != 0) ? LFS_DIRSIZ(fs, ep) : 0; spacefree = ulfs_rw16(ep->d_reclen, needswap) - dsize; for (loc = ulfs_rw16(ep->d_reclen, needswap); loc < ulr->ulr_count; ) { uint16_t reclen; @@ -907,7 +899,7 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr, dsize = 0; continue; } - dsize = LFS_DIRSIZ(FSFMT(dvp), nep, needswap); + dsize = LFS_DIRSIZ(fs, nep); spacefree += reclen - dsize; #ifdef LFS_DIRHASH if (dp->i_dirhash != NULL) @@ -928,7 +920,7 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr, */ if (ep->d_ino == 0 || (ulfs_rw32(ep->d_ino, needswap) == ULFS_WINO && - memcmp(ep->d_name, dirp->d_name, dirp->d_namlen) == 0)) { + memcmp(ep->d_name, dirp->d_name, lfs_dir_getnamlen(fs, dirp)) == 0)) { if (spacefree + dsize < newentrysize) panic("ulfs_direnter: compact1"); dirp->d_reclen = spacefree + dsize; @@ -941,17 +933,7 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr, } dirp->d_reclen = ulfs_rw16(dirp->d_reclen, needswap); dirp->d_ino = ulfs_rw32(dirp->d_ino, needswap); - if (FSFMT(dvp)) { -#if (BYTE_ORDER == LITTLE_ENDIAN) - if (needswap == 0) { -#else - if (needswap != 0) { -#endif - u_char tmp = dirp->d_namlen; - dirp->d_namlen = dirp->d_type; - dirp->d_type = tmp; - } - } + /* d_type/d_namlen are handled in ulfs_makedirentry */ #ifdef LFS_DIRHASH if (dp->i_dirhash != NULL && (ep->d_ino == 0 || dirp->d_reclen == spacefree)) @@ -1023,6 +1005,7 @@ ulfs_dirremove(struct vnode *dvp, const struct ulfs_lookup_results *ulr, struct inode *ip, int flags, int isrmdir) { struct inode *dp = VTOI(dvp); + struct lfs *fs = dp->i_lfs; struct lfs_direct *ep; struct buf *bp; int error; @@ -1037,7 +1020,7 @@ ulfs_dirremove(struct vnode *dvp, const struct ulfs_lookup_results *ulr, if (error) return (error); ep->d_ino = ulfs_rw32(ULFS_WINO, needswap); - ep->d_type = LFS_DT_WHT; + lfs_dir_settype(fs, ep, LFS_DT_WHT); goto out; } @@ -1126,6 +1109,7 @@ ulfs_dirrewrite(struct inode *dp, off_t offset, struct inode *oip, ino_t newinum, int newtype, int isrmdir, int iflags) { + struct lfs *fs = dp->i_lfs; struct buf *bp; struct lfs_direct *ep; struct vnode *vdp = ITOV(dp); @@ -1135,8 +1119,7 @@ ulfs_dirrewrite(struct inode *dp, off_t offset, if (error) return (error); ep->d_ino = ulfs_rw32(newinum, ULFS_IPNEEDSWAP(dp)); - if (!FSFMT(vdp)) - ep->d_type = newtype; + lfs_dir_settype(fs, ep, newtype); oip->i_nlink--; DIP_ASSIGN(oip, nlink, oip->i_nlink); oip->i_flag |= IN_CHANGE; @@ -1164,6 +1147,7 @@ ulfs_dirrewrite(struct inode *dp, off_t offset, int ulfs_dirempty(struct inode *ip, ino_t parentino, kauth_cred_t cred) { + struct lfs *fs = ip->i_lfs; doff_t off; struct lfs_dirtemplate dbuf; struct lfs_direct *dp = (struct lfs_direct *)&dbuf; @@ -1189,17 +1173,7 @@ ulfs_dirempty(struct inode *ip, ino_t parentino, kauth_cred_t cred) if (dp->d_ino == 0 || ulfs_rw32(dp->d_ino, needswap) == ULFS_WINO) continue; /* accept only "." and ".." */ -#if (BYTE_ORDER == LITTLE_ENDIAN) - if (FSFMT(ITOV(ip)) && needswap == 0) - namlen = dp->d_type; - else - namlen = dp->d_namlen; -#else - if (FSFMT(ITOV(ip)) && needswap != 0) - namlen = dp->d_type; - else - namlen = dp->d_namlen; -#endif + namlen = lfs_dir_getnamlen(fs, dp); if (namlen > 2) return (0); if (dp->d_name[0] != '.') diff --git a/sys/ufs/lfs/ulfs_vfsops.c b/sys/ufs/lfs/ulfs_vfsops.c index 04776b542fc6..2c844f2b2227 100644 --- a/sys/ufs/lfs/ulfs_vfsops.c +++ b/sys/ufs/lfs/ulfs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_vfsops.c,v 1.9 2015/05/31 15:48:03 hannken Exp $ */ +/* $NetBSD: ulfs_vfsops.c,v 1.10 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: ufs_vfsops.c,v 1.52 2013/01/22 09:39:18 dholland Exp */ /* @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ulfs_vfsops.c,v 1.9 2015/05/31 15:48:03 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_vfsops.c,v 1.10 2015/09/01 06:16:59 dholland Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -58,6 +58,7 @@ __KERNEL_RCSID(0, "$NetBSD: ulfs_vfsops.c,v 1.9 2015/05/31 15:48:03 hannken Exp #include #include +#include #include #include #include diff --git a/sys/ufs/lfs/ulfs_vnops.c b/sys/ufs/lfs/ulfs_vnops.c index fd27b8750cf0..1c967939a43e 100644 --- a/sys/ufs/lfs/ulfs_vnops.c +++ b/sys/ufs/lfs/ulfs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_vnops.c,v 1.27 2015/09/01 06:08:37 dholland Exp $ */ +/* $NetBSD: ulfs_vnops.c,v 1.28 2015/09/01 06:16:59 dholland Exp $ */ /* from NetBSD: ufs_vnops.c,v 1.213 2013/06/08 05:47:02 kardel Exp */ /*- @@ -67,7 +67,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.27 2015/09/01 06:08:37 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.28 2015/09/01 06:16:59 dholland Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -97,6 +97,10 @@ __KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.27 2015/09/01 06:08:37 dholland Exp #include #include +#include +#include +#include + #include #include #include @@ -104,9 +108,6 @@ __KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.27 2015/09/01 06:08:37 dholland Exp #ifdef LFS_DIRHASH #include #endif -#include -#include -#include #include @@ -646,12 +647,8 @@ ulfs_whiteout(void *v) #endif newdir = pool_cache_get(ulfs_direct_cache, PR_WAITOK); - newdir->d_ino = ULFS_WINO; - newdir->d_namlen = cnp->cn_namelen; - memcpy(newdir->d_name, cnp->cn_nameptr, - (size_t)cnp->cn_namelen); - newdir->d_name[cnp->cn_namelen] = '\0'; - newdir->d_type = LFS_DT_WHT; + ulfs_makedirentry_bytype(fs, cnp, ULFS_WINO, LFS_DT_WHT, + newdir); error = ulfs_direnter(dvp, ulr, NULL, newdir, cnp, NULL); pool_cache_put(ulfs_direct_cache, newdir); break; @@ -798,11 +795,6 @@ ulfs_readdir(void *v) struct ulfsmount *ump = VFSTOULFS(vp->v_mount); struct lfs *fs = ump->um_lfs; int nswap = ULFS_MPNEEDSWAP(fs); -#if BYTE_ORDER == LITTLE_ENDIAN - int needswap = fs->um_maxsymlinklen <= 0 && nswap == 0; -#else - int needswap = fs->um_maxsymlinklen <= 0 && nswap != 0; -#endif uio = ap->a_uio; count = uio->uio_resid; rcount = count - ((uio->uio_offset + count) & (fs->um_dirblksiz - 1)); @@ -873,13 +865,8 @@ ulfs_readdir(void *v) cdp = ecdp; break; } - if (needswap) { - ndp->d_type = cdp->d_namlen; - ndp->d_namlen = cdp->d_type; - } else { - ndp->d_type = cdp->d_type; - ndp->d_namlen = cdp->d_namlen; - } + ndp->d_type = lfs_dir_gettype(fs, cdp); + ndp->d_namlen = lfs_dir_getnamlen(fs, cdp); ndp->d_reclen = _DIRENT_RECLEN(ndp, ndp->d_namlen); if ((char *)(void *)ndp + ndp->d_reclen + _DIRENT_MINSIZE(ndp) > endp)