Merge tag 'pstore-v4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees...
[cascardo/linux.git] / fs / ceph / addr.c
index 26a9d10..d5b6f95 100644 (file)
@@ -1730,7 +1730,8 @@ enum {
        POOL_WRITE      = 2,
 };
 
-static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
+static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
+                               s64 pool, struct ceph_string *pool_ns)
 {
        struct ceph_fs_client *fsc = ceph_inode_to_client(&ci->vfs_inode);
        struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -1738,6 +1739,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
        struct rb_node **p, *parent;
        struct ceph_pool_perm *perm;
        struct page **pages;
+       size_t pool_ns_len;
        int err = 0, err2 = 0, have = 0;
 
        down_read(&mdsc->pool_perm_rwsem);
@@ -1749,17 +1751,31 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
                else if (pool > perm->pool)
                        p = &(*p)->rb_right;
                else {
-                       have = perm->perm;
-                       break;
+                       int ret = ceph_compare_string(pool_ns,
+                                               perm->pool_ns,
+                                               perm->pool_ns_len);
+                       if (ret < 0)
+                               p = &(*p)->rb_left;
+                       else if (ret > 0)
+                               p = &(*p)->rb_right;
+                       else {
+                               have = perm->perm;
+                               break;
+                       }
                }
        }
        up_read(&mdsc->pool_perm_rwsem);
        if (*p)
                goto out;
 
-       dout("__ceph_pool_perm_get pool %u no perm cached\n", pool);
+       if (pool_ns)
+               dout("__ceph_pool_perm_get pool %lld ns %.*s no perm cached\n",
+                    pool, (int)pool_ns->len, pool_ns->str);
+       else
+               dout("__ceph_pool_perm_get pool %lld no perm cached\n", pool);
 
        down_write(&mdsc->pool_perm_rwsem);
+       p = &mdsc->pool_perm_tree.rb_node;
        parent = NULL;
        while (*p) {
                parent = *p;
@@ -1769,8 +1785,17 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
                else if (pool > perm->pool)
                        p = &(*p)->rb_right;
                else {
-                       have = perm->perm;
-                       break;
+                       int ret = ceph_compare_string(pool_ns,
+                                               perm->pool_ns,
+                                               perm->pool_ns_len);
+                       if (ret < 0)
+                               p = &(*p)->rb_left;
+                       else if (ret > 0)
+                               p = &(*p)->rb_right;
+                       else {
+                               have = perm->perm;
+                               break;
+                       }
                }
        }
        if (*p) {
@@ -1788,6 +1813,8 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
        rd_req->r_flags = CEPH_OSD_FLAG_READ;
        osd_req_op_init(rd_req, 0, CEPH_OSD_OP_STAT, 0);
        rd_req->r_base_oloc.pool = pool;
+       if (pool_ns)
+               rd_req->r_base_oloc.pool_ns = ceph_get_string(pool_ns);
        ceph_oid_printf(&rd_req->r_base_oid, "%llx.00000000", ci->i_vino.ino);
 
        err = ceph_osdc_alloc_messages(rd_req, GFP_NOFS);
@@ -1841,7 +1868,8 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
                goto out_unlock;
        }
 
-       perm = kmalloc(sizeof(*perm), GFP_NOFS);
+       pool_ns_len = pool_ns ? pool_ns->len : 0;
+       perm = kmalloc(sizeof(*perm) + pool_ns_len + 1, GFP_NOFS);
        if (!perm) {
                err = -ENOMEM;
                goto out_unlock;
@@ -1849,6 +1877,11 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
 
        perm->pool = pool;
        perm->perm = have;
+       perm->pool_ns_len = pool_ns_len;
+       if (pool_ns_len > 0)
+               memcpy(perm->pool_ns, pool_ns->str, pool_ns_len);
+       perm->pool_ns[pool_ns_len] = 0;
+
        rb_link_node(&perm->node, parent, p);
        rb_insert_color(&perm->node, &mdsc->pool_perm_tree);
        err = 0;
@@ -1860,43 +1893,46 @@ out_unlock:
 out:
        if (!err)
                err = have;
-       dout("__ceph_pool_perm_get pool %u result = %d\n", pool, err);
+       if (pool_ns)
+               dout("__ceph_pool_perm_get pool %lld ns %.*s result = %d\n",
+                    pool, (int)pool_ns->len, pool_ns->str, err);
+       else
+               dout("__ceph_pool_perm_get pool %lld result = %d\n", pool, err);
        return err;
 }
 
 int ceph_pool_perm_check(struct ceph_inode_info *ci, int need)
 {
-       u32 pool;
+       s64 pool;
+       struct ceph_string *pool_ns;
        int ret, flags;
 
-       /* does not support pool namespace yet */
-       if (ci->i_pool_ns_len)
-               return -EIO;
-
        if (ceph_test_mount_opt(ceph_inode_to_client(&ci->vfs_inode),
                                NOPOOLPERM))
                return 0;
 
        spin_lock(&ci->i_ceph_lock);
        flags = ci->i_ceph_flags;
-       pool = ceph_file_layout_pg_pool(ci->i_layout);
+       pool = ci->i_layout.pool_id;
        spin_unlock(&ci->i_ceph_lock);
 check:
        if (flags & CEPH_I_POOL_PERM) {
                if ((need & CEPH_CAP_FILE_RD) && !(flags & CEPH_I_POOL_RD)) {
-                       dout("ceph_pool_perm_check pool %u no read perm\n",
+                       dout("ceph_pool_perm_check pool %lld no read perm\n",
                             pool);
                        return -EPERM;
                }
                if ((need & CEPH_CAP_FILE_WR) && !(flags & CEPH_I_POOL_WR)) {
-                       dout("ceph_pool_perm_check pool %u no write perm\n",
+                       dout("ceph_pool_perm_check pool %lld no write perm\n",
                             pool);
                        return -EPERM;
                }
                return 0;
        }
 
-       ret = __ceph_pool_perm_get(ci, pool);
+       pool_ns = ceph_try_get_string(ci->i_layout.pool_ns);
+       ret = __ceph_pool_perm_get(ci, pool, pool_ns);
+       ceph_put_string(pool_ns);
        if (ret < 0)
                return ret;
 
@@ -1907,10 +1943,11 @@ check:
                flags |= CEPH_I_POOL_WR;
 
        spin_lock(&ci->i_ceph_lock);
-       if (pool == ceph_file_layout_pg_pool(ci->i_layout)) {
-               ci->i_ceph_flags = flags;
+       if (pool == ci->i_layout.pool_id &&
+           pool_ns == rcu_dereference_raw(ci->i_layout.pool_ns)) {
+               ci->i_ceph_flags |= flags;
         } else {
-               pool = ceph_file_layout_pg_pool(ci->i_layout);
+               pool = ci->i_layout.pool_id;
                flags = ci->i_ceph_flags;
        }
        spin_unlock(&ci->i_ceph_lock);