285 }
286 dbuf_rele(subdb, FTAG);
287 }
288 DB_DNODE_EXIT(db);
289 arc_buf_freeze(db->db_buf);
290 #ifdef ZFS_DEBUG
291 bp -= (end-start)+1;
292 for (i = start; i <= end; i++, bp++) {
293 if (i == start && blkid != 0)
294 continue;
295 else if (i == end && !trunc)
296 continue;
297 ASSERT0(bp->blk_birth);
298 }
299 #endif
300 ASSERT(all || blocks_freed == 0 || db->db_last_dirty);
301 return (all ? ALL : blocks_freed);
302 }
303
304 /*
305 * free_range: Traverse the indicated range of the provided file
306 * and "free" all the blocks contained there.
307 */
308 static void
309 dnode_sync_free_range(dnode_t *dn, uint64_t blkid, uint64_t nblks, dmu_tx_t *tx)
310 {
311 blkptr_t *bp = dn->dn_phys->dn_blkptr;
312 dmu_buf_impl_t *db;
313 int trunc, start, end, shift, i, err;
314 int dnlevel = dn->dn_phys->dn_nlevels;
315
316 if (blkid > dn->dn_phys->dn_maxblkid)
317 return;
318
319 ASSERT(dn->dn_phys->dn_maxblkid < UINT64_MAX);
320 trunc = blkid + nblks > dn->dn_phys->dn_maxblkid;
321 if (trunc)
322 nblks = dn->dn_phys->dn_maxblkid - blkid + 1;
323
324 /* There are no indirect blocks in the object */
325 if (dnlevel == 1) {
353 ASSERT0(err);
354 rw_exit(&dn->dn_struct_rwlock);
355
356 if (free_children(db, blkid, nblks, trunc, tx) == ALL) {
357 ASSERT3P(db->db_blkptr, ==, bp);
358 (void) free_blocks(dn, bp, 1, tx);
359 }
360 dbuf_rele(db, FTAG);
361 }
362 if (trunc) {
363 uint64_t off = (dn->dn_phys->dn_maxblkid + 1) *
364 (dn->dn_phys->dn_datablkszsec << SPA_MINBLOCKSHIFT);
365 dn->dn_phys->dn_maxblkid = (blkid ? blkid - 1 : 0);
366 ASSERT(off < dn->dn_phys->dn_maxblkid ||
367 dn->dn_phys->dn_maxblkid == 0 ||
368 dnode_next_offset(dn, 0, &off, 1, 1, 0) != 0);
369 }
370 }
371
372 /*
373 * Try to kick all the dnodes dbufs out of the cache...
374 */
375 void
376 dnode_evict_dbufs(dnode_t *dn)
377 {
378 int progress;
379 int pass = 0;
380
381 do {
382 dmu_buf_impl_t *db, marker;
383 int evicting = FALSE;
384
385 progress = FALSE;
386 mutex_enter(&dn->dn_dbufs_mtx);
387 list_insert_tail(&dn->dn_dbufs, &marker);
388 db = list_head(&dn->dn_dbufs);
389 for (; db != ▮ db = list_head(&dn->dn_dbufs)) {
390 list_remove(&dn->dn_dbufs, db);
391 list_insert_tail(&dn->dn_dbufs, db);
392 #ifdef DEBUG
393 DB_DNODE_ENTER(db);
|
285 }
286 dbuf_rele(subdb, FTAG);
287 }
288 DB_DNODE_EXIT(db);
289 arc_buf_freeze(db->db_buf);
290 #ifdef ZFS_DEBUG
291 bp -= (end-start)+1;
292 for (i = start; i <= end; i++, bp++) {
293 if (i == start && blkid != 0)
294 continue;
295 else if (i == end && !trunc)
296 continue;
297 ASSERT0(bp->blk_birth);
298 }
299 #endif
300 ASSERT(all || blocks_freed == 0 || db->db_last_dirty);
301 return (all ? ALL : blocks_freed);
302 }
303
304 /*
305 * Traverse the indicated range of the provided file
306 * and "free" all the blocks contained there.
307 */
308 static void
309 dnode_sync_free_range(dnode_t *dn, uint64_t blkid, uint64_t nblks, dmu_tx_t *tx)
310 {
311 blkptr_t *bp = dn->dn_phys->dn_blkptr;
312 dmu_buf_impl_t *db;
313 int trunc, start, end, shift, i, err;
314 int dnlevel = dn->dn_phys->dn_nlevels;
315
316 if (blkid > dn->dn_phys->dn_maxblkid)
317 return;
318
319 ASSERT(dn->dn_phys->dn_maxblkid < UINT64_MAX);
320 trunc = blkid + nblks > dn->dn_phys->dn_maxblkid;
321 if (trunc)
322 nblks = dn->dn_phys->dn_maxblkid - blkid + 1;
323
324 /* There are no indirect blocks in the object */
325 if (dnlevel == 1) {
353 ASSERT0(err);
354 rw_exit(&dn->dn_struct_rwlock);
355
356 if (free_children(db, blkid, nblks, trunc, tx) == ALL) {
357 ASSERT3P(db->db_blkptr, ==, bp);
358 (void) free_blocks(dn, bp, 1, tx);
359 }
360 dbuf_rele(db, FTAG);
361 }
362 if (trunc) {
363 uint64_t off = (dn->dn_phys->dn_maxblkid + 1) *
364 (dn->dn_phys->dn_datablkszsec << SPA_MINBLOCKSHIFT);
365 dn->dn_phys->dn_maxblkid = (blkid ? blkid - 1 : 0);
366 ASSERT(off < dn->dn_phys->dn_maxblkid ||
367 dn->dn_phys->dn_maxblkid == 0 ||
368 dnode_next_offset(dn, 0, &off, 1, 1, 0) != 0);
369 }
370 }
371
372 /*
373 * Try to kick all the dnode's dbufs out of the cache...
374 */
375 void
376 dnode_evict_dbufs(dnode_t *dn)
377 {
378 int progress;
379 int pass = 0;
380
381 do {
382 dmu_buf_impl_t *db, marker;
383 int evicting = FALSE;
384
385 progress = FALSE;
386 mutex_enter(&dn->dn_dbufs_mtx);
387 list_insert_tail(&dn->dn_dbufs, &marker);
388 db = list_head(&dn->dn_dbufs);
389 for (; db != ▮ db = list_head(&dn->dn_dbufs)) {
390 list_remove(&dn->dn_dbufs, db);
391 list_insert_tail(&dn->dn_dbufs, db);
392 #ifdef DEBUG
393 DB_DNODE_ENTER(db);
|