]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
uclient: implement basic I_COMPLETE support
authorSage Weil <sage@newdream.net>
Thu, 17 Sep 2009 21:54:36 +0000 (14:54 -0700)
committerSage Weil <sage@newdream.net>
Thu, 17 Sep 2009 21:54:36 +0000 (14:54 -0700)
src/client/Client.cc
src/client/Client.h

index a3d40e972e15a6ae1f81478a345248f63bff5f7e..3b03fdc263203e51704b2fdf7d7e0ddd71b4de62 100644 (file)
@@ -313,6 +313,11 @@ void Client::trim_cache()
     dout(15) << "trim_cache unlinking dn " << dn->name 
             << " in dir " << hex << dn->dir->parent_inode->ino 
             << dendl;
+    if (dn->dir->parent_inode->flags & I_COMPLETE) {
+      dout(10) << " clearing I_COMPLETE on " << *dn->dir->parent_inode << dendl;
+      dn->dir->parent_inode->flags &= ~I_COMPLETE;
+      dn->dir->release_count++;
+    }
     unlink(dn);
   }
 
@@ -446,6 +451,14 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, int mds)
     update_inode_file_bits(in, st->truncate_seq, st->truncate_size, st->size,
                           st->time_warp_seq, st->ctime, st->mtime, st->atime,
                           in->caps_issued());
+
+    if (in->is_dir() &&
+       (st->cap.caps & CEPH_CAP_FILE_SHARED) &&
+       in->dirstat.nfiles == 0 &&
+       in->dirstat.nsubdirs == 0) {
+      dout(10) << " marking I_COMPLETE on empty dir " << *in << dendl;
+      in->flags |= I_COMPLETE;
+    }
   }
 
   // symlink?
@@ -1856,11 +1869,11 @@ void Client::check_cap_issue(Inode *in, InodeCap *cap, unsigned issued)
       !(had & CEPH_CAP_FILE_SHARED)) {
     in->shared_gen++;
 
-    if (in->is_dir()) {
-      // ...
+    if (in->is_dir() && (in->flags & I_COMPLETE)) {
+      dout(10) << " clearing I_COMPLETE on " << *in << dendl;
+      in->flags &= ~I_COMPLETE;
     }
   }
-
 }
 
 void Client::add_update_cap(Inode *in, int mds, __u64 cap_id,
@@ -2876,6 +2889,13 @@ int Client::_lookup(Inode *dir, const string& dname, Inode **target)
       *target = dn->inode;
       goto done;
     }
+  } else {
+    // can we conclude ENOENT locally?
+    if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED) &&
+       (dir->flags & I_COMPLETE)) {
+      dout(10) << "_lookup concluded ENOENT locally for " << *dir << " dn '" << dname << "'" << dendl;
+      return -ENOENT;
+    }
   }
 
   r = _do_lookup(dir, dname.c_str(), target);
@@ -3455,6 +3475,8 @@ int Client::_opendir(Inode *in, DirResult **dirpp, int uid, int gid)
 {
   *dirpp = new DirResult(in);
   (*dirpp)->set_frag(in->dirfragtree[0]);
+  if (in->dir)
+    (*dirpp)->release_count = in->dir->release_count;
   dout(10) << "_opendir " << in->ino << ", our cache says the first dirfrag is " << (*dirpp)->frag() << dendl;
 
   // get the first frag
@@ -3602,6 +3624,11 @@ int Client::_readdir_get_frag(DirResult *dirp)
        numdn--;
       }
     }
+
+    if (diri->dir->release_count == dirp->release_count) {
+      dout(10) << " marking I_COMPLETE on " << *diri << dendl;
+      diri->flags |= I_COMPLETE;
+    }
   } else {
     dout(10) << "_readdir_get_frag got error " << res << ", setting end flag" << dendl;
     dirp->set_end();
index 3a9064919a47bf5da169cd3899a0cbaf4ae599f4..5ff02b7a7662d732bc7948a6ac541daf8f5f86a1 100644 (file)
@@ -187,8 +187,9 @@ class Dir {
  public:
   Inode    *parent_inode;  // my inode
   hash_map<nstring, Dentry*> dentries;
+  __u64 release_count;
 
-  Dir(Inode* in) { parent_inode = in; }
+  Dir(Inode* in) : release_count(0) { parent_inode = in; }
 
   bool is_empty() {  return dentries.empty(); }
 };
@@ -265,6 +266,9 @@ struct CapSnap {
 };
 
 
+// inode flags
+#define I_COMPLETE 1
+
 class Inode {
  public:
   // -- the actual inode --
@@ -306,6 +310,8 @@ class Inode {
   bool is_dir()     const { return (mode & S_IFMT) == S_IFDIR; }
   bool is_file()    const { return (mode & S_IFMT) == S_IFREG; }
 
+  unsigned flags;
+
   // about the dir (if this is one!)
   int       dir_auth;
   set<int>  dir_contacts;
@@ -401,10 +407,10 @@ class Inode {
   }
 
   Inode(vinodeno_t vino, ceph_file_layout *layout) : 
-    //inode(_inode),
     ino(vino.ino), snapid(vino.snapid),
     rdev(0), mode(0), uid(0), gid(0), nlink(0), size(0), truncate_seq(0), truncate_size(0), truncate_from(0),
     time_warp_seq(0), max_size(0), version(0), xattr_version(0),
+    flags(0),
     dir_auth(-1), dir_hashed(false), dir_replicated(false), 
     dirty_caps(0), flushing_caps(0), flushing_cap_seq(0), shared_gen(0), cache_gen(0),
     snap_caps(0), snap_cap_refs(0),
@@ -680,9 +686,10 @@ class Client : public Dispatcher {
 
     Inode *inode;
     int64_t offset;   // high bits: frag_t, low bits: an offset
+    __u64 release_count;
     map<frag_t, vector<DirEntry> > buffer;
 
-    DirResult(Inode *in) : inode(in), offset(0) { 
+    DirResult(Inode *in) : inode(in), offset(0), release_count(0) { 
       inode->get();
     }