<< " and mdsmap " << mdsmap->get_epoch()
<< endl;
- /*
- // hack: get+pin root inode
+ // hack: get+pin root inode.
+ // fuse assumes it's always there.
Inode *root;
_do_lstat("/", STAT_MASK_ALL, &root);
_ll_get(root);
- */
// trace?
if (g_conf.client_trace) {
utime_t start = g_clock.real_now();
// copy into fresh buffer (since our write may be resub, async)
- bufferptr bp = buffer::copy(buf, size);
+ bufferptr bp;
+ if (size > 0) bp = buffer::copy(buf, size);
bufferlist blist;
blist.push_back( bp );
string dname = name;
Inode *diri = 0;
+ Inode *in = 0;
int r = 0;
if (inode_map.count(parent) == 0) {
- tout << 0 << endl;
dout(1) << "ll_lookup " << parent << " " << name << " -> ENOENT (parent DNE... WTF)" << endl;
r = -ENOENT;
+ attr->st_ino = 0;
goto out;
}
diri = inode_map[parent];
if (!diri->inode.is_dir()) {
- tout << 0 << endl;
dout(1) << "ll_lookup " << parent << " " << name << " -> ENOTDIR (parent not a dir... WTF)" << endl;
r = -ENOTDIR;
+ attr->st_ino = 0;
goto out;
}
-
- // refresh the dir?
- // FIXME: this is the hackish way.
- if (!diri->dir ||
- diri->dir->dentries.count(dname) == 0) {
+ // get the inode
+ if (diri->dir &&
+ diri->dir->dentries.count(dname)) {
+ in = diri->dir->dentries[dname]->inode;
+ } else {
string path;
diri->make_path(path);
- DirResult *dirp = new DirResult(path, diri);
-
- while (1) {
- hash<string> H;
- dirp->set_frag(diri->dirfragtree[H(dname)]);
-
- dout(10) << "ll_lookup fetching frag " << dirp->frag() << " for " << name << endl;
- int r = _readdir_get_frag(dirp);
- if (r < 0) return r;
-
- if (dirp->buffer.count(diri->dirfragtree[H(dname)])) break;
- dirp->buffer.clear();
- }
-
- _closedir(dirp);
+ path += "/";
+ path += name;
+ _do_lstat(path.c_str(), 0, &in);
}
-
- // do we have it?
- if (diri->dir &&
- diri->dir->dentries.count(dname)) {
- Inode *in = diri->dir->dentries[dname]->inode;
+ if (in) {
fill_stat(in, attr);
_ll_get(in);
- assert(inode_map[in->inode.ino] == in);
} else {
r = -ENOENT;
+ attr->st_ino = 0;
}
out:
Inode *in = (*fhp)->inode;
fill_stat(in, attr);
_ll_get(in);
+ } else {
+ attr->st_ino = 0;
}
tout << (unsigned long)*fhp << endl;
tout << attr->st_ino << endl;
// inc writing counter
num_writing++;
- if (latest_caps & CAP_FILE_WRBUFFER) { // caps buffered write?
- // wait? (this may block!)
- oc->wait_for_write(size, client_lock);
-
- // async, caching, non-blocking.
- oc->file_write(inode, offset, size, blist);
- } else {
- // atomic, synchronous, blocking.
- oc->file_atomic_sync_write(inode, offset, size, blist, client_lock);
- }
+ if (size > 0) {
+ if (latest_caps & CAP_FILE_WRBUFFER) { // caps buffered write?
+ // wait? (this may block!)
+ oc->wait_for_write(size, client_lock);
+
+ // async, caching, non-blocking.
+ oc->file_write(inode, offset, size, blist);
+ } else {
+ // atomic, synchronous, blocking.
+ oc->file_atomic_sync_write(inode, offset, size, blist, client_lock);
+ }
+ }
// dec writing counter
num_writing--;
memset(b, 1, size); // let's write 1's!
client->write(fd, b, size, off);
delete[] b;
+ } else {
+ client->write(fd, NULL, 0, size+off);
}
} else if (strcmp(op, "truncate") == 0) {
const char *a = t.get_string(buf, p);
bl.push_back(bp);
bp.zero();
client->ll_write(fh, off, size, bl.c_str());
+ } else {
+ client->ll_write(fh, off+size, 0, NULL);
}
} else if (strcmp(op, "ll_release") == 0) {
int64_t f = t.get_int();
}
}
}
- assert(off == len);
+ //assert(off == len); no, directories may shrink. add this back in when we properly truncate objects on write.
// take the loaded version?
// only if we are a fresh CDir* with no prior state.
so, we don't want wanted reductions to clobber mds's notion of wanted unless we're
sure the client has seen all the latest caps.
*/
- dout(-10) << "handle_client_file_caps ignoring wanted " << cap_string(m->get_wanted())
+ dout(10) << "handle_client_file_caps ignoring wanted " << cap_string(m->get_wanted())
<< " bc seq " << m->get_seq() << " < " << cap->get_last_seq() << endl;
} else {
cap->set_wanted(wanted);