softdep.h (50480) | softdep.h (60833) |
---|---|
1/* 2 * Copyright 1998 Marshall Kirk McKusick. All Rights Reserved. 3 * 4 * The soft updates code is derived from the appendix of a University 5 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt, 6 * "Soft Updates: A Solution to the Metadata Update Problem in File 7 * Systems", CSE-TR-254-95, August 1995). 8 * --- 39 unchanged lines hidden (view full) --- 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 * 55 * @(#)softdep.h 9.6 (McKusick) 2/25/99 | 1/* 2 * Copyright 1998 Marshall Kirk McKusick. All Rights Reserved. 3 * 4 * The soft updates code is derived from the appendix of a University 5 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt, 6 * "Soft Updates: A Solution to the Metadata Update Problem in File 7 * Systems", CSE-TR-254-95, August 1995). 8 * --- 39 unchanged lines hidden (view full) --- 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 * 55 * @(#)softdep.h 9.6 (McKusick) 2/25/99 |
56 * $FreeBSD: head/sys/ufs/ffs/softdep.h 50480 1999-08-28 02:16:32Z peter $ | 56 * $FreeBSD: head/sys/ufs/ffs/softdep.h 60833 2000-05-23 20:41:01Z jake $ |
57 */ 58 59#include <sys/queue.h> 60 61/* 62 * Allocation dependencies are handled with undo/redo on the in-memory 63 * copy of the data. A particular data dependency is eliminated when 64 * it is ALLCOMPLETE: that is ATTACHED, DEPCOMPLETE, and COMPLETE. --- 58 unchanged lines hidden (view full) --- 123 * in the background rather than during execution of an application process 124 * or interrupt service routine. To realize this, we append dependency 125 * structures corresponding to such tasks to a "workitem" queue. In a soft 126 * updates implementation, most pending workitems should not wait for more 127 * than a couple of seconds, so the filesystem syncer process awakens once 128 * per second to process the items on the queue. 129 */ 130 | 57 */ 58 59#include <sys/queue.h> 60 61/* 62 * Allocation dependencies are handled with undo/redo on the in-memory 63 * copy of the data. A particular data dependency is eliminated when 64 * it is ALLCOMPLETE: that is ATTACHED, DEPCOMPLETE, and COMPLETE. --- 58 unchanged lines hidden (view full) --- 123 * in the background rather than during execution of an application process 124 * or interrupt service routine. To realize this, we append dependency 125 * structures corresponding to such tasks to a "workitem" queue. In a soft 126 * updates implementation, most pending workitems should not wait for more 127 * than a couple of seconds, so the filesystem syncer process awakens once 128 * per second to process the items on the queue. 129 */ 130 |
131/* LIST_HEAD(workhead, worklist); -- declared in buf.h */ | 131/* LIST_HEAD(workhead, struct worklist); -- declared in buf.h */ |
132 133/* 134 * Each request can be linked onto a work queue through its worklist structure. 135 * To avoid the need for a pointer to the structure itself, this structure 136 * MUST be declared FIRST in each type in which it appears! If more than one 137 * worklist is needed in the structure, then a wk_data field must be added 138 * and the macros below changed to use it. 139 */ 140struct worklist { | 132 133/* 134 * Each request can be linked onto a work queue through its worklist structure. 135 * To avoid the need for a pointer to the structure itself, this structure 136 * MUST be declared FIRST in each type in which it appears! If more than one 137 * worklist is needed in the structure, then a wk_data field must be added 138 * and the macros below changed to use it. 139 */ 140struct worklist { |
141 LIST_ENTRY(worklist) wk_list; /* list of work requests */ | 141 LIST_ENTRY(struct worklist) wk_list; /* list of work requests */ |
142 unsigned short wk_type; /* type of request */ 143 unsigned short wk_state; /* state flags */ 144}; 145#define WK_DATA(wk) ((void *)(wk)) 146#define WK_PAGEDEP(wk) ((struct pagedep *)(wk)) 147#define WK_INODEDEP(wk) ((struct inodedep *)(wk)) 148#define WK_NEWBLK(wk) ((struct newblk *)(wk)) 149#define WK_BMSAFEMAP(wk) ((struct bmsafemap *)(wk)) --- 5 unchanged lines hidden (view full) --- 155#define WK_FREEFILE(wk) ((struct freefile *)(wk)) 156#define WK_DIRADD(wk) ((struct diradd *)(wk)) 157#define WK_MKDIR(wk) ((struct mkdir *)(wk)) 158#define WK_DIRREM(wk) ((struct dirrem *)(wk)) 159 160/* 161 * Various types of lists 162 */ | 142 unsigned short wk_type; /* type of request */ 143 unsigned short wk_state; /* state flags */ 144}; 145#define WK_DATA(wk) ((void *)(wk)) 146#define WK_PAGEDEP(wk) ((struct pagedep *)(wk)) 147#define WK_INODEDEP(wk) ((struct inodedep *)(wk)) 148#define WK_NEWBLK(wk) ((struct newblk *)(wk)) 149#define WK_BMSAFEMAP(wk) ((struct bmsafemap *)(wk)) --- 5 unchanged lines hidden (view full) --- 155#define WK_FREEFILE(wk) ((struct freefile *)(wk)) 156#define WK_DIRADD(wk) ((struct diradd *)(wk)) 157#define WK_MKDIR(wk) ((struct mkdir *)(wk)) 158#define WK_DIRREM(wk) ((struct dirrem *)(wk)) 159 160/* 161 * Various types of lists 162 */ |
163LIST_HEAD(dirremhd, dirrem); 164LIST_HEAD(diraddhd, diradd); 165LIST_HEAD(newblkhd, newblk); 166LIST_HEAD(inodedephd, inodedep); 167LIST_HEAD(allocindirhd, allocindir); 168LIST_HEAD(allocdirecthd, allocdirect); 169TAILQ_HEAD(allocdirectlst, allocdirect); | 163LIST_HEAD(dirremhd, struct dirrem); 164LIST_HEAD(diraddhd, struct diradd); 165LIST_HEAD(newblkhd, struct newblk); 166LIST_HEAD(inodedephd, struct inodedep); 167LIST_HEAD(allocindirhd, struct allocindir); 168LIST_HEAD(allocdirecthd, struct allocdirect); 169TAILQ_HEAD(allocdirectlst, struct allocdirect); |
170 171/* 172 * The "pagedep" structure tracks the various dependencies related to 173 * a particular directory page. If a directory page has any dependencies, 174 * it will have a pagedep linked to its associated buffer. The 175 * pd_dirremhd list holds the list of dirrem requests which decrement 176 * inode reference counts. These requests are processed after the 177 * directory page with the corresponding zero'ed entries has been --- 8 unchanged lines hidden (view full) --- 186 * list, any removed operations are done, and the dependency structure 187 * is freed. 188 */ 189#define DAHASHSZ 6 190#define DIRADDHASH(offset) (((offset) >> 2) % DAHASHSZ) 191struct pagedep { 192 struct worklist pd_list; /* page buffer */ 193# define pd_state pd_list.wk_state /* check for multiple I/O starts */ | 170 171/* 172 * The "pagedep" structure tracks the various dependencies related to 173 * a particular directory page. If a directory page has any dependencies, 174 * it will have a pagedep linked to its associated buffer. The 175 * pd_dirremhd list holds the list of dirrem requests which decrement 176 * inode reference counts. These requests are processed after the 177 * directory page with the corresponding zero'ed entries has been --- 8 unchanged lines hidden (view full) --- 186 * list, any removed operations are done, and the dependency structure 187 * is freed. 188 */ 189#define DAHASHSZ 6 190#define DIRADDHASH(offset) (((offset) >> 2) % DAHASHSZ) 191struct pagedep { 192 struct worklist pd_list; /* page buffer */ 193# define pd_state pd_list.wk_state /* check for multiple I/O starts */ |
194 LIST_ENTRY(pagedep) pd_hash; /* hashed lookup */ | 194 LIST_ENTRY(struct pagedep) pd_hash; /* hashed lookup */ |
195 struct mount *pd_mnt; /* associated mount point */ 196 ino_t pd_ino; /* associated file */ 197 ufs_lbn_t pd_lbn; /* block within file */ 198 struct dirremhd pd_dirremhd; /* dirrem's waiting for page */ 199 struct diraddhd pd_diraddhd[DAHASHSZ]; /* diradd dir entry updates */ 200 struct diraddhd pd_pendinghd; /* directory entries awaiting write */ 201}; 202 --- 42 unchanged lines hidden (view full) --- 245 * the directory block containing the name has been written to disk. 246 * The purpose of keeping the entries on the id_pendinghd list is so that 247 * the softdep_fsync function can find and push the inode's directory 248 * name(s) as part of the fsync operation for that file. 249 */ 250struct inodedep { 251 struct worklist id_list; /* buffer holding inode block */ 252# define id_state id_list.wk_state /* inode dependency state */ | 195 struct mount *pd_mnt; /* associated mount point */ 196 ino_t pd_ino; /* associated file */ 197 ufs_lbn_t pd_lbn; /* block within file */ 198 struct dirremhd pd_dirremhd; /* dirrem's waiting for page */ 199 struct diraddhd pd_diraddhd[DAHASHSZ]; /* diradd dir entry updates */ 200 struct diraddhd pd_pendinghd; /* directory entries awaiting write */ 201}; 202 --- 42 unchanged lines hidden (view full) --- 245 * the directory block containing the name has been written to disk. 246 * The purpose of keeping the entries on the id_pendinghd list is so that 247 * the softdep_fsync function can find and push the inode's directory 248 * name(s) as part of the fsync operation for that file. 249 */ 250struct inodedep { 251 struct worklist id_list; /* buffer holding inode block */ 252# define id_state id_list.wk_state /* inode dependency state */ |
253 LIST_ENTRY(inodedep) id_hash; /* hashed lookup */ | 253 LIST_ENTRY(struct inodedep) id_hash; /* hashed lookup */ |
254 struct fs *id_fs; /* associated filesystem */ 255 ino_t id_ino; /* dependent inode */ 256 nlink_t id_nlinkdelta; /* saved effective link count */ 257 struct dinode *id_savedino; /* saved dinode contents */ | 254 struct fs *id_fs; /* associated filesystem */ 255 ino_t id_ino; /* dependent inode */ 256 nlink_t id_nlinkdelta; /* saved effective link count */ 257 struct dinode *id_savedino; /* saved dinode contents */ |
258 LIST_ENTRY(inodedep) id_deps; /* bmsafemap's list of inodedep's */ | 258 LIST_ENTRY(struct inodedep) id_deps; /* bmsafemap's list of inodedep's */ |
259 struct buf *id_buf; /* related bmsafemap (if pending) */ 260 off_t id_savedsize; /* file size saved during rollback */ 261 struct workhead id_pendinghd; /* entries awaiting directory write */ 262 struct workhead id_bufwait; /* operations after inode written */ 263 struct workhead id_inowait; /* operations waiting inode update */ 264 struct allocdirectlst id_inoupdt; /* updates before inode written */ 265 struct allocdirectlst id_newinoupdt; /* updates when inode written */ 266}; 267 268/* 269 * A "newblk" structure is attached to a bmsafemap structure when a block 270 * or fragment is allocated from a cylinder group. Its state is set to 271 * DEPCOMPLETE when its cylinder group map is written. It is consumed by 272 * an associated allocdirect or allocindir allocation which will attach 273 * themselves to the bmsafemap structure if the newblk's DEPCOMPLETE flag 274 * is not set (i.e., its cylinder group map has not been written). 275 */ 276struct newblk { | 259 struct buf *id_buf; /* related bmsafemap (if pending) */ 260 off_t id_savedsize; /* file size saved during rollback */ 261 struct workhead id_pendinghd; /* entries awaiting directory write */ 262 struct workhead id_bufwait; /* operations after inode written */ 263 struct workhead id_inowait; /* operations waiting inode update */ 264 struct allocdirectlst id_inoupdt; /* updates before inode written */ 265 struct allocdirectlst id_newinoupdt; /* updates when inode written */ 266}; 267 268/* 269 * A "newblk" structure is attached to a bmsafemap structure when a block 270 * or fragment is allocated from a cylinder group. Its state is set to 271 * DEPCOMPLETE when its cylinder group map is written. It is consumed by 272 * an associated allocdirect or allocindir allocation which will attach 273 * themselves to the bmsafemap structure if the newblk's DEPCOMPLETE flag 274 * is not set (i.e., its cylinder group map has not been written). 275 */ 276struct newblk { |
277 LIST_ENTRY(newblk) nb_hash; /* hashed lookup */ | 277 LIST_ENTRY(struct newblk) nb_hash; /* hashed lookup */ |
278 struct fs *nb_fs; /* associated filesystem */ 279 ufs_daddr_t nb_newblkno; /* allocated block number */ 280 int nb_state; /* state of bitmap dependency */ | 278 struct fs *nb_fs; /* associated filesystem */ 279 ufs_daddr_t nb_newblkno; /* allocated block number */ 280 int nb_state; /* state of bitmap dependency */ |
281 LIST_ENTRY(newblk) nb_deps; /* bmsafemap's list of newblk's */ | 281 LIST_ENTRY(struct newblk) nb_deps; /* bmsafemap's list of newblk's */ |
282 struct bmsafemap *nb_bmsafemap; /* associated bmsafemap */ 283}; 284 285/* 286 * A "bmsafemap" structure maintains a list of dependency structures 287 * that depend on the update of a particular cylinder group map. 288 * It has lists for newblks, allocdirects, allocindirs, and inodedeps. 289 * It is attached to the buffer of a cylinder group block when any of --- 26 unchanged lines hidden (view full) --- 316 * be freed once the inode claiming the new block is written to disk. 317 * This ad_fragfree request is attached to the id_inowait list of the 318 * associated inodedep (pointed to by ad_inodedep) for processing after 319 * the inode is written. 320 */ 321struct allocdirect { 322 struct worklist ad_list; /* buffer holding block */ 323# define ad_state ad_list.wk_state /* block pointer state */ | 282 struct bmsafemap *nb_bmsafemap; /* associated bmsafemap */ 283}; 284 285/* 286 * A "bmsafemap" structure maintains a list of dependency structures 287 * that depend on the update of a particular cylinder group map. 288 * It has lists for newblks, allocdirects, allocindirs, and inodedeps. 289 * It is attached to the buffer of a cylinder group block when any of --- 26 unchanged lines hidden (view full) --- 316 * be freed once the inode claiming the new block is written to disk. 317 * This ad_fragfree request is attached to the id_inowait list of the 318 * associated inodedep (pointed to by ad_inodedep) for processing after 319 * the inode is written. 320 */ 321struct allocdirect { 322 struct worklist ad_list; /* buffer holding block */ 323# define ad_state ad_list.wk_state /* block pointer state */ |
324 TAILQ_ENTRY(allocdirect) ad_next; /* inodedep's list of allocdirect's */ | 324 TAILQ_ENTRY(struct allocdirect) ad_next; /* inodedep's list of allocdirect's */ |
325 ufs_lbn_t ad_lbn; /* block within file */ 326 ufs_daddr_t ad_newblkno; /* new value of block pointer */ 327 ufs_daddr_t ad_oldblkno; /* old value of block pointer */ 328 long ad_newsize; /* size of new block */ 329 long ad_oldsize; /* size of old block */ | 325 ufs_lbn_t ad_lbn; /* block within file */ 326 ufs_daddr_t ad_newblkno; /* new value of block pointer */ 327 ufs_daddr_t ad_oldblkno; /* old value of block pointer */ 328 long ad_newsize; /* size of new block */ 329 long ad_oldsize; /* size of old block */ |
330 LIST_ENTRY(allocdirect) ad_deps; /* bmsafemap's list of allocdirect's */ | 330 LIST_ENTRY(struct allocdirect) ad_deps; /* bmsafemap's list of allocdirect's */ |
331 struct buf *ad_buf; /* cylgrp buffer (if pending) */ 332 struct inodedep *ad_inodedep; /* associated inodedep */ 333 struct freefrag *ad_freefrag; /* fragment to be freed (if any) */ 334}; 335 336/* 337 * A single "indirdep" structure manages all allocation dependencies for 338 * pointers in an indirect block. The up-to-date state of the indirect --- 31 unchanged lines hidden (view full) --- 370 * is written, the COMPLETE flag is set. Once both the cylinder group map 371 * and the data itself have been written, it is safe to write the entry in 372 * the indirect block that claims the block; the "allocindir" dependency 373 * can then be freed as it is no longer applicable. 374 */ 375struct allocindir { 376 struct worklist ai_list; /* buffer holding indirect block */ 377# define ai_state ai_list.wk_state /* indirect block pointer state */ | 331 struct buf *ad_buf; /* cylgrp buffer (if pending) */ 332 struct inodedep *ad_inodedep; /* associated inodedep */ 333 struct freefrag *ad_freefrag; /* fragment to be freed (if any) */ 334}; 335 336/* 337 * A single "indirdep" structure manages all allocation dependencies for 338 * pointers in an indirect block. The up-to-date state of the indirect --- 31 unchanged lines hidden (view full) --- 370 * is written, the COMPLETE flag is set. Once both the cylinder group map 371 * and the data itself have been written, it is safe to write the entry in 372 * the indirect block that claims the block; the "allocindir" dependency 373 * can then be freed as it is no longer applicable. 374 */ 375struct allocindir { 376 struct worklist ai_list; /* buffer holding indirect block */ 377# define ai_state ai_list.wk_state /* indirect block pointer state */ |
378 LIST_ENTRY(allocindir) ai_next; /* indirdep's list of allocindir's */ | 378 LIST_ENTRY(struct allocindir) ai_next; /* indirdep's list of allocindir's */ |
379 int ai_offset; /* pointer offset in indirect block */ 380 ufs_daddr_t ai_newblkno; /* new block pointer value */ 381 ufs_daddr_t ai_oldblkno; /* old block pointer value */ 382 struct freefrag *ai_freefrag; /* block to be freed when complete */ 383 struct indirdep *ai_indirdep; /* address of associated indirdep */ | 379 int ai_offset; /* pointer offset in indirect block */ 380 ufs_daddr_t ai_newblkno; /* new block pointer value */ 381 ufs_daddr_t ai_oldblkno; /* old block pointer value */ 382 struct freefrag *ai_freefrag; /* block to be freed when complete */ 383 struct indirdep *ai_indirdep; /* address of associated indirdep */ |
384 LIST_ENTRY(allocindir) ai_deps; /* bmsafemap's list of allocindir's */ | 384 LIST_ENTRY(struct allocindir) ai_deps; /* bmsafemap's list of allocindir's */ |
385 struct buf *ai_buf; /* cylgrp buffer (if pending) */ 386}; 387 388/* 389 * A "freefrag" structure is attached to an "inodedep" when a previously 390 * allocated fragment is replaced with a larger fragment, rather than extended. 391 * The "freefrag" structure is constructed and attached when the replacement 392 * block is first allocated. It is processed after the inode claiming the --- 80 unchanged lines hidden (view full) --- 473 * in the associated dirrem entry. If the DIRCHG flag is set, the 474 * da_previous entry is valid; if not set the da_pagedep entry is valid. 475 * The DIRCHG flag never changes; it is set when the structure is created 476 * if appropriate and is never cleared. 477 */ 478struct diradd { 479 struct worklist da_list; /* id_inowait or id_pendinghd list */ 480# define da_state da_list.wk_state /* state of the new directory entry */ | 385 struct buf *ai_buf; /* cylgrp buffer (if pending) */ 386}; 387 388/* 389 * A "freefrag" structure is attached to an "inodedep" when a previously 390 * allocated fragment is replaced with a larger fragment, rather than extended. 391 * The "freefrag" structure is constructed and attached when the replacement 392 * block is first allocated. It is processed after the inode claiming the --- 80 unchanged lines hidden (view full) --- 473 * in the associated dirrem entry. If the DIRCHG flag is set, the 474 * da_previous entry is valid; if not set the da_pagedep entry is valid. 475 * The DIRCHG flag never changes; it is set when the structure is created 476 * if appropriate and is never cleared. 477 */ 478struct diradd { 479 struct worklist da_list; /* id_inowait or id_pendinghd list */ 480# define da_state da_list.wk_state /* state of the new directory entry */ |
481 LIST_ENTRY(diradd) da_pdlist; /* pagedep holding directory block */ | 481 LIST_ENTRY(struct diradd) da_pdlist; /* pagedep holding directory block */ |
482 doff_t da_offset; /* offset of new dir entry in dir blk */ 483 ino_t da_newinum; /* inode number for the new dir entry */ 484 union { 485 struct dirrem *dau_previous; /* entry being replaced in dir change */ 486 struct pagedep *dau_pagedep; /* pagedep dependency for addition */ 487 } da_un; 488}; 489#define da_previous da_un.dau_previous --- 23 unchanged lines hidden (view full) --- 513 * the associated mkdir's. However, this would increase the size of the diradd 514 * structure from 32 to 64-bits to speed a very infrequent operation. 515 */ 516struct mkdir { 517 struct worklist md_list; /* id_inowait or buffer holding dir */ 518# define md_state md_list.wk_state /* type: MKDIR_PARENT or MKDIR_BODY */ 519 struct diradd *md_diradd; /* associated diradd */ 520 struct buf *md_buf; /* MKDIR_BODY: buffer holding dir */ | 482 doff_t da_offset; /* offset of new dir entry in dir blk */ 483 ino_t da_newinum; /* inode number for the new dir entry */ 484 union { 485 struct dirrem *dau_previous; /* entry being replaced in dir change */ 486 struct pagedep *dau_pagedep; /* pagedep dependency for addition */ 487 } da_un; 488}; 489#define da_previous da_un.dau_previous --- 23 unchanged lines hidden (view full) --- 513 * the associated mkdir's. However, this would increase the size of the diradd 514 * structure from 32 to 64-bits to speed a very infrequent operation. 515 */ 516struct mkdir { 517 struct worklist md_list; /* id_inowait or buffer holding dir */ 518# define md_state md_list.wk_state /* type: MKDIR_PARENT or MKDIR_BODY */ 519 struct diradd *md_diradd; /* associated diradd */ 520 struct buf *md_buf; /* MKDIR_BODY: buffer holding dir */ |
521 LIST_ENTRY(mkdir) md_mkdirs; /* list of all mkdirs */ | 521 LIST_ENTRY(struct mkdir) md_mkdirs; /* list of all mkdirs */ |
522}; | 522}; |
523LIST_HEAD(mkdirlist, mkdir) mkdirlisthd; | 523LIST_HEAD(mkdirlist, struct mkdir) mkdirlisthd; |
524 525/* 526 * A "dirrem" structure describes an operation to decrement the link 527 * count on an inode. The dirrem structure is attached to the pg_dirremhd 528 * list of the pagedep for the directory page that contains the entry. 529 * It is processed after the directory page with the deleted entry has 530 * been written to disk. 531 * 532 * The overlaying of dm_pagedep and dm_dirinum is done to keep the 533 * structure down to 32 bytes in size on a 32-bit machine. It works 534 * because they are never used concurrently. 535 */ 536struct dirrem { 537 struct worklist dm_list; /* delayed worklist */ 538# define dm_state dm_list.wk_state /* state of the old directory entry */ | 524 525/* 526 * A "dirrem" structure describes an operation to decrement the link 527 * count on an inode. The dirrem structure is attached to the pg_dirremhd 528 * list of the pagedep for the directory page that contains the entry. 529 * It is processed after the directory page with the deleted entry has 530 * been written to disk. 531 * 532 * The overlaying of dm_pagedep and dm_dirinum is done to keep the 533 * structure down to 32 bytes in size on a 32-bit machine. It works 534 * because they are never used concurrently. 535 */ 536struct dirrem { 537 struct worklist dm_list; /* delayed worklist */ 538# define dm_state dm_list.wk_state /* state of the old directory entry */ |
539 LIST_ENTRY(dirrem) dm_next; /* pagedep's list of dirrem's */ | 539 LIST_ENTRY(struct dirrem) dm_next; /* pagedep's list of dirrem's */ |
540 struct mount *dm_mnt; /* associated mount point */ 541 ino_t dm_oldinum; /* inum of the removed dir entry */ 542 union { 543 struct pagedep *dmu_pagedep; /* pagedep dependency for remove */ 544 ino_t dmu_dirinum; /* parent inode number (for rmdir) */ 545 } dm_un; 546}; 547#define dm_pagedep dm_un.dmu_pagedep 548#define dm_dirinum dm_un.dmu_dirinum | 540 struct mount *dm_mnt; /* associated mount point */ 541 ino_t dm_oldinum; /* inum of the removed dir entry */ 542 union { 543 struct pagedep *dmu_pagedep; /* pagedep dependency for remove */ 544 ino_t dmu_dirinum; /* parent inode number (for rmdir) */ 545 } dm_un; 546}; 547#define dm_pagedep dm_un.dmu_pagedep 548#define dm_dirinum dm_un.dmu_dirinum |