};
struct Inode {
struct stat stbuf;
- map<string,Dir*> parents;
+ map<pair<string,ino_t>,Dir*> parents;
Dir *dir;
int ref;
Inode() : dir(0), ref(0) {}
};
+Inode *root = 0;
hash_map<ino_t, Inode*> inode_map;
void make_inode_path(string &buf, Inode *in)
if (!in->parents.empty()) {
make_inode_path(buf, in->parents.begin()->second->inode);
buf += "/";
- buf += in->parents.begin()->first;
+ buf += in->parents.begin()->first.first;
} else {
+ assert(in == root);
+ assert(in->stbuf.st_ino == 1);
buf = basedir;
buf += "/";
}
- //cout << "path: " << in->stbuf.st_ino << " -> " << buf << endl;
+ //dout << "path: " << in->stbuf.st_ino << " -> " << buf << endl;
}
void make_inode_path(string &buf, Inode *in, const char *name)
void add_dentry(Inode *parent, const string& dname, Inode *in)
{
+ dout << "add_dentry " << parent->stbuf.st_ino << " " << dname << " to " << in->stbuf.st_ino << endl;
+
if (!parent->dir) parent->dir = new Dir(parent);
parent->dir->dentries[dname] = in;
- in->parents[dname] = parent->dir;
+ in->parents[pair<string,ino_t>(dname,parent->stbuf.st_ino)] = parent->dir;
}
void remove_dentry(Inode *pin, const string& dname)
Inode *in = pin->dir->dentries[dname];
pin->dir->dentries.erase(dname);
- in->parents.erase(dname);
+ in->parents.erase(pair<string,ino_t>(dname,pin->stbuf.st_ino));
dout << "remove_dentry " << pin->stbuf.st_ino << " " << dname
<< " ... inode " << in->stbuf.st_ino << " ref " << in->ref
// remove parent links
while (!in->parents.empty()) {
Inode *parent = in->parents.begin()->second->inode;
- string dname = in->parents.begin()->first;
+ string dname = in->parents.begin()->first.first;
remove_dentry(parent, dname);
}
}
inode_map.erase(in->stbuf.st_ino);
- //cout << "remove_inode " << in->stbuf.st_ino << " done" << endl;
+ dout << "remove_inode " << in->stbuf.st_ino << " done" << endl;
delete in;
}
Inode *add_inode(Inode *parent, const char *name, struct stat *attr)
{
+ dout << "add_inode " << attr->st_ino << endl;
+
Inode *in = new Inode;
memcpy(&in->stbuf, attr, sizeof(*attr));
-
inode_map[in->stbuf.st_ino] = in;
string dname(name);
//parent->ref++;
string dname(name);
+ string path;
+ make_inode_path(path, parent, name);
+
Inode *in = 0;
if (parent->dir->dentries.count(dname)) {
in = parent->dir->dentries[dname];
+
+ // re-stat, for good measure
+ res = ::lstat(path.c_str(), &in->stbuf);
+
+ // hrm!
+ if (res != 0) {
+ dout << "** WEIRD ** lookup on " << pino << " " << name << " inode went away!" << endl;
+ in = 0;
+ res = errno;
+ }
+
//cout << "have " << in->stbuf.st_ino << endl;
} else {
- string path;
- make_inode_path(path, parent, name);
in = new Inode;
- res = lstat(path.c_str(), &in->stbuf);
+ res = ::lstat(path.c_str(), &in->stbuf);
//cout << "stat " << path << " res = " << res << endl;
if (res == 0) {
inode_map[in->stbuf.st_ino] = in;
if (in->ref <= 0)
remove_inode(in);
} else {
- dout << "**** BAD **** forget on nonexistent inode " << ino << endl;
+ dout << "**** BAD **** forget " << nlookup << " on nonexistent inode " << ino << endl;
}
lock.Unlock();
}
res = ::lstat(path.c_str(), &attr);
//cout << "getattr stat on " << path << " res " << res << endl;
- if (ino == 1)
- in->stbuf.st_ino = 1;
+ if (ino == 1) attr.st_ino = 1;
trace_lock.Lock();
traceout << "ll_getattr" << endl << ino << endl;
if (res == 0) {
lock.Lock();
::lstat(path.c_str(), &in->stbuf);
+ if (ino == 1) in->stbuf.st_ino = 1;
memcpy(attr, &in->stbuf, sizeof(*attr));
lock.Unlock();
fuse_reply_attr(req, attr, 0);
int res = ::link(path.c_str(), newpath.c_str());
if (res == 0) {
+ struct fuse_entry_param fe;
+ memset(&fe, 0, sizeof(fe));
+ ::lstat(newpath.c_str(), &fe.attr);
+
lock.Lock();
string newdname(newname);
add_dentry(newpin, newdname, in);
in->ref++;
+ memcpy(&in->stbuf, &fe.attr, sizeof(fe.attr)); // re-read, bc we changed the link count
lock.Unlock();
- struct fuse_entry_param fe;
- memset(&fe, 0, sizeof(fe));
- ::lstat(newpath.c_str(), &fe.attr);
fe.ino = fe.attr.st_ino;
fuse_reply_entry(req, &fe);
} else
char *buf = new char[size];
int res = ::pread(fi->fh, buf, size, off);
+ //cout << "read " << path << " " << off << "~" << size << endl;
trace_lock.Lock();
traceout << "ll_read" << endl
<< fi->fh << endl
cout << "basedir is " << basedir << endl;
// create root ino
- Inode *root = new Inode;
- lstat(basedir, &root->stbuf);
+ root = new Inode;
+ ::lstat(basedir, &root->stbuf);
root->stbuf.st_ino = 1;
inode_map[1] = root;
root->ref++;