#define traceout (tracefile.is_open() ? tracefile : cout)
char *basedir = 0;
+int debug = 0;
+
+#define dout if (debug) cout
Mutex lock;
struct Inode;
buf += name;
}
-void remove_inode(Inode *in);
+void add_dentry(Inode *parent, const string& dname, Inode *in)
+{
+ if (!parent->dir) parent->dir = new Dir(parent);
+ parent->dir->dentries[dname] = in;
+ in->parents[dname] = parent->dir;
+}
-void remove_dentry(Dir *dir, const string& dname)
+void remove_dentry(Inode *pin, const string& dname)
{
- cout << "remove_dentry " << dir->inode->stbuf.st_ino << " " << dname << endl;
+ dout << "remove_dentry " << pin->stbuf.st_ino << " " << dname << endl;
- map<string,Inode*>::iterator p = dir->dentries.find(dname);
- if (p == dir->dentries.end())
- return; // dne
+ if (!pin->dir) return;
+ if (pin->dir->dentries.count(dname) == 0) return; // dne;
- Inode *in = p->second;
- assert(in->parents.count(dname));
+ Inode *in = pin->dir->dentries[dname];
+ pin->dir->dentries.erase(dname);
in->parents.erase(dname);
- if (in->ref == 0 && in->parents.empty())
- remove_inode(in);
-
- dir->dentries.erase(p);
+ dout << "remove_dentry " << pin->stbuf.st_ino << " " << dname
+ << " ... inode " << in->stbuf.st_ino << " ref " << in->ref
+ << endl;
}
void remove_inode(Inode *in)
{
- cout << "remove_inode " << in->stbuf.st_ino << endl;
- for (map<string,Dir*>::iterator p = in->parents.begin();
- p != in->parents.end();
- ++p)
- p->second->dentries.erase(p->first);
-
- inode_map.erase(in->stbuf.st_ino);
+ dout << "remove_inode " << in->stbuf.st_ino << " ref " << in->ref << endl;
+
+ // remove parent links
+ while (!in->parents.empty()) {
+ Inode *parent = in->parents.begin()->second->inode;
+ string dname = in->parents.begin()->first;
+ remove_dentry(parent, dname);
+ }
+
+ // remove children
if (in->dir) {
while (!in->dir->dentries.empty())
- remove_dentry(in->dir, in->dir->dentries.begin()->first);
+ remove_dentry(in, in->dir->dentries.begin()->first);
delete in->dir;
}
+
+ inode_map.erase(in->stbuf.st_ino);
+ //cout << "remove_inode " << in->stbuf.st_ino << " done" << endl;
delete in;
}
Inode *in = new Inode;
memcpy(&in->stbuf, attr, sizeof(*attr));
- if (!parent->dir) parent->dir = new Dir(parent);
-
- string dname(name);
- parent->dir->dentries[dname] = in;
inode_map[in->stbuf.st_ino] = in;
- in->parents[dname] = parent->dir;
+ string dname(name);
+ add_dentry(parent, dname, in);
return in;
}
{
int res = 0;
- //cout << "lookup " << pino << " " << name << endl;
+ //dout << "lookup " << pino << " " << name << endl;
struct fuse_entry_param fe;
memset(&fe, 0, sizeof(fe));
Inode *parent = inode_map[pino];
assert(parent);
if (!parent->dir) parent->dir = new Dir(parent);
- parent->ref++;
+ //parent->ref++;
string dname(name);
Inode *in = 0;
res = lstat(path.c_str(), &in->stbuf);
//cout << "stat " << path << " res = " << res << endl;
if (res == 0) {
- parent->dir->dentries[dname] = in;
inode_map[in->stbuf.st_ino] = in;
- in->parents[dname] = parent->dir;
+ add_dentry(parent, dname, in);
} else {
delete in;
in = 0;
}
}
if (in) {
+ in->ref++;
fe.ino = in->stbuf.st_ino;
memcpy(&fe.attr, &in->stbuf, sizeof(in->stbuf));
}
lock.Lock();
Inode *in = inode_map[ino];
if (in) {
+ dout << "forget on " << ino << " ref " << in->ref << ", forget " << nlookup << endl;
+ if (in->ref < nlookup)
+ dout << "**** BAD **** forget on " << ino << " ref " << in->ref << ", forget " << nlookup << endl;
+
in->ref -= nlookup;
- if (in->ref == 0)
+ if (in->ref <= 0)
remove_inode(in);
} else {
- //cout << "weird, don't have inode " << ino << endl;
+ dout << "**** BAD **** forget on nonexistent inode " << ino << endl;
}
lock.Unlock();
}
::lstat(path.c_str(), &fe.attr);
fe.ino = fe.attr.st_ino;
lock.Lock();
- add_inode(pin, name, &fe.attr);
+ Inode *in = add_inode(pin, name, &fe.attr);
+ in->ref++;
lock.Unlock();
}
::lstat(path.c_str(), &fe.attr);
fe.ino = fe.attr.st_ino;
lock.Lock();
- add_inode(pin, name, &fe.attr);
+ Inode *in = add_inode(pin, name, &fe.attr);
+ in->ref++;
lock.Unlock();
}
::lstat(path.c_str(), &fe.attr);
fe.ino = fe.attr.st_ino;
lock.Lock();
- add_inode(pin, name, &fe.attr);
+ Inode *in = add_inode(pin, name, &fe.attr);
+ in->ref++;
lock.Unlock();
}
// remove from out cache
lock.Lock();
string dname(name);
- if (pin->dir &&
- pin->dir->dentries.count(dname))
- remove_dentry(pin->dir, dname);
+ remove_dentry(pin, dname);
lock.Unlock();
fuse_reply_err(req, 0);
} else
// remove from out cache
lock.Lock();
string dname(name);
- if (pin->dir &&
- pin->dir->dentries.count(dname))
- remove_dentry(pin->dir, dname);
+ remove_dentry(pin, dname);
lock.Unlock();
fuse_reply_err(req, 0);
} else
if (pin->dir &&
pin->dir->dentries.count(dname)) {
Inode *in = pin->dir->dentries[dname];
- pin->dir->dentries.erase(dname);
-
- if (!newpin->dir) newpin->dir = new Dir(newpin);
- newpin->dir->dentries[newdname] = in;
- in->parents[dname] = newpin->dir;
+ add_dentry(newpin, newdname, in);
+ remove_dentry(pin, dname);
+ } else {
+ dout << "hrm, rename didn't have renamed inode.. " << path << " to " << newpath << endl;
}
lock.Unlock();
fuse_reply_err(req, 0);
if (res == 0) {
lock.Lock();
string newdname(newname);
- if (!newpin->dir) newpin->dir = new Dir(newpin);
- newpin->dir->dentries[newdname] = in;
- in->parents[newdname] = newpin->dir;
+ add_dentry(newpin, newdname, in);
+ in->ref++;
lock.Unlock();
struct fuse_entry_param fe;
tracefile.open(argv[++i], ios::out|ios::trunc);
if (!tracefile.is_open())
cerr << "** couldn't open trace file " << argv[i] << endl;
+ } else if (strcmp(argv[i], "--debug") == 0) {
+ debug = 1;
} else {
cout << "arg: " << newargc << " " << argv[i] << endl;
newargv[newargc++] = argv[i];