CEPH_MDS_OP_OPEN = 301,
CEPH_MDS_OP_TRUNCATE = 1303,
- CEPH_MDS_OP_FSYNC = 303
+ CEPH_MDS_OP_FSYNC = 303,
+ CEPH_MDS_OP_CREATE = 304
};
struct ceph_mds_request_head {
return err;
}
-
-/*
-
-
static int
ceph_dir_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
-}
+ struct ceph_mds_client *mdsc = &ceph_inode_to_client(dir)->mdsc;
+ ceph_ino_t pathbase;
+ char *path;
+ int pathlen;
+ struct ceph_msg *req;
+ struct ceph_mds_request_head *rhead;
+ struct ceph_mds_reply_info rinfo;
+ struct ceph_mds_session *session;
+ int err;
+ struct inode *inode;
+
+ dout(5, "create dir %p dentry %p name '%s' flags %d\n", dir, dentry, dentry->d_name.name, mode);
+ pathbase = dir->i_sb->s_root->d_inode->i_ino;
+ path = ceph_build_dentry_path(dentry, &pathlen);
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+ req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_CREATE, pathbase, path, 0, 0);
+ kfree(path);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+ rhead = req->front.iov_base;
+ rhead->args.open.flags = O_CREAT;
+ rhead->args.open.mode = mode;
+ if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, &session)) < 0)
+ return err;
+
+ dout(10, "create got and parsed result\n");
+
+ err = le32_to_cpu(rinfo.head->result);
+ if (err == 0) {
+ err = ceph_fill_trace(dir->i_sb, &rinfo, &inode, NULL);
+ if (err < 0) {
+ goto done_create;
+ }
-*/
+ if (inode == NULL) {
+ err = -ENOMEM;
+ goto done_create;
+ }
+ dout(10, "rinfo.dir_in=%p rinfo.trace_nr=%d\n", rinfo.trace_in, rinfo.trace_nr);
+ }
+done_create:
+ return err;
+}
const struct inode_operations ceph_dir_iops = {
.lookup = ceph_dir_lookup,
.unlink = ceph_dir_unlink,
.rmdir = ceph_dir_unlink,
.rename = ceph_dir_rename,
-/* .create = ceph_dir_create,
- .getattr = ceph_vfs_getattr,
- .setattr = ceph_vfs_setattr,
-*/
+ .create = ceph_dir_create,
};
// funky.
case CEPH_MDS_OP_OPEN:
if (req->head.args.open.flags & O_CREAT)
- handle_client_openc(mdr);
+ handle_client_openc(mdr, true);
else
handle_client_open(mdr);
break;
+ case CEPH_MDS_OP_CREATE:
+ handle_client_openc(mdr, false);
+ break;
// namespace.
// no prior locks.
case CEPH_MDS_OP_MKNOD:
MDRequest *mdr;
CDentry *dn;
CInode *newi;
+ bool should_open;
version_t pv;
public:
- C_MDS_openc_finish(MDS *m, MDRequest *r, CDentry *d, CInode *ni) :
- mds(m), mdr(r), dn(d), newi(ni),
+ C_MDS_openc_finish(MDS *m, MDRequest *r, CDentry *d, CInode *ni, bool open) :
+ mds(m), mdr(r), dn(d), newi(ni), should_open(open),
pv(d->get_projected_version()) {}
void finish(int r) {
assert(r == 0);
// downgrade xlock to rdlock
//mds->locker->dentry_xlock_downgrade_to_rdlock(dn, mdr);
- // set/pin ref inode for open()
- mdr->ref = newi;
- mdr->pin(newi);
+ if (should_open) {
+ // set/pin ref inode for open()
+ mdr->ref = newi;
+ mdr->pin(newi);
- // ok, do the open.
- mds->server->handle_client_open(mdr);
+ // ok, do the open.
+ mds->server->handle_client_open(mdr);
+ } else {
+ MClientReply *reply = new MClientReply(mdr->client_request);
+ mds->server->reply_request(mdr, reply, newi);
+ }
}
};
-void Server::handle_client_openc(MDRequest *mdr)
+void Server::handle_client_openc(MDRequest *mdr, bool open)
{
MClientRequest *req = mdr->client_request;
}
// pass to regular open handler.
- handle_client_open(mdr);
+ if (open) {
+ handle_client_open(mdr);
+ } else {
+ MClientReply *reply = new MClientReply(req);
+ reply_request(mdr, reply, dn->get_dir()->get_inode());
+ }
return;
}
in->inode.version = dn->pre_dirty() - 1;
// prepare finisher
- C_MDS_openc_finish *fin = new C_MDS_openc_finish(mds, mdr, dn, in);
+ C_MDS_openc_finish *fin = new C_MDS_openc_finish(mds, mdr, dn, in, open);
mdr->ls = mdlog->get_current_segment();
EUpdate *le = new EUpdate(mdlog, "openc");
le->metablob.add_client_req(req->get_reqid());
// open
void handle_client_open(MDRequest *mdr);
- void handle_client_openc(MDRequest *mdr); // O_CREAT variant.
+ void handle_client_openc(MDRequest *mdr, bool open); // O_CREAT variant.
void handle_client_opent(MDRequest *mdr); // O_TRUNC variant.
void _do_open(MDRequest *mdr, CInode *ref);