return MIN(t, first);
}
-old_inode_t& CInode::cow_old_inode(snapid_t follows, inode_t *pi)
+old_inode_t& CInode::cow_old_inode(snapid_t follows, bool cow_head)
{
assert(follows >= first);
+ inode_t *pi = cow_head ? get_projected_inode() : get_previous_projected_inode();
+ map<string,bufferptr> *px = cow_head ? get_projected_xattrs() : get_previous_projected_xattrs();
+
old_inode_t &old = old_inodes[follows];
old.first = first;
old.inode = *pi;
- old.xattrs = *get_previous_projected_xattrs();
+ old.xattrs = *px;
+ dout(10) << " " << px->size() << " xattrs cowed, " << *px << dendl;
+
old.inode.trim_client_ranges(follows);
if (!(old.inode.rstat == old.inode.accounted_rstat))
first = follows+1;
- dout(10) << "cow_old_inode to [" << old.first << "," << follows << "] on "
+ dout(10) << "cow_old_inode " << (cow_head ? "head" : "previous_head" )
+ << " to [" << old.first << "," << follows << "] on "
<< *this << dendl;
return old;
{
snapid_t follows = find_snaprealm()->get_newest_seq();
if (first <= follows)
- cow_old_inode(follows, get_projected_inode());
+ cow_old_inode(follows, true);
}
void CInode::purge_stale_snap_data(const set<snapid_t>& snaps)
// xattr
i = pxattr ? pi:oi;
bool had_latest_xattrs = cap && (cap->issued() & CEPH_CAP_XATTR_SHARED) &&
- cap->client_xattr_version == i->xattr_version;
+ cap->client_xattr_version == i->xattr_version &&
+ snapid == CEPH_NOSNAP;
// xattr
bufferlist xbl;
e.xattr_version = i->xattr_version;
- if (!had_latest_xattrs && cap) {
+ if (!had_latest_xattrs) {
if (!pxattrs)
pxattrs = pxattr ? get_projected_xattrs() : &xattrs;
::encode(*pxattrs, xbl);
}
e.cap.flags = is_auth() ? CEPH_CAP_FLAG_AUTH:0;
dout(10) << "encode_inodestat caps " << ccap_string(e.cap.caps)
- << " seq " << e.cap.seq
- << " mseq " << e.cap.mseq << dendl;
+ << " seq " << e.cap.seq << " mseq " << e.cap.mseq
+ << " xattrv " << e.xattr_version << " len " << xbl.length()
+ << dendl;
// include those xattrs?
- if (xbl.length()) {
- if (cap && (cap->pending() & CEPH_CAP_XATTR_SHARED)) {
+ if (xbl.length() && cap) {
+ if (cap->pending() & CEPH_CAP_XATTR_SHARED) {
dout(10) << "including xattrs version " << i->xattr_version << dendl;
cap->client_xattr_version = i->xattr_version;
} else {
- xbl.clear(); // no xattrs
+ dout(10) << "dropping xattrs version " << i->xattr_version << dendl;
+ xbl.clear(); // no xattrs .. XXX what's this about?!?
}
}
void pop_projected_snaprealm(sr_t *next_snaprealm);
public:
- old_inode_t& cow_old_inode(snapid_t follows, inode_t *pi);
+ old_inode_t& cow_old_inode(snapid_t follows, bool cow_head);
old_inode_t *pick_old_inode(snapid_t last);
void pre_cow_old_inode();
void purge_stale_snap_data(const set<snapid_t>& snaps);
// normal metadata updates that we can apply to the head as well.
- // xattrs update?
+ // update xattrs?
+ bool xattrs = false;
map<string,bufferptr> *px = 0;
if ((dirty & CEPH_CAP_XATTR_EXCL) &&
m->xattrbl.length() &&
m->head.xattr_version > in->get_projected_inode()->xattr_version)
- px = new map<string,bufferptr>;
-
- inode_t *pi = in->project_inode(px);
- pi->version = in->pre_dirty();
+ xattrs = true;
+ old_inode_t *oi = 0;
if (in->is_multiversion()) {
- old_inode_t *oi = in->pick_old_inode(snap);
+ oi = in->pick_old_inode(snap);
if (oi) {
dout(10) << " writing into old inode" << dendl;
- pi = &oi->inode;
+ if (xattrs)
+ px = &oi->xattrs;
}
- }
+ }
+ if (xattrs && !px)
+ px = new map<string,bufferptr>;
+
+ inode_t *pi = in->project_inode(px);
+ pi->version = in->pre_dirty();
+ if (oi)
+ pi = &oi->inode;
_update_cap_fields(in, dirty, m, pi);
// xattr
if (px) {
- dout(7) << " xattrs v" << pi->xattr_version << " -> " << m->head.xattr_version << dendl;
+ dout(7) << " xattrs v" << pi->xattr_version << " -> " << m->head.xattr_version
+ << " len " << m->xattrbl.length() << dendl;
pi->xattr_version = m->head.xattr_version;
bufferlist::iterator p = m->xattrbl.begin();
::decode(*px, p);
return;
}
- in->cow_old_inode(follows, in->get_previous_projected_inode());
+ in->cow_old_inode(follows, false);
} else {
if (follows == CEPH_NOSNAP)
accounted_rstat = rstat;
- inode_t *pi_to_cow = cow_head ? pin->get_projected_inode() : pin->get_previous_projected_inode();
-
while (last >= ofirst) {
inode_t *pi;
snapid_t first;
pi = pin->get_projected_inode();
first = MAX(ofirst, pin->first);
if (first > pin->first) {
- old_inode_t& old = pin->cow_old_inode(first-1, pi_to_cow);
+ old_inode_t& old = pin->cow_old_inode(first-1, cow_head);
dout(20) << " cloned old_inode rstat is " << old.inode.rstat << dendl;
}
} else {
if (last >= pin->first) {
first = pin->first;
- pin->cow_old_inode(last, pi_to_cow);
+ pin->cow_old_inode(last, cow_head);
} else {
// our life is easier here because old_inodes is not sparse
// (although it may not begin at snapid 1)