summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-02-17 21:27:51 -0800
committerSage Weil <sage@newdream.net>2009-02-19 15:25:46 -0800
commite8d370a91a97adc1a084b04d563c1a8bd6a014af (patch)
tree82ffe2163692b82f37b4937d3f1cef1a6b53ed37
parent142af495d85d1de32a54d21307dbafaad57bdab6 (diff)
downloadceph-e8d370a91a97adc1a084b04d563c1a8bd6a014af.tar.gz
mds: CREATE op for async creation writeback
-rw-r--r--src/include/ceph_fs.h8
-rw-r--r--src/mds/Server.cc59
-rw-r--r--src/mds/Server.h1
3 files changed, 68 insertions, 0 deletions
diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h
index e583a276b29..f2cade77fd7 100644
--- a/src/include/ceph_fs.h
+++ b/src/include/ceph_fs.h
@@ -690,6 +690,8 @@ enum {
CEPH_MDS_OP_RMDIR = 0x01221,
CEPH_MDS_OP_SYMLINK = 0x01222,
+ CEPH_MDS_OP_CREATE = 0x01230,
+
CEPH_MDS_OP_OPEN = 0x10302,
CEPH_MDS_OP_TRUNCATE = 0x11303,
CEPH_MDS_OP_LTRUNCATE = 0x01303,
@@ -773,6 +775,12 @@ union ceph_mds_request_args {
__le32 mode;
} __attribute__ ((packed)) mkdir;
struct {
+ __le32 uid, gid, mode, rdev;
+ __le64 size;
+ struct ceph_timespec ctime, mtime, atime;
+ __le32 caps, wanted;
+ } __attribute__ ((packed)) create;
+ struct {
__le32 flags;
__le32 mode;
} __attribute__ ((packed)) open;
diff --git a/src/mds/Server.cc b/src/mds/Server.cc
index 5002d2c7570..0665442600d 100644
--- a/src/mds/Server.cc
+++ b/src/mds/Server.cc
@@ -962,6 +962,9 @@ void Server::dispatch_client_request(MDRequest *mdr)
case CEPH_MDS_OP_SYMLINK:
handle_client_symlink(mdr);
break;
+ case CEPH_MDS_OP_CREATE:
+ handle_client_create(mdr);
+ break;
// snaps
@@ -2557,6 +2560,62 @@ void Server::handle_client_symlink(MDRequest *mdr)
}
+void Server::handle_client_create(MDRequest *mdr)
+{
+ MClientRequest *req = mdr->client_request;
+
+ CDentry *dn = rdlock_path_xlock_dentry(mdr, false, false);
+ if (!dn) return;
+
+ mdr->now = g_clock.real_now();
+ snapid_t follows = dn->get_dir()->inode->find_snaprealm()->get_newest_seq();
+
+ CInode *newi = prepare_new_inode(mdr, dn->get_dir(), inodeno_t(req->head.ino));
+ assert(newi);
+
+ dn->push_projected_linkage(newi);
+
+ newi->inode.mode = req->head.args.create.mode;
+ newi->inode.rdev = req->head.args.create.rdev;
+ newi->inode.uid = req->head.args.create.uid;
+ newi->inode.gid = req->head.args.create.gid;
+
+ newi->inode.size = req->head.args.create.size;
+ newi->inode.mtime = req->head.args.create.mtime;
+ newi->inode.ctime = req->head.args.create.ctime;
+ newi->inode.atime = req->head.args.create.atime;
+
+ newi->inode.rstat.rbytes = newi->inode.size;
+ newi->inode.rstat.rfiles = 1;
+ newi->inode.version = dn->pre_dirty();
+
+ newi->symlink = req->get_path2();
+
+ dn->first = newi->first = follows+1;
+
+ // prepare finisher
+ mdr->ls = mdlog->get_current_segment();
+ EUpdate *le = new EUpdate(mdlog, "create");
+ le->metablob.add_client_req(req->get_reqid());
+ journal_allocated_inos(mdr, &le->metablob);
+ mdcache->predirty_journal_parents(mdr, &le->metablob, newi, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
+ le->metablob.add_primary_dentry(dn, true, newi);
+
+ int client = mdr->get_client();
+ Capability *cap = newi->get_client_cap(client);
+ int keep = req->head.args.create.caps;
+ cap->set_wanted(req->head.args.create.wanted);
+ cap->issue(keep);
+
+ newi->filelock.set_state((keep & CEPH_CAP_FILE_EXCL) ? LOCK_EXCL:LOCK_SYNC);
+ newi->authlock.set_state((keep & CEPH_CAP_AUTH_EXCL) ? LOCK_EXCL:LOCK_SYNC);
+ newi->linklock.set_state((keep & CEPH_CAP_LINK_EXCL) ? LOCK_EXCL:LOCK_SYNC);
+ newi->xattrlock.set_state((keep & CEPH_CAP_XATTR_EXCL) ? LOCK_EXCL:LOCK_SYNC);
+
+ mdlog->submit_entry(le, new C_MDS_mknod_finish(mds, mdr, dn, newi, follows), true);
+}
+
+
diff --git a/src/mds/Server.h b/src/mds/Server.h
index 8b974de5b0a..c7acdf3100f 100644
--- a/src/mds/Server.h
+++ b/src/mds/Server.h
@@ -133,6 +133,7 @@ public:
void handle_client_mknod(MDRequest *mdr);
void handle_client_mkdir(MDRequest *mdr);
void handle_client_symlink(MDRequest *mdr);
+ void handle_client_create(MDRequest *mdr);
// link
void handle_client_link(MDRequest *mdr);