dijous, de setembre 09, 2004

Seguir el joc a l'Oops de l'XFS (II)

Després de mirar el changelog del 2.6.9-rc1 m'he adonat de l'enorme quantitat de canvis que ha sofert el sistema XFS en només una revisió del kernel. Encara no entenc com pot ser el sistema de fitxers més estable de tots els que he provat i el més inocu a les interrupcions violentes del fluxe de corrent elèctric.

Seguint amb l'Oops de l'altre dia, pareix que el problema d'assignació de memòria es va crear per un excés de fragmentació del disc dur. O almenys això diuen els desenvolupadors de SGI sobre reports iguals al meu. Els sectors són d'un tamany fixe de 4096 bytes, pel que la fragmentació ha de ser interna. Tenint en compte que tinc espai lliure al disc dur de sobra, aquest error d'assignació de memòria s'hauria de solucionar :-)

Hi ha tants de canvis respecte de l'XFS als changelogs del kernel que m'és impossible veure si s'ha corregit el bug si no és provant la darrera versió (amb el darrer release candidate esper que basti) i recreant les condicions per a l'Oops (¿?).

Mirant l'Oops de més aprop, es pot veure que peta quan l'IP apunta a xfs_bmap_insert_exlist, a l'offset 0xd2. El primer és fer un grep per saber a quin fitxer es troba definida la funció, el qual resulta ser fs/xfs/xfs_bmap.c. A continuació em baso en el procediment detallat per Denis Vlasenko i companyia [kerneltrap]:

/*
* Insert new item(s) in the extent list for inode "ip".
* Count new items are inserted at offset idx.
*/
STATIC void
xfs_bmap_insert_exlist(
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* starting index of new items */
xfs_extnum_t count, /* number of inserted items */
xfs_bmbt_irec_t *new, /* items to insert */
int whichfork) /* data or attr fork */

{
xfs_bmbt_rec_t *base; /* extent list base */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_extnum_t nextents; /* extent list size */
xfs_extnum_t to; /* extent list index */

ifp = XFS_IFORK_PTR(ip, whichfork);
ASSERT(ifp->if_flags & XFS_IFEXTENTS);
xfs_iext_realloc(ip, count, whichfork);
base = ifp->if_u1.if_extents;
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
memmove(&base[idx + count], &base[idx],
(nextents - (idx + count)) * sizeof(*base));
for (to = idx; to < idx + count; to++, new++)
xfs_bmbt_set_all(&base[to], new);
}
A continuació desensemblam el codi:

# objdump -d fs/xfs/xfs_bmap.o > fs/xfs/xfs_bmap.disasm

Cercam la funció xfs_bmap_insert_exlist a dintre del fitxer .disasm:
00006170 <xfs_bmap_insert_exlist><xfs_bmap_insert_exlist>:
6170: 55 push %ebp
6171: 57 push %edi

Per trobar la línia d'interés, sumam l'offset 0xd2 a 0x6170, que resulta en 0x6242:
6242: f3 a4 repz movsb %ds:(%esi),%es:(%edi)
6244: fc cld
6245: eb a9 jmp 61f0 <xfs_bmap_insert_exlist+0x80>
6247: 89 f6 mov %esi,%esi
6249: 8d bc 27 00 00 00 00 lea 0x0(%edi),%edi

El codi de les instruccions coincideix amb el proporcionat per l'Oops: Code: f3 a4 fc eb a9 89 f6 8d bc 27 00 00 00 00 55 57 56 53 83 ec

Malauradament no sé dir de quina línia de codi prové el repz. Seguim insistint amb la creació del fitxer mig compilat en assemblador:

# make fs/xfs/xfs_bmap.s

Cercam la funció xfs_bmap_insert_exlist a l'xfs_bmap.s:
xfs_bmap_insert_exlist:
pushl %ebp
I miram de trobar la instrucció en qüestió una mica més avall, tot comparant amb l'xfs_bmap.disasm:
.L994:
leal -1(%edx,%esi), %esi
leal -1(%edx,%edi), %edi
movl %edx, %ecx
#APP
std
rep
movsb <--
cld
#NO_APP
jmp .L1010
I personalment em quedo igual que abans, sense saber a quina línia del .c pertany aquest codi. Quin conyàs. Paciència i modificam el .c:
{
[...]
ifp = XFS_IFORK_PTR(ip, whichfork);
asm("#1");
ASSERT(ifp->if_flags & XFS_IFEXTENTS);
asm("#2");
xfs_iext_realloc(ip, count, whichfork);
asm("#3");
base = ifp->if_u1.if_extents;
asm("#4");
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
asm("#5");
memmove(&base[idx + count], &base[idx],
(nextents - (idx + count)) * sizeof(*base));
asm("#6");
for (to = idx; to < idx + count; to++, new++)
xfs_bmbt_set_all(&base[to], new);
asm("#7");
}
Repetim el "make fs/xfs/xfs_bmap.s". Ara hi ha més pistes al .s:
#APP
#7
#NO_APP
addl $16, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.L1007:
movl %edx, 8(%esp)
movl %esi, 4(%esp)
movl %edi, (%esp)
call _mmx_memcpy
jmp .L1010
.L994:
leal -1(%edx,%esi), %esi
leal -1(%edx,%edi), %edi
movl %edx, %ecx
#APP
std
rep
movsb
cld
#NO_APP
jmp .L1010
.size xfs_bmap_insert_exlist, .-xfs_bmap_insert_exlist
.p2align 4,,15
.type xfs_bmap_local_to_extents, @function
L'error es troba dintre de la funció for(). El "jmp .L1010" ens torna just davant l'etiqueta 6:
#NO_APP
.L1010:
#APP
#6
#NO_APP
movl 40(%esp), %esi
Malauradament al for() es crida una altra funció, la xfs_bmbt_set_all, la qual expandeix tot el codi en assemblador i fa que ens perdem una altra vegada. Volta a començar amb el mateix a la xfs_bmbt_set_all :-)

Comentaris:
hola,
no hablo mucho espanol. soy gringa. estudia espanol dos anos.

Did that make any sense?

Te amo!
 
T'has drogat xaval?
Pren-te una til·la.

The Tiger of Massanella
 
Tiger: Ho dius per tot el text de més adalt o pel primer comentari?

El nivell de tot això és realment newbe. Ni tan sols està acabat (ho he deixat per un altre dia amb més ganes). Ni tan sols importa saber ensamblador ni compiladors. Acceptable per qualsevol aficionat als ordinadors, i per estudiants d'informàtica o telecomunicacions és de rialles (les assignatures de computadors tenen pràctiques moolt més complicades!). Evidentment la meva àvia s'hi estaria tota la vida...

Si és pel comentari de vadergrrrl, pots anar als seu weblog i comprovar que, realment, sí s'ha près algo (és broma).
 
Publica un comentari a l'entrada

<< Principal