if (ttl > in->ttl)
in->ttl = ttl;
- // or do we have newer size/mtime from writing?
- if (in->file_wr_size > in->inode.size)
- in->inode.size = in->file_wr_size;
- if (in->file_wr_mtime > in->inode.mtime)
- in->inode.mtime = in->file_wr_mtime;
-
// symlink?
if (in->inode.is_symlink()) {
if (!in->symlink)
if (g_conf.client_oc)
in->fc.truncate(in->inode.size, m->get_size());
- in->inode.size = in->file_wr_size = m->get_size();
+ in->inode.size = m->get_size();
delete m;
return;
}
<< " was " << cap_string(old_caps) << dendl;
// update inode
- in->inode.size = m->get_size(); // might have updated size... FIXME this is overkill!
- in->inode.mtime = m->get_mtime();
- in->inode.atime = m->get_atime();
-
- // preserve our (possibly newer) file size, mtime
- if (in->file_wr_size > in->inode.size) {
- in->inode.size = in->file_wr_size;
- m->set_size(in->file_wr_size);
- }
- if (in->file_wr_mtime > in->inode.mtime) {
- in->inode.mtime = in->file_wr_mtime;
- m->set_mtime(in->file_wr_mtime);
- }
-
+ if (m->get_size() > in->inode.size)
+ in->inode.size = m->get_size();
+ if (m->get_mtime() > in->inode.mtime && (old_caps & CEPH_CAP_EXCL) == 0)
+ in->inode.mtime = m->get_mtime();
+ if (m->get_atime() > in->inode.atime && (old_caps & CEPH_CAP_EXCL) == 0)
+ in->inode.atime = m->get_atime();
+
+ // share our (possibly newer) file size, mtime, atime
+ m->set_size(in->inode.size);
+ m->set_mtime(in->inode.mtime);
+ m->set_atime(in->inode.atime);
if (g_conf.client_oc) {
// caching on, use FileCache.
dout(5) << "implemented_caps " << cap_string(m->get_caps())
<< ", acking to " << m->get_source() << dendl;
- if (in->file_caps() == 0) {
- in->file_wr_mtime = utime_t();
- in->file_wr_size = 0;
- }
-
messenger->send_message(m, m->get_source_inst());
}
in->caps.clear();
put_inode(in);
}
-
- if (in->file_caps() == 0) {
- in->file_wr_mtime = utime_t();
- in->file_wr_size = 0;
- }
}
void Client::update_caps_wanted(Inode *in)
int Client::_unlink(const char *path)
{
-
MClientRequest *req = new MClientRequest(CEPH_MDS_OP_UNLINK, messenger->get_myinst());
req->set_path(path);
int Client::_utimes(const char *path, utime_t mtime, utime_t atime)
{
dout(3) << "_utimes(" << path << ", " << mtime << ", " << atime << ")" << dendl;
+
+ filepath fpath(path);
+ Dentry *dn = lookup(fpath);
+ int want = CEPH_CAP_WR|CEPH_CAP_WRBUFFER|CEPH_CAP_EXCL;
+ if (dn && dn->inode &&
+ (dn->inode->file_caps() & want) == want) {
+ dout(5) << " have WR and EXCL caps, just updating our m/atime" << dendl;
+ dn->inode->inode.mtime = mtime;
+ dn->inode->inode.atime = atime;
+ return 0;
+ }
+
MClientRequest *req = new MClientRequest(CEPH_MDS_OP_UTIME, messenger->get_myinst());
req->set_path(path);
mtime.encode_timeval(&req->head.args.utime.mtime);
bool lazy = f->mode == FILE_MODE_LAZY;
- dout(10) << "cur file size is " << in->inode.size << " wr size " << in->file_wr_size << dendl;
+ dout(10) << "cur file size is " << in->inode.size << dendl;
// time it.
utime_t start = g_clock.real_now();
// extend file?
if (totalwritten + offset > in->inode.size) {
- in->inode.size = in->file_wr_size = totalwritten + offset;
+ in->inode.size = totalwritten + offset;
dout(7) << "wrote to " << totalwritten+offset << ", extending file size" << dendl;
} else {
dout(7) << "wrote to " << totalwritten+offset << ", leaving file size at " << in->inode.size << dendl;
}
// mtime
- in->file_wr_mtime = in->inode.mtime = g_clock.real_now();
+ in->inode.mtime = g_clock.real_now();
// ok!
return totalwritten;
map<int,InodeCap> caps; // mds -> InodeCap
map<int,InodeCap> stale_caps; // mds -> cap .. stale
- utime_t file_wr_mtime; // [writers] time of last write
- off_t file_wr_size; // [writers] largest offset we've written to
int num_open_rd, num_open_wr, num_open_lazy; // num readers, writers
int ref; // ref count. 1 for each dentry, fh that links to me.
inode(_inode),
mask(0),
dir_auth(-1), dir_hashed(false), dir_replicated(false),
- file_wr_mtime(0, 0), file_wr_size(0),
num_open_rd(0), num_open_wr(0), num_open_lazy(0),
ref(0), ll_ref(0),
dir(0), dn(0), symlink(0),
}
int file_caps_wanted() {
- int w = 0;
+ int w = CEPH_CAP_EXCL; // always ask
if (num_open_rd) w |= CEPH_CAP_RD|CEPH_CAP_RDCACHE;
if (num_open_wr) w |= CEPH_CAP_WR|CEPH_CAP_WRBUFFER;
if (num_open_lazy) w |= CEPH_CAP_LAZYIO;
// atime|mtime|size?
bool had_or_has_wr = (had|has) & CEPH_CAP_WR;
- bool dirty = false;
- //if (atime > latest->atime)
- //dirty = true;
+ bool excl = (had|has) & CEPH_CAP_EXCL;
+ bool dirty_atime = false;
+ bool dirty_mtime = false;
+ bool dirty_size = false;
if (had_or_has_wr) {
- if (mtime > latest->mtime)
- dirty = true;
+ if (mtime > latest->mtime || (excl && mtime != latest->mtime))
+ dirty_mtime = true;
if (size > latest->size)
- dirty = true;
+ dirty_size = true;
}
+ if (excl && atime != latest->atime)
+ dirty_atime = true;
+ bool dirty = dirty_atime || dirty_mtime || dirty_size;
// increase max_size?
bool increase_max = false;
dout(7) << " increasing max_size " << pi->max_size << " to " << new_max << dendl;
pi->max_size = new_max;
}
- if (mtime > latest->mtime) {
- dout(7) << " taking mtime " << mtime << " > "
- << in->inode.mtime << " for " << *in << dendl;
+ if (dirty_mtime) {
+ dout(7) << " mtime " << pi->mtime << " -> " << mtime
+ << " for " << *in << dendl;
pi->mtime = mtime;
}
- if (size > latest->size) {
- dout(7) << " taking size " << size << " > "
- << in->inode.size << " for " << *in << dendl;
+ if (dirty_size) {
+ dout(7) << " size " << pi->size << " -> " << size
+ << " for " << *in << dendl;
pi->size = size;
}
- if (atime > latest->atime) {
- dout(7) << " taking atime " << atime << " > "
- << in->inode.atime << " for " << *in << dendl;
+ if (dirty_atime) {
+ dout(7) << " atime " << pi->atime << " -> " << atime
+ << " for " << *in << dendl;
pi->atime = atime;
}
le->metablob.add_dir_context(in->get_parent_dir());