Skip to content

Commit ac2dc6d

Browse files
committed
Merge tag 'ceph-for-7.1-rc1' of https://github.com/ceph/ceph-client
Pull ceph updates from Ilya Dryomov: "We have a series from Alex which extends CephFS client metrics with support for per-subvolume data I/O performance and latency tracking (metadata operations aren't included) and a good variety of fixes and cleanups across RBD and CephFS" * tag 'ceph-for-7.1-rc1' of https://github.com/ceph/ceph-client: ceph: add subvolume metrics collection and reporting ceph: parse subvolume_id from InodeStat v9 and store in inode ceph: handle InodeStat v8 versioned field in reply parsing libceph: Fix slab-out-of-bounds access in auth message processing rbd: fix null-ptr-deref when device_add_disk() fails crush: cleanup in crush_do_rule() method ceph: clear s_cap_reconnect when ceph_pagelist_encode_32() fails ceph: only d_add() negative dentries when they are unhashed libceph: update outdated comment in ceph_sock_write_space() libceph: Remove obsolete session key alignment logic ceph: fix num_ops off-by-one when crypto allocation fails libceph: Prevent potential null-ptr-deref in ceph_handle_auth_reply()
2 parents ff9726d + b1137e0 commit ac2dc6d

20 files changed

Lines changed: 1144 additions & 50 deletions

drivers/block/rbd.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7165,7 +7165,7 @@ static ssize_t do_rbd_add(const char *buf, size_t count)
71657165

71667166
rc = device_add_disk(&rbd_dev->dev, rbd_dev->disk, NULL);
71677167
if (rc)
7168-
goto err_out_cleanup_disk;
7168+
goto err_out_device;
71697169

71707170
spin_lock(&rbd_dev_list_lock);
71717171
list_add_tail(&rbd_dev->node, &rbd_dev_list);
@@ -7179,8 +7179,8 @@ static ssize_t do_rbd_add(const char *buf, size_t count)
71797179
module_put(THIS_MODULE);
71807180
return rc;
71817181

7182-
err_out_cleanup_disk:
7183-
rbd_free_disk(rbd_dev);
7182+
err_out_device:
7183+
device_del(&rbd_dev->dev);
71847184
err_out_image_lock:
71857185
rbd_dev_image_unlock(rbd_dev);
71867186
rbd_dev_device_release(rbd_dev);

fs/ceph/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ obj-$(CONFIG_CEPH_FS) += ceph.o
88
ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
99
export.o caps.o snap.o xattr.o quota.o io.o \
1010
mds_client.o mdsmap.o strings.o ceph_frag.o \
11-
debugfs.o util.o metric.o
11+
debugfs.o util.o metric.o subvolume_metrics.o
1212

1313
ceph-$(CONFIG_CEPH_FSCACHE) += cache.o
1414
ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o

