diff --git a/ceph/Makefile b/ceph/Makefile index 78978d152b4..8a64d00068e 100644 --- a/ceph/Makefile +++ b/ceph/Makefile @@ -51,6 +51,9 @@ COMMON_OBJS= \ common/Timer.o\ config.o +SYN_OBJS = \ + client/Trace.o + TEST_TARGETS = fakemds mpitest TARGETS = import singleclient mpifuse fakefuse mpisyn fakesyn tcpsyn @@ -65,6 +68,8 @@ obfs: depend obfstest gprof-helper.so: test/gprof-helper.c gcc -shared -fPIC test/gprof-helper.c -o gprof-helper.so -lpthread -ldl + +# old test crap import: mds/allmds.o osd/OSD.o msg/FakeMessenger.o import.cc ${COMMON_OBJS} ${CC} ${CFLAGS} ${LIBS} $^ -o $@ @@ -86,26 +91,32 @@ mpitest: test/mpitest.o msg/MPIMessenger.cc mds/allmds.o osd/OSD.o fakeclient/Fa mttest: test/mttest.cc msg/MTMessenger.cc ${COMMON_OBJS} ${MPICC} ${CFLAGS} ${LIBS} $^ -o $@ -mpifuse: mpifuse.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o client/fuse.o msg/MPIMessenger.cc ${COMMON_OBJS} - ${MPICC} ${CFLAGS} ${LIBS} -lfuse $^ -o $@ + +# fuse +fakefuse: fakefuse.cc mds/allmds.o client/Client.o client/Buffercache.o osd/OSD.o client/fuse.o msg/FakeMessenger.cc ${COMMON_OBJS} + ${CC} -pg ${CFLAGS} ${LIBS} -lfuse $^ -o $@ tcpfuse: tcpfuse.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o client/fuse.o msg/TCPMessenger.cc ${COMMON_OBJS} ${MPICC} ${CFLAGS} ${LIBS} -lfuse $^ -o $@ -mpisyn: mpisyn.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o msg/MPIMessenger.cc ${COMMON_OBJS} +mpifuse: mpifuse.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o client/fuse.o msg/MPIMessenger.cc ${COMMON_OBJS} + ${MPICC} ${CFLAGS} ${LIBS} -lfuse $^ -o $@ + +# synthetic workload +fakesyn: fakesyn.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o msg/FakeMessenger.o ${COMMON_OBJS} ${SYN_OBJS} + ${CC} -pg ${CFLAGS} ${LIBS} $^ -o $@ + +mpisyn: mpisyn.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o msg/MPIMessenger.cc ${COMMON_OBJS} ${SYN_OBJS} ${MPICC} ${MPICFLAGS} ${MPILIBS} $^ -o $@ -tcpsyn: tcpsyn.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o msg/TCPMessenger.cc ${COMMON_OBJS} +tcpsyn: tcpsyn.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o msg/TCPMessenger.cc ${COMMON_OBJS} ${SYN_OBJS} ${MPICC} ${MPICFLAGS} ${MPILIBS} $^ -o $@ +# obfs + synthetic obfstest: tcpsyn.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.cc osd/OBFSStore.o msg/TCPMessenger.cc ${COMMON_OBJS} ${MPICC} -DUSE_OBFS ${MPICFLAGS} ${MPILIBS} $^ -o $@ ../uofs/uofs.a -fakesyn: fakesyn.cc mds/allmds.o client/Client.o client/Buffercache.o client/SyntheticClient.o osd/OSD.o msg/FakeMessenger.o ${COMMON_OBJS} - ${CC} -pg ${CFLAGS} ${LIBS} $^ -o $@ -fakefuse: fakefuse.cc mds/allmds.o client/Client.o client/Buffercache.o osd/OSD.o client/fuse.o msg/FakeMessenger.cc ${COMMON_OBJS} - ${CC} -pg ${CFLAGS} ${LIBS} -lfuse $^ -o $@ testmpi: test/testmpi.cc msg/MPIMessenger.cc config.o common/Timer.o common/clock.o msg/Messenger.o msg/Dispatcher.o msg/error.o ${MPICC} ${CFLAGS} ${LIBS} $^ -o $@ diff --git a/ceph/TODO b/ceph/TODO index 3dc47c5bf37..d987f397c93 100644 --- a/ceph/TODO +++ b/ceph/TODO @@ -1,3 +1,11 @@ +known bugs to fix after fast +- RDWR on synthetic client results in +fakesyn: mds/MDS.cc:2334: void MDS::handle_client_close(MClientRequest*, CInode*): Assertion `cur->softlock.can_write(true)' failed. +- caps needs to be rewritten + - MDS currently not reclaiming fh's (otherwise a client assertion eventually fails) +- hard links! + + !!! - test mds scaling w/ makedirs, vs mds_log_on_request diff --git a/ceph/client/Client.cc b/ceph/client/Client.cc index 0f8b312e4b3..e171d26b9ef 100644 --- a/ceph/client/Client.cc +++ b/ceph/client/Client.cc @@ -21,9 +21,9 @@ #include "include/config.h" #undef dout -#define dout(l) if (l<=g_conf.debug || l<=g_conf.debug_client) cout << "client" << "." << pthread_self() << " " - +#define dout(l) if (l<=g_conf.debug || l<=g_conf.debug_client) cout << "client" << whoami << "." << pthread_self() << " " +#define tout if (g_conf.client_trace) cout << "trace: " @@ -555,6 +555,15 @@ int Client::mount(int mkfs) delete reply; client_lock.Unlock(); + + dout(3) << "op: // client trace data structs" << endl; + dout(3) << "op: struct stat st;" << endl; + dout(3) << "op: struct utimbuf utim;" << endl; + dout(3) << "op: int readlinkbuf_len = 1000;" << endl; + dout(3) << "op: char readlinkbuf[readlinkbuf_len];" << endl; + dout(3) << "op: map dir_contents;" << endl; + dout(3) << "op: map open_files;" << endl; + dout(3) << "op: fileh_t fh;" << endl; } int Client::unmount() @@ -584,11 +593,15 @@ int Client::unmount() int Client::link(const char *existing, const char *newname) { client_lock.Lock(); + dout(3) << "op: client->link(\"" << existing << "\", \"" << newname << "\");" << endl; + tout << "link" << endl; + tout << existing << endl; + tout << newname << endl; + // main path arg is new link name // sarg is target (existing file) - dout(3) << "link " << existing << " " << newname << endl; MClientRequest *req = new MClientRequest(MDS_OP_LINK, whoami); req->set_path(newname); @@ -614,8 +627,11 @@ int Client::link(const char *existing, const char *newname) int Client::unlink(const char *path) { client_lock.Lock(); + dout(3) << "op: client->unlink\(\"" << path << "\");" << endl; + tout << "unlink" << endl; + tout << path << endl; + - dout(3) << "unlink " << path << endl; MClientRequest *req = new MClientRequest(MDS_OP_UNLINK, whoami); req->set_path(path); @@ -628,9 +644,10 @@ int Client::unlink(const char *path) MClientReply *reply = make_request(req); int res = reply->get_result(); if (res == 0) { - //this crashes, haven't looked at why yet - //Dentry *dn = lookup(req->get_filepath()); - //if (dn) unlink(dn); + // remove from local cache + filepath fp(path); + Dentry *dn = lookup(fp); + if (dn) unlink(dn); } this->insert_trace(reply->get_trace()); delete reply; @@ -644,8 +661,12 @@ int Client::unlink(const char *path) int Client::rename(const char *from, const char *to) { client_lock.Lock(); + dout(3) << "op: client->rename(\"" << from << "\", \"" << to << "\");" << endl; + tout << "rename" << endl; + tout << from << endl; + tout << to << endl; + - dout(3) << "rename " << from << " " << to << endl; MClientRequest *req = new MClientRequest(MDS_OP_RENAME, whoami); req->set_path(from); req->set_sarg(to); @@ -672,8 +693,12 @@ int Client::rename(const char *from, const char *to) int Client::mkdir(const char *path, mode_t mode) { client_lock.Lock(); + dout(3) << "op: client->mkdir(\"" << path << "\", " << mode << ");" << endl; + tout << "mkdir" << endl; + tout << path << endl; + tout << mode << endl; + - dout(3) << "mkdir " << path << " mode " << mode << endl; MClientRequest *req = new MClientRequest(MDS_OP_MKDIR, whoami); req->set_path(path); req->set_iarg( (int)mode ); @@ -698,8 +723,11 @@ int Client::mkdir(const char *path, mode_t mode) int Client::rmdir(const char *path) { client_lock.Lock(); + dout(3) << "op: client->rmdir(\"" << path << "\");" << endl; + tout << "rmdir" << endl; + tout << path << endl; + - dout(3) << "rmdir " << path << endl; MClientRequest *req = new MClientRequest(MDS_OP_RMDIR, whoami); req->set_path(path); @@ -712,8 +740,14 @@ int Client::rmdir(const char *path) MClientReply *reply = make_request(req); int res = reply->get_result(); if (res == 0) { - // crashes, not sure why yet - //unlink(lookup(req->get_filepath())); + // remove from local cache + filepath fp(path); + Dentry *dn = lookup(fp); + if (dn) { + if (dn->inode->dir && dn->inode->dir->is_empty()) + close_dir(dn->inode->dir); // FIXME: maybe i shoudl proactively hose the whole subtree from cache? + unlink(dn); + } } this->insert_trace(reply->get_trace()); delete reply; @@ -729,8 +763,12 @@ int Client::rmdir(const char *path) int Client::symlink(const char *target, const char *link) { client_lock.Lock(); + dout(3) << "op: client->symlink(\"" << target << "\", \"" << link << "\");" << endl; + tout << "symlink" << endl; + tout << target << endl; + tout << link << endl; + - dout(3) << "symlink target " << target << " link " << link << endl; MClientRequest *req = new MClientRequest(MDS_OP_SYMLINK, whoami); req->set_path(link); req->set_sarg(target); @@ -754,7 +792,12 @@ int Client::symlink(const char *target, const char *link) int Client::readlink(const char *path, char *buf, size_t size) { - dout(3) << "readlink " << path << endl; + client_lock.Lock(); + dout(3) << "op: client->readlink(\"" << path << "\", readlinkbuf, readlinkbuf_len);" << endl; + tout << "readlink" << endl; + tout << path << endl; + client_lock.Unlock(); + // stat first (FIXME, PERF access cache directly) **** struct stat stbuf; int r = this->lstat(path, &stbuf); @@ -783,8 +826,11 @@ int Client::readlink(const char *path, char *buf, size_t size) int Client::lstat(const char *path, struct stat *stbuf) { client_lock.Lock(); + dout(3) << "op: client->lstat(\"" << path << "\", &st);" << endl; + tout << "lstat" << endl; + tout << path << endl; + - dout(3) << "lstat " << path << endl; // FIXME, PERF request allocation convenient but not necessary for cache hit MClientRequest *req = new MClientRequest(MDS_OP_STAT, whoami); req->set_path(path); @@ -849,8 +895,12 @@ int Client::lstat(const char *path, struct stat *stbuf) int Client::chmod(const char *path, mode_t mode) { client_lock.Lock(); + dout(3) << "op: client->chmod(\"" << path << "\", " << mode << ");" << endl; + tout << "chmod" << endl; + tout << path << endl; + tout << mode << endl; + - dout(3) << "chmod " << path << " mode " << mode << endl; MClientRequest *req = new MClientRequest(MDS_OP_CHMOD, whoami); req->set_path(path); req->set_iarg( (int)mode ); @@ -873,8 +923,13 @@ int Client::chmod(const char *path, mode_t mode) int Client::chown(const char *path, uid_t uid, gid_t gid) { client_lock.Lock(); + dout(3) << "op: client->chown(\"" << path << "\", " << uid << ", " << gid << ");" << endl; + tout << "chown" << endl; + tout << path << endl; + tout << uid << endl; + tout << gid << endl; + - dout(3) << "chown " << path << " " << uid << "." << gid << endl; MClientRequest *req = new MClientRequest(MDS_OP_CHOWN, whoami); req->set_path(path); req->set_iarg( (int)uid ); @@ -900,8 +955,14 @@ int Client::chown(const char *path, uid_t uid, gid_t gid) int Client::utime(const char *path, struct utimbuf *buf) { client_lock.Lock(); + dout(3) << "op: utim.actime = " << buf->actime << "; utim.modtime = " << buf->modtime << ";" << endl; + dout(3) << "op: client->utime(\"" << path << "\", &utim);" << endl; + tout << "utime" << endl; + tout << path << endl; + tout << buf->actime << endl; + tout << buf->modtime << endl; + - dout(3) << "utime " << path << endl; MClientRequest *req = new MClientRequest(MDS_OP_UTIME, whoami); req->set_path(path); req->set_targ( buf->modtime ); @@ -929,8 +990,12 @@ int Client::utime(const char *path, struct utimbuf *buf) int Client::mknod(const char *path, mode_t mode) { client_lock.Lock(); + dout(3) << "op: client->mknod(\"" << path << "\", " << mode << ");" << endl; + tout << "mknod" << endl; + tout << path << endl; + tout << mode << endl; + - dout(3) << "mknod " << path << " mode " << mode << endl; MClientRequest *req = new MClientRequest(MDS_OP_MKNOD, whoami); req->set_path(path); req->set_iarg( mode ); @@ -967,8 +1032,11 @@ int Client::mknod(const char *path, mode_t mode) int Client::getdir(const char *path, map& contents) { client_lock.Lock(); + dout(3) << "op: client->getdir(\"" << path << "\", dir_contents);" << endl; + tout << "getdir" << endl; + tout << path << endl; + - dout(3) << "getdir " << path << endl; MClientRequest *req = new MClientRequest(MDS_OP_READDIR, whoami); req->set_path(path); @@ -1026,9 +1094,12 @@ int Client::getdir(const char *path, map& contents) int Client::open(const char *path, int mode) { client_lock.Lock(); + dout(3) << "op: fh = client->open(\"" << path << "\", " << mode << ");" << endl; + tout << "open" << endl; + tout << path << endl; + tout << mode << endl; + - dout(3) << "open " << path << " mode " << mode << endl; - MClientRequest *req = new MClientRequest(MDS_OP_OPEN, whoami); req->set_path(path); req->set_iarg(mode); @@ -1039,7 +1110,8 @@ int Client::open(const char *path, int mode) MClientReply *reply = make_request(req); assert(reply); - dout(3) << "open result = " << reply->get_result() << endl; + dout(3) << "op: open_files[" << reply->get_result() << "] = fh; // fh = " << reply->get_result() << endl; + tout << reply->get_result() << endl; vector trace = reply->get_trace(); this->insert_trace(trace); @@ -1076,8 +1148,12 @@ int Client::open(const char *path, int mode) int Client::close(fileh_t fh) { client_lock.Lock(); + dout(3) << "op: client->close(open_files[ " << fh << " ]);" << endl; + dout(3) << "op: open_files.erase( " << fh << " );" << endl; + tout << "close" << endl; + tout << fh << endl; + - dout(3) << "close " << fh << endl; assert(fh_map.count(fh)); Fh *f = fh_map[fh]; Inode *in = f->inode; @@ -1378,6 +1454,9 @@ int Client::write(fileh_t fh, const char *buf, size_t size, off_t offset) cond.Wait(client_lock); } +#if 0 + } +#endif // assume success for now. FIXME. @@ -1401,9 +1480,43 @@ int Client::write(fileh_t fh, const char *buf, size_t size, off_t offset) } +int Client::truncate(const char *file, off_t size) +{ + client_lock.Lock(); + dout(3) << "op: client->truncate(\"" << file << "\", " << size << ");" << endl; + tout << "truncate" << endl; + tout << file << endl; + tout << size << endl; + + + MClientRequest *req = new MClientRequest(MDS_OP_TRUNCATE, whoami); + req->set_path(file); + req->set_sizearg( size ); + + // FIXME where does FUSE maintain user information + req->set_caller_uid(getuid()); + req->set_caller_gid(getgid()); + + MClientReply *reply = make_request(req); + int res = reply->get_result(); + this->insert_trace(reply->get_trace()); + delete reply; + + dout(10) << " truncate result is " << res << endl; + + client_lock.Unlock(); + return res; +} + + int Client::fsync(fileh_t fh, bool syncdataonly) { client_lock.Lock(); + dout(3) << "op: client->fsync(open_files[ " << fh << " ], " << syncdataonly << ");" << endl; + tout << "fsync" << endl; + tout << fh << endl; + tout << syncdataonly << endl; + int r = 0; assert(fh_map.count(fh)); diff --git a/ceph/client/Client.h b/ceph/client/Client.h index 8c8c8689ff0..4f49c521d3e 100644 --- a/ceph/client/Client.h +++ b/ceph/client/Client.h @@ -171,6 +171,7 @@ class Client : public Dispatcher { in->put(); if (in->ref == 0) { inode_map.erase(in->inode.ino); + if (in == root) root = 0; delete in; } } @@ -318,7 +319,8 @@ class Client : public Dispatcher { int close(fileh_t fh); int read(fileh_t fh, char *buf, size_t size, off_t offset); int write(fileh_t fh, const char *buf, size_t size, off_t offset); - int truncate(fileh_t fh, off_t size); + int truncate(const char *file, off_t size); + //int truncate(fileh_t fh, off_t size); int fsync(fileh_t fh, bool syncdataonly); }; diff --git a/ceph/client/SyntheticClient.cc b/ceph/client/SyntheticClient.cc index f940645ee0f..da0395474da 100644 --- a/ceph/client/SyntheticClient.cc +++ b/ceph/client/SyntheticClient.cc @@ -4,6 +4,7 @@ #include "include/filepath.h" #include "mds/MDS.h" + #include #include #include @@ -15,6 +16,10 @@ #undef dout #define dout(l) if (l<=g_conf.debug || l<=g_conf.debug_client) cout << "synthetic" << client->get_nodeid() << " " +// traces +//void trace_include(SyntheticClient *syn, Client *cl, string& prefix); +//void trace_openssh(SyntheticClient *syn, Client *cl, string& prefix); + #define DBL 2 @@ -118,6 +123,38 @@ int SyntheticClient::run() read_file(sarg1, iarg1, iarg2); } break; + + + case SYNCLIENT_MODE_TRACEINCLUDE: + { + int iarg1 = iargs.front(); iargs.pop_front(); + string prefix; + if (client->whoami == 0) { + Trace t("client/traces/trace.include"); + play_trace(t, prefix); + } else { + sleep(iarg1); + } + } + break; + case SYNCLIENT_MODE_TRACEOPENSSH: + { + string prefix = get_sarg(); + int iarg1 = iargs.front(); iargs.pop_front(); + + Trace t("client/traces/trace.openssh"); + + client->mkdir(prefix.c_str(), 0755); + + for (int i=0; i open_files; + + while (!t.end()) { + + if (time_to_stop()) break; + + // op + const char *op = t.get_string(); + dout(4) << "trace op " << op << endl; + if (strcmp(op, "link") == 0) { + const char *a = t.get_string(p); + const char *b = t.get_string(p); + client->link(a,b); + } else if (strcmp(op, "unlink") == 0) { + const char *a = t.get_string(p); + client->unlink(a); + } else if (strcmp(op, "rename") == 0) { + const char *a = t.get_string(p); + const char *b = t.get_string(p); + client->rename(a,b); + } else if (strcmp(op, "mkdir") == 0) { + const char *a = t.get_string(p); + __int64_t b = t.get_int(); + client->mkdir(a, b); + } else if (strcmp(op, "rmdir") == 0) { + const char *a = t.get_string(p); + client->rmdir(a); + } else if (strcmp(op, "symlink") == 0) { + const char *a = t.get_string(p); + const char *b = t.get_string(p); + client->symlink(a,b); + } else if (strcmp(op, "readlink") == 0) { + const char *a = t.get_string(p); + char buf[100]; + client->readlink(a, buf, 100); + } else if (strcmp(op, "lstat") == 0) { + struct stat st; + const char *a = t.get_string(p); + client->lstat(a, &st); + } else if (strcmp(op, "chmod") == 0) { + const char *a = t.get_string(p); + __int64_t b = t.get_int(); + client->chmod(a, b); + } else if (strcmp(op, "chown") == 0) { + const char *a = t.get_string(p); + __int64_t b = t.get_int(); + __int64_t c = t.get_int(); + client->chown(a, b, c); + } else if (strcmp(op, "utime") == 0) { + const char *a = t.get_string(p); + __int64_t b = t.get_int(); + __int64_t c = t.get_int(); + struct utimbuf u; + u.actime = b; + u.modtime = c; + client->utime(a, &u); + } else if (strcmp(op, "mknod") == 0) { + const char *a = t.get_string(p); + __int64_t b = t.get_int(); + client->mknod(a, b); + } else if (strcmp(op, "getdir") == 0) { + const char *a = t.get_string(p); + map contents; + client->getdir(a, contents); + } else if (strcmp(op, "open") == 0) { + const char *a = t.get_string(p); + __int64_t b = t.get_int(); + __int64_t id = t.get_int(); + __int64_t fh = client->open(a, b); + open_files[id] = fh; + } else if (strcmp(op, "close") == 0) { + __int64_t id = t.get_int(); + __int64_t fh = open_files[id]; + if (fh > 0) client->close(fh); + open_files.erase(id); + } else if (strcmp(op, "truncate") == 0) { + const char *a = t.get_string(p); + __int64_t b = t.get_int(); + client->truncate(a,b); + } else if (strcmp(op, "fsync") == 0) { + assert(0); + } else + assert(0); + } + + // close open files + for (map<__int64_t, __int64_t>::iterator fi = open_files.begin(); + fi != open_files.end(); + fi++) { + client->close(fi->second); + } + +} + + +int SyntheticClient::clean_dir(string& basedir) +{ + // read dir + map contents; + int r = client->getdir(basedir.c_str(), contents); + if (r < 0) { + dout(1) << "readdir on " << basedir << " returns " << r << endl; + return r; + } + + for (map::iterator it = contents.begin(); + it != contents.end(); + it++) { + string file = basedir + "/" + it->first; + + if (time_to_stop()) break; + + struct stat st; + int r = client->lstat(file.c_str(), &st); + if (r < 0) { + dout(1) << "stat error on " << file << " r=" << r << endl; + continue; + } + + if (st.st_mode & INODE_MODE_DIR) { + clean_dir(file); + client->rmdir(file.c_str()); + } else { + client->unlink(file.c_str()); + } + } + + return 0; + +} int SyntheticClient::full_walk(string& basedir) { - if (run_until.first && g_clock.gettimepair() > run_until) return -1; + if (time_to_stop()) return -1; // read dir map contents; @@ -220,7 +394,7 @@ int SyntheticClient::full_walk(string& basedir) int SyntheticClient::make_dirs(const char *basedir, int dirs, int files, int depth) { - if (run_until.first && g_clock.gettimepair() > run_until) return 0; + if (time_to_stop()) return 0; // make sure base dir exists int r = client->mkdir(basedir, 0755); @@ -261,7 +435,7 @@ int SyntheticClient::write_file(string& fn, int size, int wrsize) // size is i if (fd < 0) return fd; for (int i=0; i run_until) break; + if (time_to_stop()) break; dout(2) << "writing block " << i << "/" << chunks << endl; client->write(fd, buf, wrsize, i*wrsize); } @@ -281,7 +455,7 @@ int SyntheticClient::read_file(string& fn, int size, int rdsize) // size is in if (fd < 0) return fd; for (int i=0; i run_until) break; + if (time_to_stop()) break; dout(2) << "reading block " << i << "/" << chunks << endl; client->read(fd, buf, rdsize, i*rdsize); } @@ -303,7 +477,7 @@ int SyntheticClient::random_walk(int num_req) while (left > 0) { left--; - if (run_until.first && g_clock.gettimepair() > run_until) break; + if (time_to_stop()) break; // ascend? if (cwd.depth() && !roll_die(pow(.9, cwd.depth()))) { @@ -476,3 +650,5 @@ int SyntheticClient::random_walk(int num_req) dout(DBL) << "done" << endl; return 0; } + + diff --git a/ceph/client/SyntheticClient.h b/ceph/client/SyntheticClient.h index 7745c59d226..004a2505ff6 100644 --- a/ceph/client/SyntheticClient.h +++ b/ceph/client/SyntheticClient.h @@ -6,6 +6,8 @@ #include "Client.h" #include "include/Distribution.h" +#include "Trace.h" + #define SYNCLIENT_MODE_RANDOMWALK 1 #define SYNCLIENT_MODE_FULLWALK 2 #define SYNCLIENT_MODE_MAKEDIRS 3 @@ -14,6 +16,9 @@ #define SYNCLIENT_MODE_UNTIL 6 #define SYNCLIENT_MODE_REPEATWALK 7 +#define SYNCLIENT_MODE_TRACEOPENSSH 8 +#define SYNCLIENT_MODE_TRACEINCLUDE 9 + class SyntheticClient { Client *client; @@ -105,13 +110,27 @@ class SyntheticClient { timepair_t run_until; string get_sarg(); - + + bool time_to_stop() { + if (run_until.first && g_clock.gettimepair() > run_until) + return true; + else + return false; + } + + string compose_path(string& prefix, char *rest) { + return prefix + rest; + } + int full_walk(string& fromdir); int random_walk(int n); int make_dirs(const char *basedir, int dirs, int files, int depth); int write_file(string& fn, int mb, int chunk); int read_file(string& fn, int mb, int chunk); + int clean_dir(string& basedir); + + int play_trace(Trace& t, string& prefix); }; diff --git a/ceph/client/Trace.cc b/ceph/client/Trace.cc new file mode 100644 index 00000000000..d1fa6af92db --- /dev/null +++ b/ceph/client/Trace.cc @@ -0,0 +1,105 @@ + +#include "Trace.h" + +#include +#include +#include +using namespace __gnu_cxx; + +#include "common/Mutex.h" + +#include "include/config.h" + +#include +#include +#include + + +Mutex trace_lock; + +class TokenList { +public: + string filename; + char *data; + int len; + list tokens; + + int ref; +}; + +map traces; + + +// +Trace::Trace(const char* f) +{ + string filename = f; + + trace_lock.Lock(); + + if (traces.count(filename)) + tl = traces[filename]; + else { + tl = new TokenList; + tl->ref = 0; + tl->filename = filename; + + // open file + crope cr; + int fd = open(filename.c_str(), O_RDONLY); + assert(fd > 0); + char buf[100]; + while (1) { + int r = read(fd, buf, 100); + if (r == 0) break; + assert(r > 0); + cr.append(buf, r); + } + close(fd); + + // copy + tl->len = cr.length()+1; + tl->data = new char[cr.length()]; + memcpy(tl->data, cr.c_str(), cr.length()); + tl->data[tl->len-1] = '\n'; + + // index! + int o = 0; + while (o < tl->len) { + char *n = tl->data + o; + + // find newline + while (tl->data[o] != '\n') o++; + assert(tl->data[o] == '\n'); + tl->data[o] = 0; + + if (tl->data + o > n) tl->tokens.push_back(n); + o++; + } + + dout(1) << "trace " << filename << " loaded with " << tl->tokens.size() << " tokens" << endl; + traces[filename] = tl; + } + tl->ref++; + + trace_lock.Unlock(); +} + +Trace::~Trace() +{ + trace_lock.Lock(); + + tl->ref--; + if (tl->ref == 0) { + traces.erase(tl->filename); + delete tl; + } + + trace_lock.Unlock(); +} + + +list& Trace::get_list() +{ + return tl->tokens; +} diff --git a/ceph/client/Trace.h b/ceph/client/Trace.h new file mode 100644 index 00000000000..9126b42c663 --- /dev/null +++ b/ceph/client/Trace.h @@ -0,0 +1,59 @@ +#ifndef __CLIENT_TRACE_H +#define __CLIENT_TRACE_H + +#include +#include +using namespace std; + +/* + + this class is more like an iterator over a constant tokenlist (which + is protected by a mutex, see Trace.cc) + + */ + +class Trace { + class TokenList *tl; + + public: + Trace(const char* filename); + ~Trace(); + + list& get_list(); + + list::iterator _cur; + list::iterator _end; + + void start() { + _cur = get_list().begin(); + _end = get_list().end(); + ns = 0; + } + + char strings[10][200]; + int ns; + const char *get_string(const char *prefix = 0) { + const char *s = *_cur; + _cur++; + if (prefix) { + if (strstr(s, "/prefix") == s || + strstr(s, "/prefix") == s+1) { + strcpy(strings[ns], prefix); + strcpy(strings[ns] + strlen(prefix), + s + strlen("/prefix")); + s = (const char*)strings[ns]; + ns++; + if (ns == 10) ns = 0; + } + } + return s; + } + __int64_t get_int() { + return atoll(get_string()); + } + bool end() { + return _cur == _end; + } +}; + +#endif diff --git a/ceph/client/fuse.cc b/ceph/client/fuse.cc index fcac60f6d7f..add7bcb2527 100644 --- a/ceph/client/fuse.cc +++ b/ceph/client/fuse.cc @@ -31,6 +31,8 @@ #include "Client.h" +#include "include/config.h" + // stl #include using namespace std; @@ -141,7 +143,7 @@ static int ceph_chown(const char *path, uid_t uid, gid_t gid) static int ceph_truncate(const char *path, off_t size) { - return truncate(path, size); + return client->truncate(path, size); } static int ceph_utime(const char *path, struct utimbuf *buf) @@ -276,8 +278,10 @@ int ceph_fuse_main(Client *c, int argc, char *argv[]) // large reads, direct_io (no kernel cachine) //newargv[newargc++] = "-o"; //newargv[newargc++] = "large_read"; - newargv[newargc++] = "-o"; - newargv[newargc++] = "direct_io"; + if (g_conf.fuse_direct_io) { + newargv[newargc++] = "-o"; + newargv[newargc++] = "direct_io"; + } // disable stupid fuse unlink hiding thing newargv[newargc++] = "-o"; diff --git a/ceph/config.cc b/ceph/config.cc index 50dd2ea24b2..49084f4eb36 100644 --- a/ceph/config.cc +++ b/ceph/config.cc @@ -62,6 +62,8 @@ md_config_t g_conf = { client_bcache_alloc_minsize: 1024, client_bcache_alloc_maxsize: 262144, client_bcache_ttl: 30, // seconds until dirty buffers are written to disk + client_trace: 0, + fuse_direct_io: 1, // --- mds --- mds_cache_size: MDS_CACHE_SIZE, @@ -202,6 +204,10 @@ void parse_config_options(int argc, char **argv, g_conf.client_cache_size = atoi(argv[++i]); else if (strcmp(argv[i], "--client_cache_stat_ttl") == 0) g_conf.client_cache_stat_ttl = atoi(argv[++i]); + else if (strcmp(argv[i], "--client_trace") == 0) + g_conf.client_trace = atoi(argv[++i]); + else if (strcmp(argv[i], "--fuse_direct_io") == 0) + g_conf.fuse_direct_io = atoi(argv[++i]); else if (strcmp(argv[i], "--osd_fsync") == 0) g_conf.osd_fsync = atoi(argv[++i]); diff --git a/ceph/config.h b/ceph/config.h index 8fc9c0ecc6a..e31586075c9 100644 --- a/ceph/config.h +++ b/ceph/config.h @@ -37,6 +37,8 @@ struct md_config_t { int client_bcache_alloc_minsize; int client_bcache_alloc_maxsize; int client_bcache_ttl; + int client_trace; + int fuse_direct_io; // mds int mds_cache_size; diff --git a/ceph/fakesyn.cc b/ceph/fakesyn.cc index 62ba3159237..f938923c86b 100644 --- a/ceph/fakesyn.cc +++ b/ceph/fakesyn.cc @@ -79,6 +79,12 @@ int main(int oargc, char **oargv) //syn_sargs.push_back( atoi(argv[++i]) ); } else if (strcmp(argv[i],"randomwalk") == 0) { syn_modes.push_back( SYNCLIENT_MODE_RANDOMWALK ); + syn_iargs.push_back( atoi(argv[++i]) ); + } else if (strcmp(argv[i],"trace_include") == 0) { + syn_modes.push_back( SYNCLIENT_MODE_TRACEINCLUDE ); + syn_iargs.push_back( atoi(argv[++i]) ); + } else if (strcmp(argv[i],"trace_openssh") == 0) { + syn_modes.push_back( SYNCLIENT_MODE_TRACEOPENSSH ); syn_iargs.push_back( atoi(argv[++i]) ); } else if (strcmp(argv[i],"until") == 0) { syn_modes.push_back( SYNCLIENT_MODE_UNTIL ); diff --git a/ceph/mds/MDS.cc b/ceph/mds/MDS.cc index 539ab2ac726..c361c65e45c 100644 --- a/ceph/mds/MDS.cc +++ b/ceph/mds/MDS.cc @@ -475,6 +475,7 @@ void MDS::my_dispatch(Message *m) // shut down? if (shutting_down && !shut_down) { if (mdcache->shutdown_pass()) { + dout(7) << "shutdown_pass=true, finished w/ shutdown" << endl; shutting_down = false; shut_down = true; if (whoami) shutdown_final(); @@ -713,7 +714,7 @@ void MDS::handle_client_request(MClientRequest *req) */ case MDS_OP_TRUNCATE: - if (!req->get_iarg()) break; // can be called w/ either fh OR path + if (!req->get_ino()) break; // can be called w/ either fh OR path case MDS_OP_CLOSE: case MDS_OP_FSYNC: @@ -741,7 +742,6 @@ void MDS::handle_client_request(MClientRequest *req) case MDS_OP_MKNOD: case MDS_OP_MKDIR: case MDS_OP_SYMLINK: - case MDS_OP_TRUNCATE: case MDS_OP_LINK: case MDS_OP_UNLINK: // also wrt parent dir, NOT the unlinked inode!! case MDS_OP_RMDIR: @@ -832,10 +832,10 @@ void MDS::dispatch_request(Message *m, CInode *ref) else handle_client_open(req, ref); break; - /* case MDS_OP_TRUNCATE: handle_client_truncate(req, ref); break; + /* case MDS_OP_FSYNC: handle_client_fsync(req, ref); break; @@ -2203,6 +2203,36 @@ void MDS::handle_client_symlink(MClientRequest *req, CInode *diri) +// =================================== +// TRUNCATE, FSYNC + +/* + * FIXME: this truncate implemention is WRONG WRONG WRONG + */ + +void MDS::handle_client_truncate(MClientRequest *req, CInode *cur) +{ + // write + if (!mdcache->inode_hard_write_start(cur, req)) + return; // fw or (wait for) lock + + // check permissions + + // do update + cur->inode.size = req->get_sizearg(); + cur->mark_dirty(); + + mdcache->inode_hard_write_finish(cur); + + balancer->hit_inode(cur); + + // start reply + MClientReply *reply = new MClientReply(req, 0); + + // commit + commit_request(req, reply, cur, + new EInodeUpdate(cur)); +} diff --git a/ceph/msg/FakeMessenger.cc b/ceph/msg/FakeMessenger.cc index f0235d10797..787e177e85e 100644 --- a/ceph/msg/FakeMessenger.cc +++ b/ceph/msg/FakeMessenger.cc @@ -191,8 +191,9 @@ int fakemessenger_do_loop_2() FakeMessenger::FakeMessenger(long me) : Messenger(me) { whoami = me; + lock.Lock(); directory[ whoami ] = this; - + lock.Unlock(); cout << "fakemessenger " << whoami << " messenger is " << this << endl; @@ -224,11 +225,13 @@ FakeMessenger::~FakeMessenger() int FakeMessenger::shutdown() { //cout << "shutdown on messenger " << this << " has " << num_incoming() << " queued" << endl; + lock.Lock(); directory.erase(whoami); if (directory.empty()) { ::shutdown = true; cond.Signal(); // why not - } + } + lock.Unlock(); } /* diff --git a/ceph/script/clean_trace.pl b/ceph/script/clean_trace.pl new file mode 100755 index 00000000000..cb02ff7abe7 --- /dev/null +++ b/ceph/script/clean_trace.pl @@ -0,0 +1,8 @@ +#!/usr/bin/perl + +my $n = 0; +while (<>) { + next unless /trace: /; + my $l = $'; $'; + print $l; +} diff --git a/ceph/tcpsyn.cc b/ceph/tcpsyn.cc index 36b0c03a69a..a7b67c47b34 100644 --- a/ceph/tcpsyn.cc +++ b/ceph/tcpsyn.cc @@ -81,6 +81,12 @@ int main(int oargc, char **oargv) { } else if (strcmp(argv[i],"randomwalk") == 0) { syn_modes.push_back( SYNCLIENT_MODE_RANDOMWALK ); syn_iargs.push_back( atoi(argv[++i]) ); + } else if (strcmp(argv[i],"trace_include") == 0) { + syn_modes.push_back( SYNCLIENT_MODE_TRACEINCLUDE ); + syn_iargs.push_back( atoi(argv[++i]) ); + } else if (strcmp(argv[i],"trace_openssh") == 0) { + syn_modes.push_back( SYNCLIENT_MODE_TRACEOPENSSH ); + syn_iargs.push_back( atoi(argv[++i]) ); } else if (strcmp(argv[i],"until") == 0) { syn_modes.push_back( SYNCLIENT_MODE_UNTIL ); syn_iargs.push_back( atoi(argv[++i]) );