]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
* mds: alloc RDCACHE during glockl
authorsageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Thu, 22 Mar 2007 16:58:23 +0000 (16:58 +0000)
committersageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Thu, 22 Mar 2007 16:58:23 +0000 (16:58 +0000)
* client: fixed truncate handling, implemented helper in FileCache
* osdc: implemented truncate in ObjectCacher

git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1289 29311d96-e01e-0410-9327-a35deaab8ce9

trunk/ceph/client/Client.cc
trunk/ceph/client/FileCache.cc
trunk/ceph/client/FileCache.h
trunk/ceph/client/SyntheticClient.cc
trunk/ceph/client/SyntheticClient.h
trunk/ceph/mds/Lock.h
trunk/ceph/mds/Locker.cc
trunk/ceph/osdc/ObjectCacher.cc
trunk/ceph/osdc/ObjectCacher.h

index 444acd6e48df4fb824ac52338374be2364f81c8f..5a80d7d38bc6fee33a2e0394e17134762b4e2221 100644 (file)
@@ -856,14 +856,16 @@ void Client::handle_file_caps(MClientFileCaps *m)
           << " was " << cap_string(old_caps) << endl;
   
   // did file size decrease?
-  if ((old_caps & new_caps & CAP_FILE_RDCACHE) &&
+  if ((old_caps & (CAP_FILE_RD|CAP_FILE_WR)) == 0 &&
+      (new_caps & (CAP_FILE_RD|CAP_FILE_WR)) != 0 &&
       in->inode.size > m->get_inode().size) {
-    dout(10) << "**** file size decreased from " << in->inode.size << " to " << m->get_inode().size << " FIXME" << endl;
-    // must have been a truncate() by someone.
-    // trim the buffer cache
-    // ***** fixme write me ****
+    dout(10) << "*** file size decreased from " << in->inode.size << " to " << m->get_inode().size << endl;
+    
+    // trim filecache?
+    if (g_conf.client_oc)
+      in->fc.truncate(in->inode.size, m->get_inode().size);
 
-    in->file_wr_size = m->get_inode().size; //??
+    in->inode.size = in->file_wr_size = m->get_inode().size; 
   }
 
   // update inode
index 5cc6d9ff7962b31a2784efba4285473ef9c88662..6645bef09b6df842742bf230efadf6faa9f79ba7 100644 (file)
@@ -71,6 +71,18 @@ void FileCache::tear_down()
   }
 }
 
+// truncate
+
+void FileCache::truncate(off_t olds, off_t news)
+{
+  dout(5) << "truncate " << olds << " -> " << news << endl;
+
+  // map range to objects
+  list<ObjectExtent> ls;
+  oc->filer.file_to_extents(inode, news, olds-news, ls);
+  oc->truncate_set(inode.ino, ls);
+}
+
 // caps
 
 class C_FC_CheckCaps : public Context {
@@ -107,16 +119,21 @@ void FileCache::set_caps(int caps, Context *onimplement)
   
 }
 
-
-void FileCache::check_caps()
+int FileCache::get_used_caps()
 {
-  // calc used
   int used = 0;
   if (num_reading) used |= CAP_FILE_RD;
   if (oc->set_is_cached(inode.ino)) used |= CAP_FILE_RDCACHE;
   if (num_writing) used |= CAP_FILE_WR;
   if (oc->set_is_dirty_or_committing(inode.ino)) used |= CAP_FILE_WRBUFFER;
-  dout(10) << "check_caps used " << cap_string(used) << endl;
+  return used;
+}
+
+void FileCache::check_caps()
+{
+  // calc used
+  int used = get_used_caps();
+  dout(10) << "check_caps used was " << cap_string(used) << endl;
 
   // try to implement caps?
   // BUG? latest_caps, not least caps i've seen?
@@ -127,6 +144,9 @@ void FileCache::check_caps()
       (used & CAP_FILE_WRBUFFER))
     flush_dirty(new C_FC_CheckCaps(this));
   
