History

Merge tag 'ceph-for-7.3-rc1' of https://github.com/ceph/ceph-client

Pull ceph updates from Ilya Dryomov: "A wide variety of mostly CephFS fixes and cleanups, split between changes that address edge cases (Sam, Xiubo, Matthew), efficiency improvements (Max) and AI-assisted hardening (Michael, Jeremy). One thing that stands out is Alex's change to how CephFS behaves in NEARFULL scenarios: the long-standing "make all writes synchronous" behavior has become opt-in. It was always somewhat controversial and doesn't make much sense for modern deployments; the new default is to continue normal operation (i.e. buffer writes as MDS allows, etc). The behavior in case the cluster reaches any FULL state remains the same as before" * tag 'ceph-for-7.3-rc1' of https://github.com/ceph/ceph-client: (32 commits) ceph: force a cap message when a deferred revoke can't be acked immediately libceph: reject buckets with mismatched CRUSH ids ceph: reject export_targets ranks >= CEPH_MAX_MDS in mdsmap decode ceph: fix leaked inode reference on writeback abort at umount libceph: remove ceph_put_page_vector() libceph: validate banner payload length ceph: make nearfull sync writes opt-in ceph: do not repeat ceph_trim_dentries() if no progress possible ceph: drop mdsc->mutex before decoding the MDS reply ceph: fix UAF in check_new_map() on session freed during unlock ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock ceph: pass inode pointer around instead of reloading it ceph: mark cap remove with RB_CLEAR_NODE() instead of setting ci=NULL ceph: add helper function ceph_cap_is_removed() ceph: make __ceph_remove_cap() static ceph: cap delegated inode count in ceph_parse_deleg_inos() ceph: bound num_export_targets array for mds info v2/v3 ceph: bound MDSCapAuth path and fs_name decode in handle_session() ceph: bound xattr value length in __build_xattrs() ceph: bound copied dentry name length in NFS export get_name ...

Linus Torvalds committed 2 months ago

Commit 548e7bc2 parents ce727a0 8fdf94620 files · +462 −131Browse files

Unified · Split

20 files
  1. Documentation/filesystems/ceph.rst +6 −0
  2. fs/ceph/addr.c +22 −8
  3. fs/ceph/caps.c +116 −50
  4. fs/ceph/crypto.c +37 −13
  5. fs/ceph/crypto.h +2 −2
  6. fs/ceph/dir.c +16 −6
  7. fs/ceph/export.c +17 −9
  8. fs/ceph/file.c +53 −3
  9. fs/ceph/inode.c +2 −1
  10. fs/ceph/mds_client.c +89 −21
  11. fs/ceph/mds_client.h +1 −0
  12. fs/ceph/mdsmap.c +10 −1
  13. fs/ceph/super.c +10 −0
  14. fs/ceph/super.h +43 −2
  15. fs/ceph/xattr.c +1 −0
  16. include/linux/ceph/libceph.h +0 −2
  17. net/ceph/messenger_v2.c +5 −0
  18. net/ceph/osd_client.c +30 −0
  19. net/ceph/osdmap.c +2 −0
  20. net/ceph/pagevec.c +0 −13
