]> git.neil.brown.name Git - LaFS.git/commitdiff
README update
authorNeilBrown <neilb@suse.de>
Mon, 2 May 2011 01:41:14 +0000 (11:41 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 2 May 2011 01:41:14 +0000 (11:41 +1000)
README

diff --git a/README b/README
index 21e73365e605b14deba8334e9fce1664f3a6d802..252e9b723978dcc492532bf6657c409ecc90f7df 100644 (file)
--- a/README
+++ b/README
@@ -5190,7 +5190,7 @@ DONE  - use new write_begin / write_end
      - cluster head needs mtime/ctime to log these.
      - need better tracking of which devices are in this array??
             Need to be able to have read-only devices that are shared
-            amove arrays.
+             among arrays.
      - need multiple parallel write-clusters to allow parallel writes.
      - record tuning in state block:
            - max_segs
@@ -5201,7 +5201,7 @@ DONE  - use new write_begin / write_end
      DONE - inode map - not host-endian
      - segments > 16bit:
         segusage file - what about youth?
-        cluster_hehad Clength
+        cluster_head Clength
 
 15cc/ free any stray B_ASync block found in destroy_inode
 
@@ -5254,7 +5254,7 @@ DONE 15cf/ lafs_iget_fs need to sometimes to in-kernel mounts for subset filesys
     - reading critical metadata
     ...
 
-23/ Rebase on 2.6.latest
+23/ Rebase on 2.6.latest.  Done for .38
 
 24/ load/dirty block0 before dirtying any other block in depth=0 file,
     else we might lose block0
@@ -5280,7 +5280,11 @@ DONE 15cf/ lafs_iget_fs need to sometimes to in-kernel mounts for subset filesys
 
 31/ Implement non-logged files
 
-32/ Store access time in non-logged file
+DONE 32a/ Store access time in a file
+32b/ Make it a non-logged file
+32c/ Avoid writing out dirty atime file blocks when not necessary.
+      i.e. keep the page clean and active, and trigger 'write'
+     on release_page.
 
 33/ Support quota : group / user / tree
 
@@ -7048,8 +7052,8 @@ WritePhase - what is that all about?
 
   The idea is to have a separate file for storing only 'atime'
   This is separate from the inode file because the volatility of the data
-  is very different and one of the principle of log-structured-fs is that
-  differently volatile should be kept separate.
+  is very different and one of the principles of log-structured-fs is that
+  differently volatile data should be kept separate.
 
   This does mean that an inode lookup requires getting data from two files,
   but it is hopped that the 'atime' file will mostly be in cache as each
@@ -7063,7 +7067,7 @@ WritePhase - what is that all about?
   gets added to the atime stored in the inode.  The lower 5 bits are
   the exponent, the remaining 11 bits are mantissa.  Though there is a
   little complexity in interpreting the exponent.
-     If the exponent is 0, the mantissa is and used as milliseconds -
+     If the exponent is 0, the mantissa is used as milliseconds -
        so shift left 5 and multiply by 1000000 for nanoseconds.
        The smallest change that can be recorded in 1 millisecond.
        and values up to (2^11-1) milliseconds - or 2seconds can be stored.
@@ -7072,7 +7076,6 @@ WritePhase - what is that all about?
        This ranges up to 2^(12+9) milliseconds or 30 minutes, where
        the granularity will be 2^9 millisecs or 0.5 seconds
 
-  
      For exponents from 11 up to 31 we add the 1 msb and treat
        the number as seconds after shifting (e-11).  So at e==31,
        we shift a number that is
@@ -7099,13 +7102,12 @@ WritePhase - what is that all about?
 
    Otherwise we shift down until < 4096 counting shifts, add 1 to the
    shift to form an exponent, and combine with mantissa as above.
-   
 
    So that is the format - how do we implement it?
 
    We don't want to expose to user-space numbers that we cannot store.
-   So any 'utimes' call updates the inode directly can clear the value
-   in the atime file.  Only updates due to accesses go to the atimes
+   So any 'utimes' call updates that the inode directly can clear the
+   value in the atime file.  Only updates due to accesses go to the atimes
    file.
    We define a 'getattr' function which looks at the atime stored in
    the vfs inode and if it has changed we need to deal with it.
@@ -7135,7 +7137,7 @@ WritePhase - what is that all about?
     (I_DIRTY).
     We can still keep them dirty in lafs metadata so if release_page
     is called we can schedule a write out then.
-    
+
 
    So some steps:
 
@@ -7151,3 +7153,220 @@ WritePhase - what is that all about?
        atime.  So lafs_inode probably needs an extra field to be able
        to check for changes
 
+
+
+  Hmm.. this is getting confusing...
+  When atime is changed the only way we find out is by ->dirty_inode
+  being called.  But that is called when anything is changed.
+  Filtering out whether or not we need to update the inode itself
+  is awkward... maybe there is some context we can use.
+  ->dirty_inode is called by mark_inode_dirty which is called:
+   - by touch_atime, if something changed
+   - file_update_time  - at which time we also update iversion
+   - setattr ... which has changed recently (2.3.37ish)
+   - page_symlink
+   - generic_file_direct_write - which increasing size of inode
+   - set_page_dirty_nobuffers
+
+  So either the inode is pinned, or it isn't.
+  If it isn't, then this *must* be an atime-only update.
+  If it is, then it could be anything, but in any case we update the
+  atime directly.
+  So: dirty_inode should try to get dblock and check if it is pinned.
+   If it is pinned, then update the atime immediately and the offset
+   in the atime file too.
+   If not, just update the offset
+
+
+03mar2011
+  ARGggg... checkpin is interfering with unmount - it keeps an
+    s_active count so unmount 'works' but doesn't release anything.
+
+  checkpin is needed is needed to ensure that inodes remain safe while
+  we are cleaning.  Particularly, while the inode index block is
+  pinned, we keep the inode and fs referenced as well.  I guess the
+  theory is that they won't stay pinned for long - but they do.
+  e.g. segusage blocks are permanently pinned.
+
+
+  We could have a rule about the prime filesystem always being mounted.
+  Then we don't need refcounts, but kill off the cleaner before
+  unmount...  which we sort-of do..
+
+  All subordinate filesystems have references on the prime_sb so the
+  prime_sb must be the last one to go.  When it goes it kills
+  everything off...
+  So we don't need checkpin to take a ref on the prime_sb.
+
+  There might be still an issue with files in subset filesystems
+  being permanently pinned so they stay around longer than they
+  should... need to check on that somehow.
+  The idea is that a quota file block is permanently pinned so it
+  will keep the fs pinned.  That in turn will keep everything else
+  pinned... Worry about that when we implement quotas FIXME
+
+04mar2011
+  I really need to sort this out, and it isn't easy...
+  We really want to know when "all" filesystems have been unmounted
+  so the block device(s) can be released and the cleaner stopped.
+  But we don't have a count for that.  We could if that was all
+  we counted - but that would mean that we only have a single
+  struct super_block for all filesystems.
+
+  So that is what I have to do.  A single super_block for all parts
+  of the filesystem.  I probably still need to allocated other
+  dev numbers stat->dev, but I don't need to use them internally.
+  Maybe I even allocate superblocks... Yes - we need to use
+  set_anon_super and kill_anon_super to allocate the numbers.
+  lafs_inode will need a pointer to the filesystem - we use that
+  instead of the sb.
+
+  -------
+
+  Testing...
+   bug at block.c:658.  Block not B_Valid in lafs_dirty_iblock from
+   lafs_allocate_block  from cluster_flush.
+   Block is 74/0: InoIdx block of a newly created file I think.
+    '74' was /f23, then  /mnt/1/adir.  We are creating file in that
+   dir.
+   This is a depth=0 InoIdx block - i.e. the data is in the
+   dblock, so there is no index info, so it kind-a makes sense for the
+   index block to not be Valid.
+     yes- commit d268a566605bf006cf33c confirms that.
+
+   So why are we trying to dirty it?..
+
+   Maybe:
+     We create a couple of directory entries, then flush and end up
+     with an in-line data block.
+     Then we add more, flush again and so try to dirty parent...
+   Where to we turn depth=0 inodes to depth=1??
+      - erase_dblock_locked - don't want that
+      - lafs_incorporate
+   So I guess the 'bug' is in error - it is OK to mark that invalid
+   block as dirty.
+
+04mar2011
+  So - back to the super_block reworking.  We want only one
+  superblock.
+  So we use the TypeInodeFile inodes a bit more to hold the details
+  of different filesystems.  We need to store a unique 'dev' number in
+  there use set_anon_super/kill_anon_super on a local 'struct
+  super_block' and copy s_dev in/out.
+
+  As we only have one sb, we can only have one fstype, so we cannot
+  use the fstype to choose what to do.
+    - if dev_name is a block device we try an normal mount
+    - if dev_name is a Inode file, we perform a subset mount
+    - if dev_name is a lafs dir and '-o snapshot=name', we mount that
+      snapshot
+    - if dev_name is a lafs dir in root with perm zero and
+      '-o subset=MAXSIZE', create a subset filesystem.
+
+  - lafs_iget needs an inode rather than a superblock
+    ditto for lafs_new_inode, lafs_inode_inuse, inode_map_free,
+    choose_free_inum, inode_map_new_prepare
+  - lafs_iput_fs,lafs_igrab_fs, ino_from_sb
+
+  - NFS filehandles need careful thought
+     They are 'per-super-block', not 'per-vfsmnt' which might be
+     better.
+     We could change that but.....
+     For non-snapshot files it is easy - just record two inodes, the
+     fs and the target.
+     For snapshots there is nothing that is really stable.
+     Maybe we could have different superblocks for snapshots.
+     The snapshot doesn't need the cleaner as it is read-only, though
+     the cleaner can need the snapshot...
+
+     So the cleaner might automagically mount a snapshot, but a
+     snapshot will never invoke the cleaner or any other thread stuff.
+
+  So I guess we want one superblock for the fs and one for each
+  snapshot.
+  The filehandle is then either inum+gen or inum+inum+gen where first
+  inum must be TypeInodeFile
+
+07mar2011
+  ... though I could just put a snapshot number and partial timestamp
+      in..
+
+
+08mar2011
+ This isn't a new to-do list, it is a list of the main features that are
+ still not implemented:
+   - full 2D layout
+        + at very least I don't pad with zeros yet
+        + if stripe size were multiple of 3*3*5*7*2^N, then changing
+          width might be managable.
+          e.g. stripe size: 40320 blocks.. But with megabyte chunksizes,
+          we really want 32bit segsizes and 322560 block segments.
+   - non-logged files - with interface to request access-time file
+   - quotas
+   - snapshots:  particularly cleaning
+   - error handling
+   - metadata (inode/directory/etc) CRCs and duplication
+   - fsck / debugfs
+
+
+  What would fsck do?
+   - locate and validate device and state blocks.
+   - locate and validate checkpoint cluster.
+   - locate and validate filesystem root
+   - roll forward to collect segusage and quota blocks.
+   - load inode map, read inode file, validate each inode and make sure
+     map is correct.
+   - explore each file, following all indexing, count segusage for each
+     segment and make sure segusage file is consistent.
+   - check no block is allocated twice.  This might require multiple passes,
+     each time we examine a different collection of segments.
+
+   - checking a file requires:
+          - checking inode is consistent
+          - checking index blocks are consistent with depth
+          - checking index/extent blocks are sorted with no overlaps
+          - checking block/iblock counts are correct.
+   - checking all cluster headers in the current segment to ensure they
+     look consistent and agree with file information. i.e. if cluster_header
+     identifies a block, the block must live there, or later in the segment.
+
+   - scan all directories looking for consistency of hash etc.  Count links
+     for all inodes.  This might need to be multi-pass too.
+     Could use a bitmap for single-link files, and table for others.
+
+   How to fix errors.
+     - First must find segments which are not in use according to segusage file
+       or according to block search.
+       If there are none, require a new device be provided.
+     - If anything looks incorrect, write corrected version to new segment
+       Then write out new segusage files
+
+   In some cases we might need to search all write-clusters for missing blocks??
+   That could take a very long time!
+
+
+   What do I really want to do about CRCs and hashes.
+    It might be nice to store a hash for each block in the index block.
+    But that wastes precious index-block space.
+    If I store a CRC together with address info in the block, then I could
+    be fairly sure it is the right block.  So e.g. inodes store the inode number,
+    Index blocks could hold inode+depth+address.
+    Last 8 bytes of each block could be a 4byte CRC and a 4byte identity.
+    identiy is XOR of fsinum inum blocknum generation - or a CRC of these.
+
+    Actually, we don't need to store the identity info - we just need to
+    include it in the CRC.  That either saves space, or allows more bits to
+    be used for the CRC, which is probably the best use of bits for detecting
+    errors.
+    Though it might be nice to store phys-addr in the CRC too, we cannot as
+
+21mar2011
+  My short-term todo list is:
+  - get 'lafs' to the stage where I can create an fs requiring roll-forward
+  - use 'lafs' to create images for testing, so I don't need 'fred.safe' any more.
+  - Make lots of 'layout' changes - see 15cb
+
+02may2011
+  - 'run' goes to completion, but segusage isn't updated in the final cluster
+       and the number left over from before looks wrong.
+  - 'ls -l' on a subset file gets confused.