Re: fsck_ffs: faster with lots of cylinder groups

2020-07-12 Thread Solene Rapenne
On Sun, 12 Jul 2020 09:13:47 +0200
Otto Moerbeek :

> On Mon, Jun 29, 2020 at 02:30:41PM +0200, Otto Moerbeek wrote:
> 
> > On Sun, Jun 21, 2020 at 03:35:21PM +0200, Otto Moerbeek wrote:
> >   
> > > Hi,
> > > 
> > > both phase 1 and phase 5 need cylinder group metadata.  This diff
> > > keeps the cg data read in phase 1 in memory to be used by phase 5 if
> > > possible. From FreeBSD. 
> > > 
> > >   -Otto
> > > 
> > > On an empty 30T fileystem:
> > > 
> > > $ time obj/fsck_ffs -f /dev/sd3a
> > > 2m44.10s real 0m13.21s user 0m07.38s system
> > > 
> > > $ time doas obj/fsck_ffs -f /dev/sd3a
> > > 1m32.81s real 0m12.86s user 0m05.25s system
> > > 
> > > The difference will be less if a fileystem is filled up, but still nice.  
> > 
> > Any takers?  
> 
> No feedback. I'm getting discouraged in doing more filesystem work...
> 
> What to do?
> 
> 1) Abondon the diff
> 2) Commit without ok
> 
> I did quite extensive testing, but both options are unsatisfactory.
> 
>   -Otto

I'm not sure how to test your diff.
Would running fsck on a sane filesystem enough?

Are you using Vms that you halt to force a
fsck on them? Would this be a good test too?



Re: fsck_ffs: faster with lots of cylinder groups

2020-07-12 Thread Otto Moerbeek
On Sun, Jul 12, 2020 at 11:07:05AM +0200, Solene Rapenne wrote:

> On Sun, 12 Jul 2020 09:13:47 +0200
> Otto Moerbeek :
> 
> > On Mon, Jun 29, 2020 at 02:30:41PM +0200, Otto Moerbeek wrote:
> > 
> > > On Sun, Jun 21, 2020 at 03:35:21PM +0200, Otto Moerbeek wrote:
> > >   
> > > > Hi,
> > > > 
> > > > both phase 1 and phase 5 need cylinder group metadata.  This diff
> > > > keeps the cg data read in phase 1 in memory to be used by phase 5 if
> > > > possible. From FreeBSD. 
> > > > 
> > > > -Otto
> > > > 
> > > > On an empty 30T fileystem:
> > > > 
> > > > $ time obj/fsck_ffs -f /dev/sd3a
> > > > 2m44.10s real 0m13.21s user 0m07.38s system
> > > > 
> > > > $ time doas obj/fsck_ffs -f /dev/sd3a
> > > > 1m32.81s real 0m12.86s user 0m05.25s system
> > > > 
> > > > The difference will be less if a fileystem is filled up, but still 
> > > > nice.  
> > > 
> > > Any takers?  
> > 
> > No feedback. I'm getting discouraged in doing more filesystem work...
> > 
> > What to do?
> > 
> > 1) Abondon the diff
> > 2) Commit without ok
> > 
> > I did quite extensive testing, but both options are unsatisfactory.
> > 
> > -Otto
> 
> I'm not sure how to test your diff.
> Would running fsck on a sane filesystem enough?
> 
> Are you using Vms that you halt to force a
> fsck on them? Would this be a good test too?

I have used both large and small fieysystems, clean and with
inconsistencies, both ffs1 and ffs2. Sometimes I create
inconsistencies by power cycling a machine, buut I have created faulty
filesystems by carefully overwriting meta data with dd in the past as
well.

In this case running with a restricted ulimit -d to force the fallback
code to kick in is also an good idea.

-Otto



Re: fsck_ffs: faster with lots of cylinder groups

2020-07-12 Thread Otto Moerbeek
On Mon, Jun 29, 2020 at 02:30:41PM +0200, Otto Moerbeek wrote:

