- reference count lease validations on path lookup?
kernel client
-- truncate
- - do locally if EXCL
- - helper that is called when mds does a truncate
-- setattr should check lease before believing something is a no-op
-- trim expired leases so we don't indefinitely hold dcache refs...
+- trim expired leases so we don't indefinitely hold dcache/icache refs...
+- apply_truncate needs to truncate page cache, or something?
- procfs/debugfs
- adjust granular debug levels too
- should we be using debugfs?
- vfs
- can we use dentry_path(), if it gets merged into mainline?
- io / osd client
- - writepages should do io on more than 14 pages at a time!
- carry wrbuffer/rdcache caps until data is flushed
- this should make the utimes bit kick in
- invalidate cache pages?
- kick requests when new map arrives
- - sync?
- - sync on unmount?
- capability changes (flush.. need way to initiate/block on writeback initiated by mds)
- osd ack vs commit handling. hmm!
- mon client
return ret;
}
+void apply_truncate(struct inode *inode, loff_t size)
+{
+ spin_lock(&inode->i_lock);
+ dout(10, "apply_truncate %p size %lld -> %llu\n", inode,
+ inode->i_size, size);
+ inode->i_size = size;
+ spin_unlock(&inode->i_lock);
+
+ /*
+ * FIXME: how to truncate the page cache here?
+ */
+}
+
int ceph_handle_cap_trunc(struct inode *inode, struct ceph_mds_file_caps *trunc,
struct ceph_mds_session *session)
{
dout(10, "handle_cap_trunc inode %p ci %p mds%d seq %d\n", inode, ci,
mds, seq);
- spin_lock(&inode->i_lock);
- dout(10, "trunc size %lld -> %llu\n", inode->i_size, size);
- inode->i_size = size;
- spin_unlock(&inode->i_lock);
-
- /*
- * FIXME: how to truncate the page cache here?
- */
+ apply_truncate(inode, size);
return 0;
}
return req;
}
+
int ceph_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
/* utimes */
if (ia_valid & (ATTR_ATIME|ATTR_MTIME)) {
/* do i hold CAP_EXCL? */
- if (__ceph_caps_issued(ci) & CEPH_CAP_EXCL) {
+ if (ceph_caps_issued(ci) & CEPH_CAP_EXCL) {
dout(10, "utime holding EXCL, doing locally\n");
inode->i_atime = attr->ia_atime;
inode->i_mtime = attr->ia_mtime;
!(((ia_valid & ATTR_MTIME) &&
!timespec_equal(&inode->i_atime, &attr->ia_atime)) ||
((ia_valid & ATTR_MTIME) &&
- !timespec_equal(&inode->i_mtime, &attr->ia_mtime))))
- return 0; /* lease is valid, and this is a no-op */
+ !timespec_equal(&inode->i_mtime, &attr->ia_mtime)))) {
+ dout(10, "lease indicates utimes is a no-op\n");
+ return 0;
+ }
req = prepare_setattr(mdsc, dentry, CEPH_MDS_OP_UTIME);
if (IS_ERR(req))
return PTR_ERR(req);
}
/* truncate? */
- if (ia_valid & ATTR_SIZE &&
- attr->ia_size < inode->i_size) { /* fixme? */
+ if (ia_valid & ATTR_SIZE) {
+ if (ceph_caps_issued(ci) & CEPH_CAP_EXCL) {
+ dout(10, "holding EXCL, doing truncate locally\n");
+ apply_truncate(inode, attr->ia_size);
+ return 0;
+ }
dout(10, "truncate: ia_size %d i_size %d\n",
(int)attr->ia_size, (int)inode->i_size);
+ if (ceph_inode_lease_valid(inode, CEPH_LOCK_ICONTENT) &&
+ attr->ia_size < inode->i_size) {
+ dout(10, "lease indicates truncate is a no-op\n");
+ return 0;
+ }
if (ia_valid & ATTR_FILE)
req = ceph_mdsc_create_request(mdsc,
CEPH_MDS_OP_TRUNCATE,