Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ceph: size handling in MClientRequest, cap updates and inode traces

For encrypted inodes, transmit a rounded-up size to the MDS as the
normal file size and send the real inode size in fscrypt_file field.
Also, fix up creates and truncates to also transmit fscrypt_file.

When we get an inode trace from the MDS, grab the fscrypt_file field if
the inode is encrypted, and use it to populate the i_size field instead
of the regular inode size field.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-and-tested-by: Luís Henriques <lhenriques@suse.de>
Reviewed-by: Milind Changire <mchangir@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

authored by

Jeff Layton and committed by
Ilya Dryomov
16be62fc 14e034a6

+73 -25
+29 -21
fs/ceph/caps.c
··· 1217 1217 umode_t mode; 1218 1218 bool inline_data; 1219 1219 bool wake; 1220 + bool encrypted; 1220 1221 u32 fscrypt_auth_len; 1221 - u32 fscrypt_file_len; 1222 1222 u8 fscrypt_auth[sizeof(struct ceph_fscrypt_auth)]; // for context 1223 - u8 fscrypt_file[sizeof(u64)]; // for size 1224 1223 }; 1225 1224 1226 1225 /* Marshal up the cap msg to the MDS */ ··· 1254 1255 fc->ino = cpu_to_le64(arg->ino); 1255 1256 fc->snap_follows = cpu_to_le64(arg->follows); 1256 1257 1257 - fc->size = cpu_to_le64(arg->size); 1258 + #if IS_ENABLED(CONFIG_FS_ENCRYPTION) 1259 + if (arg->encrypted) 1260 + fc->size = cpu_to_le64(round_up(arg->size, 1261 + CEPH_FSCRYPT_BLOCK_SIZE)); 1262 + else 1263 + #endif 1264 + fc->size = cpu_to_le64(arg->size); 1258 1265 fc->max_size = cpu_to_le64(arg->max_size); 1259 1266 ceph_encode_timespec64(&fc->mtime, &arg->mtime); 1260 1267 ceph_encode_timespec64(&fc->atime, &arg->atime); ··· 1320 1315 ceph_encode_64(&p, 0); 1321 1316 1322 1317 #if IS_ENABLED(CONFIG_FS_ENCRYPTION) 1323 - /* fscrypt_auth and fscrypt_file (version 12) */ 1318 + /* 1319 + * fscrypt_auth and fscrypt_file (version 12) 1320 + * 1321 + * fscrypt_auth holds the crypto context (if any). fscrypt_file 1322 + * tracks the real i_size as an __le64 field (and we use a rounded-up 1323 + * i_size in the traditional size field). 1324 + */ 1324 1325 ceph_encode_32(&p, arg->fscrypt_auth_len); 1325 1326 ceph_encode_copy(&p, arg->fscrypt_auth, arg->fscrypt_auth_len); 1326 - ceph_encode_32(&p, arg->fscrypt_file_len); 1327 - ceph_encode_copy(&p, arg->fscrypt_file, arg->fscrypt_file_len); 1327 + ceph_encode_32(&p, sizeof(__le64)); 1328 + ceph_encode_64(&p, arg->size); 1328 1329 #else /* CONFIG_FS_ENCRYPTION */ 1329 1330 ceph_encode_32(&p, 0); 1330 1331 ceph_encode_32(&p, 0); ··· 1402 1391 arg->follows = flushing ? ci->i_head_snapc->seq : 0; 1403 1392 arg->flush_tid = flush_tid; 1404 1393 arg->oldest_flush_tid = oldest_flush_tid; 1405 - 1406 1394 arg->size = i_size_read(inode); 1407 1395 ci->i_reported_size = arg->size; 1408 1396 arg->max_size = ci->i_wanted_max_size; ··· 1455 1445 } 1456 1446 } 1457 1447 arg->flags = flags; 1448 + arg->encrypted = IS_ENCRYPTED(inode); 1458 1449 #if IS_ENABLED(CONFIG_FS_ENCRYPTION) 1459 1450 if (ci->fscrypt_auth_len && 1460 1451 WARN_ON_ONCE(ci->fscrypt_auth_len > sizeof(struct ceph_fscrypt_auth))) { ··· 1467 1456 min_t(size_t, ci->fscrypt_auth_len, 1468 1457 sizeof(arg->fscrypt_auth))); 1469 1458 } 1470 - /* FIXME: use this to track "real" size */ 1471 - arg->fscrypt_file_len = 0; 1472 1459 #endif /* CONFIG_FS_ENCRYPTION */ 1473 1460 } 1474 1461 1462 + #if IS_ENABLED(CONFIG_FS_ENCRYPTION) 1463 + #define CAP_MSG_FIXED_FIELDS (sizeof(struct ceph_mds_caps) + \ 1464 + 4 + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + 8 + 4 + 4 + 8) 1465 + 1466 + static inline int cap_msg_size(struct cap_msg_args *arg) 1467 + { 1468 + return CAP_MSG_FIXED_FIELDS + arg->fscrypt_auth_len; 1469 + } 1470 + #else 1475 1471 #define CAP_MSG_FIXED_FIELDS (sizeof(struct ceph_mds_caps) + \ 1476 1472 4 + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + 8 + 4 + 4) 1477 1473 1478 - #if IS_ENABLED(CONFIG_FS_ENCRYPTION) 1479 - static inline int cap_msg_size(struct cap_msg_args *arg) 1480 - { 1481 - return CAP_MSG_FIXED_FIELDS + arg->fscrypt_auth_len + 1482 - arg->fscrypt_file_len; 1483 - } 1484 - #else 1485 1474 static inline int cap_msg_size(struct cap_msg_args *arg) 1486 1475 { 1487 1476 return CAP_MSG_FIXED_FIELDS; ··· 1561 1550 arg.inline_data = capsnap->inline_data; 1562 1551 arg.flags = 0; 1563 1552 arg.wake = false; 1553 + arg.encrypted = IS_ENCRYPTED(inode); 1564 1554 1565 - /* 1566 - * No fscrypt_auth changes from a capsnap. It will need 1567 - * to update fscrypt_file on size changes (TODO). 1568 - */ 1555 + /* No fscrypt_auth changes from a capsnap.*/ 1569 1556 arg.fscrypt_auth_len = 0; 1570 - arg.fscrypt_file_len = 0; 1571 1557 1572 1558 msg = ceph_msg_new(CEPH_MSG_CLIENT_CAPS, cap_msg_size(&arg), 1573 1559 GFP_NOFS, false);
+3
fs/ceph/dir.c
··· 915 915 goto out_req; 916 916 } 917 917 918 + if (S_ISREG(mode) && IS_ENCRYPTED(dir)) 919 + set_bit(CEPH_MDS_R_FSCRYPT_FILE, &req->r_req_flags); 920 + 918 921 req->r_dentry = dget(dentry); 919 922 req->r_num_caps = 2; 920 923 req->r_parent = dir;
+1
fs/ceph/file.c
··· 790 790 req->r_parent = dir; 791 791 ihold(dir); 792 792 if (IS_ENCRYPTED(dir)) { 793 + set_bit(CEPH_MDS_R_FSCRYPT_FILE, &req->r_req_flags); 793 794 if (!fscrypt_has_encryption_key(dir)) { 794 795 spin_lock(&dentry->d_lock); 795 796 dentry->d_flags |= DCACHE_NOKEY_NAME;
+30 -3
fs/ceph/inode.c
··· 1028 1028 1029 1029 if (new_version || 1030 1030 (new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) { 1031 + u64 size = le64_to_cpu(info->size); 1031 1032 s64 old_pool = ci->i_layout.pool_id; 1032 1033 struct ceph_string *old_ns; 1033 1034 ··· 1042 1041 1043 1042 pool_ns = old_ns; 1044 1043 1044 + if (IS_ENCRYPTED(inode) && size && 1045 + iinfo->fscrypt_file_len == sizeof(__le64)) { 1046 + u64 fsize = __le64_to_cpu(*(__le64 *)iinfo->fscrypt_file); 1047 + 1048 + if (size == round_up(fsize, CEPH_FSCRYPT_BLOCK_SIZE)) { 1049 + size = fsize; 1050 + } else { 1051 + pr_warn("fscrypt size mismatch: size=%llu fscrypt_file=%llu, discarding fscrypt_file size.\n", 1052 + info->size, size); 1053 + } 1054 + } 1055 + 1045 1056 queue_trunc = ceph_fill_file_size(inode, issued, 1046 1057 le32_to_cpu(info->truncate_seq), 1047 1058 le64_to_cpu(info->truncate_size), 1048 - le64_to_cpu(info->size)); 1059 + size); 1049 1060 /* only update max_size on auth cap */ 1050 1061 if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) && 1051 1062 ci->i_max_size != le64_to_cpu(info->max_size)) { ··· 2401 2388 } 2402 2389 } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 || 2403 2390 attr->ia_size != isize) { 2404 - req->r_args.setattr.size = cpu_to_le64(attr->ia_size); 2405 - req->r_args.setattr.old_size = cpu_to_le64(isize); 2406 2391 mask |= CEPH_SETATTR_SIZE; 2407 2392 release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL | 2408 2393 CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR; 2394 + if (IS_ENCRYPTED(inode) && attr->ia_size) { 2395 + set_bit(CEPH_MDS_R_FSCRYPT_FILE, &req->r_req_flags); 2396 + mask |= CEPH_SETATTR_FSCRYPT_FILE; 2397 + req->r_args.setattr.size = 2398 + cpu_to_le64(round_up(attr->ia_size, 2399 + CEPH_FSCRYPT_BLOCK_SIZE)); 2400 + req->r_args.setattr.old_size = 2401 + cpu_to_le64(round_up(isize, 2402 + CEPH_FSCRYPT_BLOCK_SIZE)); 2403 + req->r_fscrypt_file = attr->ia_size; 2404 + /* FIXME: client must zero out any partial blocks! */ 2405 + } else { 2406 + req->r_args.setattr.size = cpu_to_le64(attr->ia_size); 2407 + req->r_args.setattr.old_size = cpu_to_le64(isize); 2408 + req->r_fscrypt_file = 0; 2409 + } 2409 2410 } 2410 2411 } 2411 2412 if (ia_valid & ATTR_MTIME) {
+8 -1
fs/ceph/mds_client.c
··· 2832 2832 } else { 2833 2833 ceph_encode_32(p, 0); 2834 2834 } 2835 - ceph_encode_32(p, 0); // fscrypt_file for now 2835 + if (test_bit(CEPH_MDS_R_FSCRYPT_FILE, &req->r_req_flags)) { 2836 + ceph_encode_32(p, sizeof(__le64)); 2837 + ceph_encode_64(p, req->r_fscrypt_file); 2838 + } else { 2839 + ceph_encode_32(p, 0); 2840 + } 2836 2841 } 2837 2842 2838 2843 /* ··· 2927 2922 2928 2923 /* fscrypt_file */ 2929 2924 len += sizeof(u32); 2925 + if (test_bit(CEPH_MDS_R_FSCRYPT_FILE, &req->r_req_flags)) 2926 + len += sizeof(__le64); 2930 2927 2931 2928 msg = ceph_msg_new2(CEPH_MSG_CLIENT_REQUEST, len, 1, GFP_NOFS, false); 2932 2929 if (!msg) {
+2
fs/ceph/mds_client.h
··· 282 282 #define CEPH_MDS_R_DID_PREPOPULATE (6) /* prepopulated readdir */ 283 283 #define CEPH_MDS_R_PARENT_LOCKED (7) /* is r_parent->i_rwsem wlocked? */ 284 284 #define CEPH_MDS_R_ASYNC (8) /* async request */ 285 + #define CEPH_MDS_R_FSCRYPT_FILE (9) /* must marshal fscrypt_file field */ 285 286 unsigned long r_req_flags; 286 287 287 288 struct mutex r_fill_mutex; ··· 290 289 union ceph_mds_request_args r_args; 291 290 292 291 struct ceph_fscrypt_auth *r_fscrypt_auth; 292 + u64 r_fscrypt_file; 293 293 294 294 u8 *r_altname; /* fscrypt binary crypttext for long filenames */ 295 295 u32 r_altname_len; /* length of r_altname */