Whamcloud - gitweb
git://git.whamcloud.com
/
fs
/
lustre-release.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
| inline |
side by side
LU-2360 ptlrpc: a few fixes for req_history read
[fs/lustre-release.git]
/
lustre
/
ptlrpc
/
lproc_ptlrpc.c
diff --git
a/lustre/ptlrpc/lproc_ptlrpc.c
b/lustre/ptlrpc/lproc_ptlrpc.c
index
0d6ceec
..
ab7d146
100644
(file)
--- a/
lustre/ptlrpc/lproc_ptlrpc.c
+++ b/
lustre/ptlrpc/lproc_ptlrpc.c
@@
-111,6
+111,7
@@
struct ll_rpc_opcode {
{ OBD_PING, "obd_ping" },
{ OBD_LOG_CANCEL, "llog_origin_handle_cancel" },
{ OBD_QC_CALLBACK, "obd_quota_callback" },
+ { OBD_IDX_READ, "dt_index_read" },
{ LLOG_ORIGIN_HANDLE_CREATE, "llog_origin_handle_create" },
{ LLOG_ORIGIN_HANDLE_NEXT_BLOCK, "llog_origin_handle_next_block" },
{ LLOG_ORIGIN_HANDLE_READ_HEADER,"llog_origin_handle_read_header" },
@@
-251,30
+252,44
@@
ptlrpc_lprocfs_read_req_history_len(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct ptlrpc_service *svc = data;
+ struct ptlrpc_service_part *svcpt;
+ int total = 0;
+ int i;
*eof = 1;
- return snprintf(page, count, "%d\n", svc->srv_part->scp_hist_nrqbds);
+
+ ptlrpc_service_for_each_part(svcpt, i, svc)
+ total += svcpt->scp_hist_nrqbds;
+
+ return snprintf(page, count, "%d\n", total);
}
static int
ptlrpc_lprocfs_read_req_history_max(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
- struct ptlrpc_service *svc = data;
+ struct ptlrpc_service *svc = data;
+ struct ptlrpc_service_part *svcpt;
+ int total = 0;
+ int i;
+
+ *eof = 1;
+ ptlrpc_service_for_each_part(svcpt, i, svc)
+ total += svc->srv_hist_nrqbds_cpt_max;
- *eof = 1;
- return snprintf(page, count, "%d\n", svc->srv_max_history_rqbds);
+ return snprintf(page, count, "%d\n", total);
}
static int
ptlrpc_lprocfs_write_req_history_max(struct file *file, const char *buffer,
unsigned long count, void *data)
{
-
struct ptlrpc_service
*svc = data;
-
int
bufpages;
-
int
val;
-
int rc = lprocfs_write_helper(buffer, count, &val)
;
+
struct ptlrpc_service
*svc = data;
+
int
bufpages;
+
int
val;
+
int rc
;
+ rc = lprocfs_write_helper(buffer, count, &val);
if (rc < 0)
return rc;
@@
-288,44
+303,51
@@
ptlrpc_lprocfs_write_req_history_max(struct file *file, const char *buffer,
if (val > cfs_num_physpages/(2 * bufpages))
return -ERANGE;
- cfs_spin_lock(&svc->srv_lock);
- svc->srv_max_history_rqbds = val;
- cfs_spin_unlock(&svc->srv_lock);
+ spin_lock(&svc->srv_lock);
+
+ if (val == 0)
+ svc->srv_hist_nrqbds_cpt_max = 0;
+ else
+ svc->srv_hist_nrqbds_cpt_max = max(1, (val / svc->srv_ncpts));
+
+ spin_unlock(&svc->srv_lock);
return count;
}
static int
ptlrpc_lprocfs_rd_threads_min(char *page, char **start, off_t off,
-
int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
-
struct ptlrpc_service *svc = data;
+ struct ptlrpc_service *svc = data;
- return snprintf(page, count, "%d\n", svc->srv_threads_min);
+ return snprintf(page, count, "%d\n",
+ svc->srv_nthrs_cpt_init * svc->srv_ncpts);
}
static int
ptlrpc_lprocfs_wr_threads_min(struct file *file, const char *buffer,
unsigned long count, void *data)
{
-
struct ptlrpc_service
*svc = data;
-
int
val;
-
int
rc = lprocfs_write_helper(buffer, count, &val);
+
struct ptlrpc_service
*svc = data;
+
int
val;
+
int
rc = lprocfs_write_helper(buffer, count, &val);
-
if (rc < 0)
-
return rc;
+ if (rc < 0)
+ return rc;
-
if (val < 2
)
-
return -ERANGE;
+
if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT
)
+ return -ERANGE;
-
cfs_
spin_lock(&svc->srv_lock);
- if (val > svc->srv_
threads_max
) {
-
cfs_
spin_unlock(&svc->srv_lock);
+ spin_lock(&svc->srv_lock);
+ if (val > svc->srv_
nthrs_cpt_limit * svc->srv_ncpts
) {
+ spin_unlock(&svc->srv_lock);
return -ERANGE;
}
- svc->srv_threads_min = val;
- cfs_spin_unlock(&svc->srv_lock);
+ svc->srv_nthrs_cpt_init = val / svc->srv_ncpts;
+
+ spin_unlock(&svc->srv_lock);
return count;
}
@@
-335,50
+357,58
@@
ptlrpc_lprocfs_rd_threads_started(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct ptlrpc_service *svc = data;
+ struct ptlrpc_service_part *svcpt;
+ int total = 0;
+ int i;
- LASSERT(svc->srv_part != NULL);
- return snprintf(page, count, "%d\n",
- svc->srv_part->scp_nthrs_running);
+ LASSERT(svc->srv_parts != NULL);
+ ptlrpc_service_for_each_part(svcpt, i, svc)
+ total += svcpt->scp_nthrs_running;
+
+ return snprintf(page, count, "%d\n", total);
}
static int
ptlrpc_lprocfs_rd_threads_max(char *page, char **start, off_t off,
-
int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
-
struct ptlrpc_service *svc = data;
+ struct ptlrpc_service *svc = data;
- return snprintf(page, count, "%d\n", svc->srv_threads_max);
+ return snprintf(page, count, "%d\n",
+ svc->srv_nthrs_cpt_limit * svc->srv_ncpts);
}
static int
ptlrpc_lprocfs_wr_threads_max(struct file *file, const char *buffer,
-
unsigned long count, void *data)
+ unsigned long count, void *data)
{
-
struct ptlrpc_service *svc = data;
-
int
val;
-
int
rc = lprocfs_write_helper(buffer, count, &val);
+ struct ptlrpc_service *svc = data;
+
int
val;
+
int
rc = lprocfs_write_helper(buffer, count, &val);
-
if (rc < 0)
-
return rc;
+ if (rc < 0)
+ return rc;
-
if (val < 2
)
-
return -ERANGE;
+
if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT
)
+ return -ERANGE;
-
cfs_
spin_lock(&svc->srv_lock);
- if (val < svc->srv_
threads_min
) {
-
cfs_
spin_unlock(&svc->srv_lock);
+ spin_lock(&svc->srv_lock);
+ if (val < svc->srv_
nthrs_cpt_init * svc->srv_ncpts
) {
+ spin_unlock(&svc->srv_lock);
return -ERANGE;
}
- svc->srv_threads_max = val;
- cfs_spin_unlock(&svc->srv_lock);
+ svc->srv_nthrs_cpt_limit = val / svc->srv_ncpts;
+
+ spin_unlock(&svc->srv_lock);
return count;
}
struct ptlrpc_srh_iterator {
- __u64 srhi_seq;
- struct ptlrpc_request *srhi_req;
+ int srhi_idx;
+ __u64 srhi_seq;
+ struct ptlrpc_request *srhi_req;
};
int
@@
-398,8
+428,15
@@
ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt,
* Since the service history is LRU (i.e. culled reqs will
* be near the head), we shouldn't have to do long
* re-scans */
- LASSERT (srhi->srhi_seq == srhi->srhi_req->rq_history_seq);
- LASSERT(!cfs_list_empty(&svcpt->scp_hist_reqs));
+ LASSERTF(srhi->srhi_seq == srhi->srhi_req->rq_history_seq,
+ "%s:%d: seek seq "LPU64", request seq "LPU64"\n",
+ svcpt->scp_service->srv_name, svcpt->scp_cpt,
+ srhi->srhi_seq, srhi->srhi_req->rq_history_seq);
+ LASSERTF(!cfs_list_empty(&svcpt->scp_hist_reqs),
+ "%s:%d: seek offset "LPU64", request seq "LPU64", "
+ "last culled "LPU64"\n",
+ svcpt->scp_service->srv_name, svcpt->scp_cpt,
+ seq, srhi->srhi_seq, svcpt->scp_hist_seq_culled);
e = &srhi->srhi_req->rq_history_list;
} else {
/* search from start */
@@
-420,31
+457,83
@@
ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt,
return -ENOENT;
}
+/*
+ * ptlrpc history sequence is used as "position" of seq_file, in some case,
+ * seq_read() will increase "position" to indicate reading the next
+ * element, however, low bits of history sequence are reserved for CPT id
+ * (check the details from comments before ptlrpc_req_add_history), which
+ * means seq_read() might change CPT id of history sequence and never
+ * finish reading of requests on a CPT. To make it work, we have to shift
+ * CPT id to high bits and timestamp to low bits, so seq_read() will only
+ * increase timestamp which can correctly indicate the next position.
+ */
+
+/* convert seq_file pos to cpt */
+#define PTLRPC_REQ_POS2CPT(svc, pos) \
+ ((svc)->srv_cpt_bits == 0 ? 0 : \
+ (__u64)(pos) >> (64 - (svc)->srv_cpt_bits))
+
+/* make up seq_file pos from cpt */
+#define PTLRPC_REQ_CPT2POS(svc, cpt) \
+ ((svc)->srv_cpt_bits == 0 ? 0 : \
+ (cpt) << (64 - (svc)->srv_cpt_bits))
+
+/* convert sequence to position */
+#define PTLRPC_REQ_SEQ2POS(svc, seq) \
+ ((svc)->srv_cpt_bits == 0 ? (seq) : \
+ ((seq) >> (svc)->srv_cpt_bits) | \
+ ((seq) << (64 - (svc)->srv_cpt_bits)))
+
+/* convert position to sequence */
+#define PTLRPC_REQ_POS2SEQ(svc, pos) \
+ ((svc)->srv_cpt_bits == 0 ? (pos) : \
+ ((__u64)(pos) << (svc)->srv_cpt_bits) | \
+ ((__u64)(pos) >> (64 - (svc)->srv_cpt_bits)))
+
static void *
ptlrpc_lprocfs_svc_req_history_start(struct seq_file *s, loff_t *pos)
{
- struct ptlrpc_service *svc = s->private;
- struct ptlrpc_srh_iterator *srhi;
- int rc;
-
- OBD_ALLOC(srhi, sizeof(*srhi));
- if (srhi == NULL)
- return NULL;
-
- srhi->srhi_seq = 0;
- srhi->srhi_req = NULL;
+ struct ptlrpc_service *svc = s->private;
+ struct ptlrpc_service_part *svcpt;
+ struct ptlrpc_srh_iterator *srhi;
+ unsigned int cpt;
+ int rc;
+ int i;
- cfs_spin_lock(&svc->srv_part->scp_lock);
- rc = ptlrpc_lprocfs_svc_req_history_seek(svc->srv_part, srhi, *pos);
- cfs_spin_unlock(&svc->srv_part->scp_lock);
+ if (sizeof(loff_t) != sizeof(__u64)) { /* can't support */
+ CWARN("Failed to read request history because size of loff_t "
+ "%d can't match size of u64\n", (int)sizeof(loff_t));
+ return NULL;
+ }
- if (rc == 0) {
- *pos = srhi->srhi_seq;
- return srhi;
- }
+ OBD_ALLOC(srhi, sizeof(*srhi));
+ if (srhi == NULL)
+ return NULL;
+
+ srhi->srhi_seq = 0;
+ srhi->srhi_req = NULL;
+
+ cpt = PTLRPC_REQ_POS2CPT(svc, *pos);
+
+ ptlrpc_service_for_each_part(svcpt, i, svc) {
+ if (i < cpt) /* skip */
+ continue;
+ if (i > cpt) /* make up the lowest position for this CPT */
+ *pos = PTLRPC_REQ_CPT2POS(svc, i);
+
+ spin_lock(&svcpt->scp_lock);
+ rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi,
+ PTLRPC_REQ_POS2SEQ(svc, *pos));
+ spin_unlock(&svcpt->scp_lock);
+ if (rc == 0) {
+ *pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq);
+ srhi->srhi_idx = i;
+ return srhi;
+ }
+ }
-
OBD_FREE(srhi, sizeof(*srhi));
-
return NULL;
+ OBD_FREE(srhi, sizeof(*srhi));
+ return NULL;
}
static void
@@
-461,21
+550,34
@@
ptlrpc_lprocfs_svc_req_history_next(struct seq_file *s,
void *iter, loff_t *pos)
{
struct ptlrpc_service *svc = s->private;
- struct ptlrpc_service_part *svcpt = svc->srv_part;
struct ptlrpc_srh_iterator *srhi = iter;
+ struct ptlrpc_service_part *svcpt;
+ __u64 seq;
int rc;
+ int i;
+
+ for (i = srhi->srhi_idx; i < svc->srv_ncpts; i++) {
+ svcpt = svc->srv_parts[i];
+
+ if (i > srhi->srhi_idx) { /* reset iterator for a new CPT */
+ srhi->srhi_req = NULL;
+ seq = srhi->srhi_seq = 0;
+ } else { /* the next sequence */
+ seq = srhi->srhi_seq + (1 << svc->srv_cpt_bits);
+ }
+
+ spin_lock(&svcpt->scp_lock);
+ rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, seq);
+ spin_unlock(&svcpt->scp_lock);
+ if (rc == 0) {
+ *pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq);
+ srhi->srhi_idx = i;
+ return srhi;
+ }
+ }
- cfs_spin_lock(&svcpt->scp_lock);
- rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, *pos + 1);
- cfs_spin_unlock(&svcpt->scp_lock);
-
- if (rc != 0) {
- OBD_FREE(srhi, sizeof(*srhi));
- return NULL;
- }
-
- *pos = srhi->srhi_seq;
- return srhi;
+ OBD_FREE(srhi, sizeof(*srhi));
+ return NULL;
}
/* common ost/mdt so_req_printer */
@@
-511,12
+613,16
@@
EXPORT_SYMBOL(target_print_req);
static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
{
struct ptlrpc_service *svc = s->private;
- struct ptlrpc_service_part *svcpt = svc->srv_part;
struct ptlrpc_srh_iterator *srhi = iter;
+ struct ptlrpc_service_part *svcpt;
struct ptlrpc_request *req;
int rc;
- cfs_spin_lock(&svcpt->scp_lock);
+ LASSERT(srhi->srhi_idx < svc->srv_ncpts);
+
+ svcpt = svc->srv_parts[srhi->srhi_idx];
+
+ spin_lock(&svcpt->scp_lock);
rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, srhi->srhi_seq);
@@
-542,7
+648,7
@@
static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
svc->srv_ops.so_req_printer(s, srhi->srhi_req);
}
-
cfs_
spin_unlock(&svcpt->scp_lock);
+ spin_unlock(&svcpt->scp_lock);
return rc;
}
@@
-581,25
+687,50
@@
static int ptlrpc_lprocfs_rd_timeouts(char *page, char **start, off_t off,
time_t worstt;
unsigned int cur;
unsigned int worst;
+ int nob = 0;
int rc = 0;
+ int i;
- svcpt = svc->srv_part;
- LASSERT(svcpt != NULL);
+ LASSERT(svc->srv_parts != NULL);
+
+ if (AT_OFF) {
+ rc += snprintf(page + rc, count - rc,
+ "adaptive timeouts off, using obd_timeout %u\n",
+ obd_timeout);
+ return rc;
+ }
+
+ ptlrpc_service_for_each_part(svcpt, i, svc) {
+ cur = at_get(&svcpt->scp_at_estimate);
+ worst = svcpt->scp_at_estimate.at_worst_ever;
+ worstt = svcpt->scp_at_estimate.at_worst_time;
+ s2dhms(&ts, cfs_time_current_sec() - worstt);
+
+ nob = snprintf(page, count,
+ "%10s : cur %3u worst %3u (at %ld, "
+ DHMS_FMT" ago) ", "service",
+ cur, worst, worstt, DHMS_VARS(&ts));
+
+ nob = lprocfs_at_hist_helper(page, count, nob,
+ &svcpt->scp_at_estimate);
+ rc += nob;
+ page += nob;
+ count -= nob;
+
+ /*
+ * NB: for lustre proc read, the read count must be less
+ * than PAGE_SIZE, please see details in lprocfs_fops_read.
+ * It's unlikely that we exceed PAGE_SIZE at here because
+ * it means the service has more than 50 partitions.
+ */
+ if (count <= 0) {
+ CWARN("Can't fit AT information of %s in one page, "
+ "please contact with developer to fix this.\n",
+ svc->srv_name);
+ break;
+ }
+ }
- *eof = 1;
- cur = at_get(&svcpt->scp_at_estimate);
- worst = svcpt->scp_at_estimate.at_worst_ever;
- worstt = svcpt->scp_at_estimate.at_worst_time;
- s2dhms(&ts, cfs_time_current_sec() - worstt);
- if (AT_OFF)
- rc += snprintf(page + rc, count - rc,
- "adaptive timeouts off, using obd_timeout %u\n",
- obd_timeout);
- rc += snprintf(page + rc, count - rc,
- "%10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
- "service", cur, worst, worstt,
- DHMS_VARS(&ts));
- rc = lprocfs_at_hist_helper(page, count, rc, &svcpt->scp_at_estimate);
return rc;
}
@@
-612,20
+743,22
@@
static int ptlrpc_lprocfs_rd_hp_ratio(char *page, char **start, off_t off,
}
static int ptlrpc_lprocfs_wr_hp_ratio(struct file *file, const char *buffer,
-
unsigned long count, void *data)
+ unsigned long count, void *data)
{
- struct ptlrpc_service *svc = data;
- int rc, val;
+ struct ptlrpc_service *svc = data;
+ int rc;
+ int val;
- rc = lprocfs_write_helper(buffer, count, &val);
- if (rc < 0)
- return rc;
- if (val < 0)
- return -ERANGE;
+ rc = lprocfs_write_helper(buffer, count, &val);
+ if (rc < 0)
+ return rc;
- cfs_spin_lock(&svc->srv_lock);
+ if (val < 0)
+ return -ERANGE;
+
+ spin_lock(&svc->srv_lock);
svc->srv_hpreq_ratio = val;
-
cfs_
spin_unlock(&svc->srv_lock);
+ spin_unlock(&svc->srv_lock);
return count;
}
@@
-787,8
+920,8
@@
int lprocfs_wr_evict_client(struct file *file, const char *buffer,
* the proc entries under the being destroyed export{}, so I have
* to drop the lock at first here.
* - jay, jxiong@clusterfs.com */
- class_incref(obd, __FUNCTION__, cfs_current());
LPROCFS_EXIT();
+ class_incref(obd, __FUNCTION__, cfs_current());
if (strncmp(tmpbuf, "nid:", 4) == 0)
obd_export_evict_by_nid(obd, tmpbuf + 4);
@@
-797,8
+930,8
@@
int lprocfs_wr_evict_client(struct file *file, const char *buffer,
else
obd_export_evict_by_uuid(obd, tmpbuf);
+ class_decref(obd, __FUNCTION__, cfs_current());
LPROCFS_ENTRY();
- class_decref(obd, __FUNCTION__, cfs_current());
out:
OBD_FREE(kbuf, BUFLEN);
@@
-930,12
+1063,12
@@
int lprocfs_wr_pinger_recov(struct file *file, const char *buffer,
return -ERANGE;
LPROCFS_CLIMP_CHECK(obd);
-
cfs_
spin_lock(&imp->imp_lock);
-
imp->imp_no_pinger_recover = !val;
-
cfs_
spin_unlock(&imp->imp_lock);
-
LPROCFS_CLIMP_EXIT(obd);
+ spin_lock(&imp->imp_lock);
+ imp->imp_no_pinger_recover = !val;
+ spin_unlock(&imp->imp_lock);
+ LPROCFS_CLIMP_EXIT(obd);
-
return count;
+ return count;
}
EXPORT_SYMBOL(lprocfs_wr_pinger_recov);