From 170b7b2a4fa6aa39057bf28fa5fd1c33f182765a Mon Sep 17 00:00:00 2001 From: sageweil Date: Fri, 3 Aug 2007 21:46:11 +0000 Subject: [PATCH] fuse_ll mkdir, mknod, symlink git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1593 29311d96-e01e-0410-9327-a35deaab8ce9 --- branches/sage/mds/client/Client.cc | 201 ++++++++++++++++---- branches/sage/mds/client/Client.h | 18 +- branches/sage/mds/client/SyntheticClient.cc | 2 +- branches/sage/mds/client/fuse_ll.cc | 80 +++++++- branches/sage/mds/include/types.h | 1 + branches/sage/mds/include/utime.h | 2 + branches/sage/mds/mds/Server.cc | 1 + branches/sage/mds/messages/MClientRequest.h | 1 + 8 files changed, 262 insertions(+), 44 deletions(-) diff --git a/branches/sage/mds/client/Client.cc b/branches/sage/mds/client/Client.cc index 01736b1e9300c..8fdf302bbab80 100644 --- a/branches/sage/mds/client/Client.cc +++ b/branches/sage/mds/client/Client.cc @@ -55,6 +55,7 @@ using namespace std; #include "common/Logger.h" + #include "config.h" #undef dout #define dout(l) if (l<=g_conf.debug || l <= g_conf.debug_client) cout << g_clock.now() << " client" << whoami << "." << pthread_self() << " " @@ -1584,8 +1585,12 @@ int Client::rename(const char *relfrom, const char *relto) int Client::mkdir(const char *relpath, mode_t mode) { - client_lock.Lock(); + Mutex::Locker lock(client_lock); + return _mkdir(relpath, mode); +} +int Client::_mkdir(const char *relpath, mode_t mode) +{ string abspath; mkabspath(relpath, abspath); const char *path = abspath.c_str(); @@ -1613,7 +1618,6 @@ int Client::mkdir(const char *relpath, mode_t mode) dout(10) << "mkdir result is " << res << endl; trim_cache(); - client_lock.Unlock(); return res; } @@ -1664,8 +1668,12 @@ int Client::rmdir(const char *relpath) int Client::symlink(const char *reltarget, const char *rellink) { - client_lock.Lock(); + Mutex::Locker lock(client_lock); + return _symlink(reltarget, rellink); +} +int Client::_symlink(const char *reltarget, const char *rellink) +{ string abstarget; mkabspath(reltarget, abstarget); const char *target = abstarget.c_str(); @@ -1696,7 +1704,6 @@ int Client::symlink(const char *reltarget, const char *rellink) dout(10) << "symlink result is " << res << endl; trim_cache(); - client_lock.Unlock(); return res; } @@ -1796,6 +1803,7 @@ int Client::fill_stat(Inode *in, struct stat *st) memset(st, 0, sizeof(struct stat)); st->st_ino = in->inode.ino; st->st_mode = in->inode.mode; + st->st_rdev = in->inode.rdev; st->st_nlink = in->inode.nlink; st->st_uid = in->inode.uid; st->st_gid = in->inode.gid; @@ -1885,8 +1893,12 @@ int Client::lstatlite(const char *relpath, struct statlite *stl) int Client::chmod(const char *relpath, mode_t mode) { - client_lock.Lock(); + Mutex::Locker lock(client_lock); + return _chmod(relpath, mode); +} +int Client::_chmod(const char *relpath, mode_t mode) +{ string abspath; mkabspath(relpath, abspath); const char *path = abspath.c_str(); @@ -1912,14 +1924,17 @@ int Client::chmod(const char *relpath, mode_t mode) dout(10) << "chmod result is " << res << endl; trim_cache(); - client_lock.Unlock(); return res; } int Client::chown(const char *relpath, uid_t uid, gid_t gid) { - client_lock.Lock(); + Mutex::Locker lock(client_lock); + return _chown(relpath, uid, gid); +} +int Client::_chown(const char *relpath, uid_t uid, gid_t gid) +{ string abspath; mkabspath(relpath, abspath); const char *path = abspath.c_str(); @@ -1930,7 +1945,6 @@ int Client::chown(const char *relpath, uid_t uid, gid_t gid) tout << uid << endl; tout << gid << endl; - MClientRequest *req = new MClientRequest(MDS_OP_CHOWN, messenger->get_myinst()); req->set_path(path); req->args.chown.uid = uid; @@ -1949,32 +1963,32 @@ int Client::chown(const char *relpath, uid_t uid, gid_t gid) dout(10) << "chown result is " << res << endl; trim_cache(); - client_lock.Unlock(); return res; } int Client::utime(const char *relpath, struct utimbuf *buf) { - client_lock.Lock(); + Mutex::Locker lock(client_lock); + return _utime(relpath, utime_t(buf->modtime,0), utime_t(buf->actime,0)); +} +int Client::_utime(const char *relpath, utime_t mtime, utime_t atime) +{ string abspath; mkabspath(relpath, abspath); const char *path = abspath.c_str(); - dout(3) << "op: utim.actime = " << buf->actime << "; utim.modtime = " << buf->modtime << ";" << endl; + dout(3) << "op: utim.actime = " << mtime << "; utim.modtime = " << atime << ";" << endl; dout(3) << "op: client->utime(\"" << path << "\", &utim);" << endl; tout << "utime" << endl; tout << path << endl; - tout << buf->actime << endl; - tout << buf->modtime << endl; - + tout << mtime.sec() << endl; + tout << atime.sec() << endl; MClientRequest *req = new MClientRequest(MDS_OP_UTIME, messenger->get_myinst()); req->set_path(path); - req->args.utime.mtime.tv_sec = buf->modtime; - req->args.utime.mtime.tv_usec = 0; - req->args.utime.atime.tv_sec = buf->actime; - req->args.utime.atime.tv_usec = 0; + req->args.utime.mtime = mtime.tv_ref(); + req->args.utime.atime = atime.tv_ref(); // FIXME where does FUSE maintain user information req->set_caller_uid(getuid()); @@ -1989,16 +2003,19 @@ int Client::utime(const char *relpath, struct utimbuf *buf) dout(10) << "utime result is " << res << endl; trim_cache(); - client_lock.Unlock(); return res; } -int Client::mknod(const char *relpath, mode_t mode) +int Client::mknod(const char *relpath, mode_t mode, dev_t rdev) { - client_lock.Lock(); + Mutex::Locker lock(client_lock); + return _mknod(relpath, mode, rdev); +} +int Client::_mknod(const char *relpath, mode_t mode, dev_t rdev) +{ string abspath; mkabspath(relpath, abspath); const char *path = abspath.c_str(); @@ -2008,10 +2025,10 @@ int Client::mknod(const char *relpath, mode_t mode) tout << path << endl; tout << mode << endl; - MClientRequest *req = new MClientRequest(MDS_OP_MKNOD, messenger->get_myinst()); req->set_path(path); req->args.mknod.mode = mode; + req->args.mknod.rdev = rdev; // FIXME where does FUSE maintain user information req->set_caller_uid(getuid()); @@ -2028,7 +2045,6 @@ int Client::mknod(const char *relpath, mode_t mode) delete reply; trim_cache(); - client_lock.Unlock(); return res; } @@ -2873,13 +2889,17 @@ int Client::write(fh_t fh, const char *buf, off_t size, off_t offset) int Client::truncate(const char *file, off_t length) { - client_lock.Lock(); + Mutex::Locker lock(client_lock); + return _truncate(file, length); +} + +int Client::_truncate(const char *file, off_t length) +{ dout(3) << "op: client->truncate(\"" << file << "\", " << length << ");" << endl; tout << "truncate" << endl; tout << file << endl; tout << length << endl; - MClientRequest *req = new MClientRequest(MDS_OP_TRUNCATE, messenger->get_myinst()); req->set_path(file); req->args.truncate.length = length; @@ -2895,7 +2915,6 @@ int Client::truncate(const char *file, off_t length) dout(10) << " truncate result is " << res << endl; - client_lock.Unlock(); return res; } @@ -3038,11 +3057,19 @@ int Client::lazyio_synchronize(int fd, off_t offset, size_t count) // ========================================= // low level +// ugly hack for ll +#define FUSE_SET_ATTR_MODE (1 << 0) +#define FUSE_SET_ATTR_UID (1 << 1) +#define FUSE_SET_ATTR_GID (1 << 2) +#define FUSE_SET_ATTR_SIZE (1 << 3) +#define FUSE_SET_ATTR_ATIME (1 << 4) +#define FUSE_SET_ATTR_MTIME (1 << 5) + int Client::ll_lookup(inodeno_t parent, const char *name, struct stat *attr, double *attr_timeout, double *entry_timeout) { Mutex::Locker lock(client_lock); - dout(3) << "ll_lookp " << parent << " " << name << endl; + dout(3) << "ll_lookup " << parent << " " << name << endl; if (inode_map.count(parent) == 0) return -ENOENT; Inode *diri = inode_map[parent]; @@ -3095,6 +3122,9 @@ void Client::ll_forget(inodeno_t ino, int num) { Mutex::Locker lock(client_lock); dout(3) << "ll_forget " << ino << " " << num << endl; + + if (ino == 1) return; // ignore forget on root. + if (inode_map.count(ino) == 0) { dout(1) << "WARNING: ll_forget on " << ino << " " << num << ", which I don't have" << endl; @@ -3105,23 +3135,126 @@ void Client::ll_forget(inodeno_t ino, int num) } } -int Client::ll_getattr(inodeno_t ino, struct stat *st, double *attr_timeout) +Inode *Client::_ll_get_inode(inodeno_t ino) { - Mutex::Locker lock(client_lock); - dout(3) << "ll_getattr " << ino << endl; - Inode *in; if (inode_map.count(ino) == 0) { assert(ino == 1); // must be the root inode. + Inode *in; int r = _lstat("/", 0, &in); - if (r < 0) return r; + assert(r >= 0); + return in; } else { - in = inode_map[ino]; + return inode_map[ino]; } - assert(in); +} + + +int Client::ll_getattr(inodeno_t ino, struct stat *st, double *attr_timeout) +{ + Mutex::Locker lock(client_lock); + dout(3) << "ll_getattr " << ino << endl; + Inode *in = _ll_get_inode(ino); fill_stat(in, st); return 0; } +int Client::ll_setattr(inodeno_t ino, struct stat *st, int mask) +{ + Mutex::Locker lock(client_lock); + dout(3) << "ll_setattr " << ino << endl; + Inode *in = _ll_get_inode(ino); + + string path; + in->make_path(path); + + int r; + if ((mask & FUSE_SET_ATTR_MODE) && + (r = _chmod(path.c_str(), st->st_mode) < 0)) return r; + if ((mask & FUSE_SET_ATTR_UID) && + (r = _chown(path.c_str(), st->st_uid, st->st_gid) < 0)) return r; + //if ((mask & FUSE_SET_ATTR_GID) && + //(r = client->_chgrp(path.c_str(), st->st_gid) < 0)) return r; + if ((mask & FUSE_SET_ATTR_SIZE) && + (r = _truncate(path.c_str(), st->st_size) < 0)) return r; + if ((mask & FUSE_SET_ATTR_MTIME) && + (r = _utime(path.c_str(), utime_t(st->st_mtime,0), utime_t()) < 0)) return r; + if ((mask & FUSE_SET_ATTR_ATIME) && + (r = _utime(path.c_str(), utime_t(), utime_t(st->st_atime,0)) < 0)) return r; + + return 0; +} + +int Client::ll_readlink(inodeno_t ino, const char **value) +{ + Mutex::Locker lock(client_lock); + dout(3) << "ll_readlink " << ino << endl; + Inode *in = _ll_get_inode(ino); + if (in->inode.is_symlink()) { + *value = in->symlink->c_str(); + return 0; + } else { + return -EINVAL; + } +} + +int Client::ll_symlink(inodeno_t parent, const char *name, const char *value, struct stat *attr) +{ + Mutex::Locker lock(client_lock); + dout(3) << "ll_mknod " << parent << " " << name << " -> " << value << endl; + Inode *diri = _ll_get_inode(parent); + + string path; + diri->make_path(path); + path += "/"; + path += name; + int r = _symlink(value, path.c_str()); + if (r < 0) return r; + + string dname(name); + Inode *in = diri->dir->dentries[dname]->inode; + fill_stat(in, attr); + return 0; +} + +int Client::ll_mknod(inodeno_t parent, const char *name, mode_t mode, dev_t rdev, struct stat *attr) +{ + Mutex::Locker lock(client_lock); + dout(3) << "ll_mknod " << parent << " " << name << endl; + Inode *diri = _ll_get_inode(parent); + + string path; + diri->make_path(path); + path += "/"; + path += name; + int r = _mknod(path.c_str(), mode, rdev); + if (r < 0) return r; + + string dname(name); + Inode *in = diri->dir->dentries[dname]->inode; + fill_stat(in, attr); + return 0; +} + +int Client::ll_mkdir(inodeno_t parent, const char *name, mode_t mode, struct stat *attr) +{ + Mutex::Locker lock(client_lock); + dout(3) << "ll_mkdir " << parent << " " << name << endl; + Inode *diri = _ll_get_inode(parent); + + string path; + diri->make_path(path); + path += "/"; + path += name; + int r = _mkdir(path.c_str(), mode); + if (r < 0) return r; + + string dname(name); + Inode *in = diri->dir->dentries[dname]->inode; + fill_stat(in, attr); + return 0; +} + + int Client::ll_opendir(inodeno_t ino, void **dirpp) { string path; diff --git a/branches/sage/mds/client/Client.h b/branches/sage/mds/client/Client.h index a466c5f8b1f4b..257fe7a759c62 100644 --- a/branches/sage/mds/client/Client.h +++ b/branches/sage/mds/client/Client.h @@ -678,11 +678,13 @@ public: // dirs int mkdir(const char *path, mode_t mode); + int _mkdir(const char *path, mode_t mode); int rmdir(const char *path); // symlinks int readlink(const char *path, char *buf, off_t size); int symlink(const char *existing, const char *newname); + int _symlink(const char *existing, const char *newname); // inode stuff int _lstat(const char *path, int mask, Inode **in); @@ -690,11 +692,15 @@ public: int lstatlite(const char *path, struct statlite *buf); int chmod(const char *path, mode_t mode); + int _chmod(const char *relpath, mode_t mode); int chown(const char *path, uid_t uid, gid_t gid); + int _chown(const char *relpath, uid_t uid, gid_t gid); int utime(const char *path, struct utimbuf *buf); - + int _utime(const char *relpath, utime_t mtime, utime_t atime); + // file ops - int mknod(const char *path, mode_t mode); + int mknod(const char *path, mode_t mode, dev_t rdev=0); + int _mknod(const char *path, mode_t mode, dev_t rdev); int open(const char *path, int flags, mode_t mode=0); int close(fh_t fh); off_t lseek(fh_t fh, off_t offset, int whence); @@ -702,7 +708,7 @@ public: 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 _truncate(const char *file, off_t length); int fsync(fh_t fh, bool syncdataonly); @@ -722,8 +728,14 @@ public: int ll_lookup(inodeno_t parent, const char *name, struct stat *attr, double *attr_timeout, double *entry_timeout); void ll_forget(inodeno_t ino, int count); + Inode *_ll_get_inode(inodeno_t ino); int ll_getattr(inodeno_t ino, struct stat *st, double *attr_timeout); + int ll_setattr(inodeno_t ino, struct stat *st, int mask); int ll_opendir(inodeno_t ino, void **dirpp); + int ll_readlink(inodeno_t ino, const char **value); + int ll_mknod(inodeno_t ino, const char *name, mode_t mode, dev_t rdev, struct stat *attr); + int ll_mkdir(inodeno_t ino, const char *name, mode_t mode, struct stat *attr); + int ll_symlink(inodeno_t ino, const char *name, const char *value, struct stat *attr); // failure void ms_handle_failure(Message*, const entity_inst_t& inst); diff --git a/branches/sage/mds/client/SyntheticClient.cc b/branches/sage/mds/client/SyntheticClient.cc index 2597c16d2f530..dfb72651f4e1d 100644 --- a/branches/sage/mds/client/SyntheticClient.cc +++ b/branches/sage/mds/client/SyntheticClient.cc @@ -591,7 +591,7 @@ int SyntheticClient::run() { int count = iargs.front(); iargs.pop_front(); if (run_me()) { - client->mknod("test",0777); + client->mknod("test", 0777); struct stat st; for (int i=0; ilstat("test", &st); diff --git a/branches/sage/mds/client/fuse_ll.cc b/branches/sage/mds/client/fuse_ll.cc index 30e288f2a4fd0..531677c429c4e 100644 --- a/branches/sage/mds/client/fuse_ll.cc +++ b/branches/sage/mds/client/fuse_ll.cc @@ -66,6 +66,16 @@ static void ceph_ll_getattr(fuse_req_t req, fuse_ino_t ino, fuse_reply_err(req, ENOENT); } +static void ceph_ll_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info *fi) +{ + int r = client->ll_setattr(ino, attr, to_set); + if (r == 0) + fuse_reply_attr(req, attr, 0); + else + fuse_reply_err(req, -r); +} + static void ceph_ll_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { void *dirp; @@ -78,6 +88,60 @@ static void ceph_ll_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_inf } } +static void ceph_ll_readlink(fuse_req_t req, fuse_ino_t ino) +{ + const char *value; + int r = client->ll_readlink(ino, &value); + if (r == 0) + fuse_reply_readlink(req, value); + else + fuse_reply_err(req, -r); +} + +static void ceph_ll_mknod(fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev) +{ + struct fuse_entry_param fe; + memset(&fe, 0, sizeof(fe)); + + int r = client->ll_mknod(parent, name, mode, rdev, &fe.attr); + if (r == 0) { + fe.ino = fe.attr.st_ino; + fuse_reply_entry(req, &fe); + } else { + fuse_reply_err(req, -r); + } +} + +static void ceph_ll_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode) +{ + struct fuse_entry_param fe; + memset(&fe, 0, sizeof(fe)); + + int r = client->ll_mkdir(parent, name, mode, &fe.attr); + if (r == 0) { + fe.ino = fe.attr.st_ino; + fuse_reply_entry(req, &fe); + } else { + fuse_reply_err(req, -r); + } +} + +static void ceph_ll_symlink(fuse_req_t req, const char *existing, fuse_ino_t parent, const char *name) +{ + struct fuse_entry_param fe; + memset(&fe, 0, sizeof(fe)); + + int r = client->ll_symlink(parent, name, existing, &fe.attr); + if (r == 0) { + fe.ino = fe.attr.st_ino; + fuse_reply_entry(req, &fe); + } else { + fuse_reply_err(req, -r); + } +} + static void ceph_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { @@ -107,10 +171,14 @@ static void ceph_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, if (r < 0) break; st.st_ino = de.d_ino; st.st_mode = DT_TO_MODE(de.d_type); - + off_t off = client->telldir(dirp); size_t entrysize = fuse_add_direntry(req, buf + pos, size - pos, de.d_name, &st, off); + + cout << "ceph_ll_readdir added " << de.d_name << " at " << buf + pos << " len " << entrysize + << " (buffer size is " << size << ")" << endl; + if (entrysize > size - pos) break; // didn't fit, done for now. pos += entrysize; @@ -134,13 +202,13 @@ static struct fuse_lowlevel_ops ceph_ll_oper = { lookup: ceph_ll_lookup, forget: ceph_ll_forget, getattr: ceph_ll_getattr, - setattr: 0, - readlink: 0, - mknod: 0, - mkdir: 0, + setattr: ceph_ll_setattr, + readlink: ceph_ll_readlink, + mknod: ceph_ll_mknod, + mkdir: ceph_ll_mkdir, unlink: 0, rmdir: 0, - symlink: 0, + symlink: ceph_ll_symlink, rename: 0, link: 0, open: 0, diff --git a/branches/sage/mds/include/types.h b/branches/sage/mds/include/types.h index 4ec867cd60ecc..b2179e197b756 100644 --- a/branches/sage/mds/include/types.h +++ b/branches/sage/mds/include/types.h @@ -238,6 +238,7 @@ struct inode_t { // base (immutable) inodeno_t ino; FileLayout layout; // ?immutable? + dev_t rdev; // if special file // affected by any inode change... utime_t ctime; // inode change time diff --git a/branches/sage/mds/include/utime.h b/branches/sage/mds/include/utime.h index e8bca1d100d08..41df4ae2ee017 100644 --- a/branches/sage/mds/include/utime.h +++ b/branches/sage/mds/include/utime.h @@ -63,6 +63,8 @@ class utime_t { // is just casting it to long& OK? long& usec_ref() { return (long&) tv.tv_usec; } + struct timeval& tv_ref() { return tv; } + // cast to double operator double() { return (double)sec() + ((double)usec() / 1000000.0L); diff --git a/branches/sage/mds/mds/Server.cc b/branches/sage/mds/mds/Server.cc index 9a2fab97df5d6..7d23668ac7038 100644 --- a/branches/sage/mds/mds/Server.cc +++ b/branches/sage/mds/mds/Server.cc @@ -1602,6 +1602,7 @@ void Server::handle_client_mknod(MDRequest *mdr) assert(newi); // it's a file. + newi->inode.rdev = req->args.mknod.rdev; newi->inode.mode = req->args.mknod.mode; newi->inode.mode &= ~INODE_TYPE_MASK; newi->inode.mode |= INODE_MODE_FILE; diff --git a/branches/sage/mds/messages/MClientRequest.h b/branches/sage/mds/messages/MClientRequest.h index fe6053eff8c37..8f03044cf5a4f 100644 --- a/branches/sage/mds/messages/MClientRequest.h +++ b/branches/sage/mds/messages/MClientRequest.h @@ -119,6 +119,7 @@ class MClientRequest : public Message { } chown; struct { mode_t mode; + dev_t rdev; } mknod; struct { mode_t mode; -- 2.39.5