//
root = 0;
- set_cache_size(g_conf.client_cache_size);
+ lru.lru_set_max(g_conf.client_cache_size);
// file handles
free_fh_set.insert(10, 1<<30);
Dentry *dn = (Dentry*)lru.lru_expire();
if (!dn) break; // done
- //dout(10) << "trim_cache unlinking dn " << dn->name << " in dir " << hex << dn->dir->inode->inode.ino << endl;
+ dout(15) << "trim_cache unlinking dn " << dn->name
+ << " in dir " << hex << dn->dir->parent_inode->inode.ino
+ << endl;
unlink(dn);
}
dout(12) << "insert_inode " << dname << " ino " << st->inode.ino
<< " size " << st->inode.size
<< " mtime " << st->inode.mtime
+ << " mask " << st->mask
+ << " in dir " << dir->parent_inode->inode.ino
<< endl;
if (dn) {
} else {
// actually update info
dout(12) << " stat inode mask is " << st->mask << endl;
- dn->inode->inode = st->inode;
- dn->inode->dirfragtree = st->dirfragtree; // FIXME look at the mask!
+ if (st->mask & STAT_MASK_BASE) {
+ dn->inode->inode = st->inode;
+ dn->inode->dirfragtree = st->dirfragtree; // FIXME look at the mask!
+ }
// ...but don't clobber our mtime, size!
- if ((dn->inode->mask & INODE_MASK_SIZE) == 0 &&
+ /* isn't this handled below?
+ if ((dn->inode->mask & STAT_MASK_SIZE) == 0 &&
dn->inode->file_wr_size > dn->inode->inode.size)
dn->inode->inode.size = dn->inode->file_wr_size;
- if ((dn->inode->mask & INODE_MASK_MTIME) == 0 &&
+ if ((dn->inode->mask & STAT_MASK_MTIME) == 0 &&
dn->inode->file_wr_mtime > dn->inode->inode.mtime)
dn->inode->inode.mtime = dn->inode->file_wr_mtime;
+ */
}
// OK, we found it!
assert(dn && dn->inode);
+
+ // save the mask
+ dn->inode->mask = st->mask;
// or do we have newer size/mtime from writing?
if (dn->inode->file_caps() & CAP_FILE_WR) {
}
// symlink?
- if ((dn->inode->inode.mode & INODE_TYPE_MASK) == INODE_MODE_SYMLINK) {
+ if (dn->inode->inode.is_symlink()) {
if (!dn->inode->symlink)
dn->inode->symlink = new string;
*(dn->inode->symlink) = st->symlink;
int Client::_link(const char *existing, const char *newname)
{
- dout(3) << "op: client->link(\"" << existing << "\", \"" << newname << "\");" << endl;
tout << "link" << endl;
tout << existing << endl;
tout << newname << endl;
dout(10) << "link result is " << res << endl;
trim_cache();
+ dout(3) << "link(\"" << existing << "\", \"" << newname << "\") = " << res << endl;
return res;
}
int Client::_unlink(const char *path)
{
- dout(3) << "op: client->unlink\(\"" << path << "\");" << endl;
tout << "unlink" << endl;
tout << path << endl;
-
MClientRequest *req = new MClientRequest(MDS_OP_UNLINK, messenger->get_myinst());
req->set_path(path);
dout(10) << "unlink result is " << res << endl;
trim_cache();
+ dout(3) << "unlink(\"" << path << "\") = " << res << endl;
return res;
}
int Client::_rename(const char *from, const char *to)
{
-
- dout(3) << "op: client->rename(\"" << from << "\", \"" << to << "\");" << endl;
tout << "rename" << endl;
tout << from << endl;
tout << to << endl;
-
MClientRequest *req = new MClientRequest(MDS_OP_RENAME, messenger->get_myinst());
req->set_path(from);
req->set_sarg(to);
dout(10) << "rename result is " << res << endl;
trim_cache();
+ dout(3) << "rename(\"" << from << "\", \"" << to << "\") = " << res << endl;
return res;
}
int Client::_mkdir(const char *path, mode_t mode)
{
- dout(3) << "op: client->mkdir(\"" << path << "\", " << mode << ");" << endl;
tout << "mkdir" << endl;
tout << path << endl;
tout << mode << endl;
-
MClientRequest *req = new MClientRequest(MDS_OP_MKDIR, messenger->get_myinst());
req->set_path(path);
req->args.mkdir.mode = mode;
dout(10) << "mkdir result is " << res << endl;
trim_cache();
+
+ dout(3) << "mkdir(\"" << path << "\", 0" << oct << mode << dec << ") = " << res << endl;
return res;
}
int Client::_rmdir(const char *path)
{
- dout(3) << "op: client->rmdir(\"" << path << "\");" << endl;
tout << "rmdir" << endl;
tout << path << endl;
-
MClientRequest *req = new MClientRequest(MDS_OP_RMDIR, messenger->get_myinst());
req->set_path(path);
}
insert_trace(reply);
delete reply;
- dout(10) << "rmdir result is " << res << endl;
trim_cache();
+ dout(3) << "rmdir(\"" << path << "\") = " << res << endl;
return res;
}
int Client::_symlink(const char *target, const char *link)
{
- dout(3) << "op: client->symlink(\"" << target << "\", \"" << link << "\");" << endl;
tout << "symlink" << endl;
tout << target << endl;
tout << link << endl;
-
MClientRequest *req = new MClientRequest(MDS_OP_SYMLINK, messenger->get_myinst());
req->set_path(link);
req->set_sarg(target);
int res = reply->get_result();
insert_trace(reply); //FIXME assuming trace of link, not of target
delete reply;
- dout(10) << "symlink result is " << res << endl;
trim_cache();
+ dout(3) << "symlink(\"" << target << "\", \"" << link << "\") = " << res << endl;
return res;
}
int Client::_readlink(const char *path, char *buf, off_t size)
{
- dout(3) << "op: client->readlink(\"" << path << "\", readlinkbuf, readlinkbuf_len);" << endl;
tout << "readlink" << endl;
tout << path << endl;
Inode *in;
- int r = _lstat(path, INODE_MASK_ALL_STAT, &in);
- if (r != 0) return r;
-
- // copy into buf (at most size bytes)
- unsigned res = in->symlink->length();
- if (res > size) res = size;
- memcpy(buf, in->symlink->c_str(), res);
-
+ int r = _lstat(path, STAT_MASK_BASE, &in);
+ if (r == 0 && !in->inode.is_symlink()) r = -EINVAL;
+ if (r == 0) {
+ // copy into buf (at most size bytes)
+ r = in->symlink->length();
+ if (r > size) r = size;
+ memcpy(buf, in->symlink->c_str(), r);
+ } else {
+ buf[0] = 0;
+ }
trim_cache();
- return res; // return length in bytes (to mimic the system call)
+
+ dout(3) << "readlink(\"" << path << "\", \"" << buf << "\", " << size << ") = " << r << endl;
+ return r;
}
Dentry *dn = lookup(fpath);
inode_t inode;
utime_t now = g_clock.real_now();
+
if (dn &&
- now <= dn->inode->valid_until &&
- ((dn->inode->mask & INODE_MASK_ALL_STAT) == INODE_MASK_ALL_STAT)) {
+ now <= dn->inode->valid_until)
+ dout(10) << "_lstat has inode " << path << " with mask " << dn->inode->mask << ", want " << mask << endl;
+
+ if (dn && dn->inode &&
+ ((mask & ~STAT_MASK_BASE) || now <= dn->inode->valid_until) &&
+ ((dn->inode->mask & mask) == mask)) {
inode = dn->inode->inode;
- dout(10) << "lstat cache hit w/ sufficient inode.mask, valid until " << dn->inode->valid_until << endl;
+ dout(10) << "lstat cache hit w/ sufficient mask, valid until " << dn->inode->valid_until << endl;
if (g_conf.client_cache_stat_ttl == 0)
dn->inode->valid_until = utime_t(); // only one stat allowed after each readdir
{
client_lock.Lock();
+ tout << "lstat" << endl;
+ tout << relpath << endl;
+
string abspath;
mkabspath(relpath, abspath);
const char *path = abspath.c_str();
- dout(3) << "op: client->lstat(\"" << path << "\", &st);" << endl;
- tout << "lstat" << endl;
- tout << path << endl;
-
Inode *in = 0;
-
- int res = _lstat(path, INODE_MASK_ALL_STAT, &in);
+ int res = _lstat(path, STAT_MASK_ALL, &in);
if (res == 0) {
assert(in);
fill_stat(in, stbuf);
}
trim_cache();
+ dout(3) << "lstat(\"" << relpath << "\", " << stbuf << ") = " << res << endl;
client_lock.Unlock();
return res;
}
int Client::_chmod(const char *path, mode_t mode)
{
- dout(3) << "op: client->chmod(\"" << path << "\", " << mode << ");" << endl;
tout << "chmod" << endl;
tout << path << endl;
tout << mode << endl;
-
MClientRequest *req = new MClientRequest(MDS_OP_CHMOD, messenger->get_myinst());
req->set_path(path);
req->args.chmod.mode = mode;
dout(10) << "chmod result is " << res << endl;
trim_cache();
+ dout(3) << "chmod(\"" << path << "\", " << mode << ") = " << res << endl;
return res;
}
int Client::_chown(const char *path, uid_t uid, gid_t gid)
{
- dout(3) << "op: client->chown(\"" << path << "\", " << uid << ", " << gid << ");" << endl;
tout << "chown" << endl;
tout << path << endl;
tout << uid << endl;
dout(10) << "chown result is " << res << endl;
trim_cache();
+ dout(3) << "chown(\"" << path << "\", " << uid << ", " << gid << ") = " << res << endl;
return res;
}
int Client::_utime(const char *path, utime_t mtime, utime_t atime)
{
- 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 << mtime.sec() << endl;
req->set_caller_uid(getuid());
req->set_caller_gid(getgid());
- //FIXME enforce caller uid rights?
-
MClientReply *reply = make_request(req);
int res = reply->get_result();
insert_trace(reply);
delete reply;
- dout(10) << "utime result is " << res << endl;
+ dout(3) << "utime(\"" << path << "\", " << mtime << ", " << atime << ") = " << res << endl;
trim_cache();
return res;
}
int Client::_mknod(const char *path, mode_t mode, dev_t rdev)
{
- dout(3) << "op: client->mknod(\"" << path << "\", " << mode << ");" << endl;
tout << "mknod" << endl;
tout << path << endl;
tout << mode << endl;
int res = reply->get_result();
insert_trace(reply);
- dout(10) << "mknod result is " << res << endl;
-
delete reply;
trim_cache();
+
+ dout(3) << "mknod(\"" << path << "\", " << mode << ") = " << res << endl;
return res;
}
int Client::getdir(const char *relpath, list<string>& contents)
{
- dout(3) << "getdir " << relpath << endl;
+ dout(3) << "getdir(" << relpath << ")" << endl;
DIR *d;
int r = opendir(relpath, &d);
if (r < 0) {
dout(3) << "opendir " << name << " err = " << r << endl;
delete dirp;
- return r;
+ } else {
+ // yay!
+ *((DirResult**)dirpp) = dirp;
+ dout(3) << "opendir(" << name << ") = " << dirp << endl;
}
-
- // yay!
- *((DirResult**)dirpp) = dirp;
-
- dout(3) << "opendir " << name << " = " << *dirpp << endl;
- return 0;
+ return r;
}
-
void Client::_readdir_add_dirent(DirResult *dirp, const string& name, Inode *in)
{
struct stat st;
struct stat st;
memset(&st, 0, sizeof(st));
st.st_mode = DT_TO_MODE(d_type);
- int stmask = InodeStat::MASK_TYPE;
+ int stmask = STAT_MASK_TYPE;
frag_t fg = dirp->frag();
dirp->buffer[fg].push_back(DirEntry(name, st, stmask));
dout(10) << "_readdir_add_dirent added " << name << ", size now " << dirp->buffer[fg].size() << endl;
de->d_reclen = 1;
de->d_type = MODE_TO_DT(entry->st.st_mode);
strncpy(de->d_name, entry->d_name.c_str(), 256);
+ dout(10) << "_readdir_fill_dirent " << de->d_name << " " << de->d_ino
+ << " type " << (int)de->d_type << " at off " << off << endl;
}
int Client::closedir(DIR *dir)
{
- dout(3) << "closedir " << dir << endl;
+ dout(3) << "closedir(" << dir << ") = 0" << endl;
DirResult *dirp = (DirResult*)dir;
if (dirp->inode) {
void Client::rewinddir(DIR *dirp)
{
+ dout(3) << "rewinddir(" << dirp << ")" << endl;
DirResult *d = (DirResult*)dirp;
d->offset = 0;
d->buffer.clear();
off_t Client::telldir(DIR *dirp)
{
DirResult *d = (DirResult*)dirp;
+ dout(3) << "telldir(" << dirp << ") = " << d->offset << endl;
return d->offset;
}
void Client::seekdir(DIR *dirp, off_t offset)
{
+ dout(3) << "seekdir(" << dirp << ", " << offset << ")" << endl;
DirResult *d = (DirResult*)dirp;
d->offset = offset;
}
Fh *fh;
int r = _open(abspath.c_str(), flags, mode, &fh);
- if (r < 0) return r; // error
-
- // allocate a integer file descriptor
- assert(fh);
- int fd = get_fh();
- assert(fh_map.count(fd) == 0);
- fh_map[fd] = fh;
- dout(3) << "open allocated fd " << fd << " -> " << fh << endl;
- return fd;
+ if (r >= 0) {
+ // allocate a integer file descriptor
+ assert(fh);
+ r = get_fh();
+ assert(fh_map.count(r) == 0);
+ fh_map[r] = fh;
+ }
+ dout(3) << "open(" << relpath << ", " << flags << ") = " << r << endl;
+ return r;
}
int Client::_open(const char *path, int flags, mode_t mode, Fh **fhp)
{
- dout(3) << "op: fh = client->open(\"" << path << "\", " << flags << ");" << endl;
tout << "open" << endl;
tout << path << endl;
tout << flags << endl;
if (fhp) *fhp = f;
f->mode = cmode;
+ tout << (long)f << endl;
+
// inode
f->inode = inode_map[reply->get_ino()];
assert(f->inode);
dout(3) << "open success, fh is " << f << " combined caps " << cap_string(f->inode->file_caps()) << endl;
} else {
dout(0) << "open failure result " << result << endl;
+ tout << 0 << endl;
}
delete reply;
int Client::close(fh_t fd)
{
Mutex::Locker lock(client_lock);
+ dout(3) << "close(" << fd << ")" << endl;
assert(fh_map.count(fd));
Fh *fh = fh_map[fd];
_release(fh);
{
//dout(3) << "op: client->close(open_files[ " << fh << " ]);" << endl;
//dout(3) << "op: open_files.erase( " << fh << " );" << endl;
- dout(3) << "_release " << f << endl;
+ dout(5) << "_release " << f << endl;
tout << "close" << endl;
tout << f << endl;
off_t Client::lseek(fh_t fh, off_t offset, int whence)
{
- client_lock.Lock();
- dout(3) << "op: client->lseek(" << fh << ", " << offset << ", " << whence << ");" << endl;
+ Mutex::Locker lock(client_lock);
assert(fh_map.count(fh));
Fh *f = fh_map[fh];
}
off_t pos = f->pos;
- client_lock.Unlock();
+ dout(3) << "lseek(" << fh << ", " << offset << ", " << whence << ") = " << pos << endl;
return pos;
}
dout(10) << "file size: " << in->inode.size << endl;
if (offset > 0 && offset >= in->inode.size) {
if (movepos) unlock_fh_pos(f);
- client_lock.Unlock();
return 0;
}
if (offset + size > (off_t)in->inode.size)
if (size == 0) {
dout(10) << "read is size=0, returning 0" << endl;
if (movepos) unlock_fh_pos(f);
- client_lock.Unlock();
return 0;
}
} else {
#include <stdint.h>
#include <map>
#include <list>
+#include <iostream>
#include "buffer.h"
/*
// accessors
unsigned value() const { return _enc & 0xffffff; }
unsigned bits() const { return _enc >> 24; }
- unsigned mask() const { return 0xffffffffUL >> (32-bits()); }
+ unsigned mask() const { return 0xffffffffULL >> (32-bits()); }
+
operator _frag_t() const { return _enc; }
// tests
}
// splitting
- void split(int nb, list<frag_t>& fragments) const {
+ void split(int nb, std::list<frag_t>& fragments) const {
assert(nb > 0);
unsigned nway = 1 << nb;
for (unsigned i=0; i<nway; i++)
}
};
-inline ostream& operator<<(ostream& out, frag_t hb)
+inline std::ostream& operator<<(std::ostream& out, frag_t hb)
{
- return out << hex << hb.value() << dec << "/" << hb.bits();
+ return out << std::hex << hb.value() << std::dec << "/" << hb.bits();
}
bool is_leaf(frag_t x) const {
- list<frag_t> ls;
+ std::list<frag_t> ls;
get_leaves_under_split(x, ls);
if (!ls.empty() &&
ls.front() == x)
/**
* get_leaves -- list all leaves
*/
- void get_leaves(list<frag_t>& ls) const {
+ void get_leaves(std::list<frag_t>& ls) const {
return get_leaves_under_split(frag_t(), ls);
}
/**
* get_leaves_under_split -- list all leaves under a known split point (or root)
*/
- void get_leaves_under_split(frag_t under, list<frag_t>& ls) const {
- list<frag_t> q;
+ void get_leaves_under_split(frag_t under, std::list<frag_t>& ls) const {
+ std::list<frag_t> q;
q.push_back(under);
while (!q.empty()) {
frag_t t = q.front();
/**
* get_leaves_under(x, ls) -- search for any leaves fully contained by x
*/
- void get_leaves_under(frag_t x, list<frag_t>& ls) const {
- list<frag_t> q;
+ void get_leaves_under(frag_t x, std::list<frag_t>& ls) const {
+ std::list<frag_t> q;
q.push_back(get_branch(x));
while (!q.empty()) {
frag_t t = q.front();
* contains(fg) -- does fragtree contain the specific frag @x
*/
bool contains(frag_t x) const {
- list<frag_t> q;
+ std::list<frag_t> q;
q.push_back(get_branch(x));
while (!q.empty()) {
frag_t t = q.front();
void try_assimilate_children(frag_t x) {
int nb = get_split(x);
if (!nb) return;
- list<frag_t> children;
+ std::list<frag_t> children;
x.split(nb, children);
int childbits = 0;
- for (list<frag_t>::iterator p = children.begin();
+ for (std::list<frag_t>::iterator p = children.begin();
p != children.end();
++p) {
int cb = get_split(*p);
childbits = cb;
}
// all children are split with childbits!
- for (list<frag_t>::iterator p = children.begin();
+ for (std::list<frag_t>::iterator p = children.begin();
p != children.end();
++p)
_splits.erase(*p);
merge(parent, nb);
split(parent, spread);
- list<frag_t> subs;
+ std::list<frag_t> subs;
parent.split(spread, subs);
- for (list<frag_t>::iterator p = subs.begin();
+ for (std::list<frag_t>::iterator p = subs.begin();
p != subs.end();
++p)
split(*p, nb - spread);
// x is now a leaf or split.
// hoover up any children.
- list<frag_t> q;
+ std::list<frag_t> q;
q.push_back(x);
while (!q.empty()) {
frag_t t = q.front();
::_decode(_splits, bl, off);
}
- void print(ostream& out) {
+ void print(std::ostream& out) {
out << "fragtree_t(";
- list<frag_t> q;
+ std::list<frag_t> q;
q.push_back(frag_t());
while (!q.empty()) {
frag_t t = q.front();
}
};
-inline ostream& operator<<(ostream& out, fragtree_t& ft)
+inline std::ostream& operator<<(std::ostream& out, fragtree_t& ft)
{
out << "fragtree_t(";
- list<frag_t> q;
+ std::list<frag_t> q;
q.push_back(frag_t());
while (!q.empty()) {
frag_t t = q.front();
* fragset_t -- a set of fragments
*/
class fragset_t {
- set<frag_t> _set;
+ std::set<frag_t> _set;
public:
- set<frag_t> &get() { return _set; }
- set<frag_t>::iterator begin() { return _set.begin(); }
- set<frag_t>::iterator end() { return _set.end(); }
+ std::set<frag_t> &get() { return _set; }
+ std::set<frag_t>::iterator begin() { return _set.begin(); }
+ std::set<frag_t>::iterator end() { return _set.end(); }
bool empty() const { return _set.empty(); }
void simplify() {
while (1) {
bool clean = true;
- set<frag_t>::iterator p = _set.begin();
+ std::set<frag_t>::iterator p = _set.begin();
while (p != _set.end()) {
if (!p->is_root() &&
_set.count(p->get_sibling())) {
}
};
-inline ostream& operator<<(ostream& out, fragset_t& fs)
+inline std::ostream& operator<<(std::ostream& out, fragset_t& fs)
{
return out << "fragset_t(" << fs.get() << ")";
}