From 5fe205fbba67ec66929921aeef6a4a976e692f1a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 27 Mar 2008 11:34:56 -0700 Subject: [PATCH] kclient: set time granularity; do utimes locally if holding EXCL --- src/TODO | 2 ++ src/kernel/file.c | 3 ++- src/kernel/inode.c | 49 ++++++++++++++++++++++++++++++++++------------ src/kernel/super.c | 3 +++ src/kernel/super.h | 7 ++++--- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/TODO b/src/TODO index 2127ef236c535..3c923dd2b6946 100644 --- a/src/TODO +++ b/src/TODO @@ -26,6 +26,8 @@ userspace client - reference count lease validations on path lookup? kernel client +- carry wrbuffer/rdcache caps until data is flushed + - this should make the utimes bit kick in - make sure link/unlink results reflected by inode/dentry cache (let fill_trace do it? invalidate? do actual update?) - procfs/debugfs - adjust granular debug levels too diff --git a/src/kernel/file.c b/src/kernel/file.c index cb84e3f6e9080..3060b5781b0e2 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -170,9 +170,10 @@ int ceph_release(struct inode *inode, struct file *file) mode = cf->mode; ci->i_nr_by_mode[mode]--; wanted = ceph_caps_wanted(ci); - dout(10, "released %p flags 0%o mode %d nr now %d. wanted %d was %d\n", + dout(10, "released %p flags 0%o mode %d nr now %d, wanted %d -> %d\n", file, file->f_flags, mode, ci->i_nr_by_mode[mode], wanted, ci->i_cap_wanted); + wanted |= ceph_caps_used(ci); if (wanted != ci->i_cap_wanted) ceph_mdsc_update_cap_wanted(ci, wanted); diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 07765941bc37e..9684a2e7db8a0 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -473,7 +473,7 @@ int ceph_handle_cap_grant(struct inode *inode, struct ceph_mds_file_caps *grant, int seq = le32_to_cpu(grant->seq); int newcaps; int used; - int wanted = ceph_caps_wanted(ci); + int wanted = ceph_caps_wanted(ci) | ceph_caps_used(ci); int ret = 0; u64 size = le64_to_cpu(grant->size); u64 max_size = le64_to_cpu(grant->max_size); @@ -605,16 +605,29 @@ int ceph_get_cap_refs(struct ceph_inode_info *ci, int need, int want, int *got) void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) { + int last = 0, wanted; + spin_lock(&ci->vfs_inode.i_lock); if (had & CEPH_CAP_RD) - ci->i_rd_ref--; + if (--ci->i_rd_ref == 0) + last++; if (had & CEPH_CAP_RDCACHE) - ci->i_rdcache_ref--; + if (--ci->i_rdcache_ref == 0) + last++; if (had & CEPH_CAP_WR) - ci->i_wr_ref--; + if (--ci->i_wr_ref == 0) + last++; if (had & CEPH_CAP_WRBUFFER) - ci->i_wrbuffer_ref--; + if (--ci->i_wrbuffer_ref) + last++; spin_unlock(&ci->vfs_inode.i_lock); + + if (last) { + wanted = ceph_caps_wanted(ci); + wanted |= ceph_caps_used(ci); + if (wanted != ci->i_cap_wanted) + ceph_mdsc_update_cap_wanted(ci, wanted); + } } @@ -638,17 +651,19 @@ const struct inode_operations ceph_symlink_iops = { /* * generics */ -struct ceph_mds_request *prepare_setattr(struct ceph_mds_client *mdsc, struct dentry *dentry, int op) +struct ceph_mds_request *prepare_setattr(struct ceph_mds_client *mdsc, + struct dentry *dentry, int op) { char *path; int pathlen; struct ceph_mds_request *req; + __u64 baseino = ceph_ino(dentry->d_inode->i_sb->s_root->d_inode); dout(5, "prepare_setattr dentry %p\n", dentry); path = ceph_build_dentry_path(dentry, &pathlen); if (IS_ERR(path)) return ERR_PTR(PTR_ERR(path)); - req = ceph_mdsc_create_request(mdsc, op, ceph_ino(dentry->d_inode->i_sb->s_root->d_inode), path, 0, 0); + req = ceph_mdsc_create_request(mdsc, op, baseino, path, 0, 0); kfree(path); return req; } @@ -670,9 +685,11 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) if (ia_valid & ATTR_GID) dout(10, "setattr: gid %d -> %d\n", inode->i_uid, attr->ia_uid); if (ia_valid & ATTR_MODE) - dout(10, "setattr: mode %d -> %d\n", inode->i_mode, attr->ia_mode); + dout(10, "setattr: mode %d -> %d\n", inode->i_mode, + attr->ia_mode); if (ia_valid & ATTR_SIZE) - dout(10, "setattr: size %lld -> %lld\n", inode->i_size, attr->ia_size); + dout(10, "setattr: size %lld -> %lld\n", inode->i_size, + attr->ia_size); if (ia_valid & ATTR_ATIME) dout(10, "setattr: atime %ld.%ld -> %ld.%ld\n", inode->i_atime.tv_sec, inode->i_atime.tv_nsec, @@ -720,9 +737,17 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) } /* utimes */ - /* FIXME: second resolution here is a hack to avoid setattr on open... :/ */ - if (((ia_valid & ATTR_ATIME) && inode->i_atime.tv_sec != attr->ia_atime.tv_sec) || - ((ia_valid & ATTR_MTIME) && inode->i_mtime.tv_sec != attr->ia_mtime.tv_sec)) { + if (((ia_valid & ATTR_ATIME) && + !timespec_equal(&inode->i_atime, &attr->ia_atime)) || + ((ia_valid & ATTR_MTIME) && + !timespec_equal(&inode->i_mtime, &attr->ia_mtime))) { + /* do i hold CAP_EXCL? */ + if (ceph_caps_issued(ci) & CEPH_CAP_EXCL) { + dout(10, "utime holding EXCL, doing nothing\n"); + inode->i_atime = attr->ia_atime; + inode->i_mtime = attr->ia_mtime; + return 0; + } req = prepare_setattr(mdsc, dentry, CEPH_MDS_OP_UTIME); if (IS_ERR(req)) return PTR_ERR(req); diff --git a/src/kernel/super.c b/src/kernel/super.c index 54fe405eb2d24..2420c5a478982 100644 --- a/src/kernel/super.c +++ b/src/kernel/super.c @@ -395,6 +395,9 @@ static int ceph_set_super(struct super_block *s, void *data) s->s_op = &ceph_sops; memcpy(&client->mount_args, args, sizeof(*args)); + /* set time granularity */ + s->s_time_gran = 1000; /* 1 us == 1000 ns */ + ret = set_anon_super(s, 0); /* what is the second arg for? */ if (ret != 0) goto bail; diff --git a/src/kernel/super.h b/src/kernel/super.h index d19ce506e5ffc..9d8dcbec169fb 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -151,7 +151,7 @@ struct ceph_inode_info { wait_queue_head_t i_cap_wq; int i_nr_by_mode[4]; - int i_cap_wanted; + int i_cap_wanted; /* what we've told the mds(s) */ loff_t i_max_size; /* size authorized by mds */ loff_t i_wr_size; /* largest offset we've written (+1) */ struct timespec i_wr_mtime; @@ -223,9 +223,10 @@ static inline int ceph_caps_wanted(struct ceph_inode_info *ci) want |= CEPH_CAP_RD|CEPH_CAP_RDCACHE; if (ci->i_nr_by_mode[2]) want |= CEPH_CAP_RD|CEPH_CAP_RDCACHE| - CEPH_CAP_WR|CEPH_CAP_WRBUFFER; + CEPH_CAP_WR|CEPH_CAP_WRBUFFER| + CEPH_CAP_EXCL; if (ci->i_nr_by_mode[3]) - want |= CEPH_CAP_WR|CEPH_CAP_WRBUFFER; + want |= CEPH_CAP_WR|CEPH_CAP_WRBUFFER|CEPH_CAP_EXCL; return want; } -- 2.39.5