fs/ceph/addr.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "mds_client.h"
2020
#include "cache.h"
2121
#include "metric.h"
22+
#include "subvolume_metrics.h"
2223
#include "crypto.h"
2324
#include <linux/ceph/osd_client.h>
2425
#include <linux/ceph/striper.h>
@@ -259,6 +260,10 @@ static void finish_netfs_read(struct ceph_osd_request *req)
259260
osd_data->length), false);
260261
}
261262
if (err > 0) {
263+
ceph_subvolume_metrics_record_io(fsc->mdsc, ceph_inode(inode),
264+
false, err,
265+
req->r_start_latency,
266+
req->r_end_latency);
262267
subreq->transferred = err;
263268
err = 0;
264269
}
@@ -823,6 +828,10 @@ static int write_folio_nounlock(struct folio *folio,
823828

824829
ceph_update_write_metrics(&fsc->mdsc->metric, req->r_start_latency,
825830
req->r_end_latency, len, err);
831+
if (err >= 0 && len > 0)
832+
ceph_subvolume_metrics_record_io(fsc->mdsc, ci, true, len,
833+
req->r_start_latency,
834+
req->r_end_latency);
826835
fscrypt_free_bounce_page(bounce_page);
827836
ceph_osdc_put_request(req);
828837
if (err == 0)
@@ -963,6 +972,11 @@ static void writepages_finish(struct ceph_osd_request *req)
963972
ceph_update_write_metrics(&fsc->mdsc->metric, req->r_start_latency,
964973
req->r_end_latency, len, rc);
965974

975+
if (rc >= 0 && len > 0)
976+
ceph_subvolume_metrics_record_io(mdsc, ci, true, len,
977+
req->r_start_latency,
978+
req->r_end_latency);
979+
966980
ceph_put_wrbuffer_cap_refs(ci, total_pages, snapc);
967981

968982
osd_data = osd_req_op_extent_osd_data(req, 0);
@@ -1365,6 +1379,10 @@ void ceph_process_folio_batch(struct address_space *mapping,
13651379
rc = move_dirty_folio_in_page_array(mapping, wbc, ceph_wbc,
13661380
folio);
13671381
if (rc) {
1382+
/* Did we just begin a new contiguous op? Nevermind! */
1383+
if (ceph_wbc->len == 0)
1384+
ceph_wbc->num_ops--;
1385+
13681386
folio_redirty_for_writepage(wbc, folio);
13691387
folio_unlock(folio);
13701388
break;

fs/ceph/debugfs.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,50 @@
99
#include <linux/seq_file.h>
1010
#include <linux/math64.h>
1111
#include <linux/ktime.h>
12+
#include <linux/atomic.h>
1213

1314
#include <linux/ceph/libceph.h>
1415
#include <linux/ceph/mon_client.h>
1516
#include <linux/ceph/auth.h>
1617
#include <linux/ceph/debugfs.h>
18+
#include <linux/ceph/decode.h>
1719

1820
#include "super.h"
1921

2022
#ifdef CONFIG_DEBUG_FS
2123

2224
#include "mds_client.h"
2325
#include "metric.h"
26+
#include "subvolume_metrics.h"
27+
28+
/**
29+
* struct ceph_session_feature_desc - Maps feature bits to names for debugfs
30+
* @bit: Feature bit number from enum ceph_feature_type (see mds_client.h)
31+
* @name: Human-readable feature name for debugfs output
32+
*
33+
* Used by metric_features_show() to display negotiated session features.
34+
*/
35+
struct ceph_session_feature_desc {
36+
unsigned int bit;
37+
const char *name;
38+
};
39+
40+
static const struct ceph_session_feature_desc ceph_session_feature_table[] = {
41+
{ CEPHFS_FEATURE_METRIC_COLLECT, "METRIC_COLLECT" },
42+
{ CEPHFS_FEATURE_REPLY_ENCODING, "REPLY_ENCODING" },
43+
{ CEPHFS_FEATURE_RECLAIM_CLIENT, "RECLAIM_CLIENT" },
44+
{ CEPHFS_FEATURE_LAZY_CAP_WANTED, "LAZY_CAP_WANTED" },
45+
{ CEPHFS_FEATURE_MULTI_RECONNECT, "MULTI_RECONNECT" },
46+
{ CEPHFS_FEATURE_DELEG_INO, "DELEG_INO" },
47+
{ CEPHFS_FEATURE_ALTERNATE_NAME, "ALTERNATE_NAME" },
48+
{ CEPHFS_FEATURE_NOTIFY_SESSION_STATE, "NOTIFY_SESSION_STATE" },
49+
{ CEPHFS_FEATURE_OP_GETVXATTR, "OP_GETVXATTR" },
50+
{ CEPHFS_FEATURE_32BITS_RETRY_FWD, "32BITS_RETRY_FWD" },
51+
{ CEPHFS_FEATURE_NEW_SNAPREALM_INFO, "NEW_SNAPREALM_INFO" },
52+
{ CEPHFS_FEATURE_HAS_OWNER_UIDGID, "HAS_OWNER_UIDGID" },
53+
{ CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK, "MDS_AUTH_CAPS_CHECK" },
54+
{ CEPHFS_FEATURE_SUBVOLUME_METRICS, "SUBVOLUME_METRICS" },
55+
};
2456

2557
static int mdsmap_show(struct seq_file *s, void *p)
2658
{
@@ -360,6 +392,59 @@ static int status_show(struct seq_file *s, void *p)
360392
return 0;
361393
}
362394

395+
static int subvolume_metrics_show(struct seq_file *s, void *p)
396+
{
397+
struct ceph_fs_client *fsc = s->private;
398+
struct ceph_mds_client *mdsc = fsc->mdsc;
399+
struct ceph_subvol_metric_snapshot *snapshot = NULL;
400+
u32 nr = 0;
401+
u64 total_sent = 0;
402+
u64 nonzero_sends = 0;
403+
u32 i;
404+
405+
if (!mdsc) {
406+
seq_puts(s, "mds client unavailable\n");
407+
return 0;
408+
}
409+
410+
mutex_lock(&mdsc->subvol_metrics_last_mutex);
411+
if (mdsc->subvol_metrics_last && mdsc->subvol_metrics_last_nr) {
412+
nr = mdsc->subvol_metrics_last_nr;
413+
snapshot = kmemdup_array(mdsc->subvol_metrics_last, nr,
414+
sizeof(*snapshot), GFP_KERNEL);
415+
if (!snapshot)
416+
nr = 0;
417+
}
418+
total_sent = mdsc->subvol_metrics_sent;
419+
nonzero_sends = mdsc->subvol_metrics_nonzero_sends;
420+
mutex_unlock(&mdsc->subvol_metrics_last_mutex);
421+
422+
seq_puts(s, "Last sent subvolume metrics:\n");
423+
if (!nr) {
424+
seq_puts(s, " (none)\n");
425+
} else {
426+
seq_puts(s, " subvol_id rd_ops wr_ops rd_bytes wr_bytes rd_lat_us wr_lat_us\n");
427+
for (i = 0; i < nr; i++) {
428+
const struct ceph_subvol_metric_snapshot *e = &snapshot[i];
429+
430+
seq_printf(s, " %-18llu %-9llu %-9llu %-14llu %-14llu %-14llu %-14llu\n",
431+
e->subvolume_id,
432+
e->read_ops, e->write_ops,
433+
e->read_bytes, e->write_bytes,
434+
e->read_latency_us, e->write_latency_us);
435+
}
436+
}
437+
kfree(snapshot);
438+
439+
seq_puts(s, "\nStatistics:\n");
440+
seq_printf(s, " entries_sent: %llu\n", total_sent);
441+
seq_printf(s, " non_zero_sends: %llu\n", nonzero_sends);
442+
443+
seq_puts(s, "\nPending (unsent) subvolume metrics:\n");
444+
ceph_subvolume_metrics_dump(&mdsc->subvol_metrics, s);
445+
return 0;
446+
}
447+
363448
DEFINE_SHOW_ATTRIBUTE(mdsmap);
364449
DEFINE_SHOW_ATTRIBUTE(mdsc);
365450
DEFINE_SHOW_ATTRIBUTE(caps);
@@ -369,7 +454,72 @@ DEFINE_SHOW_ATTRIBUTE(metrics_file);
369454
DEFINE_SHOW_ATTRIBUTE(metrics_latency);
370455
DEFINE_SHOW_ATTRIBUTE(metrics_size);
371456
DEFINE_SHOW_ATTRIBUTE(metrics_caps);
457+
DEFINE_SHOW_ATTRIBUTE(subvolume_metrics);
458+
459+
static int metric_features_show(struct seq_file *s, void *p)
460+
{
461+
struct ceph_fs_client *fsc = s->private;
462+
struct ceph_mds_client *mdsc = fsc->mdsc;
463+
unsigned long session_features = 0;
464+
bool have_session = false;
465+
bool metric_collect = false;
466+
bool subvol_support = false;
467+
bool metrics_enabled = false;
468+
bool subvol_enabled = false;
469+
int i;
470+
471+
if (!mdsc) {
472+
seq_puts(s, "mds client unavailable\n");
473+
return 0;
474+
}
475+
476+
mutex_lock(&mdsc->mutex);
477+
if (mdsc->metric.session) {
478+
have_session = true;
479+
session_features = mdsc->metric.session->s_features;
480+
}
481+
mutex_unlock(&mdsc->mutex);
482+
483+
if (have_session) {
484+
metric_collect =
485+
test_bit(CEPHFS_FEATURE_METRIC_COLLECT,
486+
&session_features);
487+
subvol_support =
488+
test_bit(CEPHFS_FEATURE_SUBVOLUME_METRICS,
489+
&session_features);
490+
}
491+
492+
metrics_enabled = !disable_send_metrics && have_session && metric_collect;
493+
subvol_enabled = metrics_enabled && subvol_support;
494+
495+
seq_printf(s,
496+
"metrics_enabled: %s (disable_send_metrics=%d, session=%s, metric_collect=%s)\n",
497+
metrics_enabled ? "yes" : "no",
498+
disable_send_metrics ? 1 : 0,
499+
have_session ? "yes" : "no",
500+
metric_collect ? "yes" : "no");
501+
seq_printf(s, "subvolume_metrics_enabled: %s\n",
502+
subvol_enabled ? "yes" : "no");
503+
seq_printf(s, "session_feature_bits: 0x%lx\n", session_features);
504+
505+
if (!have_session) {
506+
seq_puts(s, "(no active MDS session for metrics)\n");
507+
return 0;
508+
}
509+
510+
for (i = 0; i < ARRAY_SIZE(ceph_session_feature_table); i++) {
511+
const struct ceph_session_feature_desc *desc =
512+
&ceph_session_feature_table[i];
513+
bool set = test_bit(desc->bit, &session_features);
514+
515+
seq_printf(s, " %-24s : %s\n", desc->name,
516+
set ? "yes" : "no");
517+
}
518+
519+
return 0;
520+
}
372521

522+
DEFINE_SHOW_ATTRIBUTE(metric_features);
373523

374524
/*
375525
* debugfs
@@ -404,6 +554,7 @@ void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
404554
debugfs_remove(fsc->debugfs_caps);
405555
debugfs_remove(fsc->debugfs_status);
406556
debugfs_remove(fsc->debugfs_mdsc);
557+
debugfs_remove(fsc->debugfs_subvolume_metrics);
407558
debugfs_remove_recursive(fsc->debugfs_metrics_dir);
408559
doutc(fsc->client, "done\n");
409560
}
@@ -468,6 +619,12 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
468619
&metrics_size_fops);
469620
debugfs_create_file("caps", 0400, fsc->debugfs_metrics_dir, fsc,
470621
&metrics_caps_fops);
622+
debugfs_create_file("metric_features", 0400, fsc->debugfs_metrics_dir,
623+
fsc, &metric_features_fops);
624+
fsc->debugfs_subvolume_metrics =
625+
debugfs_create_file("subvolumes", 0400,
626+
fsc->debugfs_metrics_dir, fsc,
627+
&subvolume_metrics_fops);
471628
doutc(fsc->client, "done\n");
472629
}
473630

fs/ceph/dir.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,8 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
769769
d_drop(dentry);
770770
err = -ENOENT;
771771
} else {
772-
d_add(dentry, NULL);
772+
if (d_unhashed(dentry))
773+
d_add(dentry, NULL);
773774
}
774775
}
775776
}
@@ -840,7 +841,8 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
840841
spin_unlock(&ci->i_ceph_lock);
841842
doutc(cl, " dir %llx.%llx complete, -ENOENT\n",
842843
ceph_vinop(dir));
843-
d_add(dentry, NULL);
844+
if (d_unhashed(dentry))
845+
d_add(dentry, NULL);
844846
di->lease_shared_gen = atomic_read(&ci->i_shared_gen);
845847
return NULL;
846848
}

0 commit comments

Comments
 (0)