void Client::update_inode_file_bits(Inode *in,
- __u64 size,
- utime_t ctime,
+ __u64 truncate_seq, __u64 size,
+ __u64 time_warp_seq, utime_t ctime,
utime_t mtime,
utime_t atime,
- int issued,
- __u64 time_warp_seq)
+ int issued)
{
bool warn = false;
+ if (truncate_seq > in->inode.truncate_seq ||
+ (truncate_seq == in->inode.truncate_seq && size > in->inode.size)) {
+ dout(10) << "size " << in->inode.size << " -> " << size << dendl;
+ in->inode.size = size;
+ in->reported_size = size;
+ }
+
// be careful with size, mtime, atime
if (issued & CEPH_CAP_EXCL) {
if (ctime > in->inode.ctime)
dout(0) << "WARNING: " << *in << " mds time_warp_seq "
<< time_warp_seq << " > " << in->inode.time_warp_seq << dendl;
} else if (issued & (CEPH_CAP_WR|CEPH_CAP_WRBUFFER)) {
- if (size > in->inode.size) {
- in->inode.size = size;
- in->reported_size = size;
- }
if (time_warp_seq > in->inode.time_warp_seq) {
in->inode.ctime = ctime;
in->inode.mtime = mtime;
} else
warn = true;
} else {
- in->inode.size = size;
- in->reported_size = size;
if (time_warp_seq >= in->inode.time_warp_seq) {
in->inode.ctime = ctime;
in->inode.mtime = mtime;
in->inode.ctime = st->ctime;
in->inode.max_size = st->max_size; // right?
- update_inode_file_bits(in, st->size, st->ctime, st->mtime, st->atime, in->caps_issued(), st->time_warp_seq);
+ update_inode_file_bits(in, st->truncate_seq, st->size,
+ st->time_warp_seq, st->ctime, st->mtime, st->atime,
+ in->caps_issued());
}
if (lease->mask &&
<< " was " << cap_string(old_caps) << dendl;
// size/ctime/mtime/atime
- update_inode_file_bits(in, m->get_size(), m->get_ctime(), m->get_mtime(), m->get_atime(), old_caps, m->get_time_warp_seq());
+ update_inode_file_bits(in, m->get_truncate_seq(), m->get_size(),
+ m->get_time_warp_seq(), m->get_ctime(), m->get_mtime(), m->get_atime(), old_caps);
// max_size
bool kick_writers = false;
void update_dir_dist(Inode *in, DirStat *st);
Inode* insert_trace(MClientReply *reply, utime_t ttl);
- void update_inode_file_bits(Inode *in, __u64 size, utime_t ctime, utime_t mtime, utime_t atime,
- int issued, __u64 time_warp_seq);
+ void update_inode_file_bits(Inode *in,
+ __u64 truncat_seq,__u64 size,
+ __u64 time_warp_seq, utime_t ctime, utime_t mtime, utime_t atime,
+ int issued);
void update_inode(Inode *in, InodeStat *st, LeaseStat *l, utime_t ttl);
Inode* insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dlease,
InodeStat *ist, LeaseStat *ilease,
__le64 time_warp_seq;
__le32 mode, uid, gid;
__le32 nlink;
- __le64 size, max_size;
+ __le64 size, max_size, truncate_seq;
__le64 files, subdirs, rbytes, rfiles, rsubdirs; /* dir stats */
struct ceph_timespec rctime;
__le32 rdev;
__le32 seq;
__le32 caps, wanted;
__le64 size, max_size;
+ __le64 truncate_seq;
__le32 migrate_seq;
struct ceph_timespec mtime, atime, ctime;
struct ceph_file_layout layout;
ceph_decode_timespec(&mtime, &grant->mtime);
ceph_decode_timespec(&atime, &grant->atime);
ceph_decode_timespec(&ctime, &grant->ctime);
- ceph_fill_file_bits(inode, issued, le64_to_cpu(grant->time_warp_seq),
- size, &ctime, &mtime, &atime);
+ ceph_fill_file_bits(inode, issued,
+ le64_to_cpu(grant->truncate_seq), size,
+ le64_to_cpu(grant->time_warp_seq), &ctime, &mtime,
+ &atime);
/* max size increase? */
if (max_size != ci->i_max_size) {
* depending on which capabilities/were help, and on the time_warp_seq
* (which we increment on utimes()).
*/
-void ceph_fill_file_bits(struct inode *inode, int issued, u64 time_warp_seq,
- u64 size, struct timespec *ctime,
+void ceph_fill_file_bits(struct inode *inode, int issued,
+ u64 truncate_seq, u64 size,
+ u64 time_warp_seq, struct timespec *ctime,
struct timespec *mtime, struct timespec *atime)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- u64 blocks = (size + (1<<9) - 1) >> 9;
int warn = 0;
+ if (truncate_seq > ci->i_truncate_seq ||
+ (truncate_seq == ci->i_truncate_seq && size > inode->i_size)) {
+ dout(10, "size %lld -> %llu\n", inode->i_size, size);
+ inode->i_size = size;
+ inode->i_blocks = (size + (1<<9) - 1) >> 9;
+ ci->i_reported_size = size;
+ ci->i_truncate_seq = truncate_seq;
+ }
+
if (issued & CEPH_CAP_EXCL) {
if (timespec_compare(ctime, &inode->i_ctime) > 0)
inode->i_ctime = *ctime;
derr(0, "WARNING: %p mds time_warp_seq %llu > %llu\n",
inode, time_warp_seq, ci->i_time_warp_seq);
} else if (issued & (CEPH_CAP_WR|CEPH_CAP_WRBUFFER)) {
- if (size > inode->i_size) {
- dout(10, "size %lld -> %llu\n", inode->i_size, size);
- inode->i_size = size;
- inode->i_blocks = blocks;
- ci->i_reported_size = size;
- }
if (time_warp_seq > ci->i_time_warp_seq) {
inode->i_ctime = *ctime;
inode->i_mtime = *mtime;
} else
warn = 1;
} else {
- inode->i_size = size;
- inode->i_blocks = blocks;
- ci->i_reported_size = size;
if (time_warp_seq >= ci->i_time_warp_seq) {
inode->i_ctime = *ctime;
inode->i_mtime = *mtime;
ceph_decode_timespec(&ctime, &info->ctime);
issued = __ceph_caps_issued(ci, 0);
- ceph_fill_file_bits(inode, issued, le64_to_cpu(info->time_warp_seq),
- size, &ctime, &mtime, &atime);
+ ceph_fill_file_bits(inode, issued,
+ le64_to_cpu(info->truncate_seq), size,
+ le64_to_cpu(info->time_warp_seq),
+ &ctime, &mtime, &atime);
inode->i_blkbits = blkbits;
dout(10, "alloc_inode %p vfsi %p\n", ci, &ci->vfs_inode);
ci->i_version = 0;
+ ci->i_truncate_seq = 0;
ci->i_time_warp_seq = 0;
ci->i_symlink = 0;
struct ceph_vino i_vino; /* ceph ino + snap */
u64 i_version;
- u64 i_time_warp_seq;
+ u64 i_truncate_seq, i_time_warp_seq;
struct ceph_file_layout i_layout;
char *i_symlink;
struct ceph_mds_reply_info_in *iinfo,
struct ceph_mds_reply_dirfrag *dirinfo);
extern void ceph_fill_file_bits(struct inode *inode, int issued,
- u64 time_warp_seq,
- u64 size, struct timespec *ctime,
+ u64 truncate_seq, u64 size,
+ u64 time_warp_seq, struct timespec *ctime,
struct timespec *mtime, struct timespec *atime);
extern int ceph_fill_trace(struct super_block *sb,
struct ceph_mds_request *req,
e.snapid = snapid ? (__u64)snapid:CEPH_NOSNAP; // 0 -> NOSNAP
e.version = i->version;
e.layout = i->layout;
+ e.size = i->size;
+ e.max_size = i->max_size;
+ e.truncate_seq = i->truncate_seq;
i->ctime.encode_timeval(&e.ctime);
i->mtime.encode_timeval(&e.mtime);
i->atime.encode_timeval(&e.atime);
e.uid = i->uid;
e.gid = i->gid;
e.nlink = i->nlink;
- e.size = i->size;
- e.max_size = i->max_size;
e.files = i->dirstat.nfiles;
e.subdirs = i->dirstat.nsubdirs;
pi->ctime = ctime;
pi->version = pdv;
pi->size = le64_to_cpu(req->head.args.truncate.length);
+ pi->truncate_seq++;
mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
mdcache->journal_dirty_inode(mdr, &le->metablob, cur);
pi->ctime = ctime;
pi->version = pdv;
pi->size = 0;
+ pi->truncate_seq++;
mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
mdcache->journal_dirty_inode(mdr, &le->metablob, cur);
ceph_file_layout layout;
uint64_t size; // on directory, # dentries
uint64_t max_size; // client(s) are auth to write this much...
+ uint64_t truncate_seq;
utime_t mtime; // file data modify time.
utime_t atime; // file data access time.
uint64_t time_warp_seq; // count of (potential) mtime/atime timewarps (i.e., utimes())
::encode(layout, bl);
::encode(size, bl);
::encode(max_size, bl);
+ ::encode(truncate_seq, bl);
::encode(mtime, bl);
::encode(atime, bl);
::encode(time_warp_seq, bl);
::decode(layout, p);
::decode(size, p);
::decode(max_size, p);
+ ::decode(truncate_seq, p);
::decode(mtime, p);
::decode(atime, p);
::decode(time_warp_seq, p);
__u64 get_size() { return head.size; }
__u64 get_max_size() { return head.max_size; }
+ __u64 get_truncate_seq() { return head.truncate_seq; }
utime_t get_ctime() { return utime_t(head.ctime); }
utime_t get_mtime() { return utime_t(head.mtime); }
utime_t get_atime() { return utime_t(head.atime); }
head.layout = inode.layout;
head.size = inode.size;
head.max_size = inode.max_size;
+ head.truncate_seq = inode.truncate_seq;
head.migrate_seq = mseq;
inode.mtime.encode_timeval(&head.mtime);
inode.atime.encode_timeval(&head.atime);
<< " caps " << cap_string(head.caps)
<< " wanted" << cap_string(head.wanted)
<< " size " << head.size << "/" << head.max_size
+ << " ts" << head.truncate_seq
<< " mtime " << utime_t(head.mtime)
<< " tws " << head.time_warp_seq
<< " follows " << snapid_t(head.snap_follows);
vinodeno_t vino;
version_t version;
ceph_file_layout layout;
- utime_t ctime, mtime, atime;
unsigned mode, uid, gid, nlink, rdev;
loff_t size, max_size;
+ version_t truncate_seq;
+ utime_t ctime, mtime, atime;
version_t time_warp_seq;
frag_info_t dirstat;
vino.snapid = snapid_t(e.snapid);
version = e.version;
layout = e.layout;
+ size = e.size;
+ max_size = e.max_size;
+ truncate_seq = e.truncate_seq;
ctime.decode_timeval(&e.ctime);
mtime.decode_timeval(&e.mtime);
atime.decode_timeval(&e.atime);
uid = e.uid;
gid = e.gid;
nlink = e.nlink;
- size = e.size;
- max_size = e.max_size;
rdev = e.rdev;
memset(&dirstat, 0, sizeof(dirstat));