Current-Users archive

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

Re: fsck seg fault failure on vmware -i386?



    Date:        Sat, 6 Feb 2010 18:36:40 -0000
    From:        yancm%sdf.lonestar.org@localhost
    Message-ID:  
<29e4d52af21ec0673eb8a526a1b8d39a.squirrel%webmail.freeshell.org@localhost>

  | Sure (debug version of fsck_ffs only):
  | http://clarity.homeip.net/stuff/fsck_ffs.gz
  | http://clarity.homeip.net/stuff/fsck_ffs.core.gz

I don't have a current system to properly look at those on (really needs
the appropriate libc, and sources), but from what I can see ...

(gdb) print t
$1 = 1264115119

(that's the same value you reported, so not a surprise), but ...

(gdb) print *dp
$2 = {dp1 = {di_mode = 56751, di_nlink = 19288, di_u = {oldids = {0, 0}, 
inumber = 0}, di_size = 13817003198315359381, 
    di_atime = -1077945624, di_atimensec = 134541206, di_mtime = 224938, 
di_mtimensec = 0, di_ctime = 134605714, 
    di_ctimensec = 0, di_db = {224938, 0, 134605973, 224938, 0, 18730, 
-1077945464, 134563445, -1077945548, 134605973, 1, 
      134563194}, di_ib = {-1148186544, 134607596, 56196}, di_flags = 72, 
di_blocks = 9, di_gen = 0, di_uid = 900, di_gid = 9, 
    di_modrev = 224938}, dp2 = {di_mode = 56751, di_nlink = 19288, di_uid = 0, 
di_gid = 134605973, di_blksize = 3217021748, 
    di_size = 577850082951420648, di_blocks = 224938, di_atime = 134605714, 
di_mtime = 224938, di_ctime = 966101488233621, 
    di_birthtime = 80444737454080, di_mtimensec = -1077945464, di_atimensec = 
134563445, di_ctimensec = -1077945548, 
    di_birthnsec = 134605973, di_gen = 1, di_kernflags = 134563194, di_flags = 
3146780752, di_extsize = 134607596, di_extb = {
      309237701508, 9}, di_db = {38654706564, 224938, 577986469637905224, 0, 
966101488190336, 0, 0, 0, 0, 0, 0, 12884901888}, 
    di_ib = {3217024120, 0, 577852247614940280}, di_modrev = 0, di_spare = {0, 
0}}}

We can ignore the dp2 part of that, since ...

(gdb) p is_ufs2
$3 = 0

Which leaves (reformatted a little for readability)

dp1 = {di_mode = 56751, di_nlink = 19288, di_u = {oldids = {0, 0}, inumber = 0}
        , di_size = 13817003198315359381,
         di_atime = -1077945624, di_atimensec = 134541206,
         di_mtime = 224938, di_mtimensec = 0,
         di_ctime = 134605714, di_ctimensec = 0,
         di_db = {224938, 0, 134605973, 224938, 0, 18730, -1077945464,
                 134563445, -1077945548, 134605973, 1, 134563194},
         di_ib = {-1148186544, 134607596, 56196},
         di_flags = 72, di_blocks = 9, di_gen = 0,
         di_uid = 900, di_gid = 9, di_modrev = 224938},

as the inode in question.  In that the mtime is shown as 224938
nothing like the value of t - and it isn't a byte swap issue (or shouldn't
be)

(gdb) p needswap
$4 = 0

What I did notice that is interesting though is

(gdb) p ino
$5 = 224938

That is, the inode number and the mtime field in the inode, are somehow
the same.    Very odd.   Of course, I might be being confused by doing
all this on an older system, with older fsck sources, and a definitely
older libc available.  If you could repeat that, and see if you see the
same values as I do, that would help.

That (very small) kind of value for mtime is one where (just possibly,
though that value isn't really small enough) you might get different
results if you have a timezone file available, and if you don't, though
in your case (west of Greenwich) I'd suspect things to be more likely to
go wrong when the file is there, than when it isn't - with a very small
time value, and west of greenwich, the time_t can become negative, and
that's a code path that is rarely tested (especially with 64 bit time_t's).

I did disprove my earlier theory that maybe the data types were messed up,
a disassembly of the pinode function shows it extracting 32 bits of time
value from the inode, and putting that, and 4 following 0 bytes, as the
arg (the address of which) is passed to ctime - I assume that's correct
little endian 64 bit integer (conversion of the inode time to 64 bits).

Or that is, it looks to be what is intended in the code - I'm not sure
it is correct, the iswap32() inline func that fsck_ffs uses to convert
the di_mtime field from 32 bits to a time_t (doing byte swapping when it
is needed) explicitly takes an unsigned arg, and returns an unsigned 32
bit value (which is then expanded to make the 64 bit time_t).   But both
the di_mtime and time_t's are signed - so we could get different results
than intended there because of the unsigned conversion.

Or that might be exactly what is intended, I have no idea whether we have
a specification of what is intended when the modified time of a file
claims to be <0 (ie: before 1970).   We know that's impossible, as unix
didn't exist then, so no unix file could possibly have been modified
(or accessed, or changed) before 1970, so leaving aside utimes() for
now, the semantics of an inode time < 0 aren't really defined I think.

For a bit greater longevity of UFS1 filesystems, treating the times in the
inodes as unsigned, rather than signed, seems like a read good idea to me
(particularly now we have 64 bit time_t's and so can deal with them properly,
even when making the timezone correction results in a value < 0).  So,
I think leaving the unsigned conversion in there is a good idea (provided
the same thing is done everywhere.)

kre



Home | Main Index | Thread Index | Old Index