> On Sun, Jun 21, 2020 at 03:35:21PM +0200, Otto Moerbeek wrote:
> 
> > Hi,
> > 
> > both phase 1 and phase 5 need cylinder group metadata.  This diff
> > keeps the cg data read in phase 1 in memory to be used by phase 5 if
> > possible. From FreeBSD. 
> > 
> > -Otto
> > 
> > On an empty 30T fileystem:
> > 
> > $ time obj/fsck_ffs -f /dev/sd3a
> > 2m44.10s real 0m13.21s user 0m07.38s system
> > 
> > $ time doas obj/fsck_ffs -f /dev/sd3a
> > 1m32.81s real 0m12.86s user 0m05.25s system
> > 
> > The difference will be less if a fileystem is filled up, but still nice.
> 
> Any takers?

No feedback. I'm getting discouraged in doing more filesystem work...

What to do?

1) Abondon the diff
2) Commit without ok

I did quite extensive testing, but both options are unsatisfactory.

-Otto

> 
> > 
> > Index: fsck.h
> > ===
> > RCS file: /cvs/src/sbin/fsck_ffs/fsck.h,v
> > retrieving revision 1.32
> > diff -u -p -r1.32 fsck.h
> > --- fsck.h  5 Jan 2018 09:33:47 -   1.32
> > +++ fsck.h  21 Jun 2020 12:48:50 -
> > @@ -136,7 +136,6 @@ struct bufarea {
> >  struct bufarea bufhead;/* head of list of other blks in 
> > filesys */
> >  struct bufarea sblk;   /* file system superblock */
> >  struct bufarea asblk;  /* alternate file system superblock */
> > -struct bufarea cgblk;  /* cylinder group blocks */
> >  struct bufarea *pdirbp;/* current directory contents */
> >  struct bufarea *pbp;   /* current inode block */
> >  struct bufarea *getdatablk(daddr_t, long);
> > @@ -148,9 +147,7 @@ struct bufarea *getdatablk(daddr_t, long
> > (bp)->b_flags = 0;
> >  
> >  #definesbdirty()   sblk.b_dirty = 1
> > -#definecgdirty()   cgblk.b_dirty = 1
> >  #definesblock  (*sblk.b_un.b_fs)
> > -#definecgrp(*cgblk.b_un.b_cg)
> >  
> >  enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
> >  
> > @@ -275,9 +272,13 @@ struct ufs2_dinode ufs2_zino;
> >  #defineFOUND   0x10
> >  
> >  union dinode *ginode(ino_t);
> > +struct bufarea *cglookup(u_int cg);
> >  struct inoinfo *getinoinfo(ino_t);
> >  void getblk(struct bufarea *, daddr_t, long);
> >  ino_t allocino(ino_t, int);
> > +void *Malloc(size_t);
> > +void *Calloc(size_t, size_t);
> > +void *Reallocarray(void *, size_t, size_t);
> >  
> >  int(*info_fn)(char *, size_t);
> >  char   *info_filesys;
> > Index: inode.c
> > ===
> > RCS file: /cvs/src/sbin/fsck_ffs/inode.c,v
> > retrieving revision 1.49
> > diff -u -p -r1.49 inode.c
> > --- inode.c 16 Sep 2018 02:43:11 -  1.49
> > +++ inode.c 21 Jun 2020 12:48:50 -
> > @@ -370,7 +370,7 @@ setinodebuf(ino_t inum)
> > partialsize = inobufsize;
> > }
> > if (inodebuf == NULL &&
> > -   (inodebuf = malloc((unsigned)inobufsize)) == NULL)
> > +   (inodebuf = Malloc((unsigned)inobufsize)) == NULL)
> > errexit("Cannot allocate space for inode buffer\n");
> >  }
> >  
> > @@ -401,7 +401,7 @@ cacheino(union dinode *dp, ino_t inumber
> > blks = howmany(DIP(dp, di_size), sblock.fs_bsize);
> > if (blks > NDADDR)
> > blks = NDADDR + NIADDR;
> > -   inp = malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
> > +   inp = Malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
> > if (inp == NULL)
> > errexit("cannot allocate memory for inode cache\n");
> > inpp = [inumber % numdirs];
> > @@ -423,10 +423,10 @@ cacheino(union dinode *dp, ino_t inumber
> > inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]);
> > if (inplast == listmax) {
> > newlistmax = listmax + 100;
> > -   newinpsort = reallocarray(inpsort,
> > +   newinpsort = Reallocarray(inpsort,
> > (unsigned)newlistmax, sizeof(struct inoinfo *));
> > if (newinpsort == NULL)
> > -   errexit("cannot increase directory list");
> > +   errexit("cannot increase directory list\n");
> > inpsort = newinpsort;
> > listmax = newlistmax;
> > }
> > @@ -582,7 +582,8 @@ allocino(ino_t request, int type)
> >  {
> > ino_t ino;
> > union dinode *dp;
> > -   struct cg *cgp = 
> > +   struct bufarea *cgbp;
> > +   struct cg *cgp;
> > int cg;
> > time_t t;
> > struct inostat *info;
> > @@ -602,7 +603,7 @@ allocino(ino_t request, int type)
> > unsigned long newalloced, i;
> > newalloced = MINIMUM(sblock.fs_ipg,
> > MAXIMUM(2 * inostathead[cg].il_numalloced, 10));
> > -   info = calloc(newalloced, sizeof(struct inostat));
> > +   info = Calloc(newalloced, sizeof(struct inostat));
> > if (info == NULL) {
> > 

Re: fsck_ffs: faster with lots of cylinder groups

2020-06-29 Thread Otto Moerbeek
On Sun, Jun 21, 2020 at 03:35:21PM +0200, Otto Moerbeek wrote:

> Hi,
> 
> both phase 1 and phase 5 need cylinder group metadata.  This diff
> keeps the cg data read in phase 1 in memory to be used by phase 5 if
> possible. From FreeBSD. 
> 
>   -Otto
> 
> On an empty 30T fileystem:
> 
> $ time obj/fsck_ffs -f /dev/sd3a
> 2m44.10s real 0m13.21s user 0m07.38s system
> 
> $ time doas obj/fsck_ffs -f /dev/sd3a
> 1m32.81s real 0m12.86s user 0m05.25s system
> 
> The difference will be less if a fileystem is filled up, but still nice.

Any takers?

-Otto

> 
> Index: fsck.h
> ===
> RCS file: /cvs/src/sbin/fsck_ffs/fsck.h,v
> retrieving revision 1.32
> diff -u -p -r1.32 fsck.h
> --- fsck.h5 Jan 2018 09:33:47 -   1.32
> +++ fsck.h21 Jun 2020 12:48:50 -
> @@ -136,7 +136,6 @@ struct bufarea {
>  struct bufarea bufhead;  /* head of list of other blks in 
> filesys */
>  struct bufarea sblk; /* file system superblock */
>  struct bufarea asblk;/* alternate file system superblock */
> -struct bufarea cgblk;/* cylinder group blocks */
>  struct bufarea *pdirbp;  /* current directory contents */
>  struct bufarea *pbp; /* current inode block */
>  struct bufarea *getdatablk(daddr_t, long);
> @@ -148,9 +147,7 @@ struct bufarea *getdatablk(daddr_t, long
>   (bp)->b_flags = 0;
>  
>  #define  sbdirty()   sblk.b_dirty = 1
> -#define  cgdirty()   cgblk.b_dirty = 1
>  #define  sblock  (*sblk.b_un.b_fs)
> -#define  cgrp(*cgblk.b_un.b_cg)
>  
>  enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
>  
> @@ -275,9 +272,13 @@ struct ufs2_dinode ufs2_zino;
>  #define  FOUND   0x10
>  
>  union dinode *ginode(ino_t);
> +struct bufarea *cglookup(u_int cg);
>  struct inoinfo *getinoinfo(ino_t);
>  void getblk(struct bufarea *, daddr_t, long);
>  ino_t allocino(ino_t, int);
> +void *Malloc(size_t);
> +void *Calloc(size_t, size_t);
> +void *Reallocarray(void *, size_t, size_t);
>  
>  int  (*info_fn)(char *, size_t);
>  char *info_filesys;
> Index: inode.c
> ===
> RCS file: /cvs/src/sbin/fsck_ffs/inode.c,v
> retrieving revision 1.49
> diff -u -p -r1.49 inode.c
> --- inode.c   16 Sep 2018 02:43:11 -  1.49
> +++ inode.c   21 Jun 2020 12:48:50 -
> @@ -370,7 +370,7 @@ setinodebuf(ino_t inum)
>   partialsize = inobufsize;
>   }
>   if (inodebuf == NULL &&
> - (inodebuf = malloc((unsigned)inobufsize)) == NULL)
> + (inodebuf = Malloc((unsigned)inobufsize)) == NULL)
>   errexit("Cannot allocate space for inode buffer\n");
>  }
>  
> @@ -401,7 +401,7 @@ cacheino(union dinode *dp, ino_t inumber
>   blks = howmany(DIP(dp, di_size), sblock.fs_bsize);
>   if (blks > NDADDR)
>   blks = NDADDR + NIADDR;
> - inp = malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
> + inp = Malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
>   if (inp == NULL)
>   errexit("cannot allocate memory for inode cache\n");
>   inpp = [inumber % numdirs];
> @@ -423,10 +423,10 @@ cacheino(union dinode *dp, ino_t inumber
>   inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]);
>   if (inplast == listmax) {
>   newlistmax = listmax + 100;
> - newinpsort = reallocarray(inpsort,
> + newinpsort = Reallocarray(inpsort,
>   (unsigned)newlistmax, sizeof(struct inoinfo *));
>   if (newinpsort == NULL)
> - errexit("cannot increase directory list");
> + errexit("cannot increase directory list\n");
>   inpsort = newinpsort;
>   listmax = newlistmax;
>   }
> @@ -582,7 +582,8 @@ allocino(ino_t request, int type)
>  {
>   ino_t ino;
>   union dinode *dp;
> - struct cg *cgp = 
> + struct bufarea *cgbp;
> + struct cg *cgp;
>   int cg;
>   time_t t;
>   struct inostat *info;
> @@ -602,7 +603,7 @@ allocino(ino_t request, int type)
>   unsigned long newalloced, i;
>   newalloced = MINIMUM(sblock.fs_ipg,
>   MAXIMUM(2 * inostathead[cg].il_numalloced, 10));
> - info = calloc(newalloced, sizeof(struct inostat));
> + info = Calloc(newalloced, sizeof(struct inostat));
>   if (info == NULL) {
>   pwarn("cannot alloc %zu bytes to extend inoinfo\n",
>   sizeof(struct inostat) * newalloced);
> @@ -619,7 +620,8 @@ allocino(ino_t request, int type)
>   inostathead[cg].il_numalloced = newalloced;
>   info = inoinfo(ino);
>   }
> - getblk(, cgtod(, cg), sblock.fs_cgsize);
> + cgbp = cglookup(cg);
> + cgp = cgbp->b_un.b_cg;
>   if 

fsck_ffs: faster with lots of cylinder groups

2020-06-21 Thread Otto Moerbeek
Hi,

both phase 1 and phase 5 need cylinder group metadata.  This diff
keeps the cg data read in phase 1 in memory to be used by phase 5 if
possible. From FreeBSD. 

-Otto

On an empty 30T fileystem:

$ time obj/fsck_ffs -f /dev/sd3a
2m44.10s real 0m13.21s user 0m07.38s system

$ time doas obj/fsck_ffs -f /dev/sd3a
1m32.81s real 0m12.86s user 0m05.25s system

The difference will be less if a fileystem is filled up, but still nice.

-Otto

Index: fsck.h
===
RCS file: /cvs/src/sbin/fsck_ffs/fsck.h,v
retrieving revision 1.32
diff -u -p -r1.32 fsck.h
--- fsck.h  5 Jan 2018 09:33:47 -   1.32
+++ fsck.h  21 Jun 2020 12:48:50 -
@@ -136,7 +136,6 @@ struct bufarea {
 struct bufarea bufhead;/* head of list of other blks in 
filesys */
 struct bufarea sblk;   /* file system superblock */
 struct bufarea asblk;  /* alternate file system superblock */
-struct bufarea cgblk;  /* cylinder group blocks */
 struct bufarea *pdirbp;/* current directory contents */
 struct bufarea *pbp;   /* current inode block */
 struct bufarea *getdatablk(daddr_t, long);
@@ -148,9 +147,7 @@ struct bufarea *getdatablk(daddr_t, long
(bp)->b_flags = 0;
 
 #definesbdirty()   sblk.b_dirty = 1
-#definecgdirty()   cgblk.b_dirty = 1
 #definesblock  (*sblk.b_un.b_fs)
-#definecgrp(*cgblk.b_un.b_cg)
 
 enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
 
@@ -275,9 +272,13 @@ struct ufs2_dinode ufs2_zino;
 #defineFOUND   0x10
 
 union dinode *ginode(ino_t);
+struct bufarea *cglookup(u_int cg);
 struct inoinfo *getinoinfo(ino_t);
 void getblk(struct bufarea *, daddr_t, long);
 ino_t allocino(ino_t, int);
+void *Malloc(size_t);
+void *Calloc(size_t, size_t);
+void *Reallocarray(void *, size_t, size_t);
 
 int(*info_fn)(char *, size_t);
 char   *info_filesys;
Index: inode.c
===
RCS file: /cvs/src/sbin/fsck_ffs/inode.c,v
retrieving revision 1.49
diff -u -p -r1.49 inode.c
--- inode.c 16 Sep 2018 02:43:11 -  1.49
+++ inode.c 21 Jun 2020 12:48:50 -
@@ -370,7 +370,7 @@ setinodebuf(ino_t inum)
partialsize = inobufsize;
}
if (inodebuf == NULL &&
-   (inodebuf = malloc((unsigned)inobufsize)) == NULL)
+   (inodebuf = Malloc((unsigned)inobufsize)) == NULL)
errexit("Cannot allocate space for inode buffer\n");
 }
 
@@ -401,7 +401,7 @@ cacheino(union dinode *dp, ino_t inumber
blks = howmany(DIP(dp, di_size), sblock.fs_bsize);
if (blks > NDADDR)
blks = NDADDR + NIADDR;
-   inp = malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
+   inp = Malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
if (inp == NULL)
errexit("cannot allocate memory for inode cache\n");
inpp = [inumber % numdirs];
@@ -423,10 +423,10 @@ cacheino(union dinode *dp, ino_t inumber
inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]);
if (inplast == listmax) {
newlistmax = listmax + 100;
-   newinpsort = reallocarray(inpsort,
+   newinpsort = Reallocarray(inpsort,
(unsigned)newlistmax, sizeof(struct inoinfo *));
if (newinpsort == NULL)
-   errexit("cannot increase directory list");
+   errexit("cannot increase directory list\n");
inpsort = newinpsort;
listmax = newlistmax;
}
@@ -582,7 +582,8 @@ allocino(ino_t request, int type)
 {
ino_t ino;
union dinode *dp;
-   struct cg *cgp = 
+   struct bufarea *cgbp;
+   struct cg *cgp;
int cg;
time_t t;
struct inostat *info;
@@ -602,7 +603,7 @@ allocino(ino_t request, int type)
unsigned long newalloced, i;
newalloced = MINIMUM(sblock.fs_ipg,
MAXIMUM(2 * inostathead[cg].il_numalloced, 10));
-   info = calloc(newalloced, sizeof(struct inostat));
+   info = Calloc(newalloced, sizeof(struct inostat));
if (info == NULL) {
pwarn("cannot alloc %zu bytes to extend inoinfo\n",
sizeof(struct inostat) * newalloced);
@@ -619,7 +620,8 @@ allocino(ino_t request, int type)
inostathead[cg].il_numalloced = newalloced;
info = inoinfo(ino);
}
-   getblk(, cgtod(, cg), sblock.fs_cgsize);
+   cgbp = cglookup(cg);
+   cgp = cgbp->b_un.b_cg;
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
@@ -637,7 +639,7 @@ allocino(ino_t request, int type)
default: