]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: xattr ops. works.
authorSage Weil <sage@newdream.net>
Mon, 19 May 2008 13:57:18 +0000 (06:57 -0700)
committerSage Weil <sage@newdream.net>
Mon, 19 May 2008 16:06:22 +0000 (09:06 -0700)
src/client/Client.cc
src/client/fuse_ll.cc
src/mds/Locker.cc
src/mds/Server.cc
src/mds/Server.h
src/mds/events/EMetaBlob.h

index dc5449a9d7331b0724a07aa053f9ed50f8310329..498be1ef329bb4df622b3470068868788800b006 100644 (file)
@@ -381,7 +381,7 @@ void Client::update_inode(Inode *in, InodeStat *st, LeaseStat *lease, utime_t fr
     in->inode.anchored = false;  /* lie */
 
     in->dirfragtree = st->dirfragtree;  // FIXME look at the mask!
-    in->xattrs = st->xattrs;
+    in->xattrs.swap(st->xattrs);
 
     in->inode.ctime = st->ctime;
     in->inode.max_size = st->max_size;  // right?
@@ -3780,7 +3780,7 @@ int Client::_getxattr(const filepath &path, const char *name, void *value, size_
       }
     }
   }
-  dout(3) << "_setxattr(\"" << path << "\", \"" << name << "\", " << size << ") = " << r << dendl;
+  dout(3) << "_getxattr(\"" << path << "\", \"" << name << "\", " << size << ") = " << r << dendl;
   return r;
 }
 
@@ -3807,15 +3807,15 @@ int Client::_listxattr(const filepath &path, char *name, size_t size,
     for (map<string,bufferptr>::iterator p = in->xattrs.begin();
         p != in->xattrs.end();
         p++)
-      r += p->second.length() + 1;
+      r += p->first.length() + 1;
     
     if (size != 0) {
       if (size >= (unsigned)r) {
        for (map<string,bufferptr>::iterator p = in->xattrs.begin();
             p != in->xattrs.end();
             p++) {
-         memcpy(name, p->second.c_str(), p->second.length());
-         name += p->second.length();
+         memcpy(name, p->first.c_str(), p->first.length());
+         name += p->first.length();
          *name = '\0';
          name++;
        }
index f835573e6bc5199f765f52582e8ed6a3117eb6d1..3dd3ac4f9a758d6d4fedae446c8e6f03b34a7957 100644 (file)
@@ -95,7 +95,7 @@ static void ceph_ll_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
   int r = client->ll_listxattr(ino, buf, size, ctx->uid, ctx->gid);
   if (size == 0 && r >= 0)
     fuse_reply_xattr(req, r);
-  else if (r >= 0)
+  else if (r >= 0) 
     fuse_reply_buf(req, buf, r);
   else
     fuse_reply_err(req, -r);
index 4868d969d41cac79cf14edf0630fa6ce9469000e..7b3ba0aa8a1513305a02d84b70556b10a48f84cc 100644 (file)
@@ -1136,6 +1136,7 @@ int Locker::issue_client_lease(CInode *in, int client,
   } else {
     if (in->filelock.can_lease()) mask |= CEPH_LOCK_IFILE;
   }
+  if (in->xattrlock.can_lease()) mask |= CEPH_LOCK_IXATTR;
 
   _issue_client_lease(in, mask, pool, client, bl, now, session);
   return mask;
index 6cc91036c8d55ab4e76d80d93d21272a289ace91..0f170d47583c44b43d58fbd11752117745ca73fa 100644 (file)
@@ -49,6 +49,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <attr/xattr.h>
 
 #include <list>
 #include <iostream>
@@ -754,6 +755,14 @@ void Server::dispatch_client_request(MDRequest *mdr)
   case CEPH_MDS_OP_LTRUNCATE:
     handle_client_truncate(mdr);
     break;
+  case CEPH_MDS_OP_SETXATTR:
+  case CEPH_MDS_OP_LSETXATTR:
+    handle_client_setxattr(mdr);
+    break;
+  case CEPH_MDS_OP_RMXATTR:
+  case CEPH_MDS_OP_LRMXATTR:
+    handle_client_removexattr(mdr);
+    break;
   case CEPH_MDS_OP_READDIR:
     handle_client_readdir(mdr);
     break;
@@ -1559,6 +1568,7 @@ void Server::handle_client_stat(MDRequest *mdr)
       mask & CEPH_LOCK_ICONTENT) rdlocks.insert(&ref->filelock);
   if (ref->is_dir() &&
       mask & CEPH_LOCK_ICONTENT) rdlocks.insert(&ref->dirlock);
+  if (mask & CEPH_LOCK_IXATTR) rdlocks.insert(&ref->xattrlock);
 
   if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
     return;
@@ -1568,8 +1578,7 @@ void Server::handle_client_stat(MDRequest *mdr)
 
   // reply
   dout(10) << "reply to stat on " << *req << dendl;
-  MClientReply *reply = new MClientReply(req);
-  reply_request(mdr, reply);
+  reply_request(mdr, 0);
 }
 
 
@@ -1747,6 +1756,111 @@ void Server::handle_client_chown(MDRequest *mdr)
 }
 
 