Documentation/filesystems/ceph.rst+6−0
@@ -194,6 +194,12 @@ Mount Options · 193 unmodified lines
194 copies. Currently, it's only used in copy_file_range, which will revert194 copies. Currently, it's only used in copy_file_range, which will revert
195 to the default VFS implementation if this option is used.195 to the default VFS implementation if this option is used.
196 196
197 nearfull_sync
198 Force written data to stable storage when the cluster or file data pool is
199 marked NEARFULL. This restores the legacy client-side backpressure
200 behavior. By default, CephFS writes are not forced synchronous solely
201 because of NEARFULL.
202
197 recover_session=<no|clean>203 recover_session=<no|clean>
198 Set auto reconnect mode in the case where the client is blocklisted. The204 Set auto reconnect mode in the case where the client is blocklisted. The
199 available modes are "no" and "clean". The default is "no".205 available modes are "no" and "clean". The default is "no".
fs/ceph/addr.c+22−8
@@ -255,9 +255,12 @@ static void finish_netfs_read(struct ceph_osd_request *req) · 254 unmodified lines
255 }255 }
256 256
257 if (osd_data->type == CEPH_OSD_DATA_TYPE_PAGES) {257 if (osd_data->type == CEPH_OSD_DATA_TYPE_PAGES) {
258 ceph_put_page_vector(osd_data->pages,258 int num_pages = calc_pages_for(osd_data->alignment,
259 calc_pages_for(osd_data->alignment,259 osd_data->length);
260 osd_data->length), false);260
261 for (int i = 0; i < num_pages; i++)
262 put_page(osd_data->pages[i]);
263 kvfree(osd_data->pages);
261 }264 }
262 if (err > 0) {265 if (err > 0) {
263 ceph_subvolume_metrics_record_io(fsc->mdsc, ceph_inode(inode),266 ceph_subvolume_metrics_record_io(fsc->mdsc, ceph_inode(inode),
@@ -1426,6 +1429,16 @@ void ceph_shift_unused_folios_left(struct folio_batch *fbatch) · 1162 unmodified lines
1426 fbatch->nr = n;1429 fbatch->nr = n;
1427}1430}
1428 1431
1432static void ceph_undo_wrbuffer_claim(struct inode *inode, struct folio *folio)
1433{
1434 struct ceph_snap_context *snapc = folio_detach_private(folio);
1435
1436 if (!snapc)
1437 return;
1438 ceph_put_wrbuffer_cap_refs(ceph_inode(inode), 1, snapc);
1439 ceph_put_snap_context(snapc);
1440}
1441
1429static1442static
1430int ceph_submit_write(struct address_space *mapping,1443int ceph_submit_write(struct address_space *mapping,
1431 struct writeback_control *wbc,1444 struct writeback_control *wbc,
@@ -1489,6 +1502,7 @@ new_request: · 57 unmodified lines
1489 if (!page)1502 if (!page)
1490 continue;1503 continue;
1491 1504
1505 ceph_undo_wrbuffer_claim(inode, page_folio(page));
1492 redirty_page_for_writepage(wbc, page);1506 redirty_page_for_writepage(wbc, page);
1493 unlock_page(page);1507 unlock_page(page);
1494 }1508 }
@@ -2464,7 +2478,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, · 969 unmodified lines
2464 }2478 }
2465 2479
2466 rd_req = ceph_osdc_alloc_request(&fsc->client->osdc, NULL,2480 rd_req = ceph_osdc_alloc_request(&fsc->client->osdc, NULL,
2467 1, false, GFP_NOFS);2481 1, false, GFP_KERNEL);
2468 if (!rd_req) {2482 if (!rd_req) {
2469 err = -ENOMEM;2483 err = -ENOMEM;
2470 goto out_unlock;2484 goto out_unlock;
@@ -2477,12 +2491,12 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, · 6 unmodified lines
2477 rd_req->r_base_oloc.pool_ns = ceph_get_string(pool_ns);2491 rd_req->r_base_oloc.pool_ns = ceph_get_string(pool_ns);
2478 ceph_oid_printf(&rd_req->r_base_oid, "%llx.00000000", ci->i_vino.ino);2492 ceph_oid_printf(&rd_req->r_base_oid, "%llx.00000000", ci->i_vino.ino);
2479 2493
2480 err = ceph_osdc_alloc_messages(rd_req, GFP_NOFS);2494 err = ceph_osdc_alloc_messages(rd_req, GFP_KERNEL);
2481 if (err)2495 if (err)
2482 goto out_unlock;2496 goto out_unlock;
2483 2497
2484 wr_req = ceph_osdc_alloc_request(&fsc->client->osdc, NULL,2498 wr_req = ceph_osdc_alloc_request(&fsc->client->osdc, NULL,
2485 1, false, GFP_NOFS);2499 1, false, GFP_KERNEL);
2486 if (!wr_req) {2500 if (!wr_req) {
2487 err = -ENOMEM;2501 err = -ENOMEM;
2488 goto out_unlock;2502 goto out_unlock;
@@ -2493,7 +2507,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, · 4 unmodified lines
2493 ceph_oloc_copy(&wr_req->r_base_oloc, &rd_req->r_base_oloc);2507 ceph_oloc_copy(&wr_req->r_base_oloc, &rd_req->r_base_oloc);
2494 ceph_oid_copy(&wr_req->r_base_oid, &rd_req->r_base_oid);2508 ceph_oid_copy(&wr_req->r_base_oid, &rd_req->r_base_oid);
2495 2509
2496 err = ceph_osdc_alloc_messages(wr_req, GFP_NOFS);2510 err = ceph_osdc_alloc_messages(wr_req, GFP_KERNEL);
2497 if (err)2511 if (err)
2498 goto out_unlock;2512 goto out_unlock;
2499 2513
@@ -2532,7 +2546,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, · 32 unmodified lines
2532 }2546 }
2533 2547
2534 pool_ns_len = pool_ns ? pool_ns->len : 0;2548 pool_ns_len = pool_ns ? pool_ns->len : 0;
2535 perm = kmalloc_flex(*perm, pool_ns, pool_ns_len + 1, GFP_NOFS);2549 perm = kmalloc_flex(*perm, pool_ns, pool_ns_len + 1, GFP_KERNEL);
2536 if (!perm) {2550 if (!perm) {
2537 err = -ENOMEM;2551 err = -ENOMEM;
2538 goto out_unlock;2552 goto out_unlock;
fs/ceph/caps.c+116−50
@@ -785,9 +785,9 @@ void ceph_add_cap(struct inode *inode, · 784 unmodified lines
785 * generation of the MDS session (i.e. has not gone 'stale' due to785 * generation of the MDS session (i.e. has not gone 'stale' due to
786 * us losing touch with the mds).786 * us losing touch with the mds).
787 */787 */
788static int __cap_is_valid(struct ceph_cap *cap)788static int __cap_is_valid(struct ceph_inode_info *ci, struct ceph_cap *cap)
789{789{
790 struct inode *inode = &cap->ci->netfs.inode;790 struct inode *inode = &ci->netfs.inode;
791 struct ceph_client *cl = cap->session->s_mdsc->fsc->client;791 struct ceph_client *cl = cap->session->s_mdsc->fsc->client;
792 unsigned long ttl;792 unsigned long ttl;
793 u32 gen;793 u32 gen;
@@ -822,7 +822,7 @@ int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented) · 28 unmodified lines
822 *implemented = 0;822 *implemented = 0;
823 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {823 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
824 cap = rb_entry(p, struct ceph_cap, ci_node);824 cap = rb_entry(p, struct ceph_cap, ci_node);
825 if (!__cap_is_valid(cap))825 if (!__cap_is_valid(ci, cap))
826 continue;826 continue;
827 doutc(cl, "%p %llx.%llx cap %p issued %s\n", inode,827 doutc(cl, "%p %llx.%llx cap %p issued %s\n", inode,
828 ceph_vinop(inode), cap, ceph_cap_string(cap->issued));828 ceph_vinop(inode), cap, ceph_cap_string(cap->issued));
@@ -855,7 +855,7 @@ int __ceph_caps_issued_other(struct ceph_inode_info *ci, struct ceph_cap *ocap) · 26 unmodified lines
855 cap = rb_entry(p, struct ceph_cap, ci_node);855 cap = rb_entry(p, struct ceph_cap, ci_node);
856 if (cap == ocap)856 if (cap == ocap)
857 continue;857 continue;
858 if (!__cap_is_valid(cap))858 if (!__cap_is_valid(ci, cap))
859 continue;859 continue;
860 have |= cap->issued;860 have |= cap->issued;
861 }861 }
@@ -866,11 +866,19 @@ int __ceph_caps_issued_other(struct ceph_inode_info *ci, struct ceph_cap *ocap) · 4 unmodified lines
866 * Move a cap to the end of the LRU (oldest caps at list head, newest866 * Move a cap to the end of the LRU (oldest caps at list head, newest
867 * at list tail).867 * at list tail).
868 */868 */
869static void __touch_cap(struct ceph_cap *cap)869static void __touch_cap(struct ceph_inode_info *ci, struct ceph_cap *cap)
870{870{
871 struct inode *inode = &cap->ci->netfs.inode;871 struct inode *inode = &ci->netfs.inode;
872 struct ceph_mds_session *s = cap->session;872 struct ceph_mds_session *s = cap->session;
873 struct ceph_client *cl = s->s_mdsc->fsc->client;873 struct ceph_client *cl = s->s_mdsc->fsc->client;
874 static u8 skip_counter;
875
876 if (data_race(++skip_counter))
877 /* skip this call most of the time to reduce lock
878 * contention; the LRU list is still accurate enough
879 * for ceph_trim_caps()
880 */
881 return;
874 882
875 spin_lock(&s->s_cap_lock);883 spin_lock(&s->s_cap_lock);
876 if (!s->s_cap_iterator) {884 if (!s->s_cap_iterator) {
@@ -906,7 +914,7 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) · 29 unmodified lines
906 914
907 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {915 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
908 cap = rb_entry(p, struct ceph_cap, ci_node);916 cap = rb_entry(p, struct ceph_cap, ci_node);
909 if (!__cap_is_valid(cap))917 if (!__cap_is_valid(ci, cap))
910 continue;918 continue;
911 if ((cap->issued & mask) == mask) {919 if ((cap->issued & mask) == mask) {
912 doutc(cl, "mask %p %llx.%llx cap %p issued %s (mask %s)\n",920 doutc(cl, "mask %p %llx.%llx cap %p issued %s (mask %s)\n",
@@ -914,7 +922,7 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) · 1 unmodified line
914 ceph_cap_string(cap->issued),922 ceph_cap_string(cap->issued),
915 ceph_cap_string(mask));923 ceph_cap_string(mask));
916 if (touch)924 if (touch)
917 __touch_cap(cap);925 __touch_cap(ci, cap);
918 return 1;926 return 1;
919 }927 }
920 928
@@ -929,15 +937,15 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) · 8 unmodified lines
929 struct rb_node *q;937 struct rb_node *q;
930 938
931 /* touch this + preceding caps */939 /* touch this + preceding caps */
932 __touch_cap(cap);940 __touch_cap(ci, cap);
933 for (q = rb_first(&ci->i_caps); q != p;941 for (q = rb_first(&ci->i_caps); q != p;
934 q = rb_next(q)) {942 q = rb_next(q)) {
935 cap = rb_entry(q, struct ceph_cap,943 cap = rb_entry(q, struct ceph_cap,
936 ci_node);944 ci_node);
937 if (!__cap_is_valid(cap))945 if (!__cap_is_valid(ci, cap))
938 continue;946 continue;
939 if (cap->issued & mask)947 if (cap->issued & mask)
940 __touch_cap(cap);948 __touch_cap(ci, cap);
941 }949 }
942 }950 }
943 return 1;951 return 1;
@@ -979,6 +987,27 @@ int __ceph_caps_revoking_other(struct ceph_inode_info *ci, · 35 unmodified lines
979 return 0;987 return 0;
980}988}
981 989
990/*
991 * Return true if any cap of this inode holds caps which the MDS has
992 * revoked, but which we have not released yet.
993 */
994static bool __ceph_is_any_revoking(const struct ceph_inode_info *ci)
995{
996 const struct rb_node *p;
997
998 lockdep_assert_held(&ci->i_ceph_lock);
999
1000 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
1001 const struct ceph_cap *cap =
1002 rb_entry(p, struct ceph_cap, ci_node);
1003
1004 if (cap->implemented & ~cap->issued)
1005 return true;
1006 }
1007
1008 return false;
1009}
1010
982int __ceph_caps_used(struct ceph_inode_info *ci)1011int __ceph_caps_used(struct ceph_inode_info *ci)
983{1012{
984 int used = 0;1013 int used = 0;
@@ -1091,7 +1120,7 @@ int __ceph_caps_mds_wanted(struct ceph_inode_info *ci, bool check) · 106 unmodified lines
1091 1120
1092 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {1121 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
1093 cap = rb_entry(p, struct ceph_cap, ci_node);1122 cap = rb_entry(p, struct ceph_cap, ci_node);
1094 if (check && !__cap_is_valid(cap))1123 if (check && !__cap_is_valid(ci, cap))
1095 continue;1124 continue;
1096 if (cap == ci->i_auth_cap)1125 if (cap == ci->i_auth_cap)
1097 mds_wanted |= cap->mds_wanted;1126 mds_wanted |= cap->mds_wanted;
@@ -1119,20 +1148,20 @@ int ceph_is_any_caps(struct inode *inode) · 21 unmodified lines
1119 * caller should hold i_ceph_lock.1148 * caller should hold i_ceph_lock.
1120 * caller will not hold session s_mutex if called from destroy_inode.1149 * caller will not hold session s_mutex if called from destroy_inode.
1121 */1150 */
1122void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)1151static void __ceph_remove_cap(struct ceph_inode_info *ci, struct ceph_cap *cap, bool queue_release)
1123{1152{
1124 struct ceph_mds_session *session = cap->session;1153 struct ceph_mds_session *session;
1125 struct ceph_client *cl = session->s_mdsc->fsc->client;1154 struct ceph_client *cl;
1126 struct ceph_inode_info *ci = cap->ci;1155 struct inode *inode;
1127 struct inode *inode = &ci->netfs.inode;
1128 struct ceph_mds_client *mdsc;1156 struct ceph_mds_client *mdsc;
1129 int removed = 0;1157 int removed = 0;
1130 1158
1131 /* 'ci' being NULL means the remove have already occurred */1159 if (ceph_cap_is_removed(cap))
1132 if (!ci) {
1133 doutc(cl, "inode is NULL\n");
1134 return;1160 return;
1135 }1161
1162 session = cap->session;
1163 cl = session->s_mdsc->fsc->client;
1164 inode = &ci->netfs.inode;
1136 1165
1137 lockdep_assert_held(&ci->i_ceph_lock);1166 lockdep_assert_held(&ci->i_ceph_lock);
1138 1167
@@ -1158,8 +1187,11 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release) · 19 unmodified lines
1158 cap->session = NULL;1187 cap->session = NULL;
1159 removed = 1;1188 removed = 1;
1160 }1189 }
1161 /* protect backpointer with s_cap_lock: see iterate_session_caps */1190
1162 cap->ci = NULL;1191 /* protect removal marker with both i_ceph_lock and
1192 s_cap_lock, so either one can be used to check for
1193 removal */
1194 RB_CLEAR_NODE(&cap->ci_node);
1163 1195
1164 /*1196 /*
1165 * s_cap_reconnect is protected by s_cap_lock. no one changes1197 * s_cap_reconnect is protected by s_cap_lock. no one changes
@@ -1196,13 +1228,12 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release) · 30 unmodified lines
1196}1228}
1197 1229
1198void ceph_remove_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,1230void ceph_remove_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
1231 struct ceph_inode_info *ci,
1199 bool queue_release)1232 bool queue_release)
1200{1233{
1201 struct ceph_inode_info *ci = cap->ci;
1202 struct ceph_fs_client *fsc;1234 struct ceph_fs_client *fsc;
1203 1235
1204 /* 'ci' being NULL means the remove have already occurred */1236 if (ceph_cap_is_removed(cap)) {
1205 if (!ci) {
1206 doutc(mdsc->fsc->client, "inode is NULL\n");1237 doutc(mdsc->fsc->client, "inode is NULL\n");
1207 return;1238 return;
1208 }1239 }
@@ -1215,7 +1246,7 @@ void ceph_remove_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, · 6 unmodified lines
1215 !fsc->blocklisted &&1246 !fsc->blocklisted &&
1216 !ceph_inode_is_shutdown(&ci->netfs.inode));1247 !ceph_inode_is_shutdown(&ci->netfs.inode));
1217 1248
1218 __ceph_remove_cap(cap, queue_release);1249 __ceph_remove_cap(ci, cap, queue_release);
1219}1250}
1220 1251
1221struct cap_msg_args {1252struct cap_msg_args {
@@ -1375,7 +1406,7 @@ void __ceph_remove_caps(struct ceph_inode_info *ci) · 153 unmodified lines
1375 while (p) {1406 while (p) {
1376 struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);1407 struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
1377 p = rb_next(p);1408 p = rb_next(p);
1378 ceph_remove_cap(mdsc, cap, true);1409 ceph_remove_cap(mdsc, cap, ci, true);
1379 }1410 }
1380 spin_unlock(&ci->i_ceph_lock);1411 spin_unlock(&ci->i_ceph_lock);
1381}1412}
@@ -1388,11 +1419,11 @@ void __ceph_remove_caps(struct ceph_inode_info *ci) · 6 unmodified lines
1388 * Make note of max_size reported/requested from mds, revoked caps1419 * Make note of max_size reported/requested from mds, revoked caps
1389 * that have now been implemented.1420 * that have now been implemented.
1390 */1421 */
1391static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,1422static void __prep_cap(struct cap_msg_args *arg, struct ceph_inode_info *ci,
1423 struct ceph_cap *cap,
1392 int op, int flags, int used, int want, int retain,1424 int op, int flags, int used, int want, int retain,
1393 int flushing, u64 flush_tid, u64 oldest_flush_tid)1425 int flushing, u64 flush_tid, u64 oldest_flush_tid)
1394{1426{
1395 struct ceph_inode_info *ci = cap->ci;
1396 struct inode *inode = &ci->netfs.inode;1427 struct inode *inode = &ci->netfs.inode;
1397 struct ceph_client *cl = ceph_inode_to_client(inode);1428 struct ceph_client *cl = ceph_inode_to_client(inode);
1398 int held, revoking;1429 int held, revoking;
@@ -1421,6 +1452,9 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap, · 22 unmodified lines
1421 cap->implemented &= cap->issued | used;1452 cap->implemented &= cap->issued | used;
1422 cap->mds_wanted = want;1453 cap->mds_wanted = want;
1423 1454
1455 if ((ci->i_ceph_flags & CEPH_I_FLUSH_FORCE) != 0 && !__ceph_is_any_revoking(ci))
1456 clear_bit(CEPH_I_FLUSH_FORCE_BIT, &ci->i_ceph_flags);
1457
1424 arg->session = cap->session;1458 arg->session = cap->session;
1425 arg->ino = ceph_vino(inode).ino;1459 arg->ino = ceph_vino(inode).ino;
1426 arg->cid = cap->cap_id;1460 arg->cid = cap->cap_id;
@@ -1842,7 +1876,7 @@ struct ceph_cap_flush *ceph_alloc_cap_flush(void) · 415 unmodified lines
1842{1876{
1843 struct ceph_cap_flush *cf;1877 struct ceph_cap_flush *cf;
1844 1878
1845 cf = kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL);1879 cf = kmem_cache_alloc(ceph_cap_flush_cachep, GFP_NOFS);
1846 if (!cf)1880 if (!cf)
1847 return NULL;1881 return NULL;
1848 1882
@@ -2038,6 +2072,14 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags) · 189 unmodified lines
2038 2072
2039 if (ci->i_ceph_flags & CEPH_I_FLUSH)2073 if (ci->i_ceph_flags & CEPH_I_FLUSH)
2040 flags |= CHECK_CAPS_FLUSH;2074 flags |= CHECK_CAPS_FLUSH;
2075 /*
2076 * A revoke whose response was deferred (see handle_cap_grant()) must
2077 * still be acknowledged. Replay the forced flush here so that even a
2078 * check triggered by writeback/invalidation completion sends a cap
2079 * message to the MDS.
2080 */
2081 if (ci->i_ceph_flags & CEPH_I_FLUSH_FORCE)
2082 flags |= CHECK_CAPS_FLUSH_FORCE;
2041retry:2083retry:
2042 /* Caps wanted by virtue of active open files. */2084 /* Caps wanted by virtue of active open files. */
2043 file_wanted = __ceph_caps_file_wanted(ci);2085 file_wanted = __ceph_caps_file_wanted(ci);
@@ -2210,7 +2252,7 @@ retry: · 166 unmodified lines
2210 if (want & ~cap->mds_wanted) {2252 if (want & ~cap->mds_wanted) {
2211 if (want & ~(cap->mds_wanted | cap->issued))2253 if (want & ~(cap->mds_wanted | cap->issued))
2212 goto ack;2254 goto ack;
2213 if (!__cap_is_valid(cap))2255 if (!__cap_is_valid(ci, cap))
2214 goto ack;2256 goto ack;
2215 }2257 }
2216 2258
@@ -2252,7 +2294,7 @@ ack: · 35 unmodified lines
2252 2294
2253 mds = cap->mds; /* remember mds, so we don't repeat */2295 mds = cap->mds; /* remember mds, so we don't repeat */
2254 2296
2255 __prep_cap(&arg, cap, CEPH_CAP_OP_UPDATE, mflags, cap_used,2297 __prep_cap(&arg, ci, cap, CEPH_CAP_OP_UPDATE, mflags, cap_used,
2256 want, retain, flushing, flush_tid, oldest_flush_tid);2298 want, retain, flushing, flush_tid, oldest_flush_tid);
2257 2299
2258 spin_unlock(&ci->i_ceph_lock);2300 spin_unlock(&ci->i_ceph_lock);
@@ -2314,7 +2356,7 @@ retry_locked: · 55 unmodified lines
2314 flush_tid = __mark_caps_flushing(inode, session, true,2356 flush_tid = __mark_caps_flushing(inode, session, true,
2315 &oldest_flush_tid);2357 &oldest_flush_tid);
2316 2358
2317 __prep_cap(&arg, cap, CEPH_CAP_OP_FLUSH, CEPH_CLIENT_CAPS_SYNC,2359 __prep_cap(&arg, ci, cap, CEPH_CAP_OP_FLUSH, CEPH_CLIENT_CAPS_SYNC,
2318 __ceph_caps_used(ci), __ceph_caps_wanted(ci),2360 __ceph_caps_used(ci), __ceph_caps_wanted(ci),
2319 (cap->issued | cap->implemented),2361 (cap->issued | cap->implemented),
2320 flushing, flush_tid, oldest_flush_tid);2362 flushing, flush_tid, oldest_flush_tid);
@@ -2589,9 +2631,14 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc, · 268 unmodified lines
2589 }2631 }
2590 }2632 }
2591 2633
2592 list_for_each_entry(cf, &ci->i_cap_flush_list, i_list) {2634 cf = list_first_entry(&ci->i_cap_flush_list, struct ceph_cap_flush, i_list);
2593 if (cf->tid < first_tid)2635 while (&cf->i_list != &ci->i_cap_flush_list) {
2636 struct ceph_cap_flush *next;
2637
2638 if (cf->tid < first_tid) {
2639 cf = list_next_entry(cf, i_list);
2594 continue;2640 continue;
2641 }
2595 2642
2596 cap = ci->i_auth_cap;2643 cap = ci->i_auth_cap;
2597 if (!(cap && cap->session == session)) {2644 if (!(cap && cap->session == session)) {
@@ -2601,6 +2648,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc, · 3 unmodified lines
2601 }2648 }
2602 2649
2603 first_tid = cf->tid + 1;2650 first_tid = cf->tid + 1;
2651 next = list_next_entry(cf, i_list);
2604 2652
2605 if (!cf->is_capsnap) {2653 if (!cf->is_capsnap) {
2606 struct cap_msg_args arg;2654 struct cap_msg_args arg;
@@ -2608,7 +2656,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc, · 1 unmodified line
2608 doutc(cl, "%p %llx.%llx cap %p tid %llu %s\n",2656 doutc(cl, "%p %llx.%llx cap %p tid %llu %s\n",
2609 inode, ceph_vinop(inode), cap, cf->tid,2657 inode, ceph_vinop(inode), cap, cf->tid,
2610 ceph_cap_string(cf->caps));2658 ceph_cap_string(cf->caps));
2611 __prep_cap(&arg, cap, CEPH_CAP_OP_FLUSH,2659 __prep_cap(&arg, ci, cap, CEPH_CAP_OP_FLUSH,
2612 (cf->tid < last_snap_flush ?2660 (cf->tid < last_snap_flush ?
2613 CEPH_CLIENT_CAPS_PENDING_CAPSNAP : 0),2661 CEPH_CLIENT_CAPS_PENDING_CAPSNAP : 0),
2614 __ceph_caps_used(ci),2662 __ceph_caps_used(ci),
@@ -2641,6 +2689,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc, · 26 unmodified lines
2641 }2689 }
2642 2690
2643 spin_lock(&ci->i_ceph_lock);2691 spin_lock(&ci->i_ceph_lock);
2692 cf = next;
2644 }2693 }
2645}2694}
2646 2695
@@ -3757,13 +3806,30 @@ static void handle_cap_grant(struct inode *inode, · 1110 unmodified lines
3757 BUG_ON(cap->issued & ~cap->implemented);3806 BUG_ON(cap->issued & ~cap->implemented);
3758 3807
3759 /* don't let check_caps skip sending a response to MDS for revoke msgs */3808 /* don't let check_caps skip sending a response to MDS for revoke msgs */
3760 if (!revoke_wait && le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {3809 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {
3761 cap->mds_wanted = 0;3810 if (revoke_wait) {
3762 flags |= CHECK_CAPS_FLUSH_FORCE;3811 /*
3763 if (cap == ci->i_auth_cap)3812 * We can't ack the revoke yet: the response is deferred
3764 check_caps = 1; /* check auth cap only */3813 * until the writeback or cache invalidation queued above
3765 else3814 * completes. Set the CEPH_I_FLUSH_FORCE flag to remember
3766 check_caps = 2; /* check all caps */3815 * that a forced cap message is owed so that deferred
3816 * completion (ceph_put_wrbuffer_cap_refs() or the
3817 * invalidate worker, both of which call ceph_check_caps())
3818 * actually sends one, even if by then the revoked caps look
3819 * unused, the inode is retaining caps, or the MDS has
3820 * re-granted them. Without this, the cap message is never
3821 * sent and the MDS hangs ("isn't responding to
3822 * mclientcaps(revoke)").
3823 */
3824 set_bit(CEPH_I_FLUSH_FORCE_BIT, &ci->i_ceph_flags);
3825 } else {
3826 cap->mds_wanted = 0;
3827 flags |= CHECK_CAPS_FLUSH_FORCE;
3828 if (cap == ci->i_auth_cap)
3829 check_caps = 1; /* check auth cap only */
3830 else
3831 check_caps = 2; /* check all caps */
3832 }
3767 }3833 }
3768 3834
3769 if (extra_info->inline_version > 0 &&3835 if (extra_info->inline_version > 0 &&
@@ -4119,7 +4185,7 @@ retry: · 349 unmodified lines
4119 goto out_unlock;4185 goto out_unlock;
4120 4186
4121 if (target < 0) {4187 if (target < 0) {
4122 ceph_remove_cap(mdsc, cap, false);4188 ceph_remove_cap(mdsc, cap, ci, false);
4123 goto out_unlock;4189 goto out_unlock;
4124 }4190 }
4125 4191
@@ -4156,7 +4222,7 @@ retry: · 30 unmodified lines
4156 change_auth_cap_ses(ci, tcap->session);4222 change_auth_cap_ses(ci, tcap->session);
4157 }4223 }
4158 }4224 }
4159 ceph_remove_cap(mdsc, cap, false);4225 ceph_remove_cap(mdsc, cap, ci, false);
4160 goto out_unlock;4226 goto out_unlock;
4161 } else if (tsession) {4227 } else if (tsession) {
4162 /* add placeholder for the export target */4228 /* add placeholder for the export target */
@@ -4173,7 +4239,7 @@ retry: · 10 unmodified lines
4173 spin_unlock(&mdsc->cap_dirty_lock);4239 spin_unlock(&mdsc->cap_dirty_lock);
4174 }4240 }
4175 4241
4176 ceph_remove_cap(mdsc, cap, false);4242 ceph_remove_cap(mdsc, cap, ci, false);
4177 goto out_unlock;4243 goto out_unlock;
4178 }4244 }
4179 4245
@@ -4289,7 +4355,7 @@ retry: · 109 unmodified lines
4289 inode, ceph_vinop(inode), peer,4355 inode, ceph_vinop(inode), peer,
4290 ocap->seq, ocap->mseq, mds, piseq, pmseq);4356 ocap->seq, ocap->mseq, mds, piseq, pmseq);
4291 }4357 }
4292 ceph_remove_cap(mdsc, ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));4358 ceph_remove_cap(mdsc, ocap, ci, (ph->flags & CEPH_CAP_FLAG_RELEASE));
4293 }4359 }
4294 4360
4295 *old_issued = issued;4361 *old_issued = issued;
@@ -4887,7 +4953,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode, · 591 unmodified lines
4887 drop &= ~(used | dirty);4953 drop &= ~(used | dirty);
4888 4954
4889 cap = __get_cap_for_mds(ci, mds);4955 cap = __get_cap_for_mds(ci, mds);
4890 if (cap && __cap_is_valid(cap)) {4956 if (cap && __cap_is_valid(ci, cap)) {
4891 unless &= cap->issued;4957 unless &= cap->issued;
4892 if (unless) {4958 if (unless) {
4893 if (unless & CEPH_CAP_AUTH_EXCL)4959 if (unless & CEPH_CAP_AUTH_EXCL)
@@ -5046,7 +5112,7 @@ int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invali · 152 unmodified lines
5046 cap, ci, inode, ceph_vinop(inode));5112 cap, ci, inode, ceph_vinop(inode));
5047 5113
5048 is_auth = (cap == ci->i_auth_cap);5114 is_auth = (cap == ci->i_auth_cap);
5049 __ceph_remove_cap(cap, false);5115 __ceph_remove_cap(ci, cap, false);
5050 if (is_auth) {5116 if (is_auth) {
5051 struct ceph_cap_flush *cf;5117 struct ceph_cap_flush *cf;
5052 5118
fs/ceph/crypto.c+37−13
@@ -298,18 +298,26 @@ out: · 297 unmodified lines
298 * Otherwise, base64 decode the string, and then ask fscrypt to format it298 * Otherwise, base64 decode the string, and then ask fscrypt to format it
299 * for userland presentation.299 * for userland presentation.
300 *300 *
301 * Though the fscrypt/crypto subsystems broadly expect all buffers to be in the
302 * linear-mapped region, this function slightly relaxes those requirements:
303 * fname->ctext, fname->name, and oname->name may be vmalloc(), but not tname.
304 *
301 * Returns 0 on success or negative error code on error.305 * Returns 0 on success or negative error code on error.
302 */306 */
303int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,307int ceph_fname_to_usr(const struct ceph_fname *fname, unsigned char *tname,
304 struct fscrypt_str *oname, bool *is_nokey)308 struct fscrypt_str *oname, bool *is_nokey)
305{309{
306 struct inode *dir = fname->dir;310 struct inode *dir = fname->dir;
307 struct fscrypt_str _tname = FSTR_INIT(NULL, 0);311 struct fscrypt_str _tname = FSTR_INIT(NULL, 0);
312 struct fscrypt_str _oname;
308 struct fscrypt_str iname;313 struct fscrypt_str iname;
309 char *name = fname->name;314 char *name = fname->name;
310 int name_len = fname->name_len;315 int name_len = fname->name_len;
311 int ret;316 int ret;
312 317
318 if (WARN_ON_ONCE(tname && is_vmalloc_addr(tname)))
319 return -EIO;
320
313 /* Sanity check that the resulting name will fit in the buffer */321 /* Sanity check that the resulting name will fit in the buffer */
314 if (fname->name_len > NAME_MAX || fname->ctext_len > NAME_MAX)322 if (fname->name_len > NAME_MAX || fname->ctext_len > NAME_MAX)
315 return -EIO;323 return -EIO;
@@ -350,31 +358,47 @@ int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname, · 34 unmodified lines
350 goto out_inode;358 goto out_inode;
351 }359 }
352 360
361 if (!tname && (fname->ctext_len == 0 ||
362 unlikely(is_vmalloc_addr(fname->ctext)) ||
363 unlikely(is_vmalloc_addr(oname->name)))) {
364 ret = fscrypt_fname_alloc_buffer(NAME_MAX, &_tname);
365 if (ret)
366 goto out_inode;
367 tname = _tname.name;
368 }
369
353 if (fname->ctext_len == 0) {370 if (fname->ctext_len == 0) {
354 int declen;371 int declen;
355 372
356 if (!tname) {373 declen = base64_decode(name, name_len, tname, false, BASE64_IMAP);
357 ret = fscrypt_fname_alloc_buffer(NAME_MAX, &_tname);
358 if (ret)
359 goto out_inode;
360 tname = &_tname;
361 }
362
363 declen = base64_decode(name, name_len,
364 tname->name, false, BASE64_IMAP);
365 if (declen <= 0) {374 if (declen <= 0) {
366 ret = -EIO;375 ret = -EIO;
367 goto out;376 goto out;
368 }377 }
369 iname.name = tname->name;378 iname.name = tname;
370 iname.len = declen;379 iname.len = declen;
380 } else if (unlikely(is_vmalloc_addr(fname->ctext))) {
381 memcpy(tname, fname->ctext, fname->ctext_len);
382
383 iname.name = tname;
384 iname.len = fname->ctext_len;
371 } else {385 } else {
372 iname.name = fname->ctext;386 iname.name = fname->ctext;
373 iname.len = fname->ctext_len;387 iname.len = fname->ctext_len;
374 }388 }
375 389
376 ret = fscrypt_fname_disk_to_usr(dir, 0, 0, &iname, oname);390 _oname.name = unlikely(is_vmalloc_addr(oname->name)) ? tname : oname->name;
377 if (!ret && (dir != fname->dir)) {391 _oname.len = oname->len;
392
393 ret = fscrypt_fname_disk_to_usr(dir, 0, 0, &iname, &_oname);
394 if (ret)
395 goto out;
396
397 if (unlikely(is_vmalloc_addr(oname->name)))
398 memcpy(oname->name, _oname.name, _oname.len);
399 oname->len = _oname.len;
400
401 if (dir != fname->dir) {
378 char tmp_buf[BASE64_CHARS(NAME_MAX)];402 char tmp_buf[BASE64_CHARS(NAME_MAX)];
379 403
380 name_len = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%llu",404 name_len = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%llu",
fs/ceph/crypto.h+2−2
@@ -115,7 +115,7 @@ static inline void ceph_fname_free_buffer(struct inode *parent, · 114 unmodified lines
115 fscrypt_fname_free_buffer(fname);115 fscrypt_fname_free_buffer(fname);
116}116}
117 117
118int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,118int ceph_fname_to_usr(const struct ceph_fname *fname, unsigned char *tname,
119 struct fscrypt_str *oname, bool *is_nokey);119 struct fscrypt_str *oname, bool *is_nokey);
120int ceph_fscrypt_prepare_readdir(struct inode *dir);120int ceph_fscrypt_prepare_readdir(struct inode *dir);
121 121
@@ -204,7 +204,7 @@ static inline void ceph_fname_free_buffer(struct inode *parent, · 82 unmodified lines
204}204}
205 205
206static inline int ceph_fname_to_usr(const struct ceph_fname *fname,206static inline int ceph_fname_to_usr(const struct ceph_fname *fname,
207 struct fscrypt_str *tname,207 unsigned char *tname,
208 struct fscrypt_str *oname, bool *is_nokey)208 struct fscrypt_str *oname, bool *is_nokey)
209{209{
210 oname->name = fname->name;210 oname->name = fname->name;
fs/ceph/dir.c+16−6
@@ -774,8 +774,13 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req, · 773 unmodified lines
774 d_drop(dentry);774 d_drop(dentry);
775 err = -ENOENT;775 err = -ENOENT;
776 } else {776 } else {
777 if (d_unhashed(dentry))777 if (d_unhashed(dentry)) {
778 d_add(dentry, NULL);778 struct inode *parent =
779 d_inode(dentry->d_parent);
780 if (!parent ||
781 ceph_snap(parent) == CEPH_NOSNAP)
782 d_add(dentry, NULL);
783 }
779 }784 }
780 }785 }
781 }786 }
@@ -840,6 +845,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, · 58 unmodified lines
840 dentry->d_name.len) &&845 dentry->d_name.len) &&
841 !is_root_ceph_dentry(dir, dentry) &&846 !is_root_ceph_dentry(dir, dentry) &&
842 ceph_test_mount_opt(fsc, DCACHE) &&847 ceph_test_mount_opt(fsc, DCACHE) &&
848 ceph_snap(dir) == CEPH_NOSNAP &&
843 __ceph_dir_is_complete(ci) &&849 __ceph_dir_is_complete(ci) &&
844 __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) {850 __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) {
845 __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD);851 __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD);
@@ -1173,7 +1179,7 @@ static struct dentry *ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir, · 327 unmodified lines
1173 !req->r_reply_info.head->is_target &&1179 !req->r_reply_info.head->is_target &&
1174 !req->r_reply_info.head->is_dentry)1180 !req->r_reply_info.head->is_dentry)
1175 err = ceph_handle_notrace_create(dir, dentry);1181 err = ceph_handle_notrace_create(dir, dentry);
1176 ret = ERR_PTR(err);1182 ret = err ? ERR_PTR(err) : NULL;
1177out_req:1183out_req:
1178 if (!IS_ERR(ret) && req->r_dentry != dentry)1184 if (!IS_ERR(ret) && req->r_dentry != dentry)
1179 /* Some other dentry was spliced in */1185 /* Some other dentry was spliced in */
@@ -1763,11 +1769,11 @@ static int __dir_lease_check(const struct dentry *dentry, · 583 unmodified lines
1763 if (ret > 0) {1769 if (ret > 0) {
1764 if (time_before(jiffies, di->time + lwc->dir_lease_ttl))1770 if (time_before(jiffies, di->time + lwc->dir_lease_ttl))
1765 return STOP;1771 return STOP;
1772 if (!lwc->expire_dir_lease)
1773 return KEEP;
1766 /* Move dentry to tail of dir lease list if we don't want1774 /* Move dentry to tail of dir lease list if we don't want
1767 * to delete it. So dentries in the list are checked in a1775 * to delete it. So dentries in the list are checked in a
1768 * round robin manner */1776 * round robin manner */
1769 if (!lwc->expire_dir_lease)
1770 return TOUCH;
1771 if (dentry->d_lockref.count > 0 ||1777 if (dentry->d_lockref.count > 0 ||
1772 (di->flags & CEPH_DENTRY_REFERENCED))1778 (di->flags & CEPH_DENTRY_REFERENCED))
1773 return TOUCH;1779 return TOUCH;
@@ -1794,7 +1800,7 @@ int ceph_trim_dentries(struct ceph_mds_client *mdsc) · 20 unmodified lines
1794 lwc.dir_lease = false;1800 lwc.dir_lease = false;
1795 lwc.nr_to_scan = CEPH_CAPS_PER_RELEASE * 2;1801 lwc.nr_to_scan = CEPH_CAPS_PER_RELEASE * 2;
1796 freed = __dentry_leases_walk(mdsc, &lwc);1802 freed = __dentry_leases_walk(mdsc, &lwc);
1797 if (!lwc.nr_to_scan) /* more invalid leases */1803 if (freed > 0 && !lwc.nr_to_scan) /* more invalid leases */
1798 return -EAGAIN;1804 return -EAGAIN;
1799 1805
1800 if (lwc.nr_to_scan < CEPH_CAPS_PER_RELEASE)1806 if (lwc.nr_to_scan < CEPH_CAPS_PER_RELEASE)
@@ -1804,6 +1810,10 @@ int ceph_trim_dentries(struct ceph_mds_client *mdsc) · 3 unmodified lines
1804 lwc.expire_dir_lease = freed < count;1810 lwc.expire_dir_lease = freed < count;
1805 lwc.dir_lease_ttl = mdsc->fsc->mount_options->caps_wanted_delay_max * HZ;1811 lwc.dir_lease_ttl = mdsc->fsc->mount_options->caps_wanted_delay_max * HZ;
1806 freed +=__dentry_leases_walk(mdsc, &lwc);1812 freed +=__dentry_leases_walk(mdsc, &lwc);
1813 if (freed == 0 && count == 0)
1814 /* no progress possible currently, retry futile */
1815 return 0;
1816
1807 if (!lwc.nr_to_scan) /* more to check */1817 if (!lwc.nr_to_scan) /* more to check */
1808 return -EAGAIN;1818 return -EAGAIN;
1809 1819
fs/ceph/export.c+17−9
@@ -442,6 +442,16 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, · 441 unmodified lines
442 return dentry;442 return dentry;
443}443}
444 444
445static int ceph_export_copy_name(char *name, const char *src, u32 len)
446{
447 if (len > NAME_MAX)
448 return -ENAMETOOLONG;
449
450 memcpy(name, src, len);
451 name[len] = '\0';
452 return 0;
453}
454
445static int __get_snap_name(struct dentry *parent, char *name,455static int __get_snap_name(struct dentry *parent, char *name,
446 struct dentry *child)456 struct dentry *child)
447{457{
@@ -513,9 +523,8 @@ static int __get_snap_name(struct dentry *parent, char *name, · 65 unmodified lines
513 BUG_ON(!rde->inode.in);523 BUG_ON(!rde->inode.in);
514 if (ceph_snap(inode) ==524 if (ceph_snap(inode) ==
515 le64_to_cpu(rde->inode.in->snapid)) {525 le64_to_cpu(rde->inode.in->snapid)) {
516 memcpy(name, rde->name, rde->name_len);526 err = ceph_export_copy_name(name, rde->name,
517 name[rde->name_len] = '\0';527 rde->name_len);
518 err = 0;
519 goto out;528 goto out;
520 }529 }
521 }530 }
@@ -580,8 +589,8 @@ static int ceph_get_name(struct dentry *parent, char *name, · 58 unmodified lines
580 589
581 rinfo = &req->r_reply_info;590 rinfo = &req->r_reply_info;
582 if (!IS_ENCRYPTED(dir)) {591 if (!IS_ENCRYPTED(dir)) {
583 memcpy(name, rinfo->dname, rinfo->dname_len);592 err = ceph_export_copy_name(name, rinfo->dname,
584 name[rinfo->dname_len] = 0;593 rinfo->dname_len);
585 } else {594 } else {
586 struct fscrypt_str oname = FSTR_INIT(NULL, 0);595 struct fscrypt_str oname = FSTR_INIT(NULL, 0);
587 struct ceph_fname fname = { .dir = dir,596 struct ceph_fname fname = { .dir = dir,
@@ -595,10 +604,9 @@ static int ceph_get_name(struct dentry *parent, char *name, · 7 unmodified lines
595 goto out;604 goto out;
596 605
597 err = ceph_fname_to_usr(&fname, NULL, &oname, NULL);606 err = ceph_fname_to_usr(&fname, NULL, &oname, NULL);
598 if (!err) {607 if (!err)
599 memcpy(name, oname.name, oname.len);608 err = ceph_export_copy_name(name, oname.name,
600 name[oname.len] = 0;609 oname.len);
601 }
602 ceph_fname_free_buffer(dir, &oname);610 ceph_fname_free_buffer(dir, &oname);
603 }611 }
604out:612out:
fs/ceph/file.c+53−3
@@ -2388,7 +2388,8 @@ out_end: · 2387 unmodified lines
2388 * dropping our cap refs and allowing the pending snap to logically2388 * dropping our cap refs and allowing the pending snap to logically
2389 * complete _before_ this write occurs.2389 * complete _before_ this write occurs.
2390 *2390 *
2391 * If we are near ENOSPC, write synchronously.2391 * If requested, nearfull writes are synced to preserve the legacy
2392 * client-side backpressure behavior.
2392 */2393 */
2393static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)2394static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
2394{2395{
@@ -2477,6 +2478,54 @@ retry_snap: · 82 unmodified lines
2477 if (err < 0)2478 if (err < 0)
2478 goto out;2479 goto out;
2479 2480
2481 /*
2482 * For O_APPEND writes we may have waited for Fwx exclusive caps
2483 * while the previous Fwx holder (another client) extended the
2484 * file. i_size has been updated via the cap grant message from
2485 * the MDS, but ki_pos is still the old EOF. Re-read i_size here
2486 * (no extra MDS round-trip needed) and adjust ki_pos to the true
2487 * EOF. Since we hold Fwx, no other client can change the file.
2488 */
2489 if (iocb->ki_flags & IOCB_APPEND) {
2490 loff_t cur_eof = i_size_read(inode);
2491
2492 if (cur_eof != pos) {
2493 doutc(cl,
2494 "%p %llx.%llx O_APPEND: pos adjusted %lld -> %lld\n",
2495 inode, ceph_vinop(inode), pos, cur_eof);
2496 iocb->ki_pos = cur_eof;
2497 pos = cur_eof;
2498 if (pos >= limit) {
2499 err = -EFBIG;
2500 goto out_caps;
2501 }
2502 iov_iter_truncate(from, limit - pos);
2503 count = iov_iter_count(from);
2504
2505 /*
2506 * ceph_get_caps() validated the old endoff
2507 * against i_max_size; adjusting ki_pos forward
2508 * may have shifted the write range beyond the
2509 * granted max_size. Re-check and truncate if
2510 * necessary.
2511 */
2512 spin_lock(&ci->i_ceph_lock);
2513 if (pos + count > (loff_t)ci->i_max_size) {
2514 loff_t max_size = ci->i_max_size;
2515
2516 spin_unlock(&ci->i_ceph_lock);
2517 if (pos >= max_size) {
2518 err = -EFBIG;
2519 goto out_caps;
2520 }
2521 iov_iter_truncate(from, max_size - pos);
2522 count = iov_iter_count(from);
2523 } else {
2524 spin_unlock(&ci->i_ceph_lock);
2525 }
2526 }
2527 }
2528
2480 err = file_update_time(file);2529 err = file_update_time(file);
2481 if (err)2530 if (err)
2482 goto out_caps;2531 goto out_caps;
@@ -2556,8 +2605,9 @@ retry_snap: · 73 unmodified lines
2556 }2605 }
2557 2606
2558 if (written >= 0) {2607 if (written >= 0) {
2559 if ((map_flags & CEPH_OSDMAP_NEARFULL) ||2608 if (ceph_test_mount_opt(fsc, NEARFULL_SYNC) &&
2560 (pool_flags & CEPH_POOL_FLAG_NEARFULL))2609 ((map_flags & CEPH_OSDMAP_NEARFULL) ||
2610 (pool_flags & CEPH_POOL_FLAG_NEARFULL)))
2561 iocb->ki_flags |= IOCB_DSYNC;2611 iocb->ki_flags |= IOCB_DSYNC;
2562 written = generic_write_sync(iocb, written);2612 written = generic_write_sync(iocb, written);
2563 }2613 }
fs/ceph/inode.c+2−1
@@ -1814,7 +1814,8 @@ retry_lookup: · 1813 unmodified lines
1814 ceph_dir_clear_ordered(dir);1814 ceph_dir_clear_ordered(dir);
1815 d_delete(dn);1815 d_delete(dn);
1816 } else if (have_lease) {1816 } else if (have_lease) {
1817 if (d_unhashed(dn))1817 if (d_unhashed(dn) &&
1818 ceph_snap(dir) == CEPH_NOSNAP)
1818 d_add(dn, NULL);1819 d_add(dn, NULL);
1819 }1820 }
1820 1821
fs/ceph/mds_client.c+89−21
@@ -491,11 +491,11 @@ static int parse_reply_info_readdir(void **p, void *end, · 490 unmodified lines
491 struct inode *inode = d_inode(req->r_dentry);491 struct inode *inode = d_inode(req->r_dentry);
492 struct ceph_inode_info *ci = ceph_inode(inode);492 struct ceph_inode_info *ci = ceph_inode(inode);
493 struct ceph_mds_reply_dir_entry *rde = info->dir_entries + i;493 struct ceph_mds_reply_dir_entry *rde = info->dir_entries + i;
494 struct fscrypt_str tname = FSTR_INIT(NULL, 0);
495 struct fscrypt_str oname = FSTR_INIT(NULL, 0);494 struct fscrypt_str oname = FSTR_INIT(NULL, 0);
496 struct ceph_fname fname;495 struct ceph_fname fname;
497 u32 altname_len, _name_len;496 u32 altname_len, _name_len;
498 u8 *altname, *_name;497 u8 *altname, *_name;
498 u8 *tname = NULL;
499 499
500 /* dentry */500 /* dentry */
501 ceph_decode_32_safe(p, end, _name_len, bad);501 ceph_decode_32_safe(p, end, _name_len, bad);
@@ -541,9 +541,13 @@ static int parse_reply_info_readdir(void **p, void *end, · 39 unmodified lines
541 * to do the base64_decode in-place. It's541 * to do the base64_decode in-place. It's
542 * safe because the decoded string should542 * safe because the decoded string should
543 * always be shorter, which is 3/4 of origin543 * always be shorter, which is 3/4 of origin
544 * string.544 * string. If this message was allocated with
545 * vmalloc() (happens, but rarely), leave it
546 * NULL and let ceph_fname_to_usr() allocate
547 * suitable temporary working space instead.
545 */548 */
546 tname.name = _name;549 if (likely(!is_vmalloc_addr(_name)))
550 tname = _name;
547 551
548 /*552 /*
549 * Set oname to _name too, and this will be553 * Set oname to _name too, and this will be
@@ -560,7 +564,7 @@ static int parse_reply_info_readdir(void **p, void *end, · 10 unmodified lines
560 oname.len = altname_len;564 oname.len = altname_len;
561 }565 }
562 rde->is_nokey = false;566 rde->is_nokey = false;
563 err = ceph_fname_to_usr(&fname, &tname, &oname, &rde->is_nokey);567 err = ceph_fname_to_usr(&fname, tname, &oname, &rde->is_nokey);
564 if (err) {568 if (err) {
565 pr_err_client(cl, "unable to decode %.*s, got %d\n",569 pr_err_client(cl, "unable to decode %.*s, got %d\n",
566 _name_len, _name, err);570 _name_len, _name, err);
@@ -615,10 +619,36 @@ bad: · 48 unmodified lines
615 619
616#define DELEGATED_INO_AVAILABLE xa_mk_value(1)620#define DELEGATED_INO_AVAILABLE xa_mk_value(1)
617 621
622static int ceph_insert_deleg_ino(struct ceph_mds_session *s, u64 ino)
623{
624 struct ceph_client *cl = s->s_mdsc->fsc->client;
625 int err;
626
627 /*
628 * Cap how many delegated inodes a single session may hold. This is
629 * the only place that grows the count, so atomic_add_unless() bounds
630 * it at exactly CEPH_MAX_DELEG_INOS; s_num_deleg_inos can never exceed
631 * that.
632 */
633 if (!atomic_add_unless(&s->s_num_deleg_inos, 1, CEPH_MAX_DELEG_INOS)) {
634 pr_warn_ratelimited_client(cl,
635 "MDS session already holds %d delegated inodes\n",
636 CEPH_MAX_DELEG_INOS);
637 return -EOVERFLOW;
638 }
639
640 err = xa_insert(&s->s_delegated_inos, ino, DELEGATED_INO_AVAILABLE,
641 GFP_KERNEL);
642 if (err)
643 atomic_dec(&s->s_num_deleg_inos);
644 return err;
645}
646
618static int ceph_parse_deleg_inos(void **p, void *end,647static int ceph_parse_deleg_inos(void **p, void *end,
619 struct ceph_mds_session *s)648 struct ceph_mds_session *s)
620{649{
621 struct ceph_client *cl = s->s_mdsc->fsc->client;650 struct ceph_client *cl = s->s_mdsc->fsc->client;
651 u64 msg_deleg_inos = 0;
622 u32 sets;652 u32 sets;
623 653
624 ceph_decode_32_safe(p, end, sets, bad);654 ceph_decode_32_safe(p, end, sets, bad);
@@ -636,16 +666,34 @@ static int ceph_parse_deleg_inos(void **p, void *end, · 11 unmodified lines
636 start, len);666 start, len);
637 continue;667 continue;
638 }668 }
669
670 /*
671 * Bound the number of inodes one reply may delegate.
672 * ceph_insert_deleg_ino() separately caps the per-session
673 * population, so this only has to stop one reply from spinning
674 * the insert loop under an attacker-controlled len.
675 */
676 if (len > (u64)CEPH_MAX_DELEG_INOS ||
677 msg_deleg_inos > (u64)CEPH_MAX_DELEG_INOS - len) {
678 pr_warn_ratelimited_client(cl,
679 "MDS reply delegates too many inodes (have %llu, +%llu, max %d)\n",
680 msg_deleg_inos, len, CEPH_MAX_DELEG_INOS);
681 return -EIO;
682 }
683 msg_deleg_inos += len;
684
639 while (len--) {685 while (len--) {
640 int err = xa_insert(&s->s_delegated_inos, start++,686 int err = ceph_insert_deleg_ino(s, start++);
641 DELEGATED_INO_AVAILABLE,687
642 GFP_KERNEL);
643 if (!err) {688 if (!err) {
644 doutc(cl, "added delegated inode 0x%llx\n", start - 1);689 doutc(cl, "added delegated inode 0x%llx\n", start - 1);
645 } else if (err == -EBUSY) {690 } else if (err == -EBUSY) {
646 pr_warn_client(cl,691 pr_warn_client(cl,
647 "MDS delegated inode 0x%llx more than once.\n",692 "MDS delegated inode 0x%llx more than once.\n",
648 start - 1);693 start - 1);
694 } else if (err == -EOVERFLOW) {
695 /* ceph_insert_deleg_ino() already warned. */
696 return -EIO;
649 } else {697 } else {
650 return err;698 return err;
651 }699 }
@@ -663,16 +711,17 @@ u64 ceph_get_deleg_ino(struct ceph_mds_session *s) · 11 unmodified lines
663 711
664 xa_for_each(&s->s_delegated_inos, ino, val) {712 xa_for_each(&s->s_delegated_inos, ino, val) {
665 val = xa_erase(&s->s_delegated_inos, ino);713 val = xa_erase(&s->s_delegated_inos, ino);
666 if (val == DELEGATED_INO_AVAILABLE)714 if (val == DELEGATED_INO_AVAILABLE) {
715 atomic_dec(&s->s_num_deleg_inos);
667 return ino;716 return ino;
717 }
668 }718 }
669 return 0;719 return 0;
670}720}
671 721
672int ceph_restore_deleg_ino(struct ceph_mds_session *s, u64 ino)722int ceph_restore_deleg_ino(struct ceph_mds_session *s, u64 ino)
673{723{
674 return xa_insert(&s->s_delegated_inos, ino, DELEGATED_INO_AVAILABLE,724 return ceph_insert_deleg_ino(s, ino);
675 GFP_KERNEL);
676}725}
677#else /* BITS_PER_LONG == 64 */726#else /* BITS_PER_LONG == 64 */
678/*727/*
@@ -1059,6 +1108,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, · 380 unmodified lines
1059 INIT_LIST_HEAD(&s->s_waiting);1108 INIT_LIST_HEAD(&s->s_waiting);
1060 INIT_LIST_HEAD(&s->s_unsafe);1109 INIT_LIST_HEAD(&s->s_unsafe);
1061 xa_init(&s->s_delegated_inos);1110 xa_init(&s->s_delegated_inos);
1111 atomic_set(&s->s_num_deleg_inos, 0);
1062 INIT_LIST_HEAD(&s->s_cap_releases);1112 INIT_LIST_HEAD(&s->s_cap_releases);
1063 INIT_WORK(&s->s_cap_release_work, ceph_cap_release_work);1113 INIT_WORK(&s->s_cap_release_work, ceph_cap_release_work);
1064 1114
@@ -1800,16 +1850,19 @@ static void __open_export_target_sessions(struct ceph_mds_client *mdsc, · 735 unmodified lines
1800 * session caps1850 * session caps
1801 */1851 */
1802 1852
1803static void detach_cap_releases(struct ceph_mds_session *session,1853static int detach_cap_releases(struct ceph_mds_session *session,
1804 struct list_head *target)1854 struct list_head *target)
1805{1855{
1806 struct ceph_client *cl = session->s_mdsc->fsc->client;1856 struct ceph_client *cl = session->s_mdsc->fsc->client;
1857 const int num_cap_releases = session->s_num_cap_releases;
1807 1858
1808 lockdep_assert_held(&session->s_cap_lock);1859 lockdep_assert_held(&session->s_cap_lock);
1809 1860
1810 list_splice_init(&session->s_cap_releases, target);1861 list_splice_init(&session->s_cap_releases, target);
1811 session->s_num_cap_releases = 0;1862 session->s_num_cap_releases = 0;
1812 doutc(cl, "mds%d\n", session->s_mds);1863 doutc(cl, "mds%d\n", session->s_mds);
1864
1865 return num_cap_releases;
1813}1866}
1814 1867
1815static void dispose_cap_releases(struct ceph_mds_client *mdsc,1868static void dispose_cap_releases(struct ceph_mds_client *mdsc,
@@ -1903,7 +1956,7 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session, · 87 unmodified lines
1903 1956
1904 spin_lock(&session->s_cap_lock);1957 spin_lock(&session->s_cap_lock);
1905 p = p->next;1958 p = p->next;
1906 if (!cap->ci) {1959 if (ceph_cap_is_removed(cap)) {
1907 doutc(cl, "finishing cap %p removal\n", cap);1960 doutc(cl, "finishing cap %p removal\n", cap);
1908 BUG_ON(cap->session != session);1961 BUG_ON(cap->session != session);
1909 cap->session = NULL;1962 cap->session = NULL;
@@ -2259,7 +2312,7 @@ static int trim_caps_cb(struct inode *inode, int mds, void *arg) · 349 unmodified lines
2259 2312
2260 if (oissued) {2313 if (oissued) {
2261 /* we aren't the only cap.. just remove us */2314 /* we aren't the only cap.. just remove us */
2262 ceph_remove_cap(mdsc, cap, true);2315 ceph_remove_cap(mdsc, cap, ci, true);
2263 (*remaining)--;2316 (*remaining)--;
2264 } else {2317 } else {
2265 struct dentry *dentry;2318 struct dentry *dentry;
@@ -2465,9 +2518,7 @@ static void ceph_send_cap_releases(struct ceph_mds_client *mdsc, · 199 unmodified lines
2465 2518
2466 spin_lock(&session->s_cap_lock);2519 spin_lock(&session->s_cap_lock);
2467again:2520again:
2468 list_splice_init(&session->s_cap_releases, &tmp_list);2521 num_cap_releases = detach_cap_releases(session, &tmp_list);
2469 num_cap_releases = session->s_num_cap_releases;
2470 session->s_num_cap_releases = 0;
2471 spin_unlock(&session->s_cap_lock);2522 spin_unlock(&session->s_cap_lock);
2472 2523
2473 while (!list_empty(&tmp_list)) {2524 while (!list_empty(&tmp_list)) {
@@ -4091,13 +4142,19 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) · 1617 unmodified lines
4091 list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe);4142 list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe);
4092 }4143 }
4093 4144
4145 /*
4146 * Now that all mutex-protected state has been updated above
4147 * (the request has been unregistered or added to the
4148 * session's unsafe list), we can unlock it.
4149 */
4150 mutex_unlock(&mdsc->mutex);
4151
4094 doutc(cl, "tid %lld result %d\n", tid, result);4152 doutc(cl, "tid %lld result %d\n", tid, result);
4095 if (test_bit(CEPHFS_FEATURE_REPLY_ENCODING, &session->s_features))4153 if (test_bit(CEPHFS_FEATURE_REPLY_ENCODING, &session->s_features))
4096 err = parse_reply_info(session, msg, req, (u64)-1);4154 err = parse_reply_info(session, msg, req, (u64)-1);
4097 else4155 else
4098 err = parse_reply_info(session, msg, req,4156 err = parse_reply_info(session, msg, req,
4099 session->s_con.peer_features);4157 session->s_con.peer_features);
4100 mutex_unlock(&mdsc->mutex);
4101 4158
4102 /* Must find target inode outside of mutexes to avoid deadlocks */4159 /* Must find target inode outside of mutexes to avoid deadlocks */
4103 rinfo = &req->r_reply_info;4160 rinfo = &req->r_reply_info;
@@ -4441,7 +4498,9 @@ static void handle_session(struct ceph_mds_session *session, · 337 unmodified lines
4441 pr_err_client(cl, "No memory for path\n");4498 pr_err_client(cl, "No memory for path\n");
4442 goto fail;4499 goto fail;
4443 }4500 }
4444 ceph_decode_copy(&p, cap_auths[i].match.path, _len);4501 ceph_decode_copy_safe(&p, end,
4502 cap_auths[i].match.path,
4503 _len, bad);
4445 4504
4446 /* Remove the tailing '/' */4505 /* Remove the tailing '/' */
4447 while (_len && cap_auths[i].match.path[_len - 1] == '/') {4506 while (_len && cap_auths[i].match.path[_len - 1] == '/') {
@@ -4458,7 +4517,9 @@ static void handle_session(struct ceph_mds_session *session, · 10 unmodified lines
4458 pr_err_client(cl, "No memory for fs_name\n");4517 pr_err_client(cl, "No memory for fs_name\n");
4459 goto fail;4518 goto fail;
4460 }4519 }
4461 ceph_decode_copy(&p, cap_auths[i].match.fs_name, _len);4520 ceph_decode_copy_safe(&p, end,
4521 cap_auths[i].match.fs_name,
4522 _len, bad);
4462 }4523 }
4463 4524
4464 ceph_decode_8_safe(&p, end, cap_auths[i].match.root_squash, bad);4525 ceph_decode_8_safe(&p, end, cap_auths[i].match.root_squash, bad);
@@ -5106,6 +5167,7 @@ static int send_mds_reconnect(struct ceph_mds_client *mdsc, · 641 unmodified lines
5106 5167
5107 /* Serialized by s_mutex against concurrent ceph_get_deleg_ino(). */5168 /* Serialized by s_mutex against concurrent ceph_get_deleg_ino(). */
5108 xa_destroy(&session->s_delegated_inos);5169 xa_destroy(&session->s_delegated_inos);
5170 atomic_set(&session->s_num_deleg_inos, 0);
5109 if (session->s_state == CEPH_MDS_SESSION_CLOSED ||5171 if (session->s_state == CEPH_MDS_SESSION_CLOSED ||
5110 session->s_state == CEPH_MDS_SESSION_REJECTED) {5172 session->s_state == CEPH_MDS_SESSION_REJECTED) {
5111 pr_info_client(cl, "mds%d skipping reconnect, session %s\n",5173 pr_info_client(cl, "mds%d skipping reconnect, session %s\n",
@@ -5753,7 +5815,7 @@ int ceph_mdsc_schedule_reset(struct ceph_mds_client *mdsc, · 641 unmodified lines
5753 strscpy(st->last_reason, msg, sizeof(st->last_reason));5815 strscpy(st->last_reason, msg, sizeof(st->last_reason));
5754 spin_unlock(&st->lock);5816 spin_unlock(&st->lock);
5755 5817
5756 if (WARN_ON_ONCE(!queue_work(system_unbound_wq, &mdsc->reset_work))) {5818 if (WARN_ON_ONCE(!queue_work(system_dfl_wq, &mdsc->reset_work))) {
5757 spin_lock(&st->lock);5819 spin_lock(&st->lock);
5758 st->phase = CEPH_CLIENT_RESET_IDLE;5820 st->phase = CEPH_CLIENT_RESET_IDLE;
5759 st->last_errno = -EALREADY;5821 st->last_errno = -EALREADY;
@@ -5834,9 +5896,11 @@ static void check_new_map(struct ceph_mds_client *mdsc, · 74 unmodified lines
5834 ceph_mdsmap_get_addr(newmap, i),5896 ceph_mdsmap_get_addr(newmap, i),
5835 sizeof(struct ceph_entity_addr))) {5897 sizeof(struct ceph_entity_addr))) {
5836 /* just close it */5898 /* just close it */
5899 ceph_get_mds_session(s);
5837 mutex_unlock(&mdsc->mutex);5900 mutex_unlock(&mdsc->mutex);
5838 mutex_lock(&s->s_mutex);5901 mutex_lock(&s->s_mutex);
5839 mutex_lock(&mdsc->mutex);5902 mutex_lock(&mdsc->mutex);
5903 ceph_put_mds_session(s);
5840 ceph_con_close(&s->s_con);5904 ceph_con_close(&s->s_con);
5841 mutex_unlock(&s->s_mutex);5905 mutex_unlock(&s->s_mutex);
5842 s->s_state = CEPH_MDS_SESSION_RESTARTING;5906 s->s_state = CEPH_MDS_SESSION_RESTARTING;
@@ -5851,6 +5915,7 @@ static void check_new_map(struct ceph_mds_client *mdsc, · 8 unmodified lines
5851 newstate >= CEPH_MDS_STATE_RECONNECT) {5915 newstate >= CEPH_MDS_STATE_RECONNECT) {
5852 int rc;5916 int rc;
5853 5917
5918 ceph_get_mds_session(s);
5854 mutex_unlock(&mdsc->mutex);5919 mutex_unlock(&mdsc->mutex);
5855 clear_bit(i, targets);5920 clear_bit(i, targets);
5856 rc = send_mds_reconnect(mdsc, s);5921 rc = send_mds_reconnect(mdsc, s);
@@ -5859,6 +5924,7 @@ static void check_new_map(struct ceph_mds_client *mdsc, · 2 unmodified lines
5859 "mds%d reconnect failed: %d\n",5924 "mds%d reconnect failed: %d\n",
5860 i, rc);5925 i, rc);
5861 mutex_lock(&mdsc->mutex);5926 mutex_lock(&mdsc->mutex);
5927 ceph_put_mds_session(s);
5862 }5928 }
5863 5929
5864 /*5930 /*
@@ -5871,9 +5937,11 @@ static void check_new_map(struct ceph_mds_client *mdsc, · 6 unmodified lines
5871 pr_info_client(cl, "mds%d recovery completed\n",5937 pr_info_client(cl, "mds%d recovery completed\n",
5872 s->s_mds);5938 s->s_mds);
5873 kick_requests(mdsc, i);5939 kick_requests(mdsc, i);
5940 ceph_get_mds_session(s);
5874 mutex_unlock(&mdsc->mutex);5941 mutex_unlock(&mdsc->mutex);
5875 mutex_lock(&s->s_mutex);5942 mutex_lock(&s->s_mutex);
5876 mutex_lock(&mdsc->mutex);5943 mutex_lock(&mdsc->mutex);
5944 ceph_put_mds_session(s);
5877 ceph_kick_flushing_caps(mdsc, s);5945 ceph_kick_flushing_caps(mdsc, s);
5878 mutex_unlock(&s->s_mutex);5946 mutex_unlock(&s->s_mutex);
5879 wake_up_session_caps(s, RECONNECT);5947 wake_up_session_caps(s, RECONNECT);
fs/ceph/mds_client.h+1−0
@@ -300,6 +300,7 @@ struct ceph_mds_session { · 299 unmodified lines
300 struct list_head s_waiting; /* waiting requests */300 struct list_head s_waiting; /* waiting requests */
301 struct list_head s_unsafe; /* unsafe requests */301 struct list_head s_unsafe; /* unsafe requests */
302 struct xarray s_delegated_inos;302 struct xarray s_delegated_inos;
303 atomic_t s_num_deleg_inos;
303};304};
304 305
305/*306/*
fs/ceph/mdsmap.c+10−1
@@ -3,6 +3,7 @@ · 2 unmodified lines
3 3
4#include <linux/bug.h>4#include <linux/bug.h>
5#include <linux/err.h>5#include <linux/err.h>
6#include <linux/overflow.h>
6#include <linux/random.h>7#include <linux/random.h>
7#include <linux/slab.h>8#include <linux/slab.h>
8#include <linux/types.h>9#include <linux/types.h>
@@ -126,6 +127,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p, · 117 unmodified lines
126 u8 mdsmap_v;127 u8 mdsmap_v;
127 u16 mdsmap_ev;128 u16 mdsmap_ev;
128 u32 target;129 u32 target;
130 size_t export_targets_len;
129 131
130 m = kzalloc_obj(*m, GFP_NOFS);132 m = kzalloc_obj(*m, GFP_NOFS);
131 if (!m)133 if (!m)
@@ -224,8 +226,11 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p, · 92 unmodified lines
224 *p += namelen;226 *p += namelen;
225 if (info_v >= 2) {227 if (info_v >= 2) {
226 ceph_decode_32_safe(p, end, num_export_targets, bad);228 ceph_decode_32_safe(p, end, num_export_targets, bad);
229 export_targets_len = size_mul(num_export_targets,
230 sizeof(u32));
231 ceph_decode_need(p, end, export_targets_len, bad);
227 pexport_targets = *p;232 pexport_targets = *p;
228 *p += num_export_targets * sizeof(u32);233 *p += export_targets_len;
229 } else {234 } else {
230 num_export_targets = 0;235 num_export_targets = 0;
231 }236 }
@@ -264,6 +269,10 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p, · 32 unmodified lines
264 goto nomem;269 goto nomem;
265 for (j = 0; j < num_export_targets; j++) {270 for (j = 0; j < num_export_targets; j++) {
266 target = ceph_decode_32(&pexport_targets);271 target = ceph_decode_32(&pexport_targets);
272 if (target >= CEPH_MAX_MDS) {
273 err = -EIO;
274 goto corrupt;
275 }
267 info->export_targets[j] = target;276 info->export_targets[j] = target;
268 }277 }
269 } else {278 } else {
fs/ceph/super.c+10−0
@@ -177,6 +177,7 @@ enum { · 176 unmodified lines
177 Opt_wsync,177 Opt_wsync,
178 Opt_pagecache,178 Opt_pagecache,
179 Opt_sparseread,179 Opt_sparseread,
180 Opt_nearfull_sync,
180};181};
181 182
182enum ceph_recover_session_mode {183enum ceph_recover_session_mode {
@@ -205,6 +206,7 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = { · 22 unmodified lines
205 fsparam_flag_no ("ino32", Opt_ino32),206 fsparam_flag_no ("ino32", Opt_ino32),
206 fsparam_string ("mds_namespace", Opt_mds_namespace),207 fsparam_string ("mds_namespace", Opt_mds_namespace),
207 fsparam_string ("mon_addr", Opt_mon_addr),208 fsparam_string ("mon_addr", Opt_mon_addr),
209 fsparam_flag_no ("nearfull_sync", Opt_nearfull_sync),
208 fsparam_flag_no ("poolperm", Opt_poolperm),210 fsparam_flag_no ("poolperm", Opt_poolperm),
209 fsparam_flag_no ("quotadf", Opt_quotadf),211 fsparam_flag_no ("quotadf", Opt_quotadf),
210 fsparam_u32 ("rasize", Opt_rasize),212 fsparam_u32 ("rasize", Opt_rasize),
@@ -593,6 +595,12 @@ static int ceph_parse_mount_param(struct fs_context *fc, · 382 unmodified lines
593 else595 else
594 fsopt->flags |= CEPH_MOUNT_OPT_SPARSEREAD;596 fsopt->flags |= CEPH_MOUNT_OPT_SPARSEREAD;
595 break;597 break;
598 case Opt_nearfull_sync:
599 if (result.negated)
600 fsopt->flags &= ~CEPH_MOUNT_OPT_NEARFULL_SYNC;
601 else
602 fsopt->flags |= CEPH_MOUNT_OPT_NEARFULL_SYNC;
603 break;
596 case Opt_test_dummy_encryption:604 case Opt_test_dummy_encryption:
597#ifdef CONFIG_FS_ENCRYPTION605#ifdef CONFIG_FS_ENCRYPTION
598 fscrypt_free_dummy_policy(&fsopt->dummy_enc_policy);606 fscrypt_free_dummy_policy(&fsopt->dummy_enc_policy);
@@ -749,6 +757,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) · 150 unmodified lines
749 seq_puts(m, ",nopagecache");757 seq_puts(m, ",nopagecache");
750 if (fsopt->flags & CEPH_MOUNT_OPT_SPARSEREAD)758 if (fsopt->flags & CEPH_MOUNT_OPT_SPARSEREAD)
751 seq_puts(m, ",sparseread");759 seq_puts(m, ",sparseread");
760 if (fsopt->flags & CEPH_MOUNT_OPT_NEARFULL_SYNC)
761 seq_puts(m, ",nearfull_sync");
752 762
753 fscrypt_show_test_dummy_encryption(m, ',', root->d_sb);763 fscrypt_show_test_dummy_encryption(m, ',', root->d_sb);
754 764
fs/ceph/super.h+43−2
@@ -45,6 +45,7 @@ · 44 unmodified lines
45#define CEPH_MOUNT_OPT_ASYNC_DIROPS (1<<15) /* allow async directory ops */45#define CEPH_MOUNT_OPT_ASYNC_DIROPS (1<<15) /* allow async directory ops */
46#define CEPH_MOUNT_OPT_NOPAGECACHE (1<<16) /* bypass pagecache altogether */46#define CEPH_MOUNT_OPT_NOPAGECACHE (1<<16) /* bypass pagecache altogether */
47#define CEPH_MOUNT_OPT_SPARSEREAD (1<<17) /* always do sparse reads */47#define CEPH_MOUNT_OPT_SPARSEREAD (1<<17) /* always do sparse reads */
48#define CEPH_MOUNT_OPT_NEARFULL_SYNC (1<<18) /* sync writes when nearfull */
48 49
49#define CEPH_MOUNT_OPT_DEFAULT \50#define CEPH_MOUNT_OPT_DEFAULT \
50 (CEPH_MOUNT_OPT_DCACHE | \51 (CEPH_MOUNT_OPT_DCACHE | \
@@ -203,7 +204,19 @@ struct ceph_fs_client { · 152 unmodified lines
203 */204 */
204struct ceph_cap {205struct ceph_cap {
205 struct ceph_inode_info *ci;206 struct ceph_inode_info *ci;
206 struct rb_node ci_node; /* per-ci cap tree */207
208 /**
209 * Per-ci cap tree. Protected with
210 * `ceph_inode_info.i_ceph_lock`.
211 *
212 * Clearing this field with RB_CLEAR_NODE() requires holding
213 * both `ceph_inode_info.i_ceph_lock` and
214 * `ceph_mds_session->s_cap_lock`. Calling RB_EMPTY_NODE()
215 * (via ceph_cap_is_removed()) requires holding at least one
216 * of these.
217 */
218 struct rb_node ci_node;
219
207 struct ceph_mds_session *session;220 struct ceph_mds_session *session;
208 struct list_head session_caps; /* per-session caplist */221 struct list_head session_caps; /* per-session caplist */
209 u64 cap_id; /* unique cap id (mds provided) */222 u64 cap_id; /* unique cap id (mds provided) */
@@ -641,6 +654,15 @@ static inline int ceph_ino_compare(struct inode *inode, void *data) · 431 unmodified lines
641#define CEPH_MDS_INO_LOG_OFFSET (2 * CEPH_MAX_MDS)654#define CEPH_MDS_INO_LOG_OFFSET (2 * CEPH_MAX_MDS)
642#define CEPH_INO_SYSTEM_BASE ((6*CEPH_MAX_MDS) + (CEPH_MAX_MDS * CEPH_NUM_STRAY))655#define CEPH_INO_SYSTEM_BASE ((6*CEPH_MAX_MDS) + (CEPH_MAX_MDS * CEPH_NUM_STRAY))
643 656
657/*
658 * Upper bound on the number of delegated inodes a single MDS session may
659 * hold. The MDS normally hands out a small preallocation window (the
660 * userspace mds_client_prealloc_inos option defaults to 1000) and refills
661 * it as the client consumes entries. This leaves generous headroom while
662 * bounding the CPU and memory a malformed delegation interval can consume.
663 */
664#define CEPH_MAX_DELEG_INOS 8192
665
644static inline bool ceph_vino_is_reserved(const struct ceph_vino vino)666static inline bool ceph_vino_is_reserved(const struct ceph_vino vino)
645{667{
646 if (vino.ino >= CEPH_INO_SYSTEM_BASE ||668 if (vino.ino >= CEPH_INO_SYSTEM_BASE ||
@@ -687,6 +709,10 @@ static inline struct inode *ceph_find_inode(struct super_block *sb, · 40 unmodified lines
687#define CEPH_I_ASYNC_CREATE_BIT (12) /* async create in flight for this */709#define CEPH_I_ASYNC_CREATE_BIT (12) /* async create in flight for this */
688#define CEPH_I_SHUTDOWN_BIT (13) /* inode is no longer usable */710#define CEPH_I_SHUTDOWN_BIT (13) /* inode is no longer usable */
689#define CEPH_I_ASYNC_CHECK_CAPS_BIT (14) /* check caps after async creating finishes */711#define CEPH_I_ASYNC_CHECK_CAPS_BIT (14) /* check caps after async creating finishes */
712#define CEPH_I_FLUSH_FORCE_BIT (15) /* a revoke's response was deferred;
713 * force a cap message to the MDS once
714 * the deferred work completes
715 */
690 716
691#define CEPH_I_DIR_ORDERED (1 << CEPH_I_DIR_ORDERED_BIT)717#define CEPH_I_DIR_ORDERED (1 << CEPH_I_DIR_ORDERED_BIT)
692#define CEPH_I_FLUSH (1 << CEPH_I_FLUSH_BIT)718#define CEPH_I_FLUSH (1 << CEPH_I_FLUSH_BIT)
@@ -699,6 +725,7 @@ static inline struct inode *ceph_find_inode(struct super_block *sb, · 6 unmodified lines
699#define CEPH_I_ODIRECT (1 << CEPH_I_ODIRECT_BIT)725#define CEPH_I_ODIRECT (1 << CEPH_I_ODIRECT_BIT)
700#define CEPH_I_ASYNC_CREATE (1 << CEPH_I_ASYNC_CREATE_BIT)726#define CEPH_I_ASYNC_CREATE (1 << CEPH_I_ASYNC_CREATE_BIT)
701#define CEPH_I_SHUTDOWN (1 << CEPH_I_SHUTDOWN_BIT)727#define CEPH_I_SHUTDOWN (1 << CEPH_I_SHUTDOWN_BIT)
728#define CEPH_I_FLUSH_FORCE (1 << CEPH_I_FLUSH_FORCE_BIT)
702 729
703/*730/*
704 * Masks of ceph inode work.731 * Masks of ceph inode work.
@@ -1269,8 +1296,22 @@ extern void ceph_add_cap(struct inode *inode, · 564 unmodified lines
1269 unsigned issued, unsigned wanted,1296 unsigned issued, unsigned wanted,
1270 unsigned cap, unsigned seq, u64 realmino, int flags,1297 unsigned cap, unsigned seq, u64 realmino, int flags,
1271 struct ceph_cap **new_cap);1298 struct ceph_cap **new_cap);
1272extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);1299
1300/**
1301 * Determine whether __ceph_remove_cap() has been called on this #cap
1302 * (but the object has not yet been freed because it is protected by
1303 * `ceph_mds_session.s_cap_iterator`).
1304 *
1305 * Caller must lock either `ceph_inode_info.i_ceph_lock` or
1306 * `ceph_mds_session.s_cap_lock`.
1307 */
1308static inline bool ceph_cap_is_removed(const struct ceph_cap *cap)
1309{
1310 return RB_EMPTY_NODE(&cap->ci_node);
1311}
1312
1273extern void ceph_remove_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,1313extern void ceph_remove_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
1314 struct ceph_inode_info *ci,
1274 bool queue_release);1315 bool queue_release);
1275extern void __ceph_remove_caps(struct ceph_inode_info *ci);1316extern void __ceph_remove_caps(struct ceph_inode_info *ci);
1276extern void ceph_put_cap(struct ceph_mds_client *mdsc,1317extern void ceph_put_cap(struct ceph_mds_client *mdsc,
fs/ceph/xattr.c+1−0
@@ -848,6 +848,7 @@ start: · 847 unmodified lines
848 name = p;848 name = p;
849 p += len;849 p += len;
850 ceph_decode_32_safe(&p, end, len, bad);850 ceph_decode_32_safe(&p, end, len, bad);
851 ceph_decode_need(&p, end, len, bad);
851 val = p;852 val = p;
852 p += len;853 p += len;
853 854
include/linux/ceph/libceph.h+0−2
@@ -313,8 +313,6 @@ int ceph_wait_for_latest_osdmap(struct ceph_client *client, · 312 unmodified lines
313 313
314/* pagevec.c */314/* pagevec.c */
315extern void ceph_release_page_vector(struct page **pages, int num_pages);315extern void ceph_release_page_vector(struct page **pages, int num_pages);
316extern void ceph_put_page_vector(struct page **pages, int num_pages,
317 bool dirty);
318extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);316extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
319extern void ceph_copy_from_page_vector(struct page **pages,317extern void ceph_copy_from_page_vector(struct page **pages,
320 void *data,318 void *data,
net/ceph/messenger_v2.c+5−0
@@ -2142,6 +2142,11 @@ static int process_banner_prefix(struct ceph_connection *con) · 2141 unmodified lines
2142 payload_len = ceph_decode_16(&p);2142 payload_len = ceph_decode_16(&p);
2143 dout("%s con %p payload_len %d\n", __func__, con, payload_len);2143 dout("%s con %p payload_len %d\n", __func__, con, payload_len);
2144 2144
2145 if (payload_len < sizeof(u64) + sizeof(u64)) {
2146 con->error_msg = "protocol error, bad banner payload len";
2147 return -EINVAL;
2148 }
2149
2145 return prepare_read_banner_payload(con, payload_len);2150 return prepare_read_banner_payload(con, payload_len);
2146}2151}
2147 2152
net/ceph/osd_client.c+30−0
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#include <linux/err.h>6#include <linux/err.h>
7#include <linux/highmem.h>7#include <linux/highmem.h>
8#include <linux/mm.h>8#include <linux/mm.h>
9#include <linux/overflow.h>
9#include <linux/pagemap.h>10#include <linux/pagemap.h>
10#include <linux/slab.h>11#include <linux/slab.h>
11#include <linux/uaccess.h>12#include <linux/uaccess.h>
@@ -5802,6 +5803,31 @@ static inline void convert_extent_map(struct ceph_sparse_read *sr) · 5790 unmodified lines
5802}5803}
5803#endif5804#endif
5804 5805
5806static bool sparse_extent_map_valid(struct ceph_sparse_read *sr)
5807{
5808 u64 req_end, pos;
5809 int i;
5810
5811 if (check_add_overflow(sr->sr_req_off, sr->sr_req_len, &req_end))
5812 return false;
5813
5814 pos = sr->sr_req_off;
5815 for (i = 0; i < sr->sr_count; i++) {
5816 struct ceph_sparse_extent *ext = &sr->sr_extent[i];
5817 u64 end;
5818
5819 if (ext->off < pos)
5820 return false;
5821 if (check_add_overflow(ext->off, ext->len, &end))
5822 return false;
5823 if (end > req_end)
5824 return false;
5825 pos = end;
5826 }
5827
5828 return true;
5829}
5830
5805static int osd_sparse_read(struct ceph_connection *con,5831static int osd_sparse_read(struct ceph_connection *con,
5806 struct ceph_msg_data_cursor *cursor,5832 struct ceph_msg_data_cursor *cursor,
5807 char **pbuf)5833 char **pbuf)
@@ -5852,6 +5878,10 @@ next_op: · 44 unmodified lines
5852 fallthrough;5878 fallthrough;
5853 case CEPH_SPARSE_READ_DATA_LEN:5879 case CEPH_SPARSE_READ_DATA_LEN:
5854 convert_extent_map(sr);5880 convert_extent_map(sr);
5881 if (!sparse_extent_map_valid(sr)) {
5882 pr_warn_ratelimited("invalid sparse extent map\n");
5883 return -EREMOTEIO;
5884 }
5855 ret = sizeof(sr->sr_datalen);5885 ret = sizeof(sr->sr_datalen);
5856 *pbuf = (char *)&sr->sr_datalen;5886 *pbuf = (char *)&sr->sr_datalen;
5857 sr->sr_state = CEPH_SPARSE_READ_DATA_PRE;5887 sr->sr_state = CEPH_SPARSE_READ_DATA_PRE;
net/ceph/osdmap.c+2−0
@@ -517,6 +517,8 @@ static struct crush_map *crush_decode(void *pbyval, void *end) · 516 unmodified lines
517 517
518 ceph_decode_need(p, end, 4*sizeof(u32), bad);518 ceph_decode_need(p, end, 4*sizeof(u32), bad);
519 b->id = ceph_decode_32(p);519 b->id = ceph_decode_32(p);
520 if (b->id != -1 - i)
521 goto bad;
520 b->type = ceph_decode_16(p);522 b->type = ceph_decode_16(p);
521 if (b->type == 0)523 if (b->type == 0)
522 goto bad;524 goto bad;
net/ceph/pagevec.c+0−13
@@ -10,19 +10,6 @@ · 9 unmodified lines
10 10
11#include <linux/ceph/libceph.h>11#include <linux/ceph/libceph.h>
12 12
13void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)
14{
15 int i;
16
17 for (i = 0; i < num_pages; i++) {
18 if (dirty)
19 set_page_dirty_lock(pages[i]);
20 put_page(pages[i]);
21 }
22 kvfree(pages);
23}
24EXPORT_SYMBOL(ceph_put_page_vector);
25
26void ceph_release_page_vector(struct page **pages, int num_pages)13void ceph_release_page_vector(struct page **pages, int num_pages)
27{14{
28 int i;15 int i;