+  used = get_used_caps();
+  dout(10) << "check_caps used now " << cap_string(used) << endl;
+
   // check callbacks
   map<int, list<Context*> >::iterator p = caps_callbacks.begin();
   while (p != caps_callbacks.end()) {
index d710d38c0731a186471555c6a5edda6b343d01f6..9ba82f92eb1ab94775845153fb871fd4f7b88775 100644 (file)
@@ -57,6 +57,8 @@ class FileCache {
   bool all_safe();// { return num_unsafe == 0; }
 
   void add_safe_waiter(Context *c);
+  
+  void truncate(off_t olds, off_t news);
 
   // ...
   void flush_dirty(Context *onflush=0);
@@ -69,6 +71,7 @@ class FileCache {
   void tear_down();
 
   int get_caps() { return latest_caps; }
+  int get_used_caps();
   void set_caps(int caps, Context *onimplement=0);
   void check_caps();
   
index 6f0ad60dc88ab37d7e9dd6fb69db055929a86cad..055e8e84809b6cd297c11d3775033d55365fa7b8 100644 (file)
@@ -144,6 +144,11 @@ void parse_syn_options(vector<char*>& args)
       } else if (strcmp(args[i],"optest") == 0) {
        syn_modes.push_back( SYNCLIENT_MODE_OPTEST );
         syn_iargs.push_back( atoi(args[++i]) );
+
+      } else if (strcmp(args[i],"truncate") == 0) { 
+        syn_modes.push_back( SYNCLIENT_MODE_TRUNCATE );
+       syn_sargs.push_back(args[++i]);
+        syn_iargs.push_back(atoi(args[++i]));
       } else {
         cerr << "unknown syn arg " << args[i] << endl;
         assert(0);
@@ -500,6 +505,16 @@ int SyntheticClient::run()
         }
       }
       break;
+
+    case SYNCLIENT_MODE_TRUNCATE:
+      {
+        string file = get_sarg(0);
+        sargs.push_front(file);
+        int iarg1 = iargs.front();  iargs.pop_front();
+       if (run_me()) 
+         client->truncate(file.c_str(), iarg1);
+      }
+      break;
       
     default:
       assert(0);
@@ -766,6 +781,27 @@ int SyntheticClient::full_walk(string& basedir)
        continue;
       }
       
+      // print
+      char *tm = ctime(&st.st_mtime);
+      tm[strlen(tm)-1] = 0;
+      printf("%c%c%c%c%c%c%c%c%c%c %2d %5d %5d %8d %12s %s\n",
+            S_ISDIR(st.st_mode) ? 'd':'-',
+            (st.st_mode & 0400) ? 'r':'-',
+            (st.st_mode & 0200) ? 'w':'-',
+            (st.st_mode & 0100) ? 'x':'-',
+            (st.st_mode & 040) ? 'r':'-',
+            (st.st_mode & 020) ? 'w':'-',
+            (st.st_mode & 010) ? 'x':'-',
+            (st.st_mode & 04) ? 'r':'-',
+            (st.st_mode & 02) ? 'w':'-',
+            (st.st_mode & 01) ? 'x':'-',
+            (int)st.st_nlink,
+            st.st_uid, st.st_gid,
+            (int)st.st_size,
+            tm,
+            file.c_str());
+
+      
       if ((st.st_mode & INODE_TYPE_MASK) == INODE_MODE_DIR) {
        dirq.push_back(file);
       }
index ebf96386be95c6c180de513880eadac03b7b48e4..adcf7584766e62c9c3ec24587ecf489edb685fcc 100644 (file)
@@ -53,6 +53,8 @@
 #define SYNCLIENT_MODE_RANDOMSLEEP  61
 #define SYNCLIENT_MODE_SLEEP        62
 
+#define SYNCLIENT_MODE_TRUNCATE     200
+
 
 
 
@@ -195,7 +197,6 @@ class SyntheticClient {
   int play_trace(Trace& t, string& prefix);
 
   void make_dir_mess(const char *basedir, int n);
-
 };
 
 #endif
index 0d9dabb61b6690a0238b39290ff321e46e6c40f8..59d04d5b66eb7685d1c57ef8b26278b199c5f02b 100644 (file)
@@ -32,7 +32,7 @@ using namespace std;
 #define LOCK_GLOCKR   2  // AR   R . / C . . . . .   . . / C . . . . .
 
 // file lock states
-#define LOCK_GLOCKL   3  // A    . . / . . . . . .                       loner -> lock
+#define LOCK_GLOCKL   3  // A    . . / C . . . . .                       loner -> lock
 #define LOCK_GLOCKM   4  // A    . . / . . . . . .
 #define LOCK_MIXED    5  // AR   . . / . R W A . L   . . / . R . . . L
 #define LOCK_GMIXEDR  6  // AR   R . / . R . . . L   . . / . R . . . L 
