ceph: initial CEPH_FEATURE_FS_FILE_LAYOUT_V2 support

Add support for the format change of MClientReply/MclientCaps.
Also add code that denies access to inodes with pool_ns layouts.

Signed-off-by: Yan, Zheng <zyan@redhat.com>
Reviewed-by: Sage Weil <sage@redhat.com>

authored by Yan, Zheng and committed by Ilya Dryomov 5ea5c5e0 fc77dbd3

Changed files
+49 -3
fs
include
linux
+4
fs/ceph/addr.c
··· 1756 1756 u32 pool; 1757 1757 int ret, flags; 1758 1758 1759 + /* does not support pool namespace yet */ 1760 + if (ci->i_pool_ns_len) 1761 + return -EIO; 1762 + 1759 1763 if (ceph_test_mount_opt(ceph_inode_to_client(&ci->vfs_inode), 1760 1764 NOPOOLPERM)) 1761 1765 return 0;
+24 -3
fs/ceph/caps.c
··· 2753 2753 void *inline_data, int inline_len, 2754 2754 struct ceph_buffer *xattr_buf, 2755 2755 struct ceph_mds_session *session, 2756 - struct ceph_cap *cap, int issued) 2756 + struct ceph_cap *cap, int issued, 2757 + u32 pool_ns_len) 2757 2758 __releases(ci->i_ceph_lock) 2758 2759 __releases(mdsc->snap_rwsem) 2759 2760 { ··· 2874 2873 if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) { 2875 2874 /* file layout may have changed */ 2876 2875 ci->i_layout = grant->layout; 2876 + ci->i_pool_ns_len = pool_ns_len; 2877 + 2877 2878 /* size/truncate_seq? */ 2878 2879 queue_trunc = ceph_fill_file_size(inode, issued, 2879 2880 le32_to_cpu(grant->truncate_seq), ··· 3414 3411 u32 inline_len = 0; 3415 3412 void *snaptrace; 3416 3413 size_t snaptrace_len; 3414 + u32 pool_ns_len = 0; 3417 3415 void *p, *end; 3418 3416 3419 3417 dout("handle_caps from mds%d\n", mds); ··· 3465 3461 goto bad; 3466 3462 inline_data = p; 3467 3463 p += inline_len; 3464 + } 3465 + 3466 + if (le16_to_cpu(msg->hdr.version) >= 8) { 3467 + u64 flush_tid; 3468 + u32 caller_uid, caller_gid; 3469 + u32 osd_epoch_barrier; 3470 + /* version >= 5 */ 3471 + ceph_decode_32_safe(&p, end, osd_epoch_barrier, bad); 3472 + /* version >= 6 */ 3473 + ceph_decode_64_safe(&p, end, flush_tid, bad); 3474 + /* version >= 7 */ 3475 + ceph_decode_32_safe(&p, end, caller_uid, bad); 3476 + ceph_decode_32_safe(&p, end, caller_gid, bad); 3477 + /* version >= 8 */ 3478 + ceph_decode_32_safe(&p, end, pool_ns_len, bad); 3468 3479 } 3469 3480 3470 3481 /* lookup ino */ ··· 3537 3518 &cap, &issued); 3538 3519 handle_cap_grant(mdsc, inode, h, 3539 3520 inline_version, inline_data, inline_len, 3540 - msg->middle, session, cap, issued); 3521 + msg->middle, session, cap, issued, 3522 + pool_ns_len); 3541 3523 if (realm) 3542 3524 ceph_put_snap_realm(mdsc, realm); 3543 3525 goto done_unlocked; ··· 3562 3542 issued |= __ceph_caps_dirty(ci); 3563 3543 handle_cap_grant(mdsc, inode, h, 3564 3544 inline_version, inline_data, inline_len, 3565 - msg->middle, session, cap, issued); 3545 + msg->middle, session, cap, issued, 3546 + pool_ns_len); 3566 3547 goto done_unlocked; 3567 3548 3568 3549 case CEPH_CAP_OP_FLUSH_ACK:
+2
fs/ceph/inode.c
··· 396 396 ci->i_symlink = NULL; 397 397 398 398 memset(&ci->i_dir_layout, 0, sizeof(ci->i_dir_layout)); 399 + ci->i_pool_ns_len = 0; 399 400 400 401 ci->i_fragtree = RB_ROOT; 401 402 mutex_init(&ci->i_fragtree_mutex); ··· 757 756 if (ci->i_layout.fl_pg_pool != info->layout.fl_pg_pool) 758 757 ci->i_ceph_flags &= ~CEPH_I_POOL_PERM; 759 758 ci->i_layout = info->layout; 759 + ci->i_pool_ns_len = iinfo->pool_ns_len; 760 760 761 761 queue_trunc = ceph_fill_file_size(inode, issued, 762 762 le32_to_cpu(info->truncate_seq),
+16
fs/ceph/mds_client.c
··· 100 100 } else 101 101 info->inline_version = CEPH_INLINE_NONE; 102 102 103 + if (features & CEPH_FEATURE_FS_FILE_LAYOUT_V2) { 104 + ceph_decode_32_safe(p, end, info->pool_ns_len, bad); 105 + ceph_decode_need(p, end, info->pool_ns_len, bad); 106 + *p += info->pool_ns_len; 107 + } else { 108 + info->pool_ns_len = 0; 109 + } 110 + 103 111 return 0; 104 112 bad: 105 113 return err; ··· 2305 2297 if (req->r_old_dentry_dir) 2306 2298 ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir), 2307 2299 CEPH_CAP_PIN); 2300 + 2301 + /* deny access to directories with pool_ns layouts */ 2302 + if (req->r_inode && S_ISDIR(req->r_inode->i_mode) && 2303 + ceph_inode(req->r_inode)->i_pool_ns_len) 2304 + return -EIO; 2305 + if (req->r_locked_dir && 2306 + ceph_inode(req->r_locked_dir)->i_pool_ns_len) 2307 + return -EIO; 2308 2308 2309 2309 /* issue */ 2310 2310 mutex_lock(&mdsc->mutex);
+1
fs/ceph/mds_client.h
··· 44 44 u64 inline_version; 45 45 u32 inline_len; 46 46 char *inline_data; 47 + u32 pool_ns_len; 47 48 }; 48 49 49 50 /*
+1
fs/ceph/super.h
··· 287 287 288 288 struct ceph_dir_layout i_dir_layout; 289 289 struct ceph_file_layout i_layout; 290 + size_t i_pool_ns_len; 290 291 char *i_symlink; 291 292 292 293 /* for dirs */
+1
include/linux/ceph/ceph_features.h
··· 75 75 #define CEPH_FEATURE_CRUSH_TUNABLES5 (1ULL<<58) /* chooseleaf stable mode */ 76 76 // duplicated since it was introduced at the same time as CEPH_FEATURE_CRUSH_TUNABLES5 77 77 #define CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING (1ULL<<58) /* New, v7 encoding */ 78 + #define CEPH_FEATURE_FS_FILE_LAYOUT_V2 (1ULL<<58) /* file_layout_t */ 78 79 79 80 /* 80 81 * The introduction of CEPH_FEATURE_OSD_SNAPMAPPER caused the feature