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?
}
}
}
- dout(3) << "_setxattr(\"" << path << "\", \"" << name << "\", " << size << ") = " << r << dendl;
+ dout(3) << "_getxattr(\"" << path << "\", \"" << name << "\", " << size << ") = " << r << dendl;
return r;
}
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++;
}
#include <errno.h>
#include <fcntl.h>
+#include <attr/xattr.h>
#include <list>
#include <iostream>
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;
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;
// reply
dout(10) << "reply to stat on " << *req << dendl;
- MClientReply *reply = new MClientReply(req);
- reply_request(mdr, reply);
+ reply_request(mdr, 0);
}
}
+// 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));
+}
+
+
+
// =================================================================
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() {}
::encode(dnv, bl);
::encode(inode, bl);
::encode(dirfragtree, bl);
+ ::encode(xattrs, bl);
if (inode.is_symlink())
::encode(symlink, bl);
::encode(dirty, bl);
::decode(dnv, bl);
::decode(inode, bl);
::decode(dirfragtree, bl);
+ ::decode(xattrs, bl);
if (inode.is_symlink())
::decode(symlink, bl);
::decode(dirty, bl);
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;