out << " " << in.versionlock;
// hack: spit out crap on which clients have caps
- if (!in.get_client_caps().empty()) {
-
- if (in.inode.client_ranges.size())
- out << " cr=" << in.inode.client_ranges;
+ if (in.inode.client_ranges.size())
+ out << " cr=" << in.inode.client_ranges;
+ if (!in.get_client_caps().empty()) {
out << " caps={";
for (map<int,Capability*>::iterator it = in.get_client_caps().begin();
it != in.get_client_caps().end();
};
-bool Locker::check_inode_max_size(CInode *in, bool force_wrlock,
- bool update_size, __u64 new_size, utime_t new_mtime)
+void Locker::calc_new_client_ranges(CInode *in, __u64 size, map<int,byte_range_t>& new_ranges)
{
- assert(in->is_auth());
-
inode_t *latest = in->get_projected_inode();
- map<int,byte_range_t> new_ranges;
- __u64 size = latest->size;
- if (update_size)
- size = new_size;
- bool new_max = false;
// increase ranges as appropriate.
// shrink to 0 if no WR|BUFFER caps issued.
new_ranges[p->first].last = ROUND_UP_TO((size+1)<<1, latest->get_layout_size_increment());
}
}
+
+}
+
+bool Locker::check_inode_max_size(CInode *in, bool force_wrlock,
+ bool update_size, __u64 new_size, utime_t new_mtime)
+{
+ assert(in->is_auth());
+
+ inode_t *latest = in->get_projected_inode();
+ map<int,byte_range_t> new_ranges;
+ __u64 size = latest->size;
+ if (update_size)
+ size = new_size;
+ bool new_max = false;
+
+ calc_new_client_ranges(in, size, new_ranges);
+
if (latest->client_ranges != new_ranges)
new_max = true;
void file_update_finish(CInode *in, Mutation *mut, bool share, int client, Capability *cap,
MClientCaps *ack);
public:
+ void calc_new_client_ranges(CInode *in, __u64 size, map<int,byte_range_t>& new_ranges);
bool check_inode_max_size(CInode *in, bool force_wrlock=false, bool update_size=false, __u64 newsize=0,
utime_t mtime=utime_t());
-private:
void share_inode_max_size(CInode *in);
+private:
friend class C_MDL_CheckMaxSize;
friend class C_MDL_RequestInodeFileCaps;
friend class C_Locker_FileUpdate_finish;
p++) {
Capability *cap = in->get_client_cap(p->first);
if (!cap) {
+ dout(10) << " client" << p->first << " has range " << p->second << " but no cap on " << *in << dendl;
recover = true;
break;
}
MDS *mds;
MDRequest *mdr;
CInode *in;
- bool smaller;
+ bool smaller, changed_ranges;
public:
- C_MDS_inode_update_finish(MDS *m, MDRequest *r, CInode *i, bool sm=false) :
- mds(m), mdr(r), in(i), smaller(sm) { }
+ C_MDS_inode_update_finish(MDS *m, MDRequest *r, CInode *i, bool sm=false, bool cr=false) :
+ mds(m), mdr(r), in(i), smaller(sm), changed_ranges(cr) { }
void finish(int r) {
assert(r == 0);
mds->balancer->hit_inode(mdr->now, in, META_POP_IWR);
mds->server->reply_request(mdr, 0);
+
+ if (changed_ranges)
+ mds->locker->share_inode_max_size(in);
}
};
return;
}
+ bool changed_ranges = false;
+
// project update
mdr->ls = mdlog->get_current_segment();
EUpdate *le = new EUpdate(mdlog, "setattr");
pi->size = req->head.args.setattr.size;
}
pi->rstat.rbytes = pi->size;
+
+ // adjust client's max_size?
+ map<int,byte_range_t> new_ranges;
+ mds->locker->calc_new_client_ranges(cur, pi->size, new_ranges);
+ if (pi->client_ranges != new_ranges) {
+ dout(10) << " client_ranges " << pi->client_ranges << " -> " << new_ranges << dendl;
+ pi->client_ranges = new_ranges;
+ changed_ranges = true;
+ }
}
pi->version = cur->pre_dirty();
mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
mdcache->journal_dirty_inode(mdr, &le->metablob, cur);
- journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(mds, mdr, cur, smaller));
+ journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(mds, mdr, cur, smaller, changed_ranges));
// flush immediately if there are readers/writers waiting
if (cur->get_caps_wanted() & (CEPH_CAP_FILE_RD|CEPH_CAP_FILE_WR))