]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: fix opens on snapped files
authorSage Weil <sage@newdream.net>
Fri, 3 Apr 2009 20:03:17 +0000 (13:03 -0700)
committerSage Weil <sage@newdream.net>
Fri, 3 Apr 2009 20:06:27 +0000 (13:06 -0700)
We just need to check i_snap_caps.  If we don't have what we want
(all of it), ask the MDS, who will do the locking necessary to get
data/metadata flushed and issue us the (immutable) caps we want.

src/kernel/file.c
src/kernel/inode.c

index 833d1a7eabbfd3a3245c63f7c33df2bdd72cf8f5..461d2c74ab52d517a73d61192380420adc114804 100644 (file)
@@ -101,7 +101,7 @@ int ceph_open(struct inode *inode, struct file *file)
        struct ceph_file_info *cf = file->private_data;
        struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
        int err;
-       int flags, fmode, new_want;
+       int flags, fmode, wanted;
 
        if (cf) {
                dout(5, "open file %p is already opened\n", file);
@@ -116,12 +116,14 @@ int ceph_open(struct inode *inode, struct file *file)
        dout(5, "open inode %p ino %llx.%llx file %p flags %d (%d)\n", inode,
             ceph_vinop(inode), file, flags, file->f_flags);
        fmode = ceph_flags_to_mode(flags);
-       new_want = ceph_caps_for_mode(fmode);
+       wanted = ceph_caps_for_mode(fmode);
 
-       /* trivially open snapped metadata */
-       if (ceph_snap(inode) != CEPH_NOSNAP) {
-               if (file->f_mode & FMODE_WRITE)
-                       return -EROFS;
+       /* snapped files are read-only */
+       if (ceph_snap(inode) != CEPH_NOSNAP && (file->f_mode & FMODE_WRITE))
+               return -EROFS;
+
+       /* trivially open snapdir */
+       if (ceph_snap(inode) == CEPH_SNAPDIR) {
                spin_lock(&inode->i_lock);
                __ceph_get_fmode(ci, fmode);
                spin_unlock(&inode->i_lock);
@@ -139,22 +141,27 @@ int ceph_open(struct inode *inode, struct file *file)
                int issued = __ceph_caps_issued(ci, NULL);
 
                dout(10, "open %p fmode %d want %s issued %s using existing\n",
-                    inode, fmode, ceph_cap_string(new_want),
+                    inode, fmode, ceph_cap_string(wanted),
                     ceph_cap_string(issued));
                __ceph_get_fmode(ci, fmode);
                spin_unlock(&inode->i_lock);
                
                /* adjust wanted? */
-               if ((issued & new_want) != new_want &&
-                   (mds_wanted & new_want) != new_want &&
+               if ((issued & wanted) != wanted &&
+                   (mds_wanted & wanted) != wanted &&
                    ceph_snap(inode) != CEPH_SNAPDIR)
                        ceph_check_caps(ci, 0, 0, NULL);
 
                return ceph_init_file(inode, file, fmode);
+       } else if (ceph_snap(inode) != CEPH_NOSNAP &&
+                  (ci->i_snap_caps & wanted) == wanted) {
+               __ceph_get_fmode(ci, fmode);
+               spin_unlock(&inode->i_lock);
+               return ceph_init_file(inode, file, fmode);
        }
        spin_unlock(&inode->i_lock);
 
-       dout(10, "open fmode %d wants %s\n", fmode, ceph_cap_string(new_want));
+       dout(10, "open fmode %d wants %s\n", fmode, ceph_cap_string(wanted));
        if (!ceph_caps_issued_mask(ceph_inode(inode), CEPH_CAP_FILE_EXCL))
                ceph_release_caps(inode, CEPH_CAP_FILE_RDCACHE);
        req = prepare_open_request(inode->i_sb, flags, 0);
index 3c386fe5d702af7929726e9e8abf06752b18015a..93fbd36a2e62472c8194bdab35cec78f13503db7 100644 (file)
@@ -581,6 +581,8 @@ no_change:
                                     caps_reservation);
                } else {
                        spin_lock(&inode->i_lock);
+                       dout(20, " %p got snap_caps %s\n", inode,
+                            ceph_cap_string(le32_to_cpu(info->cap.caps)));
                        ci->i_snap_caps |= le32_to_cpu(info->cap.caps);
                        if (cap_fmode >= 0)
                                __ceph_get_fmode(ci, cap_fmode);