+// XATTRS
+
+void Server::handle_client_setxattr(MDRequest *mdr)
+{
+  MClientRequest *req = mdr->client_request;
+  CInode *cur = rdlock_path_pin_ref(mdr, true);
+  if (!cur) return;
+
+  if (cur->is_root()) {
+    reply_request(mdr, -EINVAL);   // for now
+    return;
+  }
+
+  // write
+  set<SimpleLock*> rdlocks = mdr->rdlocks;
+  set<SimpleLock*> wrlocks = mdr->wrlocks;
+  set<SimpleLock*> xlocks = mdr->xlocks;
+  xlocks.insert(&cur->xattrlock);
+  if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
+    return;
+
+  string name(req->get_path2());
+  int flags = req->head.args.setxattr.flags;
+
+  if ((flags & XATTR_CREATE) && cur->xattrs.count(name)) {
+    dout(10) << "setxattr '" << name << "' XATTR_CREATE and EEXIST on " << *cur << dendl;
+    reply_request(mdr, -EEXIST);
+    return;
+  }
+  if ((flags & XATTR_REPLACE) && !cur->xattrs.count(name)) {
+    dout(10) << "setxattr '" << name << "' XATTR_REPLACE and ENOATTR on " << *cur << dendl;
+    reply_request(mdr, -ENOATTR);
+    return;
+  }
+
+  dout(10) << "setxattr '" << name << "' on " << *cur << dendl;
+
+  // project update
+  inode_t *pi = cur->project_inode();
+  pi->version = cur->pre_dirty();
+  pi->ctime = g_clock.real_now();
+
+  cur->xattrs.erase(name);
+  int len = req->get_data().length();
+  cur->xattrs[name] = buffer::create(len);
+  req->get_data().copy(0, len, cur->xattrs[name].c_str());
+  
+  // log + wait
+  mdr->ls = mdlog->get_current_segment();
+  EUpdate *le = new EUpdate(mdlog, "chown");
+  le->metablob.add_client_req(req->get_reqid());
+  le->metablob.add_dir_context(cur->get_parent_dir());
+  le->metablob.add_primary_dentry(cur->parent, true, 0, pi);
+  
+  mdlog->submit_entry(le);
+  mdlog->wait_for_sync(new C_MDS_inode_update_finish(mds, mdr, cur));
+}
+
+void Server::handle_client_removexattr(MDRequest *mdr)
+{
+  MClientRequest *req = mdr->client_request;
+  CInode *cur = rdlock_path_pin_ref(mdr, true);
+  if (!cur) return;
+
+  if (cur->is_root()) {
+    reply_request(mdr, -EINVAL);   // for now
+    return;
+  }
+
+  // write
+  set<SimpleLock*> rdlocks = mdr->rdlocks;
+  set<SimpleLock*> wrlocks = mdr->wrlocks;
+  set<SimpleLock*> xlocks = mdr->xlocks;
+  xlocks.insert(&cur->xattrlock);
+  if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
+    return;
+
+  string name(req->get_path2());
+  if (cur->xattrs.count(name) == 0) {
+    dout(10) << "removexattr '" << name << "' and ENOATTR on " << *cur << dendl;
+    reply_request(mdr, -ENOATTR);
+    return;
+  }
+
+  dout(10) << "removexattr '" << name << "' on " << *cur << dendl;
+
+  // project update
+  inode_t *pi = cur->project_inode();
+  pi->version = cur->pre_dirty();
+  pi->ctime = g_clock.real_now();
+  cur->xattrs.erase(name);
+  
+  // log + wait
+  mdr->ls = mdlog->get_current_segment();
+  EUpdate *le = new EUpdate(mdlog, "chown");
+  le->metablob.add_client_req(req->get_reqid());
+  le->metablob.add_dir_context(cur->get_parent_dir());
+  le->metablob.add_primary_dentry(cur->parent, true, 0, pi);
+  
+  mdlog->submit_entry(le);
+  mdlog->wait_for_sync(new C_MDS_inode_update_finish(mds, mdr, cur));
+}
+
+
+
 
 
 // =================================================================
