- apply_truncate needs to truncate page cache, or something?
kernel client
+- somehow get a max_size bump if we lseek into a (sparse) file ...
- why is mds_client delayed work not working?
- file_data_version stuff!
- deal with CAP_RDCACHE properly: invalidate cache pages?
- trim expired leases so we don't indefinitely hold dcache/icache refs...
-- obey file_max
-- send mds a file_cap message when we approach the current file_max
- procfs/debugfs
- adjust granular debug levels too
- should we be using debugfs?
struct page *page, void *fsdata)
{
struct inode *inode = file->f_dentry->d_inode;
+ struct ceph_inode_info *ci = ceph_inode(inode);
unsigned from = pos & (PAGE_CACHE_SIZE - 1);
dout(10, "write_end file %p inode %p page %p %d~%d (%d)\n", file,
/* did file size increase? */
/* (no need for i_size_read(); we caller holds i_mutex */
- if (pos+copied > inode->i_size)
+ if (pos+copied > inode->i_size) {
i_size_write(inode, pos + copied);
+ if ((inode->i_size << 1) >= ci->i_max_size &&
+ (ci->i_reported_size << 1) < ci->i_max_size)
+ ceph_check_caps(ci, GFP_KERNEL);
+ }
if (!PageUptodate(page))
SetPageUptodate(page);
ci->i_old_atime = inode->i_atime;
ci->i_max_size = le64_to_cpu(info->max_size);
+ ci->i_reported_size = inode->i_size; /* reset */
inode->i_mapping->a_ops = &ceph_aops;
* examine currently used, wanted versus held caps.
* release, ack revoked caps to mds as appropriate.
*/
-void ceph_check_caps_wanted(struct ceph_inode_info *ci, gfp_t gfpmask)
+void ceph_check_caps(struct ceph_inode_info *ci, gfp_t gfpmask)
{
struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode);
struct ceph_mds_client *mdsc = &client->mdsc;
goto ack;
}
+ /* approaching file_max? */
+ if ((cap->issued & CEPH_CAP_WR) &&
+ (ci->vfs_inode.i_size << 1) >= ci->i_max_size &&
+ (ci->i_reported_size << 1) < ci->i_max_size) {
+ dout(10, "i_size approaching max_size\n");
+ ci->i_reported_size = ci->vfs_inode.i_size;
+ goto ack;
+ }
+
if ((cap->issued & ~wanted) == 0)
continue; /* nothing extra, all good */
spin_unlock(&ci->vfs_inode.i_lock);
if (last)
- ceph_check_caps_wanted(ci, GFP_KERNEL);
+ ceph_check_caps(ci, GFP_KERNEL);
}
void apply_truncate(struct inode *inode, loff_t size)
{
+ struct ceph_inode_info *ci = ceph_inode(inode);
+
spin_lock(&inode->i_lock);
dout(10, "apply_truncate %p size %lld -> %llu\n", inode,
inode->i_size, size);
inode->i_size = size;
+ ci->i_reported_size = size;
spin_unlock(&inode->i_lock);
/*
u64 size = le64_to_cpu(trunc->size);
dout(10, "handle_cap_trunc inode %p ci %p mds%d seq %d\n", inode, ci,
mds, seq);
-
apply_truncate(inode, size);
return 0;
}
last ? "last":"");
if (last)
- ceph_check_caps_wanted(ci, GFP_KERNEL);
+ ceph_check_caps(ci, GFP_KERNEL);
}
void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr)
last ? "last":"");
if (last)
- ceph_check_caps_wanted(ci, GFP_KERNEL);
+ ceph_check_caps(ci, GFP_KERNEL);
}
wait_queue_head_t i_cap_wq;
int i_nr_by_mode[4];
- int i_cap_wanted; /* what we've told the mds(s) */
- loff_t i_max_size; /* size authorized by mds */
+ loff_t i_max_size; /* size authorized by mds */
+ loff_t i_reported_size; /* size we're reported to mds(s) */
struct timespec i_old_atime;
/* held references to caps */
extern void ceph_take_cap_refs(struct ceph_inode_info *ci, int got);
extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had);
extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr);
-extern void ceph_check_caps_wanted(struct ceph_inode_info *ci, gfp_t gfpmask);
+extern void ceph_check_caps(struct ceph_inode_info *ci, gfp_t gfpmask);
extern void ceph_get_mode(struct ceph_inode_info *ci, int mode);
extern void ceph_put_mode(struct ceph_inode_info *ci, int mode);
inode_t *latest = in->get_projected_inode();
int64_t inc = in->get_layout_size_increment();
if (latest->size + inc > latest->max_size) {
- int64_t new_max = ROUND_UP_TO(latest->size + inc/2, inc);
+ int64_t new_max = latest->max_size ? (latest->max_size << 1):inc;
dout(10) << "increasing max_size " << latest->max_size << " -> " << new_max << dendl;
inode_t *pi = in->project_inode();
pi->max_size = 0;
} else if (increase_max) {
int64_t inc = in->get_layout_size_increment();
- int64_t new_max = ROUND_UP_TO(latest->size + inc, inc);
+ int64_t new_max = latest->max_size ? (latest->max_size << 1):inc;
dout(7) << " increasing max_size " << pi->max_size << " to " << new_max << dendl;
pi->max_size = new_max;
}
le->metablob.add_dir_context(in->get_parent_dir());
le->metablob.add_primary_dentry(in->parent, true, 0, pi);
LogSegment *ls = mds->mdlog->get_current_segment();
- mds->mdlog->submit_entry(le, new C_Locker_FileUpdate_finish(this, in, ls));
+ mds->mdlog->submit_entry(le, new C_Locker_FileUpdate_finish(this, in, ls, increase_max));
file_wrlock_start(&in->filelock); // wrlock for duration of journal
}
class MClientUnmount : public Message {
public:
MClientUnmount() : Message(CEPH_MSG_CLIENT_UNMOUNT) { }
- /*
- MClientUnmount(entity_inst_t i) :
- Message(CEPH_MSG_CLIENT_UNMOUNT),
- inst(i) { }
- */
-
+
const char *get_type_name() { return "client_unmount"; }
- void decode_payload() {
- //int off = 0;
- //::_decode(inst, payload, off);
- }
- void encode_payload() {
- //::_encode(inst, payload);
- }
+ void decode_payload() { }
+ void encode_payload() { }
};
#endif