ReactOS 0.4.15-dev-7953-g1f49173
treefuncs.c File Reference
#include "btrfs_drv.h"
#include "crc32c.h"
Include dependency graph for treefuncs.c:

Go to the source code of this file.

Functions

 __attribute__ ((nonnull(1, 3, 4, 5)))
 
 __attribute__ ((nonnull(1, 2, 3, 4)))
 
 __attribute__ ((nonnull(1, 2, 3)))
 
 __attribute__ ((nonnull(1)))
 
 __attribute__ ((nonnull(1, 2)))
 
 __attribute__ ((nonnull(1, 2, 3, 4, 5)))
 
 __attribute__ ((nonnull(1, 3)))
 
 __attribute__ ((nonnull(1, 2, 3, 4, 6, 7)))
 

Function Documentation

◆ __attribute__() [1/8]

__attribute__ ( (nonnull(1))  )

Definition at line 264 of file treefuncs.c.

265 {
266 tree* par;
267 root* r = t->root;
268
269 // No need to acquire lock, as this is only ever called while Vcb->tree_lock held exclusively
270
271 par = t->parent;
272
273 if (r && r->treeholder.tree != t)
274 r = NULL;
275
276 if (par) {
277 if (t->paritem)
278 t->paritem->treeholder.tree = NULL;
279 }
280
281 while (!IsListEmpty(&t->itemlist)) {
283
284 if (t->header.level == 0 && td->data && td->inserted)
285 ExFreePool(td->data);
286
287 ExFreeToPagedLookasideList(&t->Vcb->tree_data_lookaside, td);
288 }
289
290 RemoveEntryList(&t->list_entry);
291
292 if (r)
293 r->treeholder.tree = NULL;
294
295 if (t->list_entry_hash.Flink) {
296 uint8_t h = t->hash >> 24;
297 if (t->Vcb->trees_ptrs[h] == &t->list_entry_hash) {
298 if (t->list_entry_hash.Flink != &t->Vcb->trees_hash) {
299 tree* t2 = CONTAINING_RECORD(t->list_entry_hash.Flink, tree, list_entry_hash);
300
301 if ((t2->hash >> 24) == h)
302 t->Vcb->trees_ptrs[h] = &t2->list_entry_hash;
303 else
304 t->Vcb->trees_ptrs[h] = NULL;
305 } else
306 t->Vcb->trees_ptrs[h] = NULL;
307 }
308
309 RemoveEntryList(&t->list_entry_hash);
310 }
311
312 if (t->buf)
313 ExFreePool(t->buf);
314
315 if (t->nonpaged)
316 ExFreePool(t->nonpaged);
317
318 ExFreePool(t);
319}
#define NULL
Definition: types.h:112
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
BYTE uint8_t
Definition: msvideo1.c:66
uint8_t * data
Definition: btrfs_drv.h:415
bool inserted
Definition: btrfs_drv.h:408
uint32_t hash
Definition: btrfs_drv.h:427
LIST_ENTRY list_entry_hash
Definition: btrfs_drv.h:436
struct _tree * parent
Definition: btrfs_drv.h:431
Definition: list.h:27
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

◆ __attribute__() [2/8]

__attribute__ ( (nonnull(1, 2))  )

Definition at line 331 of file treefuncs.c.

332 {
333 LIST_ENTRY* le = td->list_entry.Blink;
334
335 if (le == &t->itemlist)
336 return NULL;
337
339}
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122

◆ __attribute__() [3/8]

__attribute__ ( (nonnull(1, 2, 3))  )

Definition at line 221 of file treefuncs.c.

222 {
224 uint8_t* buf;
225 chunk* c;
226
227 buf = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.node_size, ALLOC_TAG);
228 if (!buf) {
229 ERR("out of memory\n");
231 }
232
233 Status = read_data(Vcb, th->address, Vcb->superblock.node_size, NULL, true, buf, NULL,
234 &c, Irp, th->generation, false, NormalPagePriority);
235 if (!NT_SUCCESS(Status)) {
236 ERR("read_data returned 0x%08lx\n", Status);
238 return Status;
239 }
240
241 if (t)
242 ExAcquireFastMutex(&t->nonpaged->mutex);
243 else
244 ExAcquireResourceExclusiveLite(&r->nonpaged->load_tree_lock, true);
245
246 Status = do_load_tree2(Vcb, th, buf, r, t, td);
247
248 if (t)
249 ExReleaseFastMutex(&t->nonpaged->mutex);
250 else
251 ExReleaseResourceLite(&r->nonpaged->load_tree_lock);
252
253 if (!th->tree || th->tree->buf != buf)
255
256 if (!NT_SUCCESS(Status)) {
257 ERR("do_load_tree2 returned %08lx\n", Status);
258 return Status;
259 }
260
261 return Status;
262}
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: debug.h:110
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ PIRP Irp
Definition: csq.h:116
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define PagedPool
Definition: env_spec_w32.h:308
Status
Definition: gdiplustypes.h:25
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define c
Definition: ke_i.h:80
@ NormalPagePriority
Definition: imports.h:56
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