index 873ef14da8d27bf636b293775f0a93aa87d3d2bf..f7974975ae8a56abe6d44ed469e6b948c754168f 100644 (file)
@@ -112,6 +112,8 @@ public:
   void handle_client_chown(MDRequest *mdr);
   void handle_client_readdir(MDRequest *mdr);
   void handle_client_truncate(MDRequest *mdr);
+  void handle_client_setxattr(MDRequest *mdr);
+  void handle_client_removexattr(MDRequest *mdr);
   void handle_client_fsync(MDRequest *mdr);
 
   // open
index a344a42a33f3919343057e7db158d68d85d78910..85974474e761f2ef3552b5d36a035d98580a8677 100644 (file)
@@ -54,13 +54,12 @@ public:
     version_t dnv;
     inode_t inode;      // if it's not
     fragtree_t dirfragtree;
-    string  symlink;
+    map<string,bufferptr> xattrs;
+    string symlink;
     bool dirty;
 
-    fullbit(const string& d, version_t v, inode_t& i, fragtree_t dft, bool dr) : 
-      dn(d), dnv(v), inode(i), dirfragtree(dft), dirty(dr) { }
-    fullbit(const string& d, version_t v, inode_t& i, fragtree_t dft, string& sym, bool dr) :
-      dn(d), dnv(v), inode(i), dirfragtree(dft), symlink(sym), dirty(dr) { }
+    fullbit(const string& d, version_t v, inode_t& i, fragtree_t &dft, map<string,bufferptr> &xa, string& sym, bool dr) :
+      dn(d), dnv(v), inode(i), dirfragtree(dft), xattrs(xa), symlink(sym), dirty(dr) { }
     fullbit(bufferlist::iterator &p) { decode(p); }
     fullbit() {}
 
@@ -69,6 +68,7 @@ public:
       ::encode(dnv, bl);
       ::encode(inode, bl);
       ::encode(dirfragtree, bl);
+      ::encode(xattrs, bl);
       if (inode.is_symlink())
        ::encode(symlink, bl);
       ::encode(dirty, bl);
@@ -78,6 +78,7 @@ public:
       ::decode(dnv, bl);
       ::decode(inode, bl);
       ::decode(dirfragtree, bl);
+      ::decode(xattrs, bl);
       if (inode.is_symlink())
        ::decode(symlink, bl);
       ::decode(dirty, bl);
@@ -380,14 +381,14 @@ private:
     if (dirty) {
       lump.get_dfull().push_front(fullbit(dn->get_name(), 
                                          dn->get_projected_version(), 
-                                         in->inode, in->dirfragtree, in->symlink, 
+                                         in->inode, in->dirfragtree, in->xattrs, in->symlink, 
                                          dirty));
       if (pi) lump.get_dfull().front().inode = *pi;
       return &lump.get_dfull().front().inode;
     } else {
       lump.get_dfull().push_back(fullbit(dn->get_name(), 
                                         dn->get_projected_version(),
-                                        in->inode, in->dirfragtree, in->symlink, 
+                                        in->inode, in->dirfragtree, in->xattrs, in->symlink, 
                                         dirty));
       if (pi) lump.get_dfull().back().inode = *pi;
       return &lump.get_dfull().back().inode;