Skip to content

Commit ddb017e

Browse files
committed
tracing: probe-events: Cleanup entry-arg storing code
Cleanup __store_entry_arg() so that it is easier to understand. The main complexity may come from combining the loops for finding stored-entry-arg and max-offset and appending new entry. This split those different loops into 3 parts, lookup the same entry-arg, find the max offset and append new entry. Link: https://lore.kernel.org/all/174323039929.348535.4705349977127704120.stgit@devnote2/ Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
1 parent d0b3b7b commit ddb017e

1 file changed

Lines changed: 69 additions & 59 deletions

File tree

kernel/trace/trace_probe.c

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -779,15 +779,44 @@ static int check_prepare_btf_string_fetch(char *typename,
779779

780780
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
781781

782+
static void store_entry_arg_at(struct fetch_insn *code, int argnum, int offset)
783+
{
784+
code[0].op = FETCH_OP_ARG;
785+
code[0].param = argnum;
786+
code[1].op = FETCH_OP_ST_EDATA;
787+
code[1].offset = offset;
788+
}
789+
790+
static int get_entry_arg_max_offset(struct probe_entry_arg *earg)
791+
{
792+
int i, max_offset = 0;
793+
794+
/*
795+
* earg->code[] array has an operation sequence which is run in
796+
* the entry handler.
797+
* The sequence stopped by FETCH_OP_END and each data stored in
798+
* the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA
799+
* stores the data at the data buffer + its offset, and all data are
800+
* "unsigned long" size. The offset must be increased when a data is
801+
* stored. Thus we need to find the last FETCH_OP_ST_EDATA in the
802+
* code array.
803+
*/
804+
for (i = 0; i < earg->size - 1 && earg->code[i].op != FETCH_OP_END; i++) {
805+
if (earg->code[i].op == FETCH_OP_ST_EDATA)
806+
if (earg->code[i].offset > max_offset)
807+
max_offset = earg->code[i].offset;
808+
}
809+
return max_offset;
810+
}
811+
782812
/*
783813
* Add the entry code to store the 'argnum'th parameter and return the offset
784814
* in the entry data buffer where the data will be stored.
785815
*/
786816
static int __store_entry_arg(struct trace_probe *tp, int argnum)
787817
{
788818
struct probe_entry_arg *earg = tp->entry_arg;
789-
bool match = false;
790-
int i, offset;
819+
int i, offset, last_offset = 0;
791820

792821
if (!earg) {
793822
earg = kzalloc(sizeof(*tp->entry_arg), GFP_KERNEL);
@@ -804,78 +833,59 @@ static int __store_entry_arg(struct trace_probe *tp, int argnum)
804833
for (i = 0; i < earg->size; i++)
805834
earg->code[i].op = FETCH_OP_END;
806835
tp->entry_arg = earg;
836+
store_entry_arg_at(earg->code, argnum, 0);
837+
return 0;
807838
}
808839

809840
/*
810-
* The entry code array is repeating the pair of
811-
* [FETCH_OP_ARG(argnum)][FETCH_OP_ST_EDATA(offset of entry data buffer)]
812-
* and the rest of entries are filled with [FETCH_OP_END].
841+
* NOTE: if anyone change the following rule, please rewrite this.
842+
* The entry code array is filled with the pair of
843+
*
844+
* [FETCH_OP_ARG(argnum)]
845+
* [FETCH_OP_ST_EDATA(offset of entry data buffer)]
813846
*
814-
* To reduce the redundant function parameter fetching, we scan the entry
815-
* code array to find the FETCH_OP_ARG which already fetches the 'argnum'
816-
* parameter. If it doesn't match, update 'offset' to find the last
817-
* offset.
818-
* If we find the FETCH_OP_END without matching FETCH_OP_ARG entry, we
819-
* will save the entry with FETCH_OP_ARG and FETCH_OP_ST_EDATA, and
820-
* return data offset so that caller can find the data offset in the entry
821-
* data buffer.
847+
* and the rest of entries are filled with [FETCH_OP_END].
848+
* The offset should be incremented, thus the last pair should
849+
* have the largest offset.
822850
*/
823-
offset = 0;
824-
for (i = 0; i < earg->size - 1; i++) {
825-
switch (earg->code[i].op) {
826-
case FETCH_OP_END:
827-
earg->code[i].op = FETCH_OP_ARG;
828-
earg->code[i].param = argnum;
829-
earg->code[i + 1].op = FETCH_OP_ST_EDATA;
830-
earg->code[i + 1].offset = offset;
831-
return offset;
832-
case FETCH_OP_ARG:
833-
match = (earg->code[i].param == argnum);
834-
break;
835-
case FETCH_OP_ST_EDATA:
836-
offset = earg->code[i].offset;
837-
if (match)
838-
return offset;
839-
offset += sizeof(unsigned long);
840-
break;
841-
default:
842-
break;
843-
}
851+
852+
/* Search the offset for the sprcified argnum. */
853+
for (i = 0; i < earg->size - 1 && earg->code[i].op != FETCH_OP_END; i += 2) {
854+
if (WARN_ON_ONCE(earg->code[i].op != FETCH_OP_ARG))
855+
return -EINVAL;
856+
857+
if (earg->code[i].param != argnum)
858+
continue;
859+
860+
if (WARN_ON_ONCE(earg->code[i + 1].op != FETCH_OP_ST_EDATA))
861+
return -EINVAL;
862+
863+
return earg->code[i + 1].offset;
844864
}
845-
return -ENOSPC;
865+
/* Not found, append new entry if possible. */
866+
if (i >= earg->size - 1)
867+
return -ENOSPC;
868+
869+
/* The last entry must have the largest offset. */
870+
if (i != 0) {
871+
if (WARN_ON_ONCE(earg->code[i - 1].op != FETCH_OP_ST_EDATA))
872+
return -EINVAL;
873+
last_offset = earg->code[i - 1].offset;
874+
}
875+
876+
offset = last_offset + sizeof(unsigned long);
877+
store_entry_arg_at(&earg->code[i], argnum, offset);
878+
return offset;
846879
}
847880

848881
int traceprobe_get_entry_data_size(struct trace_probe *tp)
849882
{
850883
struct probe_entry_arg *earg = tp->entry_arg;
851-
int i, size = 0;
852884

853885
if (!earg)
854886
return 0;
855887

856-
/*
857-
* earg->code[] array has an operation sequence which is run in
858-
* the entry handler.
859-
* The sequence stopped by FETCH_OP_END and each data stored in
860-
* the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA
861-
* stores the data at the data buffer + its offset, and all data are
862-
* "unsigned long" size. The offset must be increased when a data is
863-
* stored. Thus we need to find the last FETCH_OP_ST_EDATA in the
864-
* code array.
865-
*/
866-
for (i = 0; i < earg->size; i++) {
867-
switch (earg->code[i].op) {
868-
case FETCH_OP_END:
869-
goto out;
870-
case FETCH_OP_ST_EDATA:
871-
size = earg->code[i].offset + sizeof(unsigned long);
872-
break;
873-
default:
874-
break;
875-
}
876-
}
877-
out:
878-
return size;
888+
return get_entry_arg_max_offset(earg) + sizeof(unsigned long);
879889
}
880890

881891
void store_trace_entry_data(void *edata, struct trace_probe *tp, struct pt_regs *regs)

0 commit comments

Comments
 (0)