diff options
author | Julian Elischer <julian@FreeBSD.org> | 1998-05-19 21:05:09 +0000 |
---|---|---|
committer | Julian Elischer <julian@FreeBSD.org> | 1998-05-19 21:05:09 +0000 |
commit | a05cc7b71fb2c108a2fdeec4db1328db06ee8023 (patch) | |
tree | 327a2e9f537afdcbb2e34431f134cdc82ca0c767 | |
parent | 00316b421a810feb43b88a3c7f40026a8fa8ec8a (diff) |
Import changes from kirk which will appear in the Feb 13 snapshot.vendor/softupdates/Feb11-98-ALPHA
Notes
Notes:
svn path=/vendor-sys/softupdates/dist/; revision=36215
svn path=/vendor-sys/softupdates/Feb11-98-ALPHA/; revision=36217; tag=vendor/softupdates/Feb11-98-ALPHA
-rw-r--r-- | sys/contrib/softupdates/ffs_softdep.c | 36 | ||||
-rw-r--r-- | sys/contrib/softupdates/softdep.h | 50 |
2 files changed, 57 insertions, 29 deletions
diff --git a/sys/contrib/softupdates/ffs_softdep.c b/sys/contrib/softupdates/ffs_softdep.c index 44d29454d156..70c4cfe45799 100644 --- a/sys/contrib/softupdates/ffs_softdep.c +++ b/sys/contrib/softupdates/ffs_softdep.c @@ -52,8 +52,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * - * from: @(#)ffs_softdep.c 9.14 (McKusick) 1/15/98 + * @(#)ffs_softdep.c 9.17 (McKusick) 2/11/98 */ /* @@ -691,6 +690,7 @@ top: inodedep->id_buf = NULL; LIST_INIT(&inodedep->id_pendinghd); LIST_INIT(&inodedep->id_inowait); + LIST_INIT(&inodedep->id_bufwait); TAILQ_INIT(&inodedep->id_inoupdt); TAILQ_INIT(&inodedep->id_newinoupdt); ACQUIRE_LOCK(&lk); @@ -1457,7 +1457,7 @@ softdep_setup_freeblocks(ip, length) * Add the freeblks structure to the list of operations that * must await the zero'ed inode being written to disk. */ - WORKLIST_INSERT(&inodedep->id_inowait, &freeblks->fb_list); + WORKLIST_INSERT(&inodedep->id_bufwait, &freeblks->fb_list); /* * Because the file length has been truncated to zero, any * pending block allocation dependency structures associated @@ -1713,6 +1713,7 @@ free_inodedep(inodedep) if ((inodedep->id_state & ONWORKLIST) != 0 || (inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE || LIST_FIRST(&inodedep->id_pendinghd) != NULL || + LIST_FIRST(&inodedep->id_bufwait) != NULL || LIST_FIRST(&inodedep->id_inowait) != NULL || TAILQ_FIRST(&inodedep->id_inoupdt) != NULL || TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL || @@ -2322,12 +2323,8 @@ handle_workitem_remove(dirrem) */ if ((dirrem->dm_state & RMDIR) == 0) { ip->i_nlink--; - if (ip->i_nlink < ip->i_effnlink) { -#ifdef DIAGNOSTIC - vprint("handle_workitem_remove: bad file delta", vp); -#endif - ip->i_effnlink = ip->i_nlink; - } + if (ip->i_nlink < ip->i_effnlink) + panic("handle_workitem_remove: bad file delta"); ip->i_flag |= IN_CHANGE; vput(vp); WORKITEM_FREE(dirrem, M_DIRREM); @@ -2982,7 +2979,7 @@ handle_written_inodeblock(inodedep, bp) * before the old ones have been deleted. */ filefree = NULL; - while ((wk = LIST_FIRST(&inodedep->id_inowait)) != NULL) { + while ((wk = LIST_FIRST(&inodedep->id_bufwait)) != NULL) { WORKLIST_REMOVE(wk); switch (wk->wk_type) { @@ -3029,8 +3026,12 @@ handle_written_inodeblock(inodedep, bp) /* NOTREACHED */ } } - if (filefree != NULL) + if (filefree != NULL) { + if (free_inodedep(inodedep) == 0) + panic("handle_written_inodeblock: live inodedep"); add_to_worklist(filefree); + return (0); + } /* * If no outstanding dependencies, free it. @@ -3189,6 +3190,7 @@ softdep_load_inodeblock(ip) } if (inodedep->id_nlinkdelta != 0) { ip->i_effnlink -= inodedep->id_nlinkdelta; + ip->i_flag |= IN_MODIFIED; inodedep->id_nlinkdelta = 0; (void) free_inodedep(inodedep); } @@ -3212,6 +3214,7 @@ softdep_update_inodeblock(ip, bp, waitfor) int waitfor; /* 1 => update must be allowed */ { struct inodedep *inodedep; + struct worklist *wk; int error, gotit; /* @@ -3258,6 +3261,16 @@ softdep_update_inodeblock(ip, bp, waitfor) if (TAILQ_FIRST(&inodedep->id_inoupdt) != NULL) handle_allocdirect_partdone(TAILQ_FIRST(&inodedep->id_inoupdt)); /* + * Now that the inode has been pushed into the buffer, the + * operations dependent on the inode being written to disk + * can be moved to the id_bufwait so that they will be + * processed when the buffer I/O completes. + */ + while ((wk = LIST_FIRST(&inodedep->id_inowait)) != NULL) { + WORKLIST_REMOVE(wk); + WORKLIST_INSERT(&inodedep->id_bufwait, wk); + } + /* * Newly allocated inodes cannot be written until the bitmap * that allocates them have been written (indicated by * DEPCOMPLETE being set in id_state). If we are doing a @@ -3338,6 +3351,7 @@ softdep_fsync(vp) if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) == 0) break; if (LIST_FIRST(&inodedep->id_inowait) != NULL || + LIST_FIRST(&inodedep->id_bufwait) != NULL || TAILQ_FIRST(&inodedep->id_inoupdt) != NULL || TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL) panic("softdep_fsync: pending ops"); diff --git a/sys/contrib/softupdates/softdep.h b/sys/contrib/softupdates/softdep.h index 16c8aea068ff..3435f6304173 100644 --- a/sys/contrib/softupdates/softdep.h +++ b/sys/contrib/softupdates/softdep.h @@ -52,8 +52,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * - * from: @(#)softdep.h 9.4 (McKusick) 1/15/98 + * @(#)softdep.h 9.5 (McKusick) 2/11/98 */ #include <sys/queue.h> @@ -202,31 +201,45 @@ struct pagedep { /* * The "inodedep" structure tracks the set of dependencies associated - * with an inode. Each block that is allocated is represented by an + * with an inode. One task that it must manage is delayed operations + * (i.e., work requests that must be held until the inodedep's associated + * inode has been written to disk). Getting an inode from its incore + * state to the disk requires two steps to be taken by the filesystem + * in this order: first the inode must be copied to its disk buffer by + * the VOP_UPDATE operation; second the inode's buffer must be written + * to disk. To ensure that both operations have happened in the required + * order, the inodedep maintains two lists. Delayed operations are + * placed on the id_inowait list. When the VOP_UPDATE is done, all + * operations on the id_inowait list are moved to the id_bufwait list. + * When the buffer is written, the items on the id_bufwait list can be + * safely moved to the work queue to be processed. A second task of the + * inodedep structure is to track the status of block allocation within + * the inode. Each block that is allocated is represented by an * "allocdirect" structure (see below). It is linked onto the id_newinoupdt * list until both its contents and its allocation in the cylinder - * group map have been written to disk. Once the dependencies have been + * group map have been written to disk. Once these dependencies have been * satisfied, it is removed from the id_newinoupdt list and any followup * actions such as releasing the previous block or fragment are placed - * on the id_inowait list. When an inode is updated (copied from the - * in-core inode structure to a disk buffer containing its on-disk - * copy), the "inodedep" structure is linked onto the buffer through - * its worklist. Thus it will be notified when the buffer is about + * on the id_inowait list. When an inode is updated (a VOP_UPDATE is + * done), the "inodedep" structure is linked onto the buffer through + * its worklist. Thus, it will be notified when the buffer is about * to be written and when it is done. At the update time, all the * elements on the id_newinoupdt list are moved to the id_inoupdt list * since those changes are now relevant to the copy of the inode in the - * buffer. When the buffer containing the inode is written to disk, any - * updates listed on the id_inoupdt list are rolled back as they are - * not yet safe. Following the write, the changes are once again rolled - * forward and any actions on the id_inowait list are processed (since - * the previously allocated blocks are no longer claimed on the disk). + * buffer. Also at update time, the tasks on the id_inowait list are + * moved to the id_bufwait list so that they will be executed when + * the updated inode has been written to disk. When the buffer containing + * the inode is written to disk, any updates listed on the id_inoupdt + * list are rolled back as they are not yet safe. Following the write, + * the changes are once again rolled forward and any actions on the + * id_bufwait list are processed (since those actions are now safe). * The entries on the id_inoupdt and id_newinoupdt lists must be kept * sorted by logical block number to speed the calculation of the size * of the rolled back inode (see explanation in initiate_write_inodeblock). * When a directory entry is created, it is represented by a diradd. - * The diradd is added to the id_inowait list and is not permitted to be - * written to disk until the inode that it represents is written. After - * the inode is written, the id_inowait list is processed and the diradd + * The diradd is added to the id_inowait list as it cannot be safely + * written to disk until the inode that it represents is on disk. After + * the inode is written, the id_bufwait list is processed and the diradd * entries are moved to the id_pendinghd list where they remain until * the directory block containing the name has been written to disk. * The purpose of keeping the entries on the id_pendinghd list is so that @@ -245,7 +258,8 @@ struct inodedep { struct buf *id_buf; /* related bmsafemap (if pending) */ off_t id_savedsize; /* file size saved during rollback */ struct workhead id_pendinghd; /* entries awaiting directory write */ - struct workhead id_inowait; /* operations after inode written */ + struct workhead id_bufwait; /* operations after inode written */ + struct workhead id_inowait; /* operations waiting inode update */ struct allocdirectlst id_inoupdt; /* updates before inode written */ struct allocdirectlst id_newinoupdt; /* updates when inode written */ }; @@ -461,7 +475,7 @@ struct freefile { * if appropriate and is never cleared. */ struct diradd { - struct worklist da_list; /* id_inowait and id_pendinghd list */ + struct worklist da_list; /* id_inowait or id_pendinghd list */ # define da_state da_list.wk_state /* state of the new directory entry */ LIST_ENTRY(diradd) da_pdlist; /* pagedep holding directory block */ doff_t da_offset; /* offset of new dir entry in dir blk */ |