@@ -232,9 +232,9 @@ class CLock {
         return CAP_FILE_RDCACHE | CAP_FILE_RD | CAP_FILE_LAZYIO;
       case LOCK_LOCK:
       case LOCK_GLOCKR:
+      case LOCK_GLOCKL:
         return CAP_FILE_RDCACHE;
 
-      case LOCK_GLOCKL:
       case LOCK_GLOCKM:
         return 0;
 
index 7b47861331f072c325a940f17a3049333f49be43..e1690fe6800ad19b0cb0063d6965fc76f6c9e1c7 100644 (file)
@@ -1027,7 +1027,7 @@ void Locker::inode_file_eval(CInode *in)
     case LOCK_GLOCKR:
     case LOCK_GLOCKM:
     case LOCK_GLOCKL:
-      if (issued == 0) {
+      if ((issued & ~CAP_FILE_RDCACHE) == 0) {
         in->filelock.set_state(LOCK_LOCK);
         
         // waiters
index 0933675ae2880fab0904c018b4be0009105616fd..c406455ca540731498e55a9b569878c418651069 100644 (file)
@@ -324,6 +324,28 @@ ObjectCacher::BufferHead *ObjectCacher::Object::map_write(Objecter::OSDWrite *wr
 }
 
 
+void ObjectCacher::Object::truncate(off_t s)
+{
+  dout(10) << "truncate to " << s << endl;
+  
+  while (!data.empty()) {
+       BufferHead *bh = data.rbegin()->second;
+       if (bh->end() <= s) 
+         break;
+       
+       // split bh at truncation point?
+       if (bh->start() < s) {
+         split(bh, s);
+         continue;
+       }
+
+       // remove bh entirely
+       assert(bh->start() >= s);
+       oc->bh_remove(this, bh);
+       delete bh;
+  }
+}
+
 
 /*** ObjectCacher ***/
 
@@ -1244,7 +1266,8 @@ void ObjectCacher::purge(Object *ob)
        p != ob->data.end();
        p++) {
     BufferHead *bh = p->second;
-       dout(0) << "purge forcibly removing " << *bh << endl;
+       if (!bh->is_clean())
+         dout(0) << "purge forcibly removing " << *ob << " " << *bh << endl;
        bh_remove(ob, bh);
        delete bh;
   }
@@ -1448,6 +1471,39 @@ off_t ObjectCacher::release_set(inodeno_t ino)
   return unclean;
 }
 
+void ObjectCacher::truncate_set(inodeno_t ino, list<ObjectExtent>& exls)
+{
+  if (objects_by_ino.count(ino) == 0) {
+    dout(10) << "truncate_set on " << ino << " dne" << endl;
+    return;
+  }
+  
+  dout(10) << "truncate_set " << ino << endl;
+
+  for (list<ObjectExtent>::iterator p = exls.begin();
+          p != exls.end();
+          ++p) {
+       ObjectExtent &ex = *p;
+       if (objects.count(ex.oid) == 0) continue;
+       Object *ob = objects[ex.oid];
+
+       // purge or truncate?
+       if (ex.start == 0) {
+         dout(10) << "truncate_set purging " << *ob << endl;
+         purge(ob);
+       } else {
+         // hrm, truncate object
+         dout(10) << "truncate_set truncating " << *ob << " at " << ex.start << endl;
+         ob->truncate(ex.start);
+
+         if (ob->can_close()) {
+               dout(10) << "truncate_set trimming " << *ob << endl;
+               close_object(ob);
+         }
+       }
+  }
+}
+
 
 void ObjectCacher::kick_sync_writers(inodeno_t ino)
 {
index e9a4041008666975b7aa1ab3da0cc881e32c47d2..dbec05fa5eee930b42aa224730d10e464b35a7ba 100644 (file)
@@ -187,6 +187,7 @@ class ObjectCacher {
                  map<off_t, BufferHead*>& rx);
     BufferHead *map_write(Objecter::OSDWrite *wr);
     
+       void truncate(off_t s);
   };
   
   // ******* ObjectCacher *********
@@ -467,6 +468,8 @@ class ObjectCacher {
 
   off_t release_set(inodeno_t ino);  // returns # of bytes not released (ie non-clean)
 
+  void truncate_set(inodeno_t ino, list<ObjectExtent>& ex);
+
   void kick_sync_writers(inodeno_t ino);
   void kick_sync_readers(inodeno_t ino);