◆ __attribute__() [4/8]

__attribute__ ( (nonnull(1, 2, 3, 4))  )

Definition at line 195 of file treefuncs.c.

196 {
197 if (!th->tree) {
199 tree* nt;
200
201 Status = load_tree(Vcb, th->address, buf, r, &nt);
202 if (!NT_SUCCESS(Status)) {
203 ERR("load_tree returned %08lx\n", Status);
204 return Status;
205 }
206
207 nt->parent = t;
208
209#ifdef DEBUG_PARANOID
210 if (t && t->header.level <= nt->header.level) int3;
211#endif
212
213 nt->paritem = td;
214
215 th->tree = nt;
216 }
217
218 return STATUS_SUCCESS;
219}
NTSTATUS load_tree(device_extension *Vcb, uint64_t addr, uint8_t *buf, root *r, tree **pt) __attribute__((nonnull(1
#define int3
Definition: btrfs_drv.h:1745
IMAGE_NT_HEADERS nt
Definition: module.c:50
#define STATUS_SUCCESS
Definition: shellext.h:65

◆ __attribute__() [5/8]

__attribute__ ( (nonnull(1, 2, 3, 4, 5))  )

Definition at line 377 of file treefuncs.c.

378 {
380 tree *t1, *t2;
381 tree_data *td1, *td2;
382
383 t1 = tp->tree;
384 t2 = tp2->tree;
385
386 do {
387 td1 = t1->paritem;
388 td2 = t2->paritem;
389 t1 = t1->parent;
390 t2 = t2->parent;
391 } while (t1 && t2 && t1->header.address == t2->header.address);
392
393 while (true) {
394 traverse_ptr tp3, tp4;
395
396 Status = next_item2(Vcb, t1, td1, &tp3);
398 *ended1 = true;
399 else if (!NT_SUCCESS(Status)) {
400 ERR("next_item2 returned %08lx\n", Status);
401 return Status;
402 }
403
404 Status = next_item2(Vcb, t2, td2, &tp4);
406 *ended2 = true;
407 else if (!NT_SUCCESS(Status)) {
408 ERR("next_item2 returned %08lx\n", Status);
409 return Status;
410 }
411
412 if (*ended1 || *ended2) {
413 if (!*ended1) {
414 Status = find_item(Vcb, t1->root, tp, &tp3.item->key, false, NULL);
415 if (!NT_SUCCESS(Status)) {
416 ERR("find_item returned %08lx\n", Status);
417 return Status;
418 }
419 } else if (!*ended2) {
420 Status = find_item(Vcb, t2->root, tp2, &tp4.item->key, false, NULL);
421 if (!NT_SUCCESS(Status)) {
422 ERR("find_item returned %08lx\n", Status);
423 return Status;
424 }
425 }
426
427 return STATUS_SUCCESS;
428 }
429
430 if (tp3.tree->header.address != tp4.tree->header.address) {
431 Status = find_item(Vcb, t1->root, tp, &tp3.item->key, false, NULL);
432 if (!NT_SUCCESS(Status)) {
433 ERR("find_item returned %08lx\n", Status);
434 return Status;
435 }
436
437 Status = find_item(Vcb, t2->root, tp2, &tp4.item->key, false, NULL);
438 if (!NT_SUCCESS(Status)) {
439 ERR("find_item returned %08lx\n", Status);
440 return Status;
441 }
442
443 return STATUS_SUCCESS;
444 }
445
446 t1 = tp3.tree;
447 td1 = tp3.item;
448 t2 = tp4.tree;
449 td2 = tp4.item;
450 }
451}
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
#define STATUS_NOT_FOUND
Definition: shellext.h:72
tree_header header
Definition: btrfs_drv.h:426
struct _root * root
Definition: btrfs_drv.h:433
tree_data * paritem
Definition: btrfs_drv.h:432
tree_data * item
Definition: btrfs_drv.h:509
tree * tree
Definition: btrfs_drv.h:508
uint64_t address
Definition: btrfs.h:156

◆ __attribute__() [6/8]

__attribute__ ( (nonnull(1, 2, 3, 4, 6, 7))  )

Definition at line 1322 of file treefuncs.c.

1323 {
1324 if (bi->operation == Batch_Delete || bi->operation == Batch_SetXattr || bi->operation == Batch_DirItem || bi->operation == Batch_InodeRef ||
1325 bi->operation == Batch_InodeExtRef || bi->operation == Batch_DeleteDirItem || bi->operation == Batch_DeleteInodeRef ||
1326 bi->operation == Batch_DeleteInodeExtRef || bi->operation == Batch_DeleteXattr) {
1327 uint16_t maxlen = (uint16_t)(Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node));
1328
1329 switch (bi->operation) {
1330 case Batch_SetXattr: {
1331 if (td->size < sizeof(DIR_ITEM)) {
1332 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", bi->key.obj_id, bi->key.obj_type, bi->key.offset, td->size, sizeof(DIR_ITEM));
1333 } else {
1334 uint8_t* newdata;
1335 ULONG size = td->size;
1336 DIR_ITEM* newxa = (DIR_ITEM*)bi->data;
1337 DIR_ITEM* xa = (DIR_ITEM*)td->data;
1338
1339 while (true) {
1340 ULONG oldxasize;
1341
1342 if (size < sizeof(DIR_ITEM) || size < sizeof(DIR_ITEM) - 1 + xa->m + xa->n) {
1343 ERR("(%I64x,%x,%I64x) was truncated\n", bi->key.obj_id, bi->key.obj_type, bi->key.offset);
1344 break;
1345 }
1346
1347 oldxasize = sizeof(DIR_ITEM) - 1 + xa->m + xa->n;
1348
1349 if (xa->n == newxa->n && RtlCompareMemory(newxa->name, xa->name, xa->n) == xa->n) {
1350 uint64_t pos;
1351
1352 // replace
1353
1354 if (td->size + bi->datalen - oldxasize > maxlen)
1355 ERR("DIR_ITEM would be over maximum size, truncating (%u + %u - %lu > %u)\n", td->size, bi->datalen, oldxasize, maxlen);
1356
1357 newdata = ExAllocatePoolWithTag(PagedPool, td->size + bi->datalen - oldxasize, ALLOC_TAG);
1358 if (!newdata) {
1359 ERR("out of memory\n");
1361 }
1362
1363 pos = (uint8_t*)xa - td->data;
1364 if (pos + oldxasize < td->size) // copy after changed xattr
1365 RtlCopyMemory(newdata + pos + bi->datalen, td->data + pos + oldxasize, (ULONG)(td->size - pos - oldxasize));
1366
1367 if (pos > 0) { // copy before changed xattr
1368 RtlCopyMemory(newdata, td->data, (ULONG)pos);
1369 xa = (DIR_ITEM*)(newdata + pos);
1370 } else
1371 xa = (DIR_ITEM*)newdata;
1372
1373 RtlCopyMemory(xa, bi->data, bi->datalen);
1374
1375 bi->datalen = (uint16_t)min(td->size + bi->datalen - oldxasize, maxlen);
1376
1377 ExFreePool(bi->data);
1378 bi->data = newdata;
1379
1380 break;
1381 }
1382
1383 if ((uint8_t*)xa - (uint8_t*)td->data + oldxasize >= size) {
1384 // not found, add to end of data
1385
1386 if (td->size + bi->datalen > maxlen)
1387 ERR("DIR_ITEM would be over maximum size, truncating (%u + %u > %u)\n", td->size, bi->datalen, maxlen);
1388
1389 newdata = ExAllocatePoolWithTag(PagedPool, td->size + bi->datalen, ALLOC_TAG);
1390 if (!newdata) {
1391 ERR("out of memory\n");
1393 }
1394
1395 RtlCopyMemory(newdata, td->data, td->size);
1396
1397 xa = (DIR_ITEM*)((uint8_t*)newdata + td->size);
1398 RtlCopyMemory(xa, bi->data, bi->datalen);
1399
1400 bi->datalen = min(bi->datalen + td->size, maxlen);
1401
1402 ExFreePool(bi->data);
1403 bi->data = newdata;
1404
1405 break;
1406 } else {
1407 xa = (DIR_ITEM*)&xa->name[xa->m + xa->n];
1408 size -= oldxasize;
1409 }
1410 }
1411 }
1412 break;
1413 }
1414
1415 case Batch_DirItem: {
1416 uint8_t* newdata;
1417
1418 if (td->size + bi->datalen > maxlen) {
1419 ERR("DIR_ITEM would be over maximum size (%u + %u > %u)\n", td->size, bi->datalen, maxlen);
1420 return STATUS_INTERNAL_ERROR;
1421 }
1422
1423 newdata = ExAllocatePoolWithTag(PagedPool, td->size + bi->datalen, ALLOC_TAG);
1424 if (!newdata) {
1425 ERR("out of memory\n");
1427 }
1428
1429 RtlCopyMemory(newdata, td->data, td->size);
1430
1431 RtlCopyMemory(newdata + td->size, bi->data, bi->datalen);
1432
1433 bi->datalen += td->size;
1434
1435 ExFreePool(bi->data);
1436 bi->data = newdata;
1437
1438 break;
1439 }
1440
1441 case Batch_InodeRef: {
1442 uint8_t* newdata;
1443
1444 if (td->size + bi->datalen > maxlen) {
1445 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF) {
1446 INODE_REF* ir = (INODE_REF*)bi->data;
1447 INODE_EXTREF* ier;
1448 uint16_t ierlen;
1449 batch_item* bi2;
1450 LIST_ENTRY* le;
1451 bool inserted = false;
1452
1453 TRACE("INODE_REF would be too long, adding INODE_EXTREF instead\n");
1454
1455 ierlen = (uint16_t)(offsetof(INODE_EXTREF, name[0]) + ir->n);
1456
1458 if (!ier) {
1459 ERR("out of memory\n");
1461 }
1462
1463 ier->dir = bi->key.offset;
1464 ier->index = ir->index;
1465 ier->n = ir->n;
1466 RtlCopyMemory(ier->name, ir->name, ier->n);
1467
1468 bi2 = ExAllocateFromPagedLookasideList(&Vcb->batch_item_lookaside);
1469 if (!bi2) {
1470 ERR("out of memory\n");
1471 ExFreePool(ier);
1473 }
1474
1475 bi2->key.obj_id = bi->key.obj_id;
1476 bi2->key.obj_type = TYPE_INODE_EXTREF;
1477 bi2->key.offset = calc_crc32c((uint32_t)ier->dir, (uint8_t*)ier->name, ier->n);
1478 bi2->data = ier;
1479 bi2->datalen = ierlen;
1480 bi2->operation = Batch_InodeExtRef;
1481
1482 le = bi->list_entry.Flink;
1483 while (le != listhead) {
1485
1486 if (keycmp(bi3->key, bi2->key) != -1) {
1487 InsertHeadList(le->Blink, &bi2->list_entry);
1488 inserted = true;
1489 }
1490
1491 le = le->Flink;
1492 }
1493
1494 if (!inserted)
1495 InsertTailList(listhead, &bi2->list_entry);
1496
1497 *ignore = true;
1498 return STATUS_SUCCESS;
1499 } else {
1500 ERR("INODE_REF would be over maximum size (%u + %u > %u)\n", td->size, bi->datalen, maxlen);
1501 return STATUS_INTERNAL_ERROR;
1502 }
1503 }
1504
1505 newdata = ExAllocatePoolWithTag(PagedPool, td->size + bi->datalen, ALLOC_TAG);
1506 if (!newdata) {
1507 ERR("out of memory\n");
1509 }
1510
1511 RtlCopyMemory(newdata, td->data, td->size);
1512
1513 RtlCopyMemory(newdata + td->size, bi->data, bi->datalen);
1514
1515 bi->datalen += td->size;
1516
1517 ExFreePool(bi->data);
1518 bi->data = newdata;
1519
1520 break;
1521 }
1522
1523 case Batch_InodeExtRef: {
1524 uint8_t* newdata;
1525
1526 if (td->size + bi->datalen > maxlen) {
1527 ERR("INODE_EXTREF would be over maximum size (%u + %u > %u)\n", td->size, bi->datalen, maxlen);
1528 return STATUS_INTERNAL_ERROR;
1529 }
1530
1531 newdata = ExAllocatePoolWithTag(PagedPool, td->size + bi->datalen, ALLOC_TAG);
1532 if (!newdata) {
1533 ERR("out of memory\n");
1535 }
1536
1537 RtlCopyMemory(newdata, td->data, td->size);
1538
1539 RtlCopyMemory(newdata + td->size, bi->data, bi->datalen);
1540
1541 bi->datalen += td->size;
1542
1543 ExFreePool(bi->data);
1544 bi->data = newdata;
1545
1546 break;
1547 }
1548
1549 case Batch_DeleteDirItem: {
1550 if (td->size < sizeof(DIR_ITEM)) {
1551 ERR("DIR_ITEM was %u bytes, expected at least %Iu\n", td->size, sizeof(DIR_ITEM));
1552 return STATUS_INTERNAL_ERROR;
1553 } else {
1554 DIR_ITEM *di, *deldi;
1555 LONG len;
1556
1557 deldi = (DIR_ITEM*)bi->data;
1558 di = (DIR_ITEM*)td->data;
1559 len = td->size;
1560
1561 do {
1562 if (di->m == deldi->m && di->n == deldi->n && RtlCompareMemory(di->name, deldi->name, di->n + di->m) == di->n + di->m) {
1563 uint16_t newlen = td->size - (sizeof(DIR_ITEM) - sizeof(char) + di->n + di->m);
1564
1565 if (newlen == 0) {
1566 TRACE("deleting DIR_ITEM\n");
1567 } else {
1568 uint8_t *newdi = ExAllocatePoolWithTag(PagedPool, newlen, ALLOC_TAG), *dioff;
1569 tree_data* td2;
1570
1571 if (!newdi) {
1572 ERR("out of memory\n");
1574 }
1575
1576 TRACE("modifying DIR_ITEM\n");
1577
1578 if ((uint8_t*)di > td->data) {
1579 RtlCopyMemory(newdi, td->data, (uint8_t*)di - td->data);
1580 dioff = newdi + ((uint8_t*)di - td->data);
1581 } else {
1582 dioff = newdi;
1583 }
1584
1585 if ((uint8_t*)&di->name[di->n + di->m] < td->data + td->size)
1586 RtlCopyMemory(dioff, &di->name[di->n + di->m], td->size - ((uint8_t*)&di->name[di->n + di->m] - td->data));
1587
1588 td2 = ExAllocateFromPagedLookasideList(&Vcb->tree_data_lookaside);
1589 if (!td2) {
1590 ERR("out of memory\n");
1591 ExFreePool(newdi);
1593 }
1594
1595 td2->key = bi->key;
1596 td2->size = newlen;
1597 td2->data = newdi;
1598 td2->ignore = false;
1599 td2->inserted = true;
1600
1601 InsertHeadList(td->list_entry.Blink, &td2->list_entry);
1602
1603 t->header.num_items++;
1604 t->size += newlen + sizeof(leaf_node);
1605 t->write = true;
1606 }
1607
1608 break;
1609 }
1610
1611 len -= sizeof(DIR_ITEM) - sizeof(char) + di->n + di->m;
1612 di = (DIR_ITEM*)&di->name[di->n + di->m];
1613
1614 if (len == 0) {
1615 TRACE("could not find DIR_ITEM to delete\n");
1616 *ignore = true;
1617 return STATUS_SUCCESS;
1618 }
1619 } while (len > 0);
1620 }
1621 break;
1622 }
1623
1624 case Batch_DeleteInodeRef: {
1625 if (td->size < sizeof(INODE_REF)) {
1626 ERR("INODE_REF was %u bytes, expected at least %Iu\n", td->size, sizeof(INODE_REF));
1627 return STATUS_INTERNAL_ERROR;
1628 } else {
1629 INODE_REF *ir, *delir;
1630 ULONG len;
1631 bool changed = false;
1632
1633 delir = (INODE_REF*)bi->data;
1634 ir = (INODE_REF*)td->data;
1635 len = td->size;
1636
1637 do {
1638 uint16_t itemlen;
1639
1640 if (len < sizeof(INODE_REF) || len < offsetof(INODE_REF, name[0]) + ir->n) {
1641 ERR("INODE_REF was truncated\n");
1642 break;
1643 }
1644
1645 itemlen = (uint16_t)offsetof(INODE_REF, name[0]) + ir->n;
1646
1647 if (ir->n == delir->n && RtlCompareMemory(ir->name, delir->name, ir->n) == ir->n) {
1648 uint16_t newlen = td->size - itemlen;
1649
1650 changed = true;
1651
1652 if (newlen == 0)
1653 TRACE("deleting INODE_REF\n");
1654 else {
1655 uint8_t *newir = ExAllocatePoolWithTag(PagedPool, newlen, ALLOC_TAG), *iroff;
1656 tree_data* td2;
1657
1658 if (!newir) {
1659 ERR("out of memory\n");
1661 }
1662
1663 TRACE("modifying INODE_REF\n");
1664
1665 if ((uint8_t*)ir > td->data) {
1666 RtlCopyMemory(newir, td->data, (uint8_t*)ir - td->data);
1667 iroff = newir + ((uint8_t*)ir - td->data);
1668 } else {
1669 iroff = newir;
1670 }
1671
1672 if ((uint8_t*)&ir->name[ir->n] < td->data + td->size)
1673 RtlCopyMemory(iroff, &ir->name[ir->n], td->size - ((uint8_t*)&ir->name[ir->n] - td->data));
1674
1675 td2 = ExAllocateFromPagedLookasideList(&Vcb->tree_data_lookaside);
1676 if (!td2) {
1677 ERR("out of memory\n");
1678 ExFreePool(newir);
1680 }
1681
1682 td2->key = bi->key;
1683 td2->size = newlen;
1684 td2->data = newir;
1685 td2->ignore = false;
1686 td2->inserted = true;
1687
1688 InsertHeadList(td->list_entry.Blink, &td2->list_entry);
1689
1690 t->header.num_items++;
1691 t->size += newlen + sizeof(leaf_node);
1692 t->write = true;
1693 }
1694
1695 break;
1696 }
1697
1698 if (len > itemlen) {
1699 len -= itemlen;
1700 ir = (INODE_REF*)&ir->name[ir->n];
1701 } else
1702 break;
1703 } while (len > 0);
1704
1705 if (!changed) {
1706 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF) {
1707 TRACE("entry in INODE_REF not found, adding Batch_DeleteInodeExtRef entry\n");
1708
1709 add_delete_inode_extref(Vcb, bi, listhead);
1710
1711 *ignore = true;
1712 return STATUS_SUCCESS;
1713 } else
1714 WARN("entry not found in INODE_REF\n");
1715 }
1716 }
1717
1718 break;
1719 }
1720
1722 if (td->size < sizeof(INODE_EXTREF)) {
1723 ERR("INODE_EXTREF was %u bytes, expected at least %Iu\n", td->size, sizeof(INODE_EXTREF));
1724 return STATUS_INTERNAL_ERROR;
1725 } else {
1726 INODE_EXTREF *ier, *delier;
1727 ULONG len;
1728
1729 delier = (INODE_EXTREF*)bi->data;
1730 ier = (INODE_EXTREF*)td->data;
1731 len = td->size;
1732
1733 do {
1734 uint16_t itemlen;
1735
1736 if (len < sizeof(INODE_EXTREF) || len < offsetof(INODE_EXTREF, name[0]) + ier->n) {
1737 ERR("INODE_REF was truncated\n");
1738 break;
1739 }
1740
1741 itemlen = (uint16_t)offsetof(INODE_EXTREF, name[0]) + ier->n;
1742
1743 if (ier->dir == delier->dir && ier->n == delier->n && RtlCompareMemory(ier->name, delier->name, ier->n) == ier->n) {
1744 uint16_t newlen = td->size - itemlen;
1745
1746 if (newlen == 0)
1747 TRACE("deleting INODE_EXTREF\n");
1748 else {
1749 uint8_t *newier = ExAllocatePoolWithTag(PagedPool, newlen, ALLOC_TAG), *ieroff;
1750 tree_data* td2;
1751
1752 if (!newier) {
1753 ERR("out of memory\n");
1755 }
1756
1757 TRACE("modifying INODE_EXTREF\n");
1758
1759 if ((uint8_t*)ier > td->data) {
1760 RtlCopyMemory(newier, td->data, (uint8_t*)ier - td->data);
1761 ieroff = newier + ((uint8_t*)ier - td->data);
1762 } else {
1763 ieroff = newier;
1764 }
1765
1766 if ((uint8_t*)&ier->name[ier->n] < td->data + td->size)
1767 RtlCopyMemory(ieroff, &ier->name[ier->n], td->size - ((uint8_t*)&ier->name[ier->n] - td->data));
1768
1769 td2 = ExAllocateFromPagedLookasideList(&Vcb->tree_data_lookaside);
1770 if (!td2) {
1771 ERR("out of memory\n");
1772 ExFreePool(newier);
1774 }
1775
1776 td2->key = bi->key;
1777 td2->size = newlen;
1778 td2->data = newier;
1779 td2->ignore = false;
1780 td2->inserted = true;
1781
1782 InsertHeadList(td->list_entry.Blink, &td2->list_entry);
1783
1784 t->header.num_items++;
1785 t->size += newlen + sizeof(leaf_node);
1786 t->write = true;
1787 }
1788
1789 break;
1790 }
1791
1792 if (len > itemlen) {
1793 len -= itemlen;
1794 ier = (INODE_EXTREF*)&ier->name[ier->n];
1795 } else
1796 break;
1797 } while (len > 0);
1798 }
1799 break;
1800 }
1801
1802 case Batch_DeleteXattr: {
1803 if (td->size < sizeof(DIR_ITEM)) {
1804 ERR("XATTR_ITEM was %u bytes, expected at least %Iu\n", td->size, sizeof(DIR_ITEM));
1805 return STATUS_INTERNAL_ERROR;
1806 } else {
1807 DIR_ITEM *di, *deldi;
1808 LONG len;
1809
1810 deldi = (DIR_ITEM*)bi->data;
1811 di = (DIR_ITEM*)td->data;
1812 len = td->size;
1813
1814 do {
1815 if (di->n == deldi->n && RtlCompareMemory(di->name, deldi->name, di->n) == di->n) {
1816 uint16_t newlen = td->size - ((uint16_t)offsetof(DIR_ITEM, name[0]) + di->n + di->m);
1817
1818 if (newlen == 0)
1819 TRACE("deleting XATTR_ITEM\n");
1820 else {
1821 uint8_t *newdi = ExAllocatePoolWithTag(PagedPool, newlen, ALLOC_TAG), *dioff;
1822 tree_data* td2;
1823
1824 if (!newdi) {
1825 ERR("out of memory\n");
1827 }
1828
1829 TRACE("modifying XATTR_ITEM\n");
1830
1831 if ((uint8_t*)di > td->data) {
1832 RtlCopyMemory(newdi, td->data, (uint8_t*)di - td->data);
1833 dioff = newdi + ((uint8_t*)di - td->data);
1834 } else
1835 dioff = newdi;
1836
1837 if ((uint8_t*)&di->name[di->n + di->m] < td->data + td->size)
1838 RtlCopyMemory(dioff, &di->name[di->n + di->m], td->size - ((uint8_t*)&di->name[di->n + di->m] - td->data));
1839
1840 td2 = ExAllocateFromPagedLookasideList(&Vcb->tree_data_lookaside);
1841 if (!td2) {
1842 ERR("out of memory\n");
1843 ExFreePool(newdi);
1845 }
1846
1847 td2->key = bi->key;
1848 td2->size = newlen;
1849 td2->data = newdi;
1850 td2->ignore = false;
1851 td2->inserted = true;
1852
1853 InsertHeadList(td->list_entry.Blink, &td2->list_entry);
1854
1855 t->header.num_items++;
1856 t->size += newlen + sizeof(leaf_node);
1857 t->write = true;
1858 }
1859
1860 break;
1861 }
1862
1863 len -= sizeof(DIR_ITEM) - sizeof(char) + di->n + di->m;
1864 di = (DIR_ITEM*)&di->name[di->n + di->m];
1865
1866 if (len == 0) {
1867 TRACE("could not find DIR_ITEM to delete\n");
1868 *ignore = true;
1869 return STATUS_SUCCESS;
1870 }
1871 } while (len > 0);
1872 }
1873 break;
1874 }
1875
1876 case Batch_Delete:
1877 break;
1878
1879 default:
1880 ERR("unexpected batch operation type\n");
1881 return STATUS_INTERNAL_ERROR;
1882 }
1883
1884 // delete old item
1885 if (!td->ignore) {
1886 td->ignore = true;
1887
1888 t->header.num_items--;
1889 t->size -= sizeof(leaf_node) + td->size;
1890 t->write = true;
1891 }
1892
1893 if (newtd) {
1894 newtd->data = bi->data;
1895 newtd->size = bi->datalen;
1896 InsertHeadList(td->list_entry.Blink, &newtd->list_entry);
1897 }
1898 } else {
1899 ERR("(%I64x,%x,%I64x) already exists\n", bi->key.obj_id, bi->key.obj_type, bi->key.offset);
1900 return STATUS_INTERNAL_ERROR;
1901 }
1902
1903 *ignore = false;
1904 return STATUS_SUCCESS;
1905}
unsigned short int uint16_t
Definition: acefiex.h:54
#define WARN(fmt,...)
Definition: debug.h:112
@ Batch_InodeExtRef
Definition: btrfs_drv.h:483
@ Batch_DeleteDirItem
Definition: btrfs_drv.h:473
@ Batch_DeleteXattr
Definition: btrfs_drv.h:476
@ Batch_SetXattr
Definition: btrfs_drv.h:480
@ Batch_InodeRef
Definition: btrfs_drv.h:482
@ Batch_DeleteInodeRef
Definition: btrfs_drv.h:474
@ Batch_DeleteInodeExtRef
Definition: btrfs_drv.h:475
@ Batch_DirItem
Definition: btrfs_drv.h:481
@ Batch_Delete
Definition: btrfs_drv.h:471
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1016
crc_func calc_crc32c
Definition: crc32c.c:23
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#define TYPE_INODE_EXTREF
Definition: btrfs.h:25
#define BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF
Definition: btrfs.h:121
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
GLsizeiptr size
Definition: glext.h:5919
GLenum GLsizei len
Definition: glext.h:6722
if(dx< 0)
Definition: linetemp.h:194
#define min(a, b)
Definition: monoChain.cc:55
#define uint16_t
Definition: nsiface.idl:60
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
long LONG
Definition: pedump.c:60
#define offsetof(TYPE, MEMBER)
#define TRACE(s)
Definition: solgame.cpp:4
uint16_t m
Definition: btrfs.h:275
char name[1]
Definition: btrfs.h:278
uint16_t n
Definition: btrfs.h:276
uint64_t dir
Definition: btrfs.h:381
char name[1]
Definition: btrfs.h:384
uint16_t n
Definition: btrfs.h:383
uint64_t index
Definition: btrfs.h:375
char name[1]
Definition: btrfs.h:377
uint16_t n
Definition: btrfs.h:376
LIST_ENTRY list_entry
Definition: btrfs_drv.h:406
uint16_t size
Definition: btrfs_drv.h:414
bool ignore
Definition: btrfs_drv.h:407
Definition: name.c:39
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59

