ceph: return EBADF if waiting for caps on closed file
authorSage Weil <sage@newdream.net>
Mon, 1 Mar 2010 17:57:54 +0000 (09:57 -0800)
committerSage Weil <sage@newdream.net>
Mon, 1 Mar 2010 23:28:00 +0000 (15:28 -0800)
Verify the file is actually open for the given caps when we are
waiting for caps.  This ensures we will wake up and return EBADF
if another thread closes the file out from under us.

Note that EBADF is also the correct return code from write(2)
when called on a file handle opened for reading (although the
vfs should catch that).

Signed-off-by: Sage Weil <sage@newdream.net>
fs/ceph/caps.c
fs/ceph/file.c

index 9afa8d37a6e307076dc104d0392a715426cc07f3..06f197983be686ac725758bb59e5aae4a6caa2b2 100644 (file)
@@ -1923,14 +1923,17 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
        struct inode *inode = &ci->vfs_inode;
        int ret = 0;
        int have, implemented;
+       int file_wanted;
 
        dout("get_cap_refs %p need %s want %s\n", inode,
             ceph_cap_string(need), ceph_cap_string(want));
        spin_lock(&inode->i_lock);
 
-       /* make sure we _have_ some caps! */
-       if (!__ceph_is_any_caps(ci)) {
-               dout("get_cap_refs %p no real caps\n", inode);
+       /* make sure file is actually open */
+       file_wanted = __ceph_caps_file_wanted(ci);
+       if ((file_wanted & need) == 0) {
+               dout("try_get_cap_refs need %s file_wanted %s, EBADF\n",
+                    ceph_cap_string(need), ceph_cap_string(file_wanted));
                *err = -EBADF;
                ret = 1;
                goto out;
index 88932c9145e9ab9d726515bd179984d114532716..5d2af8464f6aaceca8b6bdddda52e63b7f0279db 100644 (file)
@@ -262,6 +262,9 @@ int ceph_release(struct inode *inode, struct file *file)
        kfree(cf->dir_info);
        dput(cf->dentry);
        kmem_cache_free(ceph_file_cachep, cf);
+
+       /* wake up anyone waiting for caps on this inode */
+       wake_up(&ci->i_cap_wq);
        return 0;
 }