From: Sage Weil Date: Mon, 19 May 2008 13:57:18 +0000 (-0700) Subject: mds: xattr ops. works. X-Git-Tag: v0.3~209^2~26 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9567c8dad3dd3d32a3b2132ef2b4d3eab66aa99f;p=ceph.git mds: xattr ops. works. --- diff --git a/src/client/Client.cc b/src/client/Client.cc index dc5449a9d733..498be1ef329b 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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::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::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++; } diff --git a/src/client/fuse_ll.cc b/src/client/fuse_ll.cc index f835573e6bc5..3dd3ac4f9a75 100644 --- a/src/client/fuse_ll.cc +++ b/src/client/fuse_ll.cc @@ -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); diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 4868d969d41c..7b3ba0aa8a15 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -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; diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 6cc91036c8d5..0f170d47583c 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -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 rdlocks = mdr->rdlocks; + set wrlocks = mdr->wrlocks; + set 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 rdlocks = mdr->rdlocks; + set wrlocks = mdr->wrlocks; + set 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)); +} + + + // ================================================================= diff --git a/src/mds/Server.h b/src/mds/Server.h index 873ef14da8d2..f7974975ae8a 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -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 diff --git a/src/mds/events/EMetaBlob.h b/src/mds/events/EMetaBlob.h index a344a42a33f3..85974474e761 100644 --- a/src/mds/events/EMetaBlob.h +++ b/src/mds/events/EMetaBlob.h @@ -54,13 +54,12 @@ public: version_t dnv; inode_t inode; // if it's not fragtree_t dirfragtree; - string symlink; + map 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 &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;