Linux magnum numerum instrumentorum habet ad debugging nucleum et applicationes. Plerique eorum negativam habent in effectu applicationis et in productione adhiberi non possunt.
A duobus annos erat
Iam multae sunt applicationes utilitates quae eBPF utuntur, et in hoc articulo videbimus quomodo scribere utilitatem tuam in bibliotheca profiling.
Ceph tarda
Ad Ceph botrum nova hostia addita est. Postquam nonnullae notitiae ad eam migrarunt, animadvertimus celeritatem processus scribendi petitiones multo inferiores esse quam in aliis servientibus.
Dissimilis alia tabulata, hospes hic bcache usus est et nova linux 4.15 nucleus. Hoc primum hospita huius configurationis adhibita est. Et tunc apparebat radicem problematis posse speculari aliquid esse.
Hostiam perscrutandis
Incipiamus aspicere quid intra processum Ceph-osd fiat. Hoc enim utemur
Imago docet munus fdatasync () Multum temporis consumpta petentibus munera generic_make_request (). Hoc significat verisimile causam problematum alicubi esse extra ipsum daemonem osd. Hoc vel acinum vel orbis esse potest. Iostat output ostendit altam latentiam in processu petitionibus per orbes subcinericios.
Cum exercitum reprehendo, invenimus daemonem systemd-udevd magnam quantitatem temporis CPU - circiter XX% in aliquot nucleis consumere. Moribus mirum est, sic debes cognoscere quare. Cum Systemd-udevd opera cum uevents, ea perspicere decrevimus udevadm monitor. Evenit ut magnus numerus mutationum eventuum pro unoquoque stipite in systematis fabrica generaretur. Hoc satis inusitatum est, ut inspicere debebimus haec omnia generantem eventa.
BCC Toolkit utens
Ut iam compertum est, nucleus (et ceph daemoniacus in systemate vocatus) multum temporis impendit in generic_make_request (). Studeamus celeritatem huius muneris metiri. IN'
Pluma celeriter operatur plerumque. Omnia facit ad petitionem fabrica coegi queue transiet.
Bcache est complexus fabrica quae consistit in tribus orbis:
- in hoc casu lento HDD est;
- caching fabrica (caching disk), hic haec est una partitio NVMe fabrica;
- bcache virtualis fabrica quo applicatio decurrit.
Scimus quod petitio tradenda tardum est, sed uter horum machinis? De hoc paulo post agemus.
Nunc scimus ueventa causa problemata esse verisimile. Quaenam earum generatio non tam facile causat. Ponamus hanc esse speciem aliquam programmatum quae periodice immissa est. Videamus quid genus programmatum currit in systemate utendi scripto execsnoop ex eodem
Exempli gratia sic:
/usr/share/bcc/tools/execsnoop | tee ./execdump
Plenum execsnoop hic exitum non demonstrabimus, sed una linea usuris nobis sic visa est:
sh 1764905 5802 0 sudo arcconf getconfig 1 AD | grep Temperature | awk -F '[:/]' '{print $2}' | sed 's/^ ([0-9]*) C.*/1/'
Tertia columna est PPID (parentis PID) processus. Processus cum PID 5802 evasit unum e sequelis systematis nostrae vigilantiae. Cum de configuratione magna ratio deprimenda, parametri erronei inventi sunt. Temperatura adaptoris HBA singulis 30 secundis capta est, quae multo saepius quam necesse est. Mutata perscriptio temporis ad longiorem, invenimus petitionem processus latendi in hoc exercitu non amplius prominens cum aliis exercitibus.
Sed adhuc incertum est cur bcache fabrica tam tardus sit. Praeparavimus testam suggestum cum identitate configurationis et conati sunt exprimere problema currendo fio in bcache, intervenit felis udevadm currens ad generandum uevents.
Scribens BCC-Substructio Tools
Studeamus scribere utilitatem simplicem indagare et tardissimam vocat ostendere generic_make_request (). Nos quoque quaero nomine coegi pro quo hoc munus appellabatur.
Consilium simplex est;
- Register kprobe on generic_make_request ():
- Nomen orbis servamus in memoriam, pervium per munus argumentum;
- Nulla in tincidunt nisi.
- Register kretprobe nam reditus ex * generic_make_request ():
- Praesens indicationem obtinemus;
- Indicationem servatam exspectamus et cum hodierna comparamus;
- Si effectus maior est quam determinatum, tunc nomen orbis servatum invenimus et in termino demonstrabimus.
Kprobes ΠΈ kretprobes utor a mechanism breakpoint ad mutationem functionis codicem in musca. Potes legere
Textus eBPF intra scriptionem Pythonis hoc modo spectat:
bpf_text = βββ # Here will be the bpf program code βββ
Ad commutationem notitia inter munera, programmata eBPF
struct data_t {
u64 pid;
u64 ts;
char comm[TASK_COMM_LEN];
u64 lat;
char disk[DISK_NAME_LEN];
};
BPF_HASH(p, u64, struct data_t);
BPF_PERF_OUTPUT(events);
Hic subcriptio tabulam Nullam dicta pCum clavem type u64 et valorem generis instruere data_t. Mensa in contextu programmatis BPF praesto erit. BPF_PERF_OUTPUT tabulam tortor aliam tabulam quae vocatur rerum, quod ponitur pro
Cum moras metiaris inter vocans munus et inde reverti, vel inter vocationes ad diversa munera, considerare debes data recepta ad eundem contextum pertinere. Aliis verbis, meminisse debes de functionibus parallelis possibilibus. Facultatem habemus latency metiri inter munus vocandi in contextu unius processus et ab illo munere in contextum alterius processus reverti, sed hoc verisimile inutile est. Exemplum bonum hic erit
Deinceps scribendus est codicem qui decurret cum munus sub studio appellatur;
void start(struct pt_regs *ctx, struct bio *bio) {
u64 pid = bpf_get_current_pid_tgid();
struct data_t data = {};
u64 ts = bpf_ktime_get_ns();
data.pid = pid;
data.ts = ts;
bpf_probe_read_str(&data.disk, sizeof(data.disk), (void*)bio->bi_disk->disk_name);
p.update(&pid, &data);
}
Prima ratio functionis vocati hic substituetur pro secundo argumento
Munus sequens vocabitur in reditu a generic_make_request ():
void stop(struct pt_regs *ctx) {
u64 pid = bpf_get_current_pid_tgid();
u64 ts = bpf_ktime_get_ns();
struct data_t* data = p.lookup(&pid);
if (data != 0 && data->ts > 0) {
bpf_get_current_comm(&data->comm, sizeof(data->comm));
data->lat = (ts - data->ts)/1000;
if (data->lat > MIN_US) {
FACTOR
data->pid >>= 32;
events.perf_submit(ctx, data, sizeof(struct data_t));
}
p.delete(&pid);
}
}
Hoc munus priori simile est: invenimus PID processus et indicatione, sed memoriam pro nova data structura non collocant. Sed quaerimus tabulam detrahere pro structura iam exsistente clavis == currenti PID. Si structura inveniatur, inueniemus nomen processus currens et adiciemus ei.
Trabea binaria hic utimur necesse est ut filum GID accipiamus. illae. PID processus principalis, qui filum incepit in contextu cuius operamur. Munus vocamus
Cum terminatio ad terminum, non currently in flumine quaeritur, sed in processu principali interest. Ubi morae inde comparato dato limine, structuram nostram transeamus Data in user spatium per mensam rerum, post quod ingressum delemus e p.
In pythonis scriptione quae hunc codicem oneret, MIN_US et factor in mora liminum ac temporum unitates reponere necesse est, quae per argumenta transibimus:
bpf_text = bpf_text.replace('MIN_US',str(min_usec))
if args.milliseconds:
bpf_text = bpf_text.replace('FACTOR','data->lat /= 1000;')
label = "msec"
else:
bpf_text = bpf_text.replace('FACTOR','')
label = "usec"
Nunc opus est programmata BPF praeparare per
b = BPF(text=bpf_text)
b.attach_kprobe(event="generic_make_request",fn_name="start")
b.attach_kretprobe(event="generic_make_request",fn_name="stop")
Volumus etiam determinare instruere data_t in nostro scripto, aliter aliquid legere non valemus;
TASK_COMM_LEN = 16 # linux/sched.h
DISK_NAME_LEN = 32 # linux/genhd.h
class Data(ct.Structure):
_fields_ = [("pid", ct.c_ulonglong),
("ts", ct.c_ulonglong),
("comm", ct.c_char * TASK_COMM_LEN),
("lat", ct.c_ulonglong),
("disk",ct.c_char * DISK_NAME_LEN)]
Ultimus gradus est notitia output ad terminum:
def print_event(cpu, data, size):
global start
event = ct.cast(data, ct.POINTER(Data)).contents
if start == 0:
start = event.ts
time_s = (float(event.ts - start)) / 1000000000
print("%-18.9f %-16s %-6d %-1s %s %s" % (time_s, event.comm, event.pid, event.lat, label, event.disk))
b["events"].open_perf_buffer(print_event)
# format output
start = 0
while 1:
try:
b.perf_buffer_poll()
except KeyboardInterrupt:
exit()
Scriptum est ipsum at
Denique! Videmus autem quod quasi fabrica stabularii beache machinam vocamus actualiter generic_make_request () conditivo in disco.
Fode in Kernel
Quidnam retardatio in petitione tradenda? Moram fieri videmus etiam ante rationem petitionis initium, i.e. de ratione petitionis specificae statisticae ulterioris output in ea (/proc/diskstats vel iostat) nondum incohata est. Hoc facile verificatur per currendo iostat producendo problema, vel
Si munus intueri generic_make_request ()tunc videbimus quod antequam petitio incipit ratiocinari, plura duo functiones vocantur. Primis - generic_make_request_checks ()peragit impediunt legitimam petitionem circa ordines orbis. Secundus -
ret = wait_event_interruptible(q->mq_freeze_wq,
(atomic_read(&q->mq_freeze_depth) == 0 &&
(preempt || !blk_queue_preempt_only(q))) ||
blk_queue_dying(q));
In ea, nucleus exspectat queue ut ungatur. Metimur mora blk_queue_enter():
~# /usr/share/bcc/tools/funclatency blk_queue_enter -i 1 -m
Tracing 1 functions for "blk_queue_enter"... Hit Ctrl-C to end.
msecs : count distribution
0 -> 1 : 341 |****************************************|
msecs : count distribution
0 -> 1 : 316 |****************************************|
msecs : count distribution
0 -> 1 : 255 |****************************************|
2 -> 3 : 0 | |
4 -> 7 : 0 | |
8 -> 15 : 1 | |
Similis sumus prope solutionem. Munera ad durandam / unfreeze a queue are
Tempus accipit ut hanc queue purgandam aequivalet discri latency sicut nucleus omnes operationes amet exspectationes ad perficiendum. Queue olim vacua est, occasus mutationes applicantur. Post quem dicitur
Nunc satis scimus ad rem emendandam. In udevadm felis mandatum facit uncinis ad fabricam applicandam. Hae uncinis describuntur in regulis udev. Invenire possumus qui occasus queue constringunt quaerendo eas per sysfs mutare vel ad fontem nuclei codicem intuendo. Possumus etiam experiri BCC utilitatem
~# /usr/share/bcc/tools/trace blk_freeze_queue -K -U
PID TID COMM FUNC
3809642 3809642 systemd-udevd blk_freeze_queue
blk_freeze_queue+0x1 [kernel]
elevator_switch+0x29 [kernel]
elv_iosched_store+0x197 [kernel]
queue_attr_store+0x5c [kernel]
sysfs_kf_write+0x3c [kernel]
kernfs_fop_write+0x125 [kernel]
__vfs_write+0x1b [kernel]
vfs_write+0xb8 [kernel]
sys_write+0x55 [kernel]
do_syscall_64+0x73 [kernel]
entry_SYSCALL_64_after_hwframe+0x3d [kernel]
__write_nocancel+0x7 [libc-2.23.so]
[unknown]
3809631 3809631 systemd-udevd blk_freeze_queue
blk_freeze_queue+0x1 [kernel]
queue_requests_store+0xb6 [kernel]
queue_attr_store+0x5c [kernel]
sysfs_kf_write+0x3c [kernel]
kernfs_fop_write+0x125 [kernel]
__vfs_write+0x1b [kernel]
vfs_write+0xb8 [kernel]
sys_write+0x55 [kernel]
do_syscall_64+0x73 [kernel]
entry_SYSCALL_64_after_hwframe+0x3d [kernel]
__write_nocancel+0x7 [libc-2.23.so]
[unknown]
Regulae Udev admodum raro mutantur, ac plerumque hoc modo moderato eveniunt. Perspicimus igitur etiam applicando valores iam statutos spicam in mora transferendi postulationem ab applicatione in disco. Utique udev generans eventus, cum nullae sunt mutationes in figura orbis (exempli gratia, fabrica non ascendit/disiuncta) non bene usus est. Sed nucleum adiuvare possumus non opus facere superfluum et durare petitionem queue si non est necesse.
Conclusio
eBPF est instrumentum flexibile et validum. In uno casu practico inspeximus articulum, et demonstravimus particulam quid fieri possit. Si vos es interested in explicando BCC utilitates, suus 'vultus captus
Aliae res commodae debugging et profilingunt instrumenta quae in eBPF nituntur. Unus eorum -
Source: www.habr.com