442
458
if (new_root) dout(10) << "setting this inode as root! " << *in << "; ino: " << root->ino << "; snapid" << root->snapid << dendl;
443
459
if (in->is_symlink())
444
460
in->symlink = st->symlink;
462
dout(12) << "add_update_inode adding " << *in << " caps " << ccap_string(st->cap.caps) << dendl;
447
dout(12) << "add_update_inode " << *in << " caps " << ccap_string(st->cap.caps) << dendl;
448
465
if (!st->cap.caps)
449
466
return in; // as with readdir returning indoes in different snaprealms (no caps!)
452
int issued = in->caps_issued(&implemented) | in->caps_dirty();
453
issued |= implemented;
468
// only update inode if mds info is strictly newer, or it is the same and projected (odd).
469
if (st->version == 0 ||
470
(in->version & ~1) < st->version) {
473
int issued = in->caps_issued(&implemented) | in->caps_dirty();
474
issued |= implemented;
476
in->version = st->version;
478
if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
484
if ((issued & CEPH_CAP_LINK_EXCL) == 0) {
485
in->nlink = st->nlink;
488
if ((issued & CEPH_CAP_XATTR_EXCL) == 0 &&
489
st->xattrbl.length() &&
490
st->xattr_version > in->xattr_version) {
491
bufferlist::iterator p = st->xattrbl.begin();
492
::decode(in->xattrs, p);
493
in->xattr_version = st->xattr_version;
496
in->dirstat = st->dirstat;
497
in->rstat = st->rstat;
500
in->dir_layout = st->dir_layout;
501
dout(20) << " dir hash is " << (int)in->dir_layout.dl_dir_hash << dendl;
504
in->layout = st->layout;
505
in->ctime = st->ctime;
506
in->max_size = st->max_size; // right?
508
update_inode_file_bits(in, st->truncate_seq, st->truncate_size, st->size,
509
st->time_warp_seq, st->ctime, st->mtime, st->atime,
513
(st->cap.caps & CEPH_CAP_FILE_SHARED) &&
514
(issued & CEPH_CAP_FILE_EXCL) == 0 &&
515
in->dirstat.nfiles == 0 &&
516
in->dirstat.nsubdirs == 0) {
517
dout(10) << " marking I_COMPLETE on empty dir " << *in << dendl;
518
in->flags |= I_COMPLETE;
520
dout(0) << "WARNING: dir is open on empty dir " << in->ino << " with "
521
<< in->dir->dentry_map.size() << " entries" << dendl;
522
in->dir->max_offset = 2;
524
// FIXME: tear down dir?
529
// move me if/when version reflects fragtree changes.
530
in->dirfragtree = st->dirfragtree;
455
532
if (in->snapid == CEPH_NOSNAP)
456
533
add_update_cap(in, mds, st->cap.cap_id, st->cap.caps, st->cap.seq, st->cap.mseq, inodeno_t(st->cap.realm), st->cap.flags);
458
535
in->snap_caps |= st->cap.caps;
460
in->dirfragtree = st->dirfragtree; // FIXME look at the mask!
462
if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
468
if ((issued & CEPH_CAP_LINK_EXCL) == 0) {
469
in->nlink = st->nlink;
472
if ((issued & CEPH_CAP_XATTR_EXCL) == 0 &&
473
st->xattrbl.length() &&
474
st->xattr_version > in->xattr_version) {
475
bufferlist::iterator p = st->xattrbl.begin();
476
::decode(in->xattrs, p);
477
in->xattr_version = st->xattr_version;
480
in->dirstat = st->dirstat;
481
in->rstat = st->rstat;
483
in->layout = st->layout;
484
in->ctime = st->ctime;
485
in->max_size = st->max_size; // right?
487
update_inode_file_bits(in, st->truncate_seq, st->truncate_size, st->size,
488
st->time_warp_seq, st->ctime, st->mtime, st->atime,
492
(st->cap.caps & CEPH_CAP_FILE_SHARED) &&
493
in->dirstat.nfiles == 0 &&
494
in->dirstat.nsubdirs == 0) {
495
dout(10) << " marking I_COMPLETE on empty dir " << *in << dendl;
496
in->flags |= I_COMPLETE;
744
840
if (g_conf.client_use_random_mds) goto random_mds;
746
842
if (req->inode) {
747
dir_inode = req->inode;
844
if (req->path.depth()) {
845
hash = ceph_str_hash(in->dir_layout.dl_dir_hash,
847
req->path[0].length());
848
dout(20) << " dir hash is " << (int)in->dir_layout.dl_dir_hash << " on " << req->path[0]
849
<< " => " << hash << dendl;
748
853
} else if (req->dentry) {
749
854
if (req->dentry->inode) {
750
dir_inode = req->dentry->inode;
855
in = req->dentry->inode;
752
dir_inode = req->dentry->dir->parent_inode;
753
hash = ceph_str_hash_linux(req->dentry->name.data(),
754
req->dentry->name.length());
857
in = req->dentry->dir->parent_inode;
858
hash = ceph_str_hash(in->dir_layout.dl_dir_hash,
859
req->dentry->name.data(),
860
req->dentry->name.length());
861
dout(20) << " dir hash is " << (int)in->dir_layout.dl_dir_hash << " on " << req->dentry->name
862
<< " => " << hash << dendl;
866
if (in && in->snapid != CEPH_NOSNAP) {
867
dout(10) << "choose_target_mds " << *in << " is snapped, using nonsnap parent" << dendl;
868
while (in->snapid != CEPH_NOSNAP) {
869
if (in->snapid == CEPH_SNAPDIR)
870
in = in->snapdir_parent;
872
in = in->dn->dir->parent_inode;
874
dout(10) << "got unlinked inode, can't look at parent" << dendl;
759
dout(20) << "choose_target_mds dir_inode" << dir_inode << " is_hash=" << is_hash
881
dout(20) << "choose_target_mds " << in << " is_hash=" << is_hash
760
882
<< " hash=" << hash << dendl;
762
if (!dir_inode) goto random_mds;
884
if (!in) goto random_mds;
764
if (is_hash && S_ISDIR(dir_inode->mode) && !dir_inode->dirfragtree.empty()) {
765
if (dir_inode->dirfragtree.contains(hash)) {
766
mds = dir_inode->fragmap[dir_inode->dirfragtree[hash].value()];
886
if (is_hash && S_ISDIR(in->mode) && !in->dirfragtree.empty()) {
887
if (in->dirfragtree.contains(hash)) {
888
mds = in->fragmap[in->dirfragtree[hash].value()];
767
889
dout(10) << "choose_target_mds from dirfragtree hash" << dendl;
772
894
if (req->auth_is_best())
773
cap = dir_inode->auth_cap;
774
if (!cap && !dir_inode->caps.empty())
775
cap = dir_inode->caps.begin()->second;
896
if (!cap && !in->caps.empty())
897
cap = in->caps.begin()->second;
778
900
mds = cap->session->mds_num;
3870
4073
// stuff dir contents to cache, DirResult
3873
// create empty result vector
3874
dirp->buffer[fg].clear();
3876
if (fg.is_leftmost()) {
3879
_readdir_add_dirent(dirp, dot, diri);
3880
string dotdot("..");
3882
_readdir_add_dirent(dirp, dotdot, diri->dn->dir->parent_inode);
3884
//_readdir_add_dirent(dirp, dotdot, DT_DIR);
3888
bufferlist::iterator p = dirbl.begin();
3896
::decode(complete, p);
3902
::decode(dlease, p);
3905
Inode *in = _ll_get_inode(ist.vino);
3906
dout(15) << "_readdir_get_frag got " << dname << " to " << in->ino << dendl;
3907
_readdir_add_dirent(dirp, dname, in);
4076
_readdir_drop_dirp_buffer(dirp);
4078
dirp->buffer = new vector<pair<string,Inode*> >;
4079
dirp->buffer->swap(req->readdir_result);
4080
dirp->buffer_frag = fg;
4082
dirp->this_offset = dirp->next_offset;
4083
dout(10) << "_readdir_get_frag " << dirp << " got frag " << dirp->buffer_frag
4084
<< " this_offset " << dirp->this_offset
4085
<< " size " << dirp->buffer->size() << dendl;
4087
if (req->readdir_end) {
4088
dirp->last_name.clear();
4089
if (fg.is_rightmost())
4090
dirp->next_offset = 2;
4092
dirp->next_offset = 0;
4094
dirp->last_name = req->readdir_last_name;
4095
dirp->next_offset += req->readdir_num;
4098
dout(10) << "_readdir_get_frag got error " << res << ", setting end flag" << dendl;
4105
int Client::_readdir_cache_cb(DirResult *dirp, add_dirent_cb_t cb, void *p)
4107
dout(10) << "_readdir_cache_cb " << dirp << " on " << dirp->inode->ino
4108
<< " at_cache_name " << dirp->at_cache_name << " offset " << hex << dirp->offset << dec
4110
Dir *dir = dirp->inode->dir;
4113
dout(10) << " dir is empty" << dendl;
4118
map<string,Dentry*>::iterator pd;
4119
if (dirp->at_cache_name.length()) {
4120
pd = dir->dentry_map.find(dirp->at_cache_name);
4121
if (pd == dir->dentry_map.end())
4122
return -EAGAIN; // weird, i give up
4125
pd = dir->dentry_map.begin();
4129
while (pd != dir->dentry_map.end()) {
4130
Dentry *dn = pd->second;
4131
if (dn->inode == NULL) {
4132
dout(15) << " skipping null '" << pd->first << "'" << dendl;
4139
int stmask = fill_stat(dn->inode, &st);
4140
fill_dirent(&de, pd->first.c_str(), st.st_mode, st.st_ino, dirp->offset + 1);
4142
uint64_t next_off = dn->offset + 1;
4144
if (pd == dir->dentry_map.end())
4145
next_off = DirResult::END;
4147
int r = cb(p, &de, &st, stmask, next_off); // _next_ offset
4148
dout(15) << " de " << de.d_name << " off " << hex << dn->offset << dec
4152
dirp->next_offset = dn->offset;
4153
dirp->at_cache_name = prev_name;
4157
prev_name = dn->name;
4158
dirp->offset = next_off;
4161
dout(10) << "_readdir_cache_cb " << dirp << " on " << dirp->inode->ino << " at end" << dendl;
4166
int Client::readdir_r_cb(DIR *d, add_dirent_cb_t cb, void *p)
4168
DirResult *dirp = (DirResult*)d;
4170
dout(10) << "readdir_r_cb " << *dirp->inode << " offset " << hex << dirp->offset << dec
4171
<< " frag " << dirp->frag() << " fragpos " << hex << dirp->fragpos() << dec
4172
<< " at_end=" << dirp->at_end()
4177
memset(&de, 0, sizeof(de));
4178
memset(&st, 0, sizeof(st));
4180
frag_t fg = dirp->frag();
4181
uint32_t off = dirp->fragpos();
4183
Inode *diri = dirp->inode;
4188
if (dirp->offset == 0) {
4189
dout(15) << " including ." << dendl;
4190
uint64_t next_off = diri->dn ? 1 : 2;
4192
fill_dirent(&de, ".", S_IFDIR, diri->ino, next_off);
4194
fill_stat(diri, &st);
4196
int r = cb(p, &de, &st, -1, next_off);
4200
dirp->offset = next_off;
4203
if (dirp->offset == 1) {
4204
dout(15) << " including .." << dendl;
4206
Inode *in = diri->dn->inode;
4207
fill_dirent(&de, "..", S_IFDIR, in->ino, 2);
4211
int r = cb(p, &de, &st, -1, 2);
4219
// can we read from our cache?
4220
dout(10) << "offset " << hex << dirp->offset << dec << " at_cache_name " << dirp->at_cache_name
4221
<< " snapid " << dirp->inode->snapid << " complete " << (bool)(dirp->inode->flags & I_COMPLETE)
4222
<< " issued " << ccap_string(dirp->inode->caps_issued())
4224
if ((dirp->offset == 2 || dirp->at_cache_name.length()) &&
4225
dirp->inode->snapid != CEPH_SNAPDIR &&
4226
(dirp->inode->flags & I_COMPLETE) &&
4227
dirp->inode->caps_issued_mask(CEPH_CAP_FILE_SHARED)) {
4228
int err = _readdir_cache_cb(dirp, cb, p);
4232
if (dirp->at_cache_name.length()) {
4233
dirp->last_name = dirp->at_cache_name;
4234
dirp->at_cache_name.clear();
4241
if (dirp->buffer_frag != dirp->frag() || dirp->buffer == NULL) {
4242
Mutex::Locker lock(client_lock);
4243
int r = _readdir_get_frag(dirp);
4246
fg = dirp->buffer_frag;
4249
dout(10) << "off " << off << " this_offset " << hex << dirp->this_offset << dec << " size " << dirp->buffer->size()
4250
<< " frag " << fg << dendl;
4251
while (off - dirp->this_offset >= 0 &&
4252
off - dirp->this_offset < dirp->buffer->size()) {
4253
uint64_t pos = DirResult::make_fpos(fg, off);
4254
pair<string,Inode*>& ent = (*dirp->buffer)[off - dirp->this_offset];
4256
int stmask = fill_stat(ent.second, &st);
4257
fill_dirent(&de, ent.first.c_str(), st.st_mode, st.st_ino, dirp->offset + 1);
4259
int r = cb(p, &de, &st, stmask, dirp->offset + 1); // _next_ offset
4260
dout(15) << " de " << de.d_name << " off " << hex << dirp->offset << dec
4267
dirp->offset = pos + 1;
4270
if (dirp->last_name.length()) {
4271
dout(10) << " fetching next chunk of this frag" << dendl;
4272
_readdir_drop_dirp_buffer(dirp);
4276
if (!fg.is_rightmost()) {
4280
dout(10) << " advancing to next frag: " << fg << " -> " << dirp->frag() << dendl;
3913
4285
if (diri->dir && diri->dir->release_count == dirp->release_count) {
3914
4286
dout(10) << " marking I_COMPLETE on " << *diri << dendl;
3915
4287
diri->flags |= I_COMPLETE;
4289
diri->dir->max_offset = dirp->offset;
3918
dout(10) << "_readdir_get_frag got error " << res << ", setting end flag" << dendl;
3919
4292
dirp->set_end();
3925
4302
int Client::readdir_r(DIR *d, struct dirent *de)
3927
4304
return readdirplus_r(d, de, 0, 0);
3932
4311
* 1 if we got a dirent
3933
4312
* 0 for end of directory
4316
struct single_readdir {
4323
static int _readdir_single_dirent_cb(void *p, struct dirent *de, struct stat *st, int stmask, off_t off)
4325
single_readdir *c = (single_readdir *)p;
4332
*c->stmask = stmask;
3936
4337
int Client::readdirplus_r(DIR *d, struct dirent *de, struct stat *st, int *stmask)
3938
DirResult *dirp = (DirResult*)d;
3940
dout(10) << "readdirplus_r " << *dirp->inode << " offset " << dirp->offset
3941
<< " frag " << dirp->frag() << " fragpos " << dirp->fragpos()
3942
<< " at_end=" << dirp->at_end()
3949
if (dirp->buffer.count(dirp->frag()) == 0) {
3950
Mutex::Locker lock(client_lock);
3951
_readdir_get_frag(dirp);
3956
frag_t fg = dirp->frag();
3957
uint32_t pos = dirp->fragpos();
3958
assert(dirp->buffer.count(fg));
3959
vector<DirEntry> &ent = dirp->buffer[fg];
3962
pos >= ent.size()) {
3963
dout(10) << "empty frag " << fg << ", moving on to next" << dendl;
3964
_readdir_next_frag(dirp);
3968
assert(pos < ent.size());
3969
_readdir_fill_dirent(de, &ent[pos], dirp->offset);
3973
*stmask = ent[pos].stmask;
3977
if (pos == ent.size())
3978
_readdir_next_frag(dirp);
4345
int r = readdir_r_cb(d, _readdir_single_dirent_cb, (void *)&sr);
4355
struct getdents_result {
4362
static int _readdir_getdent_cb(void *p, struct dirent *de, struct stat *st, int stmask, off_t off)
4364
struct getdents_result *c = (getdents_result *)p;
4370
dlen = strlen(de->d_name) + 1;
4372
if (c->pos + dlen > c->buflen)
4373
return -1; // doesn't fit
4376
memcpy(c->buf + c->pos, de, sizeof(*de));
4378
memcpy(c->buf + c->pos, de->d_name, dlen);
3985
4384
int Client::_getdents(DIR *dir, char *buf, int buflen, bool fullent)
3987
DirResult *dirp = (DirResult *)dir;
3994
if (dirp->buffer.count(dirp->frag()) == 0) {
3995
Mutex::Locker lock(client_lock);
3996
_readdir_get_frag(dirp);
4001
frag_t fg = dirp->frag();
4002
uint32_t pos = dirp->fragpos();
4003
assert(dirp->buffer.count(fg));
4004
vector<DirEntry> &ent = dirp->buffer[fg];
4007
dout(10) << "empty frag " << fg << ", moving on to next" << dendl;
4008
_readdir_next_frag(dirp);
4012
assert(pos < ent.size());
4015
int dlen = ent[pos].d_name.length();
4017
dlen += sizeof(struct dirent);
4019
dlen += 1; // null terminator
4020
if (ret + dlen > buflen) {
4022
return -ERANGE; // the buffer is too small for the first name!
4026
_readdir_fill_dirent((struct dirent *)(buf + ret), &ent[pos], dirp->offset);
4028
memcpy(buf + ret, ent[pos].d_name.c_str(), dlen);
4034
if (pos == ent.size())
4035
_readdir_next_frag(dirp);
4389
gr.fullent = fullent;
4392
int r = readdir_r_cb(dir, _readdir_getdent_cb, (void *)&gr);
4404
struct getdir_result {
4405
list<string> *contents;
4042
int Client::closedir(DIR *dir)
4409
static int _getdir_cb(void *p, struct dirent *de, struct stat *st, int stmask, off_t off)
4044
Mutex::Locker lock(client_lock);
4045
tout << "closedir" << std::endl;
4046
tout << (unsigned long)dir << std::endl;
4411
getdir_result *r = (getdir_result *)p;
4048
dout(3) << "closedir(" << dir << ") = 0" << dendl;
4049
_closedir((DirResult*)dir);
4413
r->contents->push_back(de->d_name);
4053
void Client::_closedir(DirResult *dirp)
4418
int Client::getdir(const char *relpath, list<string>& contents)
4055
dout(10) << "_closedir(" << dirp << ")" << dendl;
4057
dout(10) << "_closedir detaching inode " << dirp->inode << dendl;
4058
put_inode(dirp->inode);
4420
dout(3) << "getdir(" << relpath << ")" << dendl;
4422
Mutex::Locker lock(client_lock);
4423
tout << "getdir" << std::endl;
4424
tout << relpath << std::endl;
4064
void Client::rewinddir(DIR *dirp)
4066
dout(3) << "rewinddir(" << dirp << ")" << dendl;
4067
DirResult *d = (DirResult*)dirp;
4072
loff_t Client::telldir(DIR *dirp)
4074
DirResult *d = (DirResult*)dirp;
4075
dout(3) << "telldir(" << dirp << ") = " << d->offset << dendl;
4079
void Client::seekdir(DIR *dirp, loff_t offset)
4081
dout(3) << "seekdir(" << dirp << ", " << offset << ")" << dendl;
4082
DirResult *d = (DirResult*)dirp;
4428
int r = opendir(relpath, &d);
4433
gr.contents = &contents;
4435
r = readdir_r_cb(d, _getdir_cb, (void *)&gr);