}
}
-void CInode::adjust_num_caps_notable(int d)
-{
- if (!num_caps_notable && d > 0)
- mdcache->open_file_table.add_inode(this);
- else if (num_caps_notable > 0 && num_caps_notable == -d)
- mdcache->open_file_table.remove_inode(this);
-
- num_caps_notable +=d;
- ceph_assert(num_caps_notable >= 0);
-}
-
Capability *CInode::add_client_cap(client_t client, Session *session,
SnapRealm *conrealm, bool new_inode)
{
return false;
}
+void CInode::adjust_num_caps_notable(int d)
+{
+ if (!is_clientwriteable()) {
+ if (!num_caps_notable && d > 0)
+ mdcache->open_file_table.add_inode(this);
+ else if (num_caps_notable > 0 && num_caps_notable == -d)
+ mdcache->open_file_table.remove_inode(this);
+ }
+
+ num_caps_notable +=d;
+ ceph_assert(num_caps_notable >= 0);
+}
+
+void CInode::mark_clientwriteable()
+{
+ if (last != CEPH_NOSNAP)
+ return;
+ if (!state_test(STATE_CLIENTWRITEABLE)) {
+ if (num_caps_notable == 0)
+ mdcache->open_file_table.add_inode(this);
+ state_set(STATE_CLIENTWRITEABLE);
+ }
+}
+
+void CInode::clear_clientwriteable()
+{
+ if (state_test(STATE_CLIENTWRITEABLE)) {
+ if (num_caps_notable == 0)
+ mdcache->open_file_table.remove_inode(this);
+ state_clear(STATE_CLIENTWRITEABLE);
+ }
+}
// =============================================
}
// max_size is min of projected, actual
- uint64_t max_size;
- {
- auto it = oi->client_ranges.find(client);
- if (it == oi->client_ranges.end()) {
- max_size = 0;
- } else {
- max_size = it->second.range.last;
- if (oi != pi) {
- it = pi->client_ranges.find(client);
- if (it == pi->client_ranges.end()) {
- max_size = 0;
- } else {
- max_size = std::min(max_size, it->second.range.last);
- }
- }
- }
- }
+ uint64_t max_size =
+ std::min(oi->get_client_range(client),
+ pi->get_client_range(client));
// inline data
version_t inline_version = 0;
}
// max_size is min of projected, actual.
- {
- uint64_t max_size;
- auto it = oi->client_ranges.find(client);
- if (it == oi->client_ranges.end()) {
- max_size = 0;
- } else {
- max_size = it->second.range.last;
- if (oi != pi) {
- it = pi->client_ranges.find(client);
- if (it == pi->client_ranges.end()) {
- max_size = 0;
- } else {
- max_size = std::min(max_size, it->second.range.last);
- }
- }
- }
- m->max_size = max_size;
- }
+ uint64_t oldms = oi->get_client_range(client);
+ uint64_t newms = pi->get_client_range(client);
+ m->max_size = std::min(oldms, newms);
i = pauth ? pi:oi;
m->head.mode = i->mode;
static const int STATE_DELAYEDEXPORTPIN = (1<<19);
static const int STATE_DISTEPHEMERALPIN = (1<<20);
static const int STATE_RANDEPHEMERALPIN = (1<<21);
+ static const int STATE_CLIENTWRITEABLE = (1<<22);
+
// orphan inode needs notification of releasing reference
static const int STATE_ORPHAN = STATE_NOTIFYREF;
int get_caps_wanted(int *ploner = 0, int *pother = 0, int shift = 0, int mask = -1) const;
bool issued_caps_need_gather(SimpleLock *lock);
+ // client writeable
+ bool is_clientwriteable() const { return state & STATE_CLIENTWRITEABLE; }
+ void mark_clientwriteable();
+ void clear_clientwriteable();
+
// -- authority --
mds_authority_t authority() const override;
it = pi->client_ranges.erase(it);
updated = true;
}
+ if (updated) {
+ if (pi->client_ranges.empty())
+ in->clear_clientwriteable();
+ else
+ in->mark_clientwriteable();
+ }
return updated;
}
// increase or zero max_size?
uint64_t size = m->get_size();
bool change_max = false;
- uint64_t old_max;
- {
- auto it = latest->client_ranges.find(client);
- old_max = it != latest->client_ranges.end() ? it->second.range.last: 0;
- }
+ uint64_t old_max = latest->get_client_range(client);
uint64_t new_max = old_max;
if (in->is_file()) {
cr.range.first = 0;
cr.range.last = new_max;
cr.follows = in->first - 1;
+ in->mark_clientwriteable();
if (cap)
cap->mark_clientwriteable();
} else {
pi.inode->client_ranges.erase(client);
+ if (pi.inode->client_ranges.empty())
+ in->clear_clientwriteable();
if (cap)
cap->clear_clientwriteable();
}
o->clear_scatter_dirty();
+ o->clear_clientwriteable();
+
o->item_open_file.remove_myself();
if (o->state_test(CInode::STATE_QUEUEDEXPORTPIN))
}
bool recover = false;
- for (auto& p : in->get_inode()->client_ranges) {
- Capability *cap = in->get_client_cap(p.first);
- if (cap) {
- cap->mark_clientwriteable();
- } else {
- dout(10) << " client." << p.first << " has range " << p.second << " but no cap on " << *in << dendl;
- recover = true;
- break;
+ const auto& client_ranges = in->get_projected_inode()->client_ranges;
+ if (!client_ranges.empty()) {
+ in->mark_clientwriteable();
+ for (auto& p : client_ranges) {
+ Capability *cap = in->get_client_cap(p.first);
+ if (cap) {
+ cap->mark_clientwriteable();
+ } else {
+ dout(10) << " client." << p.first << " has range " << p.second << " but no cap on " << *in << dendl;
+ recover = true;
+ break;
+ }
}
}
in->clear_dirty_parent();
+ in->clear_clientwriteable();
+
in->clear_file_locks();
// waiters
in->clear_dirty_parent();
+ in->clear_clientwriteable();
in->state_clear(CInode::STATE_NEEDSRECOVER);
in->authlock.clear_gather();
if (in->get_inode()->is_dirty_rstat())
in->mark_dirty_rstat();
+
+ if (!in->get_inode()->client_ranges.empty())
+ in->mark_clientwriteable();
// clear if dirtyscattered, since we're going to journal this
// but not until we _actually_ finish the import...
_inode->client_ranges[client].range.first = 0;
_inode->client_ranges[client].range.last = _inode->layout.stripe_unit;
_inode->client_ranges[client].follows = follows;
+ newi->mark_clientwriteable();
cap->mark_clientwriteable();
}
pi.inode->client_ranges[client].range.last = pi.inode->get_layout_size_increment();
pi.inode->client_ranges[client].follows = realm->get_newest_seq();
changed_ranges = true;
+ in->mark_clientwriteable();
cap->mark_clientwriteable();
}
_inode->client_ranges[client].range.first = 0;
_inode->client_ranges[client].range.last = _inode->layout.stripe_unit;
_inode->client_ranges[client].follows = follows;
+ newi->mark_clientwriteable();
cap->mark_clientwriteable();
}
}
pi.inode->truncate_size = 0;
pi.inode->truncate_from = 0;
pi.inode->version = in->pre_dirty();
+ pi.inode->client_ranges.clear();
+ in->clear_clientwriteable();
CDir *dir = dn->get_dir();
auto pf = dir->project_fnode(mut);
bool is_dirty_rstat() const { return !(rstat == accounted_rstat); }
+ uint64_t get_client_range(client_t client) const {
+ auto it = client_ranges.find(client);
+ return it != client_ranges.end() ? it->second.range.last : 0;
+ }
+
uint64_t get_max_size() const {
uint64_t max = 0;
for (std::map<client_t,client_writeable_range_t>::const_iterator p = client_ranges.begin();