From 30d2087f2958bd25b05da274c72c25f481334e24 Mon Sep 17 00:00:00 2001 From: sageweil Date: Thu, 2 Aug 2007 18:20:17 +0000 Subject: [PATCH] client readdir cleanup; import_find git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1590 29311d96-e01e-0410-9327-a35deaab8ce9 --- branches/sage/mds/client/Client.cc | 21 +++- branches/sage/mds/client/Client.h | 2 + branches/sage/mds/client/SyntheticClient.cc | 113 ++++++++++++++++++++ branches/sage/mds/client/SyntheticClient.h | 9 ++ branches/sage/mds/client/fuse.cc | 3 +- 5 files changed, 145 insertions(+), 3 deletions(-) diff --git a/branches/sage/mds/client/Client.cc b/branches/sage/mds/client/Client.cc index 33202fed59bcc..4a7ec372f636c 100644 --- a/branches/sage/mds/client/Client.cc +++ b/branches/sage/mds/client/Client.cc @@ -2071,6 +2071,15 @@ void Client::_readdir_add_dirent(DirResult *dirp, const string& name, Inode *in) dout(10) << "_readdir_add_dirent added " << name << ", size now " << dirp->buffer[fg].size() << endl; } +void Client::_readdir_add_dirent(DirResult *dirp, const string& name) +{ + frag_t fg = dirp->frag(); + struct stat st; + memset(&st, 0, sizeof(st)); + dirp->buffer[fg].push_back(DirEntry(name, st, 0)); + dout(10) << "_readdir_add_dirent added " << name << ", size now " << dirp->buffer[fg].size() << endl; +} + void Client::_readdir_get_frag(DirResult *dirp) { client_lock.Lock(); @@ -2139,6 +2148,8 @@ void Client::_readdir_get_frag(DirResult *dirp) _readdir_add_dirent(dirp, dot, diri); if (diri->dn) _readdir_add_dirent(dirp, dotdot, diri->dn->dir->parent_inode); + else + _readdir_add_dirent(dirp, dotdot); } // the rest? @@ -2251,10 +2262,16 @@ int Client::readdirplus_r(DIR *d, struct dirent *de, struct stat *st, int *stmas //}; void Client::_readdir_fill_dirent(struct dirent *de, DirEntry *entry, off_t off) { - de->d_ino = entry->st.st_ino; + if (entry->stmask) + de->d_ino = entry->st.st_ino; + else + de->d_ino = 0; de->d_off = off + 1; de->d_reclen = 1; - de->d_type = MODE_TO_DT(entry->st.st_mode); + if (entry->stmask) + de->d_type = MODE_TO_DT(entry->st.st_mode); + else + de->d_type = DT_UNKNOWN; strncpy(de->d_name, entry->d_name.c_str(), 256); } diff --git a/branches/sage/mds/client/Client.h b/branches/sage/mds/client/Client.h index 95de0dfb98082..65ef1ef6c103c 100644 --- a/branches/sage/mds/client/Client.h +++ b/branches/sage/mds/client/Client.h @@ -646,6 +646,7 @@ public: int getdir(const char *relpath, list& names); // get the whole dir at once. void _readdir_add_dirent(DirResult *dirp, const string& name, Inode *in); + void _readdir_add_dirent(DirResult *dirp, const string& name); bool _readdir_have_frag(DirResult *dirp); void _readdir_get_frag(DirResult *dirp); void _readdir_next_frag(DirResult *dirp); @@ -693,6 +694,7 @@ public: off_t lseek(fh_t fh, off_t offset, int whence); int read(fh_t fh, char *buf, off_t size, off_t offset=-1); int write(fh_t fh, const char *buf, off_t size, off_t offset=-1); + int fake_write_size(fh_t fh, off_t size); int truncate(const char *file, off_t size); //int truncate(fh_t fh, long long size); int fsync(fh_t fh, bool syncdataonly); diff --git a/branches/sage/mds/client/SyntheticClient.cc b/branches/sage/mds/client/SyntheticClient.cc index ddcea8199fc13..cd8b4a71a2777 100644 --- a/branches/sage/mds/client/SyntheticClient.cc +++ b/branches/sage/mds/client/SyntheticClient.cc @@ -173,6 +173,11 @@ void parse_syn_options(vector& args) syn_modes.push_back( SYNCLIENT_MODE_TRUNCATE ); syn_sargs.push_back(args[++i]); syn_iargs.push_back(atoi(args[++i])); + } else if (strcmp(args[i],"importfind") == 0) { + syn_modes.push_back(SYNCLIENT_MODE_IMPORTFIND); + syn_sargs.push_back(args[++i]); + syn_sargs.push_back(args[++i]); + syn_iargs.push_back(atoi(args[++i])); } else { cerr << "unknown syn arg " << args[i] << endl; assert(0); @@ -605,6 +610,17 @@ int SyntheticClient::run() client->truncate(file.c_str(), iarg1); } break; + + + case SYNCLIENT_MODE_IMPORTFIND: + { + string base = get_sarg(0); + string find = get_sarg(0); + int data = get_iarg(); + if (run_me()) + import_find(base.c_str(), find.c_str(), data); + } + break; default: assert(0); @@ -1970,3 +1986,100 @@ int SyntheticClient::thrash_links(const char *basedir, int dirs, int files, int } + + +void SyntheticClient::import_find(const char *base, const char *find, bool data) +{ + dout(1) << "import_find " << base << " from " << find << " data=" << data << endl; + + /* use this to gather the trace: + * find . -exec ls -dilsn --time-style=+%s \{\} \; + */ + + client->mkdir(base, 0755); + + ifstream f(find); + assert(f.is_open()); + + while (!f.eof()) { + uint64_t ino; + int dunno, nlink; + string modestring; + int uid, gid; + off_t size; + time_t mtime; + string filename; + f >> ino; + if (f.eof()) break; + f >> dunno; + f >> modestring; + f >> nlink; + f >> uid; + f >> gid; + f >> size; + f >> mtime; + f.seekg(1, ios::cur); + getline(f, filename); + + // parse the mode + assert(modestring.length() == 10); + mode_t mode = 0; + switch (modestring[0]) { + case 'd': mode |= INODE_MODE_DIR; break; + case 'l': mode |= INODE_MODE_SYMLINK; break; + default: + case '-': mode |= INODE_MODE_FILE; break; + } + if (modestring[1] == 'r') mode |= 0400; + if (modestring[2] == 'w') mode |= 0200; + if (modestring[3] == 'x') mode |= 0100; + if (modestring[4] == 'r') mode |= 040; + if (modestring[5] == 'w') mode |= 020; + if (modestring[6] == 'x') mode |= 010; + if (modestring[7] == 'r') mode |= 04; + if (modestring[8] == 'w') mode |= 02; + if (modestring[9] == 'x') mode |= 01; + + dout(20) << " mode " << modestring << " to " << oct << mode << dec << endl; + + if (S_ISLNK(mode)) { + // target vs destination + int pos = filename.find(" -> "); + assert(pos > 0); + string link = base; + link += "/"; + link += filename.substr(0, pos); + string target; + if (filename[pos+4] == '/') { + target = base; + target += filename.substr(pos + 4); + } else { + target = filename.substr(pos + 4); + } + dout(10) << "symlink from '" << link << "' -> '" << target << "'" << endl; + client->symlink(target.c_str(), link.c_str()); + } else { + string f = base; + f += "/"; + f += filename; + if (S_ISDIR(mode)) { + client->mkdir(f.c_str(), mode); + } else { + int fd = client->open(f.c_str(), O_WRONLY|O_CREAT); + assert(fd > 0); + client->write(fd, " ", 1, size-1); + client->close(fd); + + client->chmod(f.c_str(), mode & 0777); + client->chown(f.c_str(), uid, gid); + + struct utimbuf ut; + ut.modtime = mtime; + ut.actime = mtime; + client->utime(f.c_str(), &ut); + } + } + } + + +} diff --git a/branches/sage/mds/client/SyntheticClient.h b/branches/sage/mds/client/SyntheticClient.h index c66393f67e203..0f572bd4a8588 100644 --- a/branches/sage/mds/client/SyntheticClient.h +++ b/branches/sage/mds/client/SyntheticClient.h @@ -64,6 +64,8 @@ #define SYNCLIENT_MODE_FOO 100 #define SYNCLIENT_MODE_THRASHLINKS 101 +#define SYNCLIENT_MODE_IMPORTFIND 300 + void parse_syn_options(vector& args); @@ -183,6 +185,11 @@ class SyntheticClient { int exclude; string get_sarg(int seq); + int get_iarg() { + int i = iargs.front(); + iargs.pop_front(); + return i; + } bool time_to_stop() { utime_t now = g_clock.now(); @@ -226,6 +233,8 @@ class SyntheticClient { int thrash_links(const char *basedir, int dirs, int files, int depth, int n); + void import_find(const char *basedir, const char *find, bool writedata); + }; #endif diff --git a/branches/sage/mds/client/fuse.cc b/branches/sage/mds/client/fuse.cc index 60d636cf69a9d..f97932ce9046d 100644 --- a/branches/sage/mds/client/fuse.cc +++ b/branches/sage/mds/client/fuse.cc @@ -211,9 +211,10 @@ static int ceph_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off while (res == 0) { int r = client->readdirplus_r(dirp, &de, &st, &stmask); if (r != 0) break; + int stneed = InodeStat::MASK_INO | InodeStat::MASK_TYPE; res = filler(buf, de.d_name, - &st, + ((stmask & stneed) == stneed) ? &st:0, client->telldir(dirp)); } return 0; -- 2.39.5