◆ __attribute__() [7/8]

__attribute__ ( (nonnull(1, 3))  )

Definition at line 860 of file treefuncs.c.

861 {
862 rollback_item* ri;
863
865 if (!ri) {
866 ERR("out of memory\n");
867 return;
868 }
869
870 ri->type = type;
871 ri->ptr = ptr;
873}
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1365
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static PVOID ptr
Definition: dispmode.c:27
LIST_ENTRY list_entry
Definition: btrfs_drv.h:1277
enum rollback_type type
Definition: btrfs_drv.h:1275

◆ __attribute__() [8/8]

__attribute__ ( (nonnull(1, 3, 4, 5))  )

Definition at line 21 of file treefuncs.c.

22 {
23 tree_header* th;
24 tree* t;
25 tree_data* td;
26 uint8_t h;
27 bool inserted;
28 LIST_ENTRY* le;
29
30 th = (tree_header*)buf;
31
33 if (!t) {
34 ERR("out of memory\n");
36 }
37
38 if (th->level > 0) {
40 if (!t->nonpaged) {
41 ERR("out of memory\n");
44 }
45
46 ExInitializeFastMutex(&t->nonpaged->mutex);
47 } else
48 t->nonpaged = NULL;
49
50 RtlCopyMemory(&t->header, th, sizeof(tree_header));
51 t->hash = calc_crc32c(0xffffffff, (uint8_t*)&addr, sizeof(uint64_t));
52 t->has_address = true;
53 t->Vcb = Vcb;
54 t->parent = NULL;
55 t->root = r;
56 t->paritem = NULL;
57 t->size = 0;
58 t->new_address = 0;
59 t->has_new_address = false;
60 t->updated_extents = false;
61 t->write = false;
62 t->uniqueness_determined = false;
63
64 InitializeListHead(&t->itemlist);
65
66 if (t->header.level == 0) { // leaf node
67 leaf_node* ln = (leaf_node*)(buf + sizeof(tree_header));
68 unsigned int i;
69
70 if ((t->header.num_items * sizeof(leaf_node)) + sizeof(tree_header) > Vcb->superblock.node_size) {
71 ERR("tree at %I64x has more items than expected (%x)\n", addr, t->header.num_items);
74 }
75
76 for (i = 0; i < t->header.num_items; i++) {
77 td = ExAllocateFromPagedLookasideList(&Vcb->tree_data_lookaside);
78 if (!td) {
79 ERR("out of memory\n");
82 }
83
84 td->key = ln[i].key;
85
86 if (ln[i].size > 0)
87 td->data = buf + sizeof(tree_header) + ln[i].offset;
88 else
89 td->data = NULL;
90
91 if (ln[i].size + sizeof(tree_header) + sizeof(leaf_node) > Vcb->superblock.node_size) {
92 ERR("overlarge item in tree %I64x: %u > %Iu\n", addr, ln[i].size, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node));
93 ExFreeToPagedLookasideList(&t->Vcb->tree_data_lookaside, td);
96 }
97
98 td->size = (uint16_t)ln[i].size;
99 td->ignore = false;
100 td->inserted = false;
101
102 InsertTailList(&t->itemlist, &td->list_entry);
103
104 t->size += ln[i].size;
105 }
106
107 t->size += t->header.num_items * sizeof(leaf_node);
108 t->buf = buf;
109 } else {
111 unsigned int i;
112
113 if ((t->header.num_items * sizeof(internal_node)) + sizeof(tree_header) > Vcb->superblock.node_size) {
114 ERR("tree at %I64x has more items than expected (%x)\n", addr, t->header.num_items);
115 ExFreePool(t);
117 }
118
119 for (i = 0; i < t->header.num_items; i++) {
120 td = ExAllocateFromPagedLookasideList(&Vcb->tree_data_lookaside);
121 if (!td) {
122 ERR("out of memory\n");
123 ExFreePool(t);
125 }
126
127 td->key = in[i].key;
128
129 td->treeholder.address = in[i].address;
130 td->treeholder.generation = in[i].generation;
131 td->treeholder.tree = NULL;
132 td->ignore = false;
133 td->inserted = false;
134
135 InsertTailList(&t->itemlist, &td->list_entry);
136 }
137
138 t->size = t->header.num_items * sizeof(internal_node);
139 t->buf = NULL;
140 }
141
142 ExAcquireFastMutex(&Vcb->trees_list_mutex);
143
144 InsertTailList(&Vcb->trees, &t->list_entry);
145
146 h = t->hash >> 24;
147
148 if (!Vcb->trees_ptrs[h]) {
149 uint8_t h2 = h;
150
151 le = Vcb->trees_hash.Flink;
152
153 if (h2 > 0) {
154 h2--;
155 do {
156 if (Vcb->trees_ptrs[h2]) {
157 le = Vcb->trees_ptrs[h2];
158 break;
159 }
160
161 h2--;
162 } while (h2 > 0);
163 }
164 } else
165 le = Vcb->trees_ptrs[h];
166
167 inserted = false;
168 while (le != &Vcb->trees_hash) {
169 tree* t2 = CONTAINING_RECORD(le, tree, list_entry_hash);
170
171 if (t2->hash >= t->hash) {
172 InsertHeadList(le->Blink, &t->list_entry_hash);
173 inserted = true;
174 break;
175 }
176
177 le = le->Flink;
178 }
179
180 if (!inserted)
181 InsertTailList(&Vcb->trees_hash, &t->list_entry_hash);
182
183 if (!Vcb->trees_ptrs[h] || t->list_entry_hash.Flink == Vcb->trees_ptrs[h])
184 Vcb->trees_ptrs[h] = &t->list_entry_hash;
185
186 ExReleaseFastMutex(&Vcb->trees_list_mutex);
187
188 TRACE("returning %p\n", t);
189
190 *pt = t;
191
192 return STATUS_SUCCESS;
193}
#define pt(x, y)
Definition: drawing.c:79
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
GLuint in
Definition: glext.h:9616
GLenum const GLvoid * addr
Definition: glext.h:9621
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
tree_holder treeholder
Definition: btrfs_drv.h:411
KEY key
Definition: btrfs.h:166
uint32_t size
Definition: btrfs.h:168
uint8_t level
Definition: btrfs.h:162
uint64_t address
Definition: btrfs_drv.h:399
struct _tree * tree
Definition: btrfs_drv.h:401
uint64_t generation
Definition: btrfs_drv.h:400
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274