ReactOS  0.4.15-dev-1367-g07cc0b5
free-space.c File Reference
#include "btrfs_drv.h"
#include "crc32c.h"
Include dependency graph for free-space.c:

Go to the source code of this file.

Classes

struct  superblock_stripe
 

Macros

#define CACHE_INCREMENTS   64
 

Functions

static NTSTATUS remove_free_space_inode (device_extension *Vcb, uint64_t inode, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS clear_free_space_cache (device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp)
 
NTSTATUS add_space_entry (LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
 
static void load_free_space_bitmap (device_extension *Vcb, chunk *c, uint64_t offset, void *data, uint64_t *total_space)
 
static void order_space_entry (space *s, LIST_ENTRY *list_size)
 
static NTSTATUS add_superblock_stripe (LIST_ENTRY *stripes, uint64_t off, uint64_t len)
 
static NTSTATUS get_superblock_size (chunk *c, uint64_t *size)
 
NTSTATUS load_stored_free_space_cache (device_extension *Vcb, chunk *c, bool load_only, PIRP Irp)
 
static NTSTATUS load_stored_free_space_tree (device_extension *Vcb, chunk *c, PIRP Irp)
 
static NTSTATUS load_free_space_cache (device_extension *Vcb, chunk *c, PIRP Irp)
 
NTSTATUS load_cache_chunk (device_extension *Vcb, chunk *c, PIRP Irp)
 
static NTSTATUS insert_cache_extent (fcb *fcb, uint64_t start, uint64_t length, LIST_ENTRY *rollback)
 
static NTSTATUS allocate_cache_chunk (device_extension *Vcb, chunk *c, bool *changed, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS allocate_cache (device_extension *Vcb, bool *changed, PIRP Irp, LIST_ENTRY *rollback)
 
static void add_rollback_space (LIST_ENTRY *rollback, bool add, LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c)
 
void space_list_add2 (LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
 
static void space_list_merge (LIST_ENTRY *spacelist, LIST_ENTRY *spacelist_size, LIST_ENTRY *deleting)
 
static NTSTATUS update_chunk_cache (device_extension *Vcb, chunk *c, BTRFS_TIME *now, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS update_chunk_cache_tree (device_extension *Vcb, chunk *c, LIST_ENTRY *batchlist)
 
NTSTATUS update_chunk_caches (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS update_chunk_caches_tree (device_extension *Vcb, PIRP Irp)
 
void space_list_add (chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
 
void space_list_subtract2 (LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
 
void space_list_subtract (chunk *c, bool deleting, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
 

Macro Definition Documentation

◆ CACHE_INCREMENTS

#define CACHE_INCREMENTS   64

Definition at line 23 of file free-space.c.

Function Documentation

◆ add_rollback_space()

static void add_rollback_space ( LIST_ENTRY rollback,
bool  add,
LIST_ENTRY list,
LIST_ENTRY list_size,
uint64_t  address,
uint64_t  length,
chunk c 
)
static

Definition at line 1425 of file free-space.c.

1425  {
1426  rollback_space* rs;
1427 
1429  if (!rs) {
1430  ERR("out of memory\n");
1431  return;
1432  }
1433 
1434  rs->list = list;
1435  rs->list_size = list_size;
1436  rs->address = address;
1437  rs->length = length;
1438  rs->chunk = c;
1439 
1441 }
LIST_ENTRY * list_size
Definition: btrfs_drv.h:1256
uint64_t length
Definition: btrfs_drv.h:1258
#define ALLOC_TAG
Definition: btrfs_drv.h:91
chunk * chunk
Definition: btrfs_drv.h:1259
uint64_t address
Definition: btrfs_drv.h:1257
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
GLuint address
Definition: glext.h:9393
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ERR(fmt,...)
Definition: debug.h:110
#define list
Definition: rosglue.h:35
_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:1357
#define c
Definition: ke_i.h:80
LIST_ENTRY * list
Definition: btrfs_drv.h:1255
void add_rollback(_In_ LIST_ENTRY *rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void *ptr)
Definition: treefuncs.c:837

Referenced by space_list_add2(), and space_list_subtract2().

◆ add_space_entry()

NTSTATUS add_space_entry ( LIST_ENTRY list,
LIST_ENTRY list_size,
uint64_t  offset,
uint64_t  size 
)

Definition at line 190 of file free-space.c.

190  {
191  space* s;
192 
194 
195  if (!s) {
196  ERR("out of memory\n");
198  }
199 
200  s->address = offset;
201  s->size = size;
202 
203  if (IsListEmpty(list))
204  InsertTailList(list, &s->list_entry);
205  else {
207 
208  if (s2->address < offset)
209  InsertTailList(list, &s->list_entry);
210  else {
211  LIST_ENTRY* le;
212 
213  le = list->Flink;
214  while (le != list) {
216 
217  if (s2->address > offset) {
218  InsertTailList(le, &s->list_entry);
219  goto size;
220  }
221 
222  le = le->Flink;
223  }
224  }
225  }
226 
227 size:
228  if (!list_size)
229  return STATUS_SUCCESS;
230 
231  if (IsListEmpty(list_size))
232  InsertTailList(list_size, &s->list_entry_size);
233  else {
234  space* s2 = CONTAINING_RECORD(list_size->Blink, space, list_entry_size);
235 
236  if (s2->size >= size)
237  InsertTailList(list_size, &s->list_entry_size);
238  else {
239  LIST_ENTRY* le;
240 
241  le = list_size->Flink;
242  while (le != list_size) {
243  s2 = CONTAINING_RECORD(le, space, list_entry_size);
244 
245  if (s2->size <= size) {
246  InsertHeadList(le->Blink, &s->list_entry_size);
247  return STATUS_SUCCESS;
248  }
249 
250  le = le->Flink;
251  }
252  }
253  }
254 
255  return STATUS_SUCCESS;
256 }
struct S2 s2
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define ALLOC_TAG
Definition: btrfs_drv.h:91
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLdouble s
Definition: gl.h:2039
Definition: _list.h:228
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:27
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by add_device(), find_disk_holes(), load_free_space_bitmap(), load_stored_free_space_cache(), and load_stored_free_space_tree().

◆ add_superblock_stripe()

static NTSTATUS add_superblock_stripe ( LIST_ENTRY stripes,
uint64_t  off,
uint64_t  len 
)
static

Definition at line 328 of file free-space.c.

328  {
329  uint64_t i;
330 
331  for (i = 0; i < len; i++) {
332  LIST_ENTRY* le;
334  bool ignore = false;
335 
336  le = stripes->Flink;
337  while (le != stripes) {
339 
340  if (ss->stripe == off + i) {
341  ignore = true;
342  break;
343  }
344 
345  le = le->Flink;
346  }
347 
348  if (ignore)
349  continue;
350 
352  if (!ss) {
353  ERR("out of memory\n");
355  }
356 
357  ss->stripe = off + i;
358  InsertTailList(stripes, &ss->list_entry);
359  }
360 
361  return STATUS_SUCCESS;
362 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
int ignore(int trapCode, ppc_trap_frame_t *trap)
Definition: mmuobject.c:296
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:91
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
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
Definition: list.h:27
#define ss
Definition: i386-dis.c:434
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by get_superblock_size().

◆ allocate_cache()

NTSTATUS allocate_cache ( device_extension Vcb,
bool changed,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 1379 of file free-space.c.

1379  {
1380  LIST_ENTRY *le, batchlist;
1381  NTSTATUS Status;
1382 
1383  *changed = false;
1384 
1385  InitializeListHead(&batchlist);
1386 
1387  ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
1388 
1389  le = Vcb->chunks.Flink;
1390  while (le != &Vcb->chunks) {
1392 
1393  if (c->space_changed && c->chunk_item->size >= 0x6400000) { // 100MB
1394  bool b;
1395 
1397  Status = allocate_cache_chunk(Vcb, c, &b, &batchlist, Irp, rollback);
1399 
1400  if (b)
1401  *changed = true;
1402 
1403  if (!NT_SUCCESS(Status)) {
1404  ERR("allocate_cache_chunk(%I64x) returned %08lx\n", c->offset, Status);
1405  ExReleaseResourceLite(&Vcb->chunk_lock);
1406  clear_batch_list(Vcb, &batchlist);
1407  return Status;
1408  }
1409  }
1410 
1411  le = le->Flink;
1412  }
1413 
1414  ExReleaseResourceLite(&Vcb->chunk_lock);
1415 
1416  Status = commit_batch_list(Vcb, &batchlist, Irp);
1417  if (!NT_SUCCESS(Status)) {
1418  ERR("commit_batch_list returned %08lx\n", Status);
1419  return Status;
1420  }
1421 
1422  return STATUS_SUCCESS;
1423 }
LONG NTSTATUS
Definition: precomp.h:26
release_chunk_lock(c, Vcb)
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
_In_ PIRP Irp
Definition: csq.h:116
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp)
Definition: treefuncs.c:2281
#define b
Definition: ke_i.h:79
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
void clear_batch_list(device_extension *Vcb, LIST_ENTRY *batchlist)
Definition: treefuncs.c:1204
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
_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:1357
static NTSTATUS allocate_cache_chunk(device_extension *Vcb, chunk *c, bool *changed, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: free-space.c:1043
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by do_write2().

◆ allocate_cache_chunk()

static NTSTATUS allocate_cache_chunk ( device_extension Vcb,
chunk c,
bool changed,
LIST_ENTRY batchlist,
PIRP  Irp,
LIST_ENTRY rollback 
)
static

Definition at line 1043 of file free-space.c.

1043  {
1044  LIST_ENTRY* le;
1045  NTSTATUS Status;
1046  uint64_t num_entries, new_cache_size, i;
1047  uint32_t num_sectors;
1048  bool realloc_extents = false;
1049 
1050  // FIXME - also do bitmaps
1051  // FIXME - make sure this works when sector_size is not 4096
1052 
1053  *changed = false;
1054 
1055  num_entries = 0;
1056 
1057  // num_entries is the number of entries in c->space and c->deleting - it might
1058  // be slightly higher then what we end up writing, but doing it this way is much
1059  // quicker and simpler.
1060  if (!IsListEmpty(&c->space)) {
1061  le = c->space.Flink;
1062  while (le != &c->space) {
1063  num_entries++;
1064 
1065  le = le->Flink;
1066  }
1067  }
1068 
1069  if (!IsListEmpty(&c->deleting)) {
1070  le = c->deleting.Flink;
1071  while (le != &c->deleting) {
1072  num_entries++;
1073 
1074  le = le->Flink;
1075  }
1076  }
1077 
1078  new_cache_size = sizeof(uint64_t) + (num_entries * sizeof(FREE_SPACE_ENTRY));
1079 
1080  num_sectors = (uint32_t)sector_align(new_cache_size, Vcb->superblock.sector_size) / Vcb->superblock.sector_size;
1081  num_sectors = (uint32_t)sector_align(num_sectors, CACHE_INCREMENTS);
1082 
1083  // adjust for padding
1084  // FIXME - there must be a more efficient way of doing this
1085  new_cache_size = sizeof(uint64_t) + (sizeof(uint32_t) * num_sectors);
1086  for (i = 0; i < num_entries; i++) {
1087  if ((new_cache_size / Vcb->superblock.sector_size) != ((new_cache_size + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size))
1088  new_cache_size = sector_align(new_cache_size, Vcb->superblock.sector_size);
1089 
1090  new_cache_size += sizeof(FREE_SPACE_ENTRY);
1091  }
1092 
1093  new_cache_size = sector_align(new_cache_size, CACHE_INCREMENTS * Vcb->superblock.sector_size);
1094 
1095  TRACE("chunk %I64x: cache_size = %I64x, new_cache_size = %I64x\n", c->offset, c->cache ? c->cache->inode_item.st_size : 0, new_cache_size);
1096 
1097  if (c->cache) {
1098  if (new_cache_size > c->cache->inode_item.st_size)
1099  realloc_extents = true;
1100  else {
1101  le = c->cache->extents.Flink;
1102 
1103  while (le != &c->cache->extents) {
1105 
1106  if (!ext->ignore && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
1107  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ext->extent_data.data[0];
1108 
1109  if (ed2->size != 0) {
1111 
1112  if (c2 && (c2->readonly || c2->reloc)) {
1113  realloc_extents = true;
1114  break;
1115  }
1116  }
1117  }
1118 
1119  le = le->Flink;
1120  }
1121  }
1122  }
1123 
1124  if (!c->cache) {
1125  FREE_SPACE_ITEM* fsi;
1126  KEY searchkey;
1127  traverse_ptr tp;
1128 
1129  // create new inode
1130 
1131  c->cache = create_fcb(Vcb, PagedPool);
1132  if (!c->cache) {
1133  ERR("out of memory\n");
1135  }
1136 
1137  c->cache->Vcb = Vcb;
1138 
1139  c->cache->inode_item.st_size = new_cache_size;
1140  c->cache->inode_item.st_blocks = new_cache_size;
1141  c->cache->inode_item.st_nlink = 1;
1142  c->cache->inode_item.st_mode = S_IRUSR | S_IWUSR | __S_IFREG;
1144 
1145  c->cache->Header.IsFastIoPossible = fast_io_possible(c->cache);
1146  c->cache->Header.AllocationSize.QuadPart = 0;
1147  c->cache->Header.FileSize.QuadPart = 0;
1148  c->cache->Header.ValidDataLength.QuadPart = 0;
1149 
1150  c->cache->subvol = Vcb->root_root;
1151 
1152  c->cache->inode = InterlockedIncrement64(&Vcb->root_root->lastinode);
1153 
1154  c->cache->type = BTRFS_TYPE_FILE;
1155  c->cache->created = true;
1156 
1157  // create new free space entry
1158 
1160  if (!fsi) {
1161  ERR("out of memory\n");
1162  reap_fcb(c->cache);
1163  c->cache = NULL;
1165  }
1166 
1167  searchkey.obj_id = FREE_SPACE_CACHE_ID;
1168  searchkey.obj_type = 0;
1169  searchkey.offset = c->offset;
1170 
1171  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
1172  if (!NT_SUCCESS(Status)) {
1173  ERR("error - find_item returned %08lx\n", Status);
1174  ExFreePool(fsi);
1175  reap_fcb(c->cache);
1176  c->cache = NULL;
1177  return Status;
1178  }
1179 
1180  if (!keycmp(searchkey, tp.item->key)) {
1182  if (!NT_SUCCESS(Status)) {
1183  ERR("delete_tree_item returned %08lx\n", Status);
1184  ExFreePool(fsi);
1185  reap_fcb(c->cache);
1186  c->cache = NULL;
1187  return Status;
1188  }
1189  }
1190 
1191  fsi->key.obj_id = c->cache->inode;
1192  fsi->key.obj_type = TYPE_INODE_ITEM;
1193  fsi->key.offset = 0;
1194 
1195  Status = insert_tree_item(Vcb, Vcb->root_root, FREE_SPACE_CACHE_ID, 0, c->offset, fsi, sizeof(FREE_SPACE_ITEM), NULL, Irp);
1196  if (!NT_SUCCESS(Status)) {
1197  ERR("insert_tree_item returned %08lx\n", Status);
1198  ExFreePool(fsi);
1199  reap_fcb(c->cache);
1200  c->cache = NULL;
1201  return Status;
1202  }
1203 
1204  // allocate space
1205 
1206  Status = insert_cache_extent(c->cache, 0, new_cache_size, rollback);
1207  if (!NT_SUCCESS(Status)) {
1208  ERR("insert_cache_extent returned %08lx\n", Status);
1209  reap_fcb(c->cache);
1210  c->cache = NULL;
1211  return Status;
1212  }
1213 
1214  c->cache->extents_changed = true;
1215  InsertTailList(&Vcb->all_fcbs, &c->cache->list_entry_all);
1216 
1217  Status = flush_fcb(c->cache, true, batchlist, Irp);
1218  if (!NT_SUCCESS(Status)) {
1219  ERR("flush_fcb returned %08lx\n", Status);
1220  free_fcb(c->cache);
1221  c->cache = NULL;
1222  return Status;
1223  }
1224 
1225  *changed = true;
1226  } else if (realloc_extents) {
1227  KEY searchkey;
1228  traverse_ptr tp;
1229 
1230  TRACE("reallocating extents\n");
1231 
1232  // add free_space entry to tree cache
1233 
1234  searchkey.obj_id = FREE_SPACE_CACHE_ID;
1235  searchkey.obj_type = 0;
1236  searchkey.offset = c->offset;
1237 
1238  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
1239  if (!NT_SUCCESS(Status)) {
1240  ERR("error - find_item returned %08lx\n", Status);
1241  return Status;
1242  }
1243 
1244  if (keycmp(searchkey, tp.item->key)) {
1245  ERR("could not find (%I64x,%x,%I64x) in root_root\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
1246  return STATUS_INTERNAL_ERROR;
1247  }
1248 
1249  if (tp.item->size < sizeof(FREE_SPACE_ITEM)) {
1250  ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
1251  return STATUS_INTERNAL_ERROR;
1252  }
1253 
1254  tp.tree->write = true;
1255 
1256  // remove existing extents
1257 
1258  if (c->cache->inode_item.st_size > 0) {
1259  le = c->cache->extents.Flink;
1260 
1261  while (le != &c->cache->extents) {
1263 
1264  if (!ext->ignore && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
1265  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ext->extent_data.data[0];
1266 
1267  if (ed2->size != 0) {
1269 
1270  if (c2) {
1271  c2->changed = true;
1272  c2->space_changed = true;
1273  }
1274  }
1275  }
1276 
1277  le = le->Flink;
1278  }
1279 
1280  Status = excise_extents(Vcb, c->cache, 0, c->cache->inode_item.st_size, Irp, rollback);
1281  if (!NT_SUCCESS(Status)) {
1282  ERR("excise_extents returned %08lx\n", Status);
1283  return Status;
1284  }
1285  }
1286 
1287  // add new extent
1288 
1289  Status = insert_cache_extent(c->cache, 0, new_cache_size, rollback);
1290  if (!NT_SUCCESS(Status)) {
1291  ERR("insert_cache_extent returned %08lx\n", Status);
1292  return Status;
1293  }
1294 
1295  // modify INODE_ITEM
1296 
1297  c->cache->inode_item.st_size = new_cache_size;
1298  c->cache->inode_item.st_blocks = new_cache_size;
1299 
1300  Status = flush_fcb(c->cache, true, batchlist, Irp);
1301  if (!NT_SUCCESS(Status)) {
1302  ERR("flush_fcb returned %08lx\n", Status);
1303  return Status;
1304  }
1305 
1306  *changed = true;
1307  } else {
1308  KEY searchkey;
1309  traverse_ptr tp;
1310 
1311  // add INODE_ITEM and free_space entry to tree cache, for writing later
1312 
1313  searchkey.obj_id = c->cache->inode;
1314  searchkey.obj_type = TYPE_INODE_ITEM;
1315  searchkey.offset = 0;
1316 
1317  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
1318  if (!NT_SUCCESS(Status)) {
1319  ERR("error - find_item returned %08lx\n", Status);
1320  return Status;
1321  }
1322 
1323  if (keycmp(searchkey, tp.item->key)) {
1324  INODE_ITEM* ii;
1325 
1327  if (!ii) {
1328  ERR("out of memory\n");
1330  }
1331 
1332  RtlCopyMemory(ii, &c->cache->inode_item, sizeof(INODE_ITEM));
1333 
1334  Status = insert_tree_item(Vcb, Vcb->root_root, c->cache->inode, TYPE_INODE_ITEM, 0, ii, sizeof(INODE_ITEM), NULL, Irp);
1335  if (!NT_SUCCESS(Status)) {
1336  ERR("insert_tree_item returned %08lx\n", Status);
1337  ExFreePool(ii);
1338  return Status;
1339  }
1340 
1341  *changed = true;
1342  } else {
1343  if (tp.item->size < sizeof(INODE_ITEM)) {
1344  ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(INODE_ITEM));
1345  return STATUS_INTERNAL_ERROR;
1346  }
1347 
1348  tp.tree->write = true;
1349  }
1350 
1351  searchkey.obj_id = FREE_SPACE_CACHE_ID;
1352  searchkey.obj_type = 0;
1353  searchkey.offset = c->offset;
1354 
1355  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
1356  if (!NT_SUCCESS(Status)) {
1357  ERR("error - find_item returned %08lx\n", Status);
1358  return Status;
1359  }
1360 
1361  if (keycmp(searchkey, tp.item->key)) {
1362  ERR("could not find (%I64x,%x,%I64x) in root_root\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
1363  return STATUS_INTERNAL_ERROR;
1364  }
1365 
1366  if (tp.item->size < sizeof(FREE_SPACE_ITEM)) {
1367  ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
1368  return STATUS_INTERNAL_ERROR;
1369  }
1370 
1371  tp.tree->write = true;
1372  }
1373 
1374  // FIXME - reduce inode allocation if cache is shrinking. Make sure to avoid infinite write loops
1375 
1376  return STATUS_SUCCESS;
1377 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: btrfs.h:436
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1664
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
#define CACHE_INCREMENTS
Definition: free-space.c:23
EXTENT_DATA2 * ed2
Definition: write.c:2805
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:79
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
#define FREE_SPACE_CACHE_ID
Definition: btrfs.h:86
bool readonly
Definition: btrfs_drv.h:589
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:139
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
tree * tree
Definition: btrfs_drv.h:517
_In_ PIRP Irp
Definition: csq.h:116
uint64_t address
Definition: btrfs.h:356
bool changed
Definition: btrfs_drv.h:593
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1673
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:357
bool reloc
Definition: btrfs_drv.h:590
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TRACE(s)
Definition: solgame.cpp:4
#define InterlockedIncrement64
Definition: interlocked.h:211
#define S_IWUSR
Definition: propsheet.h:33
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
static NTSTATUS insert_cache_extent(fcb *fcb, uint64_t start, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:999
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
bool space_changed
Definition: btrfs_drv.h:594
NTSTATUS flush_fcb(fcb *fcb, bool cache, LIST_ENTRY *batchlist, PIRP Irp)
Definition: flushthread.c:4818
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
Definition: typedefs.h:119
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1690
#define uint64_t
Definition: nsiface.idl:62
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define __S_IFREG
Definition: btrfs_drv.h:1803
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
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
#define S_IRUSR
Definition: propsheet.h:29
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1357
UINT32 uint32_t
Definition: types.h:75
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define BTRFS_INODE_PREALLOC
Definition: propsheet.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#define uint32_t
Definition: nsiface.idl:61
bool write
Definition: btrfs_drv.h:456
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define BTRFS_INODE_NOCOMPRESS
Definition: propsheet.h:79
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

Referenced by allocate_cache().

◆ clear_free_space_cache()

NTSTATUS clear_free_space_cache ( device_extension Vcb,
LIST_ENTRY batchlist,
PIRP  Irp 
)

Definition at line 59 of file free-space.c.

59  {
60  KEY searchkey;
61  traverse_ptr tp, next_tp;
63  bool b;
65 
67 
68  searchkey.obj_id = FREE_SPACE_CACHE_ID;
69  searchkey.obj_type = 0;
70  searchkey.offset = 0;
71 
72  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
73  if (!NT_SUCCESS(Status)) {
74  ERR("error - find_item returned %08lx\n", Status);
75  return Status;
76  }
77 
78  do {
79  if (tp.item->key.obj_id > searchkey.obj_id || (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type > searchkey.obj_type))
80  break;
81 
82  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
84  if (!NT_SUCCESS(Status)) {
85  ERR("delete_tree_item returned %08lx\n", Status);
86  return Status;
87  }
88 
89  if (tp.item->size >= sizeof(FREE_SPACE_ITEM)) {
91 
92  if (fsi->key.obj_type != TYPE_INODE_ITEM)
93  WARN("key (%I64x,%x,%I64x) does not point to an INODE_ITEM\n", fsi->key.obj_id, fsi->key.obj_type, fsi->key.offset);
94  else {
95  LIST_ENTRY* le;
96 
97  Status = remove_free_space_inode(Vcb, fsi->key.obj_id, batchlist, Irp, &rollback);
98 
99  if (!NT_SUCCESS(Status))
100  ERR("remove_free_space_inode for (%I64x,%x,%I64x) returned %08lx\n", fsi->key.obj_id, fsi->key.obj_type, fsi->key.offset, Status);
101 
102  le = Vcb->chunks.Flink;
103  while (le != &Vcb->chunks) {
105 
106  if (c->offset == tp.item->key.offset && c->cache) {
107  reap_fcb(c->cache);
108  c->cache = NULL;
109  }
110 
111  le = le->Flink;
112  }
113  }
114  } else
115  WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
116  }
117 
118  b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
119  if (b)
120  tp = next_tp;
121  } while (b);
122 
124 
125  if (NT_SUCCESS(Status))
127  else
129 
130  if (Vcb->space_root) {
131  searchkey.obj_id = 0;
132  searchkey.obj_type = 0;
133  searchkey.offset = 0;
134 
135  Status = find_item(Vcb, Vcb->space_root, &tp, &searchkey, false, Irp);
136  if (!NT_SUCCESS(Status)) {
137  ERR("find_item returned %08lx\n", Status);
138  return Status;
139  }
140 
141  do {
143  if (!NT_SUCCESS(Status)) {
144  ERR("delete_tree_item returned %08lx\n", Status);
145  return Status;
146  }
147 
148  b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
149  if (b)
150  tp = next_tp;
151  } while (b);
152  }
153 
154  // regenerate free space tree
155  if (Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE) {
156  LIST_ENTRY* le;
157 
158  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
159 
160  le = Vcb->chunks.Flink;
161  while (le != &Vcb->chunks) {
163 
164  if (!c->cache_loaded) {
166 
168  if (!NT_SUCCESS(Status)) {
169  ERR("load_cache_chunk(%I64x) returned %08lx\n", c->offset, Status);
171  ExReleaseResourceLite(&Vcb->chunk_lock);
172  return Status;
173  }
174 
175  c->changed = true;
176  c->space_changed = true;
177 
179  }
180 
181  le = le->Flink;
182  }
183 
184  ExReleaseResourceLite(&Vcb->chunk_lock);
185  }
186 
187  return Status;
188 }
uint64_t obj_id
Definition: btrfs.h:137
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
uint8_t obj_type
Definition: btrfs.h:138
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
release_chunk_lock(c, Vcb)
#define FREE_SPACE_CACHE_ID
Definition: btrfs.h:86
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
_In_ PIRP Irp
Definition: csq.h:116
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1673
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define b
Definition: ke_i.h:79
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
tree_data * item
Definition: btrfs_drv.h:518
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE
Definition: btrfs.h:105
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
static NTSTATUS remove_free_space_inode(device_extension *Vcb, uint64_t inode, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: free-space.c:25
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1357
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:980
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

Referenced by mount_vol().

◆ get_superblock_size()

static NTSTATUS get_superblock_size ( chunk c,
uint64_t size 
)
static

Definition at line 364 of file free-space.c.

364  {
366  CHUNK_ITEM* ci = c->chunk_item;
367  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
368  uint64_t off_start, off_end, space = 0;
369  uint16_t i = 0, j;
370  LIST_ENTRY stripes;
371 
372  InitializeListHead(&stripes);
373 
374  while (superblock_addrs[i] != 0) {
375  if (ci->type & BLOCK_FLAG_RAID0 || ci->type & BLOCK_FLAG_RAID10) {
376  for (j = 0; j < ci->num_stripes; j++) {
377  ULONG sub_stripes = max(ci->sub_stripes, 1);
378 
379  if (cis[j].offset + (ci->size * ci->num_stripes / sub_stripes) > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
380  off_start = superblock_addrs[i] - cis[j].offset;
381  off_start -= off_start % ci->stripe_length;
382  off_start *= ci->num_stripes / sub_stripes;
383  off_start += (j / sub_stripes) * ci->stripe_length;
384 
385  off_end = off_start + ci->stripe_length;
386 
387  Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, 1);
388  if (!NT_SUCCESS(Status)) {
389  ERR("add_superblock_stripe returned %08lx\n", Status);
390  goto end;
391  }
392  }
393  }
394  } else if (ci->type & BLOCK_FLAG_RAID5) {
395  for (j = 0; j < ci->num_stripes; j++) {
396  uint64_t stripe_size = ci->size / (ci->num_stripes - 1);
397 
398  if (cis[j].offset + stripe_size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
399  off_start = superblock_addrs[i] - cis[j].offset;
400  off_start -= off_start % (ci->stripe_length * (ci->num_stripes - 1));
401  off_start *= ci->num_stripes - 1;
402 
403  off_end = off_start + (ci->stripe_length * (ci->num_stripes - 1));
404 
405  Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
406  if (!NT_SUCCESS(Status)) {
407  ERR("add_superblock_stripe returned %08lx\n", Status);
408  goto end;
409  }
410  }
411  }
412  } else if (ci->type & BLOCK_FLAG_RAID6) {
413  for (j = 0; j < ci->num_stripes; j++) {
414  uint64_t stripe_size = ci->size / (ci->num_stripes - 2);
415 
416  if (cis[j].offset + stripe_size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
417  off_start = superblock_addrs[i] - cis[j].offset;
418  off_start -= off_start % (ci->stripe_length * (ci->num_stripes - 2));
419  off_start *= ci->num_stripes - 2;
420 
421  off_end = off_start + (ci->stripe_length * (ci->num_stripes - 2));
422 
423  Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
424  if (!NT_SUCCESS(Status)) {
425  ERR("add_superblock_stripe returned %08lx\n", Status);
426  goto end;
427  }
428  }
429  }
430  } else { // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4
431  for (j = 0; j < ci->num_stripes; j++) {
432  if (cis[j].offset + ci->size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
433  off_start = ((superblock_addrs[i] - cis[j].offset) / c->chunk_item->stripe_length) * c->chunk_item->stripe_length;
434  off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), c->chunk_item->stripe_length);
435 
436  Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
437  if (!NT_SUCCESS(Status)) {
438  ERR("add_superblock_stripe returned %08lx\n", Status);
439  goto end;
440  }
441  }
442  }
443  }
444 
445  i++;
446  }
447 
449 
450 end:
451  while (!IsListEmpty(&stripes)) {
452  LIST_ENTRY* le = RemoveHeadList(&stripes);
454 
455  space++;
456 
457  ExFreePool(ss);
458  }
459 
460  if (NT_SUCCESS(Status))
461  *size = space * ci->stripe_length;
462 
463  return Status;
464 }
#define max(a, b)
Definition: svc.c:63
uint16_t sub_stripes
Definition: btrfs.h:336
LONG NTSTATUS
Definition: precomp.h:26
uint64_t stripe_length
Definition: btrfs.h:330
unsigned short int uint16_t
Definition: acefiex.h:54
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:341
uint64_t size
Definition: btrfs.h:328
static NTSTATUS add_superblock_stripe(LIST_ENTRY *stripes, uint64_t off, uint64_t len)
Definition: free-space.c:328
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
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 GLint GLint j
Definition: glfuncs.h:250
Status
Definition: gdiplustypes.h:24
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
GLsizeiptr size
Definition: glext.h:5919
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLintptr offset
Definition: glext.h:5920
const GLubyte * c
Definition: glext.h:8905
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
GLuint GLuint end
Definition: gl.h:1545
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
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
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
static const uint64_t superblock_addrs[]
Definition: btrfs.h:13
unsigned int ULONG
Definition: retypes.h:1
uint16_t num_stripes
Definition: btrfs.h:335
#define ss
Definition: i386-dis.c:434
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
uint64_t type
Definition: btrfs.h:331
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by load_stored_free_space_cache().

◆ insert_cache_extent()

static NTSTATUS insert_cache_extent ( fcb fcb,
uint64_t  start,
uint64_t  length,
LIST_ENTRY rollback 
)
static

Definition at line 999 of file free-space.c.

999  {
1000  NTSTATUS Status;
1001  LIST_ENTRY* le = fcb->Vcb->chunks.Flink;
1002  chunk* c;
1003  uint64_t flags;
1004 
1005  flags = fcb->Vcb->data_flags;
1006 
1007  while (le != &fcb->Vcb->chunks) {
1009 
1010  if (!c->readonly && !c->reloc) {
1012 
1013  if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= length) {
1014  if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, false, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length, false, 0))
1015  return STATUS_SUCCESS;
1016  }
1017 
1019  }
1020 
1021  le = le->Flink;
1022  }
1023 
1024  Status = alloc_chunk(fcb->Vcb, flags, &c, false);
1025 
1026  if (!NT_SUCCESS(Status)) {
1027  ERR("alloc_chunk returned %08lx\n", Status);
1028  return Status;
1029  }
1030 
1032 
1033  if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= length) {
1034  if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, false, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length, false, 0))
1035  return STATUS_SUCCESS;
1036  }
1037 
1039 
1040  return STATUS_DISK_FULL;
1041 }
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
LONG NTSTATUS
Definition: precomp.h:26
release_chunk_lock(c, Vcb)
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
GLuint start
Definition: gl.h:1545
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1357
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define c
Definition: ke_i.h:80
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size)
Definition: write.c:361
struct _device_extension * Vcb
Definition: btrfs_drv.h:298

Referenced by allocate_cache_chunk().

◆ load_cache_chunk()

NTSTATUS load_cache_chunk ( device_extension Vcb,
chunk c,
PIRP  Irp 
)

Definition at line 980 of file free-space.c.

980  {
982 
983  if (c->cache_loaded)
984  return STATUS_SUCCESS;
985 
987  if (!NT_SUCCESS(Status)) {
988  ERR("load_free_space_cache returned %08lx\n", Status);
989  return Status;
990  }
991 
993 
994  c->cache_loaded = true;
995 
996  return STATUS_SUCCESS;
997 }
LONG NTSTATUS
Definition: precomp.h:26
_In_ PIRP Irp
Definition: csq.h:116
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
void protect_superblocks(_Inout_ chunk *c)
Definition: btrfs.c:3710
#define ERR(fmt,...)
Definition: debug.h:110
static NTSTATUS load_free_space_cache(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:886
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by _Function_class_(), allocate_tree_extents(), clear_free_space_cache(), find_metadata_address_in_chunk(), rationalize_extents(), reduce_tree_extent(), try_extend_data(), and update_chunk_usage().

◆ load_free_space_bitmap()

static void load_free_space_bitmap ( device_extension Vcb,
chunk c,
uint64_t  offset,
void data,
uint64_t total_space 
)
static

Definition at line 258 of file free-space.c.

258  {
259  RTL_BITMAP bmph;
260  uint32_t i, len, *dwords = data;
261  ULONG runlength, index;
262 
263  // flip bits
264  for (i = 0; i < Vcb->superblock.sector_size / sizeof(uint32_t); i++) {
265  dwords[i] = ~dwords[i];
266  }
267 
268  len = Vcb->superblock.sector_size * 8;
269 
270  RtlInitializeBitMap(&bmph, data, len);
271 
272  index = 0;
273  runlength = RtlFindFirstRunClear(&bmph, &index);
274 
275  while (runlength != 0) {
277 
278  if (index >= len)
279  break;
280 
281  if (index + runlength >= len) {
282  runlength = len - index;
283 
284  if (runlength == 0)
285  break;
286  }
287 
288  addr = offset + (index * Vcb->superblock.sector_size);
289  length = Vcb->superblock.sector_size * runlength;
290 
291  add_space_entry(&c->space, &c->space_size, addr, length);
292  index += runlength;
293  *total_space += length;
294 
295  runlength = RtlFindNextForwardRunClear(&bmph, index, &index);
296  }
297 }
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
GLuint index
Definition: glext.h:6031
GLintptr offset
Definition: glext.h:5920
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum const GLvoid * addr
Definition: glext.h:9621
#define index(s, c)
Definition: various.h:29
GLenum GLsizei len
Definition: glext.h:6722
UINT64 uint64_t
Definition: types.h:77
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
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)
UINT32 uint32_t
Definition: types.h:75
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
unsigned int ULONG
Definition: retypes.h:1
#define uint32_t
Definition: nsiface.idl:61
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190

Referenced by load_stored_free_space_cache().

◆ load_free_space_cache()

static NTSTATUS load_free_space_cache ( device_extension Vcb,
chunk c,
PIRP  Irp 
)
static

Definition at line 886 of file free-space.c.

886  {
887  traverse_ptr tp, next_tp;
888  KEY searchkey;
889  uint64_t lastaddr;
890  bool b;
891  space* s;
893 
894  if (Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE && Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID) {
896 
898  ERR("load_stored_free_space_tree returned %08lx\n", Status);
899  return Status;
900  }
901  } else if (Vcb->superblock.generation - 1 == Vcb->superblock.cache_generation) {
903 
905  ERR("load_stored_free_space_cache returned %08lx\n", Status);
906  return Status;
907  }
908  } else
910 
911  if (Status == STATUS_NOT_FOUND) {
912  TRACE("generating free space cache for chunk %I64x\n", c->offset);
913 
914  searchkey.obj_id = c->offset;
915  searchkey.obj_type = TYPE_EXTENT_ITEM;
916  searchkey.offset = 0;
917 
918  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
919  if (!NT_SUCCESS(Status)) {
920  ERR("error - find_item returned %08lx\n", Status);
921  return Status;
922  }
923 
924  lastaddr = c->offset;
925 
926  do {
927  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
928  break;
929 
930  if (tp.item->key.obj_id >= c->offset && (tp.item->key.obj_type == TYPE_EXTENT_ITEM || tp.item->key.obj_type == TYPE_METADATA_ITEM)) {
931  if (tp.item->key.obj_id > lastaddr) {
933 
934  if (!s) {
935  ERR("out of memory\n");
937  }
938 
939  s->address = lastaddr;
940  s->size = tp.item->key.obj_id - lastaddr;
941  InsertTailList(&c->space, &s->list_entry);
942 
943  order_space_entry(s, &c->space_size);
944 
945  TRACE("(%I64x,%I64x)\n", s->address, s->size);
946  }
947 
949  lastaddr = tp.item->key.obj_id + Vcb->superblock.node_size;
950  else
951  lastaddr = tp.item->key.obj_id + tp.item->key.offset;
952  }
953 
954  b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
955  if (b)
956  tp = next_tp;
957  } while (b);
958 
959  if (lastaddr < c->offset + c->chunk_item->size) {
961 
962  if (!s) {
963  ERR("out of memory\n");
965  }
966 
967  s->address = lastaddr;
968  s->size = c->offset + c->chunk_item->size - lastaddr;
969  InsertTailList(&c->space, &s->list_entry);
970 
971  order_space_entry(s, &c->space_size);
972 
973  TRACE("(%I64x,%I64x)\n", s->address, s->size);
974  }
975  }
976 
977  return STATUS_SUCCESS;
978 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static void order_space_entry(space *s, LIST_ENTRY *list_size)
Definition: free-space.c:299
LONG NTSTATUS
Definition: precomp.h:26
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID
Definition: btrfs.h:106
#define InsertTailList(ListHead, Entry)
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
uint64_t offset
Definition: btrfs.h:139
#define ALLOC_TAG
Definition: btrfs_drv.h:91
_In_ PIRP Irp
Definition: csq.h:116
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
#define b
Definition: ke_i.h:79
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
Status
Definition: gdiplustypes.h:24
#define STATUS_NOT_FOUND
Definition: shellext.h:72
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLintptr offset
Definition: glext.h:5920
NTSTATUS load_stored_free_space_cache(device_extension *Vcb, chunk *c, bool load_only, PIRP Irp)
Definition: free-space.c:466
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE
Definition: btrfs.h:105
GLdouble s
Definition: gl.h:2039
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
static NTSTATUS load_stored_free_space_tree(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:729
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by load_cache_chunk().

◆ load_stored_free_space_cache()

NTSTATUS load_stored_free_space_cache ( device_extension Vcb,
chunk c,
bool  load_only,
PIRP  Irp 
)

Definition at line 466 of file free-space.c.

466  {
467  KEY searchkey;
469  FREE_SPACE_ITEM* fsi;
471  uint8_t* data;
473  uint32_t *checksums, crc32, i, num_sectors, num_valid_sectors, size;
474  FREE_SPACE_ENTRY* fse;
475  uint64_t num_entries, num_bitmaps, extent_length, bmpnum, off, total_space = 0, superblock_size;
476  LIST_ENTRY *le, rollback;
477 
478  // FIXME - does this break if Vcb->superblock.sector_size is not 4096?
479 
480  TRACE("(%p, %I64x)\n", Vcb, c->offset);
481 
482  searchkey.obj_id = FREE_SPACE_CACHE_ID;
483  searchkey.obj_type = 0;
484  searchkey.offset = c->offset;
485 
486  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
487  if (!NT_SUCCESS(Status)) {
488  ERR("error - find_item returned %08lx\n", Status);
489  return Status;
490  }
491 
492  if (keycmp(tp.item->key, searchkey)) {
493  TRACE("(%I64x,%x,%I64x) not found\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
494  return STATUS_NOT_FOUND;
495  }
496 
497  if (tp.item->size < sizeof(FREE_SPACE_ITEM)) {
498  WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
499  return STATUS_NOT_FOUND;
500  }
501 
502  fsi = (FREE_SPACE_ITEM*)tp.item->data;
503 
504  if (fsi->key.obj_type != TYPE_INODE_ITEM) {
505  WARN("cache pointed to something other than an INODE_ITEM\n");
506  return STATUS_NOT_FOUND;
507  }
508 
509  inode = fsi->key.obj_id;
510  num_entries = fsi->num_entries;
511  num_bitmaps = fsi->num_bitmaps;
512 
513  Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, false, NULL, &c->cache, PagedPool, Irp);
514  if (!NT_SUCCESS(Status)) {
515  ERR("open_fcb returned %08lx\n", Status);
516  return STATUS_NOT_FOUND;
517  }
518 
519  if (load_only)
520  return STATUS_SUCCESS;
521 
522  if (c->cache->inode_item.st_size == 0) {
523  WARN("cache had zero length\n");
524  free_fcb(c->cache);
525  c->cache = NULL;
526  return STATUS_NOT_FOUND;
527  }
528 
529  c->cache->inode_item.flags |= BTRFS_INODE_NODATACOW;
530 
531  if (num_entries == 0 && num_bitmaps == 0)
532  return STATUS_SUCCESS;
533 
534  size = (uint32_t)sector_align(c->cache->inode_item.st_size, Vcb->superblock.sector_size);
535 
537 
538  if (!data) {
539  ERR("out of memory\n");
540  free_fcb(c->cache);
541  c->cache = NULL;
543  }
544 
545  if (c->chunk_item->size < 0x6400000) { // 100 MB
546  WARN("deleting free space cache for chunk smaller than 100MB\n");
547  goto clearcache;
548  }
549 
550  Status = read_file(c->cache, data, 0, c->cache->inode_item.st_size, NULL, NULL);
551  if (!NT_SUCCESS(Status)) {
552  ERR("read_file returned %08lx\n", Status);
553  ExFreePool(data);
554 
555  c->cache->deleted = true;
556  mark_fcb_dirty(c->cache);
557 
558  free_fcb(c->cache);
559  c->cache = NULL;
560  return STATUS_NOT_FOUND;
561  }
562 
563  if (size > c->cache->inode_item.st_size)
564  RtlZeroMemory(&data[c->cache->inode_item.st_size], (ULONG)(size - c->cache->inode_item.st_size));
565 
566  num_sectors = size / Vcb->superblock.sector_size;
567 
568  generation = (uint64_t*)(data + (num_sectors * sizeof(uint32_t)));
569 
570  if (*generation != fsi->generation) {
571  WARN("free space cache generation for %I64x was %I64x, expected %I64x\n", c->offset, *generation, fsi->generation);
572  goto clearcache;
573  }
574 
575  extent_length = (num_sectors * sizeof(uint32_t)) + sizeof(uint64_t) + (num_entries * sizeof(FREE_SPACE_ENTRY));
576 
577  num_valid_sectors = (ULONG)((sector_align(extent_length, Vcb->superblock.sector_size) / Vcb->superblock.sector_size) + num_bitmaps);
578 
579  if (num_valid_sectors > num_sectors) {
580  ERR("free space cache for %I64x was %u sectors, expected at least %u\n", c->offset, num_sectors, num_valid_sectors);
581  goto clearcache;
582  }
583 
584  checksums = (uint32_t*)data;
585 
586  for (i = 0; i < num_valid_sectors; i++) {
587  if (i * Vcb->superblock.sector_size > sizeof(uint32_t) * num_sectors)
588  crc32 = ~calc_crc32c(0xffffffff, &data[i * Vcb->superblock.sector_size], Vcb->superblock.sector_size);
589  else if ((i + 1) * Vcb->superblock.sector_size < sizeof(uint32_t) * num_sectors)
590  crc32 = 0; // FIXME - test this
591  else
592  crc32 = ~calc_crc32c(0xffffffff, &data[sizeof(uint32_t) * num_sectors], ((i + 1) * Vcb->superblock.sector_size) - (sizeof(uint32_t) * num_sectors));
593 
594  if (crc32 != checksums[i]) {
595  WARN("checksum %u was %08x, expected %08x\n", i, crc32, checksums[i]);
596  goto clearcache;
597  }
598  }
599 
600  off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
601 
602  bmpnum = 0;
603  for (i = 0; i < num_entries; i++) {
604  if ((off + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size != off / Vcb->superblock.sector_size)
605  off = sector_align(off, Vcb->superblock.sector_size);
606 
607  fse = (FREE_SPACE_ENTRY*)&data[off];
608 
609  if (fse->type == FREE_SPACE_EXTENT) {
610  Status = add_space_entry(&c->space, &c->space_size, fse->offset, fse->size);
611  if (!NT_SUCCESS(Status)) {
612  ERR("add_space_entry returned %08lx\n", Status);
613  ExFreePool(data);
614  return Status;
615  }
616 
617  total_space += fse->size;
618  } else if (fse->type != FREE_SPACE_BITMAP) {
619  ERR("unknown free-space type %x\n", fse->type);
620  }
621 
622  off += sizeof(FREE_SPACE_ENTRY);
623  }
624 
625  if (num_bitmaps > 0) {
626  bmpnum = sector_align(off, Vcb->superblock.sector_size) / Vcb->superblock.sector_size;
627  off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
628 
629  for (i = 0; i < num_entries; i++) {
630  if ((off + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size != off / Vcb->superblock.sector_size)
631  off = sector_align(off, Vcb->superblock.sector_size);
632 
633  fse = (FREE_SPACE_ENTRY*)&data[off];
634 
635  if (fse->type == FREE_SPACE_BITMAP) {
636  // FIXME - make sure we don't overflow the buffer here
637  load_free_space_bitmap(Vcb, c, fse->offset, &data[bmpnum * Vcb->superblock.sector_size], &total_space);
638  bmpnum++;
639  }
640 
641  off += sizeof(FREE_SPACE_ENTRY);
642  }
643  }
644 
645  // do sanity check
646 
647  Status = get_superblock_size(c, &superblock_size);
648  if (!NT_SUCCESS(Status)) {
649  ERR("get_superblock_size returned %08lx\n", Status);
650  ExFreePool(data);
651  return Status;
652  }
653 
654  if (c->chunk_item->size - c->used != total_space + superblock_size) {
655  WARN("invalidating cache for chunk %I64x: space was %I64x, expected %I64x\n", c->offset, total_space + superblock_size, c->chunk_item->size - c->used);
656  goto clearcache;
657  }
658 
659  le = c->space.Flink;
660  while (le != &c->space) {
662  LIST_ENTRY* le2 = le->Flink;
663 
664  if (le2 != &c->space) {
666 
667  if (s2->address == s->address + s->size) {
668  s->size += s2->size;
669 
670  RemoveEntryList(&s2->list_entry);
671  RemoveEntryList(&s2->list_entry_size);
672  ExFreePool(s2);
673 
674  RemoveEntryList(&s->list_entry_size);
675  order_space_entry(s, &c->space_size);
676 
677  le2 = le;
678  }
679  }
680 
681  le = le2;
682  }
683 
684  ExFreePool(data);
685 
686  return STATUS_SUCCESS;
687 
688 clearcache:
689  ExFreePool(data);
690 
692 
694  if (!NT_SUCCESS(Status)) {
695  ERR("delete_tree_item returned %08lx\n", Status);
696  return Status;
697  }
698 
699  Status = excise_extents(Vcb, c->cache, 0, c->cache->inode_item.st_size, Irp, &rollback);
700  if (!NT_SUCCESS(Status)) {
701  ERR("excise_extents returned %08lx\n", Status);
703  return Status;
704  }
705 
707 
708  c->cache->deleted = true;
709  mark_fcb_dirty(c->cache);
710 
711  c->old_cache = c->cache;
712  c->cache = NULL;
713 
714  le = c->space.Flink;
715  while (le != &c->space) {
717  LIST_ENTRY* le2 = le->Flink;
718 
719  RemoveEntryList(&s->list_entry);
720  RemoveEntryList(&s->list_entry_size);
721  ExFreePool(s);
722 
723  le = le2;
724  }
725 
726  return STATUS_NOT_FOUND;
727 }
uint64_t obj_id
Definition: btrfs.h:137
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
struct S2 s2
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define FREE_SPACE_EXTENT
Definition: btrfs.h:433
static void order_space_entry(space *s, LIST_ENTRY *list_size)
Definition: free-space.c:299
Definition: btrfs.h:436
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1664
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
static void load_free_space_bitmap(device_extension *Vcb, chunk *c, uint64_t offset, void *data, uint64_t *total_space)
Definition: free-space.c:258
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:699
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
#define FREE_SPACE_CACHE_ID
Definition: btrfs.h:86
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
Definition: read.c:2828
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
uint64_t size
Definition: btrfs.h:438
Definition: fs.h:78
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t generation
Definition: btrfs.h:444
uint8_t type
Definition: btrfs.h:439
_In_ PIRP Irp
Definition: csq.h:116
#define FREE_SPACE_BITMAP
Definition: btrfs.h:434
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1625
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:300
uint64_t offset
Definition: btrfs.h:437
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static NTSTATUS get_superblock_size(chunk *c, uint64_t *size)
Definition: free-space.c:364
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
crc_func calc_crc32c
Definition: crc32c.c:23
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
#define uint64_t
Definition: nsiface.idl:62
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
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
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1357
UINT32 uint32_t
Definition: types.h:75
#define crc32(crc, buf, len)
Definition: inflate.c:1081
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
uint64_t num_entries
Definition: btrfs.h:445
uint64_t num_bitmaps
Definition: btrfs.h:446
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
#define uint32_t
Definition: nsiface.idl:61
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

Referenced by drop_chunk(), and load_free_space_cache().

◆ load_stored_free_space_tree()

static NTSTATUS load_stored_free_space_tree ( device_extension Vcb,
chunk c,
PIRP  Irp 
)
static

Definition at line 729 of file free-space.c.

729  {
730  KEY searchkey;
731  traverse_ptr tp, next_tp;
733  ULONG* bmparr = NULL;
734  ULONG bmplen = 0;
735  LIST_ENTRY* le;
736 
737  TRACE("(%p, %I64x)\n", Vcb, c->offset);
738 
739  if (!Vcb->space_root)
740  return STATUS_NOT_FOUND;
741 
742  searchkey.obj_id = c->offset;
743  searchkey.obj_type = TYPE_FREE_SPACE_INFO;
744  searchkey.offset = c->chunk_item->size;
745 
746  Status = find_item(Vcb, Vcb->space_root, &tp, &searchkey, false, Irp);
747  if (!NT_SUCCESS(Status)) {
748  ERR("find_item returned %08lx\n", Status);
749  return Status;
750  }
751 
752  if (keycmp(tp.item->key, searchkey)) {
753  TRACE("(%I64x,%x,%I64x) not found\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
754  return STATUS_NOT_FOUND;
755  }
756 
757  if (tp.item->size < sizeof(FREE_SPACE_INFO)) {
758  WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_INFO));
759  return STATUS_NOT_FOUND;
760  }
761 
762  while (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
763  tp = next_tp;
764 
765  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
766  break;
767 
769  Status = add_space_entry(&c->space, &c->space_size, tp.item->key.obj_id, tp.item->key.offset);
770  if (!NT_SUCCESS(Status)) {
771  ERR("add_space_entry returned %08lx\n", Status);
772  if (bmparr) ExFreePool(bmparr);
773  return Status;
774  }
775  } else if (tp.item->key.obj_type == TYPE_FREE_SPACE_BITMAP) {
776  ULONG explen, index, runlength;
777  RTL_BITMAP bmp;
778  uint64_t lastoff;
779  ULONG bmpl;
780 
781  explen = (ULONG)(tp.item->key.offset / (Vcb->superblock.sector_size * 8));
782 
783  if (tp.item->size < explen) {
784  WARN("(%I64x,%x,%I64x) was %u bytes, expected %lu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, explen);
785  return STATUS_NOT_FOUND;
786  } else if (tp.item->size == 0) {
787  WARN("(%I64x,%x,%I64x) has size of 0\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
788  return STATUS_NOT_FOUND;
789  }
790 
791  if (bmplen < tp.item->size) {
792  if (bmparr)
793  ExFreePool(bmparr);
794 
795  bmplen = (ULONG)sector_align(tp.item->size, sizeof(ULONG));
796  bmparr = ExAllocatePoolWithTag(PagedPool, bmplen, ALLOC_TAG);
797  if (!bmparr) {
798  ERR("out of memory\n");
800  }
801  }
802 
803  // We copy the bitmap because it supposedly has to be ULONG-aligned
804  RtlCopyMemory(bmparr, tp.item->data, tp.item->size);
805 
806  bmpl = (ULONG)tp.item->key.offset / Vcb->superblock.sector_size;
807 
808  RtlInitializeBitMap(&bmp, bmparr, bmpl);
809 
810  lastoff = tp.item->key.obj_id;
811 
812  runlength = RtlFindFirstRunClear(&bmp, &index);
813 
814  while (runlength != 0) {
815  uint64_t runstart, runend;
816 
817  if (index >= bmpl)
818  break;
819 
820  if (index + runlength >= bmpl) {
821  runlength = bmpl - index;
822 
823  if (runlength == 0)
824  break;
825  }
826 
827  runstart = tp.item->key.obj_id + (index * Vcb->superblock.sector_size);
828  runend = runstart + (runlength * Vcb->superblock.sector_size);
829 
830  if (runstart > lastoff) {
831  Status = add_space_entry(&c->space, &c->space_size, lastoff, runstart - lastoff);
832  if (!NT_SUCCESS(Status)) {
833  ERR("add_space_entry returned %08lx\n", Status);
834  if (bmparr) ExFreePool(bmparr);
835  return Status;
836  }
837  }
838 
839  lastoff = runend;
840 
841  runlength = RtlFindNextForwardRunClear(&bmp, index + runlength, &index);
842  }
843 
844  if (lastoff < tp.item->key.obj_id + tp.item->key.offset) {
845  Status = add_space_entry(&c->space, &c->space_size, lastoff, tp.item->key.obj_id + tp.item->key.offset - lastoff);
846  if (!NT_SUCCESS(Status)) {
847  ERR("add_space_entry returned %08lx\n", Status);
848  if (bmparr) ExFreePool(bmparr);
849  return Status;
850  }
851  }
852  }
853  }
854 
855  if (bmparr)
856  ExFreePool(bmparr);
857 
858  le = c->space.Flink;
859  while (le != &c->space) {
861  LIST_ENTRY* le2 = le->Flink;
862 
863  if (le2 != &c->space) {
865 
866  if (s2->address == s->address + s->size) {
867  s->size += s2->size;
868 
869  RemoveEntryList(&s2->list_entry);
870  RemoveEntryList(&s2->list_entry_size);
871  ExFreePool(s2);
872 
873  RemoveEntryList(&s->list_entry_size);
874  order_space_entry(s, &c->space_size);
875 
876  le2 = le;
877  }
878  }
879 
880  le = le2;
881  }
882 
883  return STATUS_SUCCESS;
884 }
uint64_t obj_id
Definition: btrfs.h:137
struct S2 s2
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static void order_space_entry(space *s, LIST_ENTRY *list_size)
Definition: free-space.c:299
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
#define WARN(fmt,...)
Definition: debug.h:112
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define ALLOC_TAG
Definition: btrfs_drv.h:91
_In_ PIRP Irp
Definition: csq.h:116
GLuint index
Definition: glext.h:6031
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_FREE_SPACE_EXTENT
Definition: btrfs.h:40
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
BITMAP bmp
Definition: alphablend.c:62
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
#define index(s, c)
Definition: various.h:29
#define TYPE_FREE_SPACE_INFO
Definition: btrfs.h:39
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)
Definition: list.h:27
#define NULL
Definition: types.h:112
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define TYPE_FREE_SPACE_BITMAP
Definition: btrfs.h:41
Definition: path.c:41

Referenced by load_free_space_cache().

◆ order_space_entry()

static void order_space_entry ( space s,
LIST_ENTRY list_size 
)
static

Definition at line 299 of file free-space.c.

299  {
300  LIST_ENTRY* le;
301 
302  if (IsListEmpty(list_size)) {
303  InsertHeadList(list_size, &s->list_entry_size);
304  return;
305  }
306 
307  le = list_size->Flink;
308 
309  while (le != list_size) {
310  space* s2 = CONTAINING_RECORD(le, space, list_entry_size);
311 
312  if (s2->size <= s->size) {
313  InsertHeadList(le->Blink, &s->list_entry_size);
314  return;
315  }
316 
317  le = le->Flink;
318  }
319 
320  InsertTailList(list_size, &s->list_entry_size);
321 }
struct S2 s2
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119

Referenced by load_free_space_cache(), load_stored_free_space_cache(), load_stored_free_space_tree(), space_list_add2(), and space_list_subtract2().

◆ remove_free_space_inode()

static NTSTATUS remove_free_space_inode ( device_extension Vcb,
uint64_t  inode,
LIST_ENTRY batchlist,
PIRP  Irp,
LIST_ENTRY rollback 
)
static

Definition at line 25 of file free-space.c.

25  {
27  fcb* fcb;
28 
29  Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, false, NULL, &fcb, PagedPool, Irp);
30  if (!NT_SUCCESS(Status)) {
31  ERR("open_fcb returned %08lx\n", Status);
32  return Status;
33  }
34 
36 
37  if (fcb->inode_item.st_size > 0) {
38  Status = excise_extents(fcb->Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size), Irp, rollback);
39  if (!NT_SUCCESS(Status)) {
40  ERR("excise_extents returned %08lx\n", Status);
41  return Status;
42  }
43  }
44 
45  fcb->deleted = true;
46 
47  Status = flush_fcb(fcb, false, batchlist, Irp);
48  if (!NT_SUCCESS(Status)) {
49  ERR("flush_fcb returned %08lx\n", Status);
50  free_fcb(fcb);
51  return Status;
52  }
53 
54  free_fcb(fcb);
55 
56  return STATUS_SUCCESS;
57 }
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1664
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:699
LONG NTSTATUS
Definition: precomp.h:26
Definition: fs.h:78
_In_ PIRP Irp
Definition: csq.h:116
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1625
Status
Definition: gdiplustypes.h:24
uint64_t st_size
Definition: btrfs.h:282
struct _fcb fcb
Definition: btrfs_drv.h:1357
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
NTSTATUS flush_fcb(fcb *fcb, bool cache, LIST_ENTRY *batchlist, PIRP Irp)
Definition: flushthread.c:4818
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
#define ERR(fmt,...)
Definition: debug.h:110
bool deleted
Definition: btrfs_drv.h:306
#define NULL
Definition: types.h:112
_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:1357
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define STATUS_SUCCESS
Definition: shellext.h:65
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
struct _device_extension * Vcb
Definition: btrfs_drv.h:298

Referenced by clear_free_space_cache().

◆ space_list_add()

void space_list_add ( chunk c,
uint64_t  address,
uint64_t  length,
LIST_ENTRY rollback 
)

Definition at line 1959 of file free-space.c.

1959  {
1960  TRACE("(%p, %I64x, %I64x, %p)\n", c, address, length, rollback);
1961 
1962  c->changed = true;
1963  c->space_changed = true;
1964 
1965  space_list_add2(&c->deleting, NULL, address, length, c, rollback);
1966 }
void space_list_add2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:1443
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define TRACE(s)
Definition: solgame.cpp:4
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
#define NULL
Definition: types.h:112
_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:1357

Referenced by add_data_reloc(), add_metadata_reloc(), flush_changed_extent(), rationalize_extents(), and reduce_tree_extent().

◆ space_list_add2()

void space_list_add2 ( LIST_ENTRY list,
LIST_ENTRY list_size,
uint64_t  address,
uint64_t  length,
chunk c,
LIST_ENTRY rollback 
)

Definition at line 1443 of file free-space.c.

1443  {
1444  LIST_ENTRY* le;
1445  space *s, *s2;
1446 
1447  if (IsListEmpty(list)) {
1449 
1450  if (!s) {
1451  ERR("out of memory\n");
1452  return;
1453  }
1454 
1455  s->address = address;
1456  s->size = length;
1457  InsertTailList(list, &s->list_entry);
1458 
1459  if (list_size)
1460  InsertTailList(list_size, &s->list_entry_size);
1461 
1462  if (rollback)
1463  add_rollback_space(rollback, true, list, list_size, address, length, c);
1464 
1465  return;
1466  }
1467 
1468  le = list->Flink;
1469  do {
1471 
1472  // old entry envelops new one completely
1473  if (s2->address <= address && s2->address + s2->size >= address + length)
1474  return;
1475 
1476  // new entry envelops old one completely
1477  if (address <= s2->address && address + length >= s2->address + s2->size) {
1478  if (address < s2->address) {
1479  if (rollback)
1480  add_rollback_space(rollback, true, list, list_size, address, s2->address - address, c);
1481 
1482  s2->size += s2->address - address;
1483  s2->address = address;
1484 
1485  while (s2->list_entry.Blink != list) {
1486  space* s3 = CONTAINING_RECORD(s2->list_entry.Blink, space, list_entry);
1487 
1488  if (s3->address + s3->size == s2->address) {
1489  s2->address = s3->address;
1490  s2->size += s3->size;
1491 
1493 
1494  if (list_size)
1496 
1497  ExFreePool(s3);
1498  } else
1499  break;
1500  }
1501  }
1502 
1503  if (length > s2->size) {
1504  if (rollback)
1505  add_rollback_space(rollback, true, list, list_size, s2->address + s2->size, address + length - s2->address - s2->size, c);
1506 
1507  s2->size = length;
1508 
1509  while (s2->list_entry.Flink != list) {
1510  space* s3 = CONTAINING_RECORD(s2->list_entry.Flink, space, list_entry);
1511 
1512  if (s3->address <= s2->address + s2->size) {
1513  s2->size = max(s2->size, s3->address + s3->size - s2->address);
1514 
1516 
1517  if (list_size)
1519 
1520  ExFreePool(s3);
1521  } else
1522  break;
1523  }
1524  }
1525 
1526  if (list_size) {
1527  RemoveEntryList(&s2->list_entry_size);
1528  order_space_entry(s2, list_size);
1529  }
1530 
1531  return;
1532  }
1533 
1534  // new entry overlaps start of old one
1535  if (address < s2->address && address + length >= s2->address) {
1536  if (rollback)
1537  add_rollback_space(rollback, true, list, list_size, address, s2->address - address, c);
1538 
1539  s2->size += s2->address - address;
1540  s2->address = address;
1541 
1542  while (s2->list_entry.Blink != list) {
1543  space* s3 = CONTAINING_RECORD(s2->list_entry.Blink, space, list_entry);
1544 
1545  if (s3->address + s3->size == s2->address) {
1546  s2->address = s3->address;
1547  s2->size += s3->size;
1548 
1550 
1551  if (list_size)
1553 
1554  ExFreePool(s3);
1555  } else
1556  break;
1557  }
1558 
1559  if (list_size) {
1560  RemoveEntryList(&s2->list_entry_size);
1561  order_space_entry(s2, list_size);
1562  }
1563 
1564  return;
1565  }
1566 
1567  // new entry overlaps end of old one
1568  if (address <= s2->address + s2->size && address + length > s2->address + s2->size) {
1569  if (rollback)
1570  add_rollback_space(rollback, true, list, list_size, address, s2->address + s2->size - address, c);
1571 
1572  s2->size = address + length - s2->address;
1573 
1574  while (s2->list_entry.Flink != list) {
1575  space* s3 = CONTAINING_RECORD(s2->list_entry.Flink, space, list_entry);
1576 
1577  if (s3->address <= s2->address + s2->size) {
1578  s2->size = max(s2->size, s3->address + s3->size - s2->address);
1579 
1581 
1582  if (list_size)
1584 
1585  ExFreePool(s3);
1586  } else
1587  break;
1588  }
1589 
1590  if (list_size) {
1591  RemoveEntryList(&s2->list_entry_size);
1592  order_space_entry(s2, list_size);
1593  }
1594 
1595  return;
1596  }
1597 
1598  // add completely separate entry
1599  if (s2->address > address + length) {
1601 
1602  if (!s) {
1603  ERR("out of memory\n");
1604  return;
1605  }
1606 
1607  if (rollback)
1608  add_rollback_space(rollback, true, list, list_size, address, length, c);
1609 
1610  s->address = address;
1611  s->size = length;
1612  InsertHeadList(s2->list_entry.Blink, &s->list_entry);
1613 
1614  if (list_size)
1615  order_space_entry(s, list_size);
1616 
1617  return;
1618  }
1619 
1620  le = le->Flink;
1621  } while (le != list);
1622 
1623  // check if contiguous with last entry
1624  if (s2->address + s2->size == address) {
1625  s2->size += length;
1626 
1627  if (list_size) {
1628  RemoveEntryList(&s2->list_entry_size);
1629  order_space_entry(s2, list_size);
1630  }
1631 
1632  return;
1633  }
1634 
1635  // otherwise, insert at end
1637 
1638  if (!s) {
1639  ERR("out of memory\n");
1640  return;
1641  }
1642 
1643  s->address = address;
1644  s->size = length;
1645  InsertTailList(list, &s->list_entry);
1646 
1647  if (list_size)
1648  order_space_entry(s, list_size);
1649 
1650  if (rollback)
1651  add_rollback_space(rollback, true, list, list_size, address, length, c);
1652 }
#define max(a, b)
Definition: svc.c:63
struct S2 s2
static void order_space_entry(space *s, LIST_ENTRY *list_size)
Definition: free-space.c:299
static void add_rollback_space(LIST_ENTRY *rollback, bool add, LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c)
Definition: free-space.c:1425
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
uint64_t address
Definition: btrfs_drv.h:527
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLdouble s
Definition: gl.h:2039
Definition: _list.h:228
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
uint64_t size
Definition: btrfs_drv.h:528
Definition: list.h:27
_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:1357
LIST_ENTRY list_entry_size
Definition: btrfs_drv.h:530
LIST_ENTRY list_entry
Definition: btrfs_drv.h:529
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by do_rollback(), drop_chunk(), regenerate_space_list(), resize_device(), space_list_add(), and space_list_merge().

◆ space_list_merge()

static void space_list_merge ( LIST_ENTRY spacelist,
LIST_ENTRY spacelist_size,
LIST_ENTRY deleting 
)
static

Definition at line 1654 of file free-space.c.

1654  {
1655  LIST_ENTRY* le;
1656 
1657  if (!IsListEmpty(deleting)) {
1658  le = deleting->Flink;
1659  while (le != deleting) {
1661 
1662  space_list_add2(spacelist, spacelist_size, s->address, s->size, NULL, NULL);
1663 
1664  le = le->Flink;
1665  }
1666  }
1667 }
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
void space_list_add2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:1443
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
Definition: list.h:27
#define NULL
Definition: types.h:112

Referenced by update_chunk_cache(), and update_chunk_cache_tree().

◆ space_list_subtract()

void space_list_subtract ( chunk c,
bool  deleting,
uint64_t  address,
uint64_t  length,
LIST_ENTRY rollback 
)

Definition at line 2047 of file free-space.c.

2047  {
2048  LIST_ENTRY* list;
2049 
2050  list = deleting ? &c->deleting : &c->space;
2051 
2052  c->changed = true;
2053  c->space_changed = true;
2054 
2055  space_list_subtract2(list, deleting ? NULL : &c->space_size, address, length, c, rollback);
2056 }
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
Definition: _list.h:228
Definition: typedefs.h:119
#define list
Definition: rosglue.h:35
#define NULL
Definition: types.h:112
_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:1357
void space_list_subtract2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:1968

Referenced by balance_data_chunk(), insert_tree_extent(), insert_tree_extent_skinny(), protect_superblocks(), write_compressed(), and write_metadata_items().

◆ space_list_subtract2()

void space_list_subtract2 ( LIST_ENTRY list,
LIST_ENTRY list_size,
uint64_t  address,
uint64_t  length,
chunk c,
LIST_ENTRY rollback 
)

Definition at line 1968 of file free-space.c.

1968  {
1969  LIST_ENTRY *le, *le2;
1970  space *s, *s2;
1971 
1972  if (IsListEmpty(list))
1973  return;
1974 
1975  le = list->Flink;
1976  while (le != list) {
1978  le2 = le->Flink;
1979 
1980  if (s2->address >= address + length)
1981  return;
1982 
1983  if (s2->address >= address && s2->address + s2->size <= address + length) { // remove entry entirely
1984  if (rollback)
1985  add_rollback_space(rollback, false, list, list_size, s2->address, s2->size, c);
1986 
1987  RemoveEntryList(&s2->list_entry);
1988 
1989  if (list_size)
1990  RemoveEntryList(&s2->list_entry_size);
1991 
1992  ExFreePool(s2);
1993  } else if (address + length > s2->address && address + length < s2->address + s2->size) {
1994  if (address > s2->address) { // cut out hole
1995  if (rollback)
1996  add_rollback_space(rollback, false, list, list_size, address, length, c);
1997 
1999 
2000  if (!s) {
2001  ERR("out of memory\n");
2002  return;
2003  }
2004 
2005  s->address = s2->address;
2006  s->size = address - s2->address;
2007  InsertHeadList(s2->list_entry.Blink, &s->list_entry);
2008 
2009  s2->size = s2->address + s2->size - address - length;
2010  s2->address = address + length;
2011 
2012  if (list_size) {
2013  RemoveEntryList(&s2->list_entry_size);
2014  order_space_entry(s2, list_size);
2015  order_space_entry(s, list_size);
2016  }
2017 
2018  return;
2019  } else { // remove start of entry
2020  if (rollback)
2021  add_rollback_space(rollback, false, list, list_size, s2->address, address + length - s2->address, c);
2022 
2023  s2->size -= address + length - s2->address;
2024  s2->address = address + length;
2025 
2026  if (list_size) {
2027  RemoveEntryList(&s2->list_entry_size);
2028  order_space_entry(s2, list_size);
2029  }
2030  }
2031  } else if (address > s2->address && address < s2->address + s2->size) { // remove end of entry
2032  if (rollback)
2033  add_rollback_space(rollback, false, list, list_size, address, s2->address + s2->size - address, c);
2034 
2035  s2->size = address - s2->address;
2036 
2037  if (list_size) {
2038  RemoveEntryList(&s2->list_entry_size);
2039  order_space_entry(s2, list_size);
2040  }
2041  }
2042 
2043  le = le2;
2044  }
2045 }
struct S2 s2
static void order_space_entry(space *s, LIST_ENTRY *list_size)
Definition: free-space.c:299
static void add_rollback_space(LIST_ENTRY *rollback, bool add, LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c)
Definition: free-space.c:1425
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLdouble s
Definition: gl.h:2039
Definition: _list.h:228
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:27
_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:1357
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by alloc_chunk(), do_rollback(), find_disk_holes(), regenerate_space_list(), resize_device(), and space_list_subtract().

◆ update_chunk_cache()

static NTSTATUS update_chunk_cache ( device_extension Vcb,
chunk c,
BTRFS_TIME now,
LIST_ENTRY batchlist,
PIRP  Irp,
LIST_ENTRY rollback 
)
static

Definition at line 1669 of file free-space.c.

1669  {
1670  NTSTATUS Status;
1671  KEY searchkey;
1672  traverse_ptr tp;
1673  FREE_SPACE_ITEM* fsi;
1674  void* data;
1675  uint64_t num_entries, *cachegen, off;
1676  uint32_t *checksums, num_sectors, i;
1677  LIST_ENTRY* le;
1678 
1679  space_list_merge(&c->space, &c->space_size, &c->deleting);
1680 
1681  data = ExAllocatePoolWithTag(NonPagedPool, (ULONG)c->cache->inode_item.st_size, ALLOC_TAG);
1682  if (!data) {
1683  ERR("out of memory\n");
1685  }
1686 
1687  RtlZeroMemory(data, (ULONG)c->cache->inode_item.st_size);
1688 
1689  num_entries = 0;
1690  num_sectors = (uint32_t)(c->cache->inode_item.st_size / Vcb->superblock.sector_size);
1691  off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
1692 
1693  le = c->space.Flink;
1694  while (le != &c->space) {
1695  FREE_SPACE_ENTRY* fse;
1696 
1698 
1699  if ((off + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size != off / Vcb->superblock.sector_size)
1700  off = sector_align(off, Vcb->superblock.sector_size);
1701 
1702  fse = (FREE_SPACE_ENTRY*)((uint8_t*)data + off);
1703 
1704  fse->offset = s->address;
1705  fse->size = s->size;
1706  fse->type = FREE_SPACE_EXTENT;
1707  num_entries++;
1708 
1709  off += sizeof(FREE_SPACE_ENTRY);
1710 
1711  le = le->Flink;
1712  }
1713 
1714  // update INODE_ITEM
1715 
1716  c->cache->inode_item.generation = Vcb->superblock.generation;
1717  c->cache->inode_item.transid = Vcb->superblock.generation;
1718  c->cache->inode_item.sequence++;
1719  c->cache->inode_item.st_ctime = *now;
1720 
1721  Status = flush_fcb(c->cache, true, batchlist, Irp);
1722  if (!NT_SUCCESS(Status)) {
1723  ERR("flush_fcb returned %08lx\n", Status);
1724  goto end;
1725  }
1726 
1727  // update free_space item
1728 
1729  searchkey.obj_id = FREE_SPACE_CACHE_ID;
1730  searchkey.obj_type = 0;
1731  searchkey.offset = c->offset;
1732 
1733  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
1734  if (!NT_SUCCESS(Status)) {
1735  ERR("error - find_item returned %08lx\n", Status);
1736  goto end;
1737  }
1738 
1739  if (keycmp(searchkey, tp.item->key)) {
1740  ERR("could not find (%I64x,%x,%I64x) in root_root\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
1742  goto end;
1743  }
1744 
1745  if (tp.item->size < sizeof(FREE_SPACE_ITEM)) {
1746  ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
1748  goto end;
1749  }
1750 
1751  fsi = (FREE_SPACE_ITEM*)tp.item->data;
1752 
1753  fsi->generation = Vcb->superblock.generation;
1754  fsi->num_entries = num_entries;
1755  fsi->num_bitmaps = 0;
1756 
1757  // set cache generation
1758 
1759  cachegen = (uint64_t*)((uint8_t*)data + (sizeof(uint32_t) * num_sectors));
1760  *cachegen = Vcb->superblock.generation;
1761 
1762  // calculate cache checksums
1763 
1764  checksums = (uint32_t*)data;
1765 
1766  // FIXME - if we know sector is fully zeroed, use cached checksum
1767 
1768  for (i = 0; i < num_sectors; i++) {
1769  if (i * Vcb->superblock.sector_size > sizeof(uint32_t) * num_sectors)
1770  checksums[i] = ~calc_crc32c(0xffffffff, (uint8_t*)data + (i * Vcb->superblock.sector_size), Vcb->superblock.sector_size);
1771  else if ((i + 1) * Vcb->superblock.sector_size < sizeof(uint32_t) * num_sectors)
1772  checksums[i] = 0; // FIXME - test this
1773  else
1774  checksums[i] = ~calc_crc32c(0xffffffff, (uint8_t*)data + (sizeof(uint32_t) * num_sectors), ((i + 1) * Vcb->superblock.sector_size) - (sizeof(uint32_t) * num_sectors));
1775  }
1776 
1777  // write cache
1778 
1779  Status = do_write_file(c->cache, 0, c->cache->inode_item.st_size, data, NULL, false, 0, rollback);
1780  if (!NT_SUCCESS(Status)) {
1781  ERR("do_write_file returned %08lx\n", Status);
1782 
1783  // Writing the cache isn't critical, so we don't return an error if writing fails. This means
1784  // we can still flush on a degraded mount if metadata is RAID1 but data is RAID0.
1785  }
1786 
1788 
1789 end:
1790  ExFreePool(data);
1791 
1792  return Status;
1793 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define FREE_SPACE_EXTENT
Definition: btrfs.h:433
Definition: btrfs.h:436
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
#define FREE_SPACE_CACHE_ID
Definition: btrfs.h:86
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
uint64_t size
Definition: btrfs.h:438
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t generation
Definition: btrfs.h:444
uint8_t type
Definition: btrfs.h:439
_In_ PIRP Irp
Definition: csq.h:116
time_t now
Definition: finger.c:65
NTSTATUS do_write_file(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3891
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t offset
Definition: btrfs.h:437
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
NTSTATUS flush_fcb(fcb *fcb, bool cache, LIST_ENTRY *batchlist, PIRP Irp)
Definition: flushthread.c:4818
crc_func calc_crc32c
Definition: crc32c.c:23
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
#define uint64_t
Definition: nsiface.idl:62
static void space_list_merge(LIST_ENTRY *spacelist, LIST_ENTRY *spacelist_size, LIST_ENTRY *deleting)
Definition: free-space.c:1654
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
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
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1357
UINT32 uint32_t
Definition: types.h:75
uint64_t num_entries
Definition: btrfs.h:445
uint64_t num_bitmaps
Definition: btrfs.h:446
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
#define uint32_t
Definition: nsiface.idl:61
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by update_chunk_caches().

◆ update_chunk_cache_tree()

static NTSTATUS update_chunk_cache_tree ( device_extension Vcb,
chunk c,
LIST_ENTRY batchlist 
)
static

Definition at line 1795 of file free-space.c.

1795  {
1796  NTSTATUS Status;
1797  LIST_ENTRY* le;
1798  FREE_SPACE_INFO* fsi;
1799 
1801  if (!fsi) {
1802  ERR("out of memory\n");
1804  }
1805 
1806  space_list_merge(&c->space, &c->space_size, &c->deleting);
1807 
1808  fsi->count = 0;
1809  fsi->flags = 0;
1810 
1811  le = c->space.Flink;
1812  while (le != &c->space) {
1814 
1815  fsi->count++;
1816 
1817  Status = insert_tree_item_batch(batchlist, Vcb, Vcb->space_root, s->address, TYPE_FREE_SPACE_EXTENT, s->size,
1818  NULL, 0, Batch_Insert);
1819  if (!NT_SUCCESS(Status)) {
1820  ERR("insert_tree_item_batch returned %08lx\n", Status);
1821  ExFreePool(fsi);
1822  return Status;
1823  }
1824 
1825  le = le->Flink;
1826  }
1827 
1828  Status = insert_tree_item_batch(batchlist, Vcb, Vcb->space_root, c->offset, TYPE_FREE_SPACE_INFO, c->chunk_item->size,
1830  if (!NT_SUCCESS(Status)) {
1831  ERR("insert_tree_item_batch returned %08lx\n", Status);
1832  ExFreePool(fsi);
1833  return Status;
1834  }
1835 
1836  Status = insert_tree_item_batch(batchlist, Vcb, Vcb->space_root, c->offset, TYPE_FREE_SPACE_INFO, c->chunk_item->size,
1837  fsi, sizeof(FREE_SPACE_INFO), Batch_Insert);
1838  if (!NT_SUCCESS(Status)) {
1839  ERR("insert_tree_item_batch returned %08lx\n", Status);
1840  ExFreePool(fsi);
1841  return Status;
1842  }
1843 
1844  return STATUS_SUCCESS;
1845 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
uint32_t count
Definition: btrfs.h:523
#define ALLOC_TAG
Definition: btrfs_drv.h:91
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TYPE_FREE_SPACE_EXTENT
Definition: btrfs.h:40
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TYPE_FREE_SPACE_INFO
Definition: btrfs.h:39
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
static void space_list_merge(LIST_ENTRY *spacelist, LIST_ENTRY *spacelist_size, LIST_ENTRY *deleting)
Definition: free-space.c:1654
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:27
NTSTATUS insert_tree_item_batch(LIST_ENTRY *batchlist, device_extension *Vcb, root *r, uint64_t objid, uint8_t objtype, uint64_t offset, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *data, uint16_t datalen, enum batch_operation operation)
Definition: flushthread.c:4448
#define NULL
Definition: types.h:112
uint32_t flags
Definition: btrfs.h:524
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by update_chunk_caches_tree().

◆ update_chunk_caches()

NTSTATUS update_chunk_caches ( device_extension Vcb,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 1847 of file free-space.c.

1847  {
1848  LIST_ENTRY *le, batchlist;
1849  NTSTATUS Status;
1850  chunk* c;
1852  BTRFS_TIME now;
1853 
1856 
1857  InitializeListHead(&batchlist);
1858 
1859  le = Vcb->chunks.Flink;
1860  while (le != &Vcb->chunks) {
1862 
1863  if (c->space_changed && c->chunk_item->size >= 0x6400000) { // 100MB
1865  Status = update_chunk_cache(Vcb, c, &now, &batchlist, Irp, rollback);
1867 
1868  if (!NT_SUCCESS(Status)) {
1869  ERR("update_chunk_cache(%I64x) returned %08lx\n", c->offset, Status);
1870  clear_batch_list(Vcb, &batchlist);
1871  return Status;
1872  }
1873  }
1874 
1875  le = le->Flink;
1876  }
1877 
1878  Status = commit_batch_list(Vcb, &batchlist, Irp);
1879  if (!NT_SUCCESS(Status)) {
1880  ERR("commit_batch_list returned %08lx\n", Status);
1881  return Status;
1882  }
1883 
1884  le = Vcb->chunks.Flink;
1885  while (le != &Vcb->chunks) {
1887 
1888  if (c->changed && (c->chunk_item->type & BLOCK_FLAG_RAID5 || c->chunk_item->type & BLOCK_FLAG_RAID6)) {
1889  ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
1890 
1891  while (!IsListEmpty(&c->partial_stripes)) {
1893 
1894  Status = flush_partial_stripe(Vcb, c, ps);
1895 
1896  if (ps->bmparr)
1897  ExFreePool(ps->bmparr);
1898 
1899  ExFreePool(ps);
1900 
1901  if (!NT_SUCCESS(Status)) {
1902  ERR("flush_partial_stripe returned %08lx\n", Status);
1903  ExReleaseResourceLite(&c->partial_stripes_lock);
1904  return Status;
1905  }
1906  }
1907 
1908  ExReleaseResourceLite(&c->partial_stripes_lock);
1909  }
1910 
1911  le = le->Flink;
1912  }
1913 
1914  return STATUS_SUCCESS;
1915 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
ULONG * bmparr
Definition: btrfs_drv.h:563
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5863
release_chunk_lock(c, Vcb)
__u16 time
Definition: mkdosfs.c:366
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
_In_ PIRP Irp
Definition: csq.h:116
time_t now
Definition: finger.c:65
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp)
Definition: treefuncs.c:2281
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
void clear_batch_list(device_extension *Vcb, LIST_ENTRY *batchlist)
Definition: treefuncs.c:1204
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
_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:1357
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:997
#define c
Definition: ke_i.h:80
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
static NTSTATUS update_chunk_cache(device_extension *Vcb, chunk *c, BTRFS_TIME *now, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: free-space.c:1669
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by update_root_root().

◆ update_chunk_caches_tree()

NTSTATUS update_chunk_caches_tree ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 1917 of file free-space.c.

1917  {
1918  LIST_ENTRY *le, batchlist;
1919  NTSTATUS Status;
1920  chunk* c;
1921 
1922  Vcb->superblock.compat_ro_flags |= BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID;
1923 
1924  InitializeListHead(&batchlist);
1925 
1926  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
1927 
1928  le = Vcb->chunks.Flink;
1929  while (le != &Vcb->chunks) {
1931 
1932  if (c->space_changed) {
1934  Status = update_chunk_cache_tree(Vcb, c, &batchlist);
1936 
1937  if (!NT_SUCCESS(Status)) {
1938  ERR("update_chunk_cache_tree(%I64x) returned %08lx\n", c->offset, Status);
1939  ExReleaseResourceLite(&Vcb->chunk_lock);
1940  clear_batch_list(Vcb, &batchlist);
1941  return Status;
1942  }
1943  }
1944 
1945  le = le->Flink;
1946  }
1947 
1948  ExReleaseResourceLite(&Vcb->chunk_lock);
1949 
1950  Status = commit_batch_list(Vcb, &batchlist, Irp);
1951  if (!NT_SUCCESS(Status)) {
1952  ERR("commit_batch_list returned %08lx\n", Status);
1953  return Status;
1954  }
1955 
1956  return STATUS_SUCCESS;
1957 }
LONG NTSTATUS
Definition: precomp.h:26
release_chunk_lock(c, Vcb)
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID
Definition: btrfs.h:106
_In_ PIRP Irp
Definition: csq.h:116
static NTSTATUS update_chunk_cache_tree(device_extension *Vcb, chunk *c, LIST_ENTRY *batchlist)
Definition: free-space.c:1795
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp)
Definition: treefuncs.c:2281
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
void clear_batch_list(device_extension *Vcb, LIST_ENTRY *batchlist)
Definition: treefuncs.c:1204
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define c
Definition: ke_i.h:80
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by do_write2().