]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix fragstat accounting across dirfrag splits
authorSage Weil <sage@newdream.net>
Fri, 13 Jun 2008 00:23:14 +0000 (17:23 -0700)
committerSage Weil <sage@newdream.net>
Fri, 13 Jun 2008 18:58:19 +0000 (11:58 -0700)
src/mds/CDir.cc
src/mds/CInode.cc
src/mds/mdstypes.h

index 7be36c4f43428aa085cbe4c6e9863e574349c408..ccb987ada7bd6e6cab11cbb042e24e2ac0648527 100644 (file)
@@ -586,6 +586,13 @@ void CDir::split(int bits, list<CDir*>& subs, list<Context*>& waiters)
   
   double fac = 1.0 / (double)(1 << bits);  // for scaling load vecs
 
+  frag_info_t olddiff;  // old += f - af;
+  dout(10) << "           fragstat " << fnode.fragstat << dendl;
+  dout(10) << " accounted_fragstat " << fnode.accounted_fragstat << dendl;
+  olddiff.zero();
+  olddiff.take_diff(fnode.fragstat, fnode.accounted_fragstat);
+  dout(10) << "            olddiff " << olddiff << dendl;
+
   // create subfrag dirs
   int n = 0;
   for (list<frag_t>::iterator p = frags.begin(); p != frags.end(); ++p) {
@@ -625,6 +632,21 @@ void CDir::split(int bits, list<CDir*>& subs, list<Context*>& waiters)
     f->steal_dentry(dn);
   }
 
+  // fix up new frag fragstats
+  for (int i=0; i<n; i++) {
+    subfrags[i]->fnode.fragstat.version = fnode.fragstat.version;
+    subfrags[i]->fnode.accounted_fragstat = subfrags[i]->fnode.fragstat;
+    dout(10) << "      fragstat " << subfrags[i]->fnode.fragstat << " on " << *subfrags[i] << dendl;
+  }
+
+  // give any outstanding frag stat differential to first frag
+  //   af[0] -= olddiff
+  dout(10) << "giving olddiff " << olddiff << " to " << *subfrags[0] << dendl;
+  frag_info_t zero;
+  zero.zero();
+  subfrags[0]->fnode.accounted_fragstat.take_diff(zero, olddiff);
+  dout(10) << "               " << subfrags[0]->fnode.accounted_fragstat << dendl;
+
   purge_stolen(waiters);
   inode->close_dirfrag(frag); // selft deletion, watch out.
 }
index 2377f09229fd84eea7c94d31831e59a74a55454a..8fd85da9cd4c60ca479e3b4b8c96303635437cf8 100644 (file)
@@ -750,6 +750,9 @@ void CInode::finish_scatter_gather_update(int type)
       }
       pi->dirstat.version++;
       dout(20) << "        final dirstat " << pi->dirstat << dendl;
+      assert(pi->dirstat.size() >= 0);
+      assert(pi->dirstat.nfiles >= 0);
+      assert(pi->dirstat.nsubdirs >= 0);
     }
     break;
 
index e9fbaf0e71526a1e4b9b34c55dac062f28dbd128..3c1b7b6b00bb9006af50db80ebe7468ecc19c338 100644 (file)
@@ -58,18 +58,21 @@ struct frag_info_t {
 
   // this frag
   utime_t mtime;
-  __u64 nfiles;        // files
-  __u64 nsubdirs;      // subdirs
-  __u64 size() const { return nfiles + nsubdirs; }
+  __s64 nfiles;        // files
+  __s64 nsubdirs;      // subdirs
+  __s64 size() const { return nfiles + nsubdirs; }
 
   // this frag + children
   utime_t rctime;
-  __u64 rbytes;
-  __u64 rfiles;
-  __u64 rsubdirs;
-  __u64 rsize() const { return rfiles + rsubdirs; }
-  __u64 ranchors;  // for dirstat, includes inode's anchored flag.
+  __s64 rbytes;
+  __s64 rfiles;
+  __s64 rsubdirs;
+  __s64 rsize() const { return rfiles + rsubdirs; }
+  __s64 ranchors;  // for dirstat, includes inode's anchored flag.
 
+  void zero() {
+    memset(this, 0, sizeof(*this));
+  }
   void take_diff(const frag_info_t &cur, frag_info_t &acc) {
     if (cur.mtime > mtime)
       rctime = mtime = cur.mtime;