NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/42573: DIRBLKSIZ in <ufs/ufs/dir.h> should not be DEV_BSIZE constant



>Number:         42573
>Category:       kern
>Synopsis:       DIRBLKSIZ in <ufs/ufs/dir.h> should not be DEV_BSIZE constant
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 03 16:55:00 +0000 2010
>Originator:     Izumi Tsutsui
>Release:        NetBSD 5.99.23
>Organization:
>Environment:
System: NetBSD  5.99.23 updated 20100103
Architecture: all
Machine: all

>Description:
DIRBLKSIZ macro is described in <ufs/ufs/dir.h> as following:
---
 * A directory consists of some number of blocks of DIRBLKSIZ
 * bytes, where DIRBLKSIZ is chosen such that it can be transferred
 * to disk in a single atomic operation (e.g. 512 bytes on most machines).
---
and it's defined using DEV_BSIZE (i.e. currently 512):
---
#undef  DIRBLKSIZ
#define DIRBLKSIZ       DEV_BSIZE
---
But "size that can be transferred to disk in a single atomic oparation"
should not be a compile-time constant but it should be determined by
a hardware sector size stored in a certain appropriate file system
specific structure.

>How-To-Repeat:
Code inspection.
You can see it by "grep DIRBLKSIZ src/sys/ufs/*/*.[ch]" etc.

>Fix:
src/sys/ufs/ffs/ffs_vfsops.c:
 We can calculate a hardware sector size (disk block size) from
 fs->fs_fsize and fs->fsbtodb.

src/sys/ufs/lfs/lfs_vfsops.c:
 We can get a hardware sector size from dlfs->fs_fsize and dlfs->fsbtodb?
 (I'm not familiar with lfs structures)

src/sys/ufs/ufs/ufs_extattr.c:
 I'm not sure how we can get the value dynamically there.

src/sys/ufs/ufs/ufs_vnops.c:
src/sys/ufs/ufs/ufs_wapbl.c:
 I'm not sure how we can get the value there.
 We also have to prepare "struct dirtamplate mastertemplate" dynamically.

src/sbin/newfs/mkfs.c:
 The necessary sector size is specified by -S option.
 We also have to prepare struct dirent for lost+found dir dynamically. 

src/sbin/usr.sbin/makefs/ffs.c:
 The necessary sector size is specified by -S option.

(have not checked other sources)

Here is a patch for makefs(8) (using DEV_BSIZE there causes fatal errors
on cross build environment on systems DEV_BSIZE != 512 like Cygwin):

Index: ffs.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/makefs/ffs.c,v
retrieving revision 1.44
diff -u -r1.44 ffs.c
--- ffs.c       28 Apr 2009 22:49:26 -0000      1.44
+++ ffs.c       3 Jan 2010 16:46:40 -0000
@@ -134,8 +134,10 @@
 
 static int     ffs_create_image(const char *, fsinfo_t *);
 static void    ffs_dump_fsinfo(fsinfo_t *);
-static void    ffs_dump_dirbuf(dirbuf_t *, const char *, int);
-static void    ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int);
+static void    ffs_dump_dirbuf(dirbuf_t *, const char *,
+                               const fsinfo_t *);
+static void    ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *,
+                               const fsinfo_t *);
 static int     ffs_populate_dir(const char *, fsnode *, fsinfo_t *);
 static void    ffs_size_dir(fsnode *, fsinfo_t *);
 static void    ffs_validate(const char *, fsnode *, fsinfo_t *);
@@ -567,8 +569,9 @@
        if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT)                       \
                printf("ADDDIRENT: was: %s (%d) this %d cur %d\n",      \
                    e, tmpdir.d_namlen, this, curdirsize);              \
-       if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ))         \
-               curdirsize = roundup(curdirsize, DIRBLKSIZ);            \
+       if (this + curdirsize >                                         \
+           roundup(curdirsize, fsopts->sectorsize))                    \
+               curdirsize = roundup(curdirsize, fsopts->sectorsize);   \
        curdirsize += this;                                             \
        if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT)                       \
                printf("ADDDIRENT: now: %s (%d) this %d cur %d\n",      \
@@ -752,11 +755,11 @@
                                fsopts->curinode++;
                        }
                }
-               ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
+               ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts);
                if (cur == root) {              /* we're at "."; add ".." */
                        ffs_make_dirbuf(&dirbuf, "..",
                            cur->parent == NULL ? cur : cur->parent->first,
-                           fsopts->needswap);
+                           fsopts);
                        root->inode->nlink++;   /* count my parent's link */
                } else if (cur->child != NULL)
                        root->inode->nlink++;   /* count my child's link */
@@ -769,7 +772,7 @@
                 */
        }
        if (debug & DEBUG_FS_POPULATE_DIRBUF)
-               ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap);
+               ffs_dump_dirbuf(&dirbuf, dir, fsopts);
 
                /*
                 * pass 2: write out dirbuf, then non-directories at this level
@@ -955,14 +958,16 @@
 
 
 static void
-ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
+ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, const fsinfo_t *fsopts)
 {
        doff_t          i;
        struct direct   *de;
+       int             needswap;
        uint16_t        reclen;
 
        assert (dbuf != NULL);
        assert (dir != NULL);
+       needswap = fsopts->needswap;
        printf("ffs_dump_dirbuf: dir %s size %d cur %d\n",
            dir, dbuf->size, dbuf->cur);
 
@@ -980,15 +985,18 @@
 }
 
 static void
-ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
+ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node,
+    const fsinfo_t *fsopts)
 {
        struct direct   de, *dp;
+       int             needswap;
        uint16_t        llen, reclen;
        u_char          *newbuf;
 
        assert (dbuf != NULL);
        assert (name != NULL);
        assert (node != NULL);
+       needswap = fsopts->needswap;
                                        /* create direct entry */
        (void)memset(&de, 0, sizeof(de));
        de.d_fileno = ufs_rw32(node->inode->ino, needswap);
@@ -1011,16 +1019,19 @@
                    ufs_rw32(de.d_fileno, needswap), de.d_type, reclen,
                    de.d_namlen, de.d_name);
 
-       if (reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)) {
+       if (reclen + dbuf->cur + llen >
+           roundup(dbuf->size, fsopts->sectorsize)) {
                if (debug & DEBUG_FS_MAKE_DIRBUF)
                        printf("ffs_make_dirbuf: growing buf to %d\n",
-                           dbuf->size + DIRBLKSIZ);
-               if ((newbuf = realloc(dbuf->buf, dbuf->size + DIRBLKSIZ)) == 
NULL)
+                           dbuf->size + fsopts->sectorsize);
+               if ((newbuf = realloc(dbuf->buf,
+                   dbuf->size + fsopts->sectorsize)) == NULL)
                        err(1, "Allocating memory for directory buffer");
                dbuf->buf = newbuf;
-               dbuf->size += DIRBLKSIZ;
-               memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ);
-               dbuf->cur = dbuf->size - DIRBLKSIZ;
+               dbuf->size += fsopts->sectorsize;
+               memset(dbuf->buf + dbuf->size - fsopts->sectorsize, 0,
+                   fsopts->sectorsize);
+               dbuf->cur = dbuf->size - fsopts->sectorsize;
        } else if (dp) {                        /* shrink end of previous */
                dp->d_reclen = ufs_rw16(llen,needswap);
                dbuf->cur += llen;

---



Home | Main Index | Thread Index | Old Index