]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: set time granularity; do utimes locally if holding EXCL
authorSage Weil <sage@newdream.net>
Thu, 27 Mar 2008 18:34:56 +0000 (11:34 -0700)
committerSage Weil <sage@newdream.net>
Thu, 27 Mar 2008 18:34:56 +0000 (11:34 -0700)
src/TODO
src/kernel/file.c
src/kernel/inode.c
src/kernel/super.c
src/kernel/super.h

index 2127ef236c5358ea5d73262493a036c704466990..3c923dd2b69464042cc951bc2789dff5123e25c8 100644 (file)
--- 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
index cb84e3f6e9080108baf61931f3e0616faddc77ca..3060b5781b0e2007a7e983a2c488a4c813edb5f8 100644 (file)
@@ -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);
        
index 07765941bc37ea058467c69fbc8cc38cdf738b77..9684a2e7db8a0e7a5a6b4eec738716314683df9a 100644 (file)
@@ -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);
index 54fe405eb2d248d35a53120147ebea6a98f63861..2420c5a478982f168c987538214dee26e435bbfd 100644 (file)
@@ -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;
index d19ce506e5ffc218aad3629de7293969309ad3c1..9d8dcbec169fb11c842318e0cbe71d2661e71857 100644 (file)
@@ -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;
 }