Restructuring of the soft updates code to set it up so that the

single kernel-wide soft update lock can be replaced with a
per-filesystem soft-updates lock. This per-filesystem lock will
allow each filesystem to have its own soft-updates flushing thread
rather than being limited to a single soft-updates flushing thread
for the entire kernel.

Move soft update variables out of the ufsmount structure and into
their own mount_softdeps structure referenced by ufsmount field
um_softdep.  Eventually the per-filesystem lock will be in this
structure. For now there is simply a pointer to the kernel-wide
soft updates lock.

Change all instances of ACQUIRE_LOCK and FREE_LOCK to pass the lock
pointer in the mount_softdeps structure instead of a pointer to the
kernel-wide soft-updates lock.

Replace the five hash tables used by soft updates with per-filesystem
copies of these tables allocated in the mount_softdeps structure.

Several functions that flush dependencies when too many are allocated
in the kernel used to operate across all filesystems. They are now
parameterized to flush dependencies from a specified filesystem.
For now, we stick with the round-robin flushing strategy when the
kernel as a whole has too many dependencies allocated.

While there are many lines of changes, there should be no functional
change in the operation of soft updates.

Tested by:    Peter Holm and Scott Long
Sponsored by: Netflix
This commit is contained in:
Kirk McKusick 2013-10-21 00:28:02 +00:00
parent 6064b6ac48
commit 58941b9f15
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=256817
3 changed files with 872 additions and 622 deletions

File diff suppressed because it is too large Load Diff

View File

@ -143,6 +143,39 @@
#define ALLCOMPLETE (ATTACHED | COMPLETE | DEPCOMPLETE)
/*
* Values for each of the soft dependency types.
*/
#define D_PAGEDEP 0
#define D_INODEDEP 1
#define D_BMSAFEMAP 2
#define D_NEWBLK 3
#define D_ALLOCDIRECT 4
#define D_INDIRDEP 5
#define D_ALLOCINDIR 6
#define D_FREEFRAG 7
#define D_FREEBLKS 8
#define D_FREEFILE 9
#define D_DIRADD 10
#define D_MKDIR 11
#define D_DIRREM 12
#define D_NEWDIRBLK 13
#define D_FREEWORK 14
#define D_FREEDEP 15
#define D_JADDREF 16
#define D_JREMREF 17
#define D_JMVREF 18
#define D_JNEWBLK 19
#define D_JFREEBLK 20
#define D_JFREEFRAG 21
#define D_JSEG 22
#define D_JSEGDEP 23
#define D_SBDEP 24
#define D_JTRUNC 25
#define D_JFSYNC 26
#define D_SENTINEL 27
#define D_LAST D_SENTINEL
/*
* The workitem queue.
*
@ -416,7 +449,8 @@ struct newblk {
*/
struct allocdirect {
struct newblk ad_block; /* Common block logic */
# define ad_state ad_block.nb_list.wk_state /* block pointer state */
# define ad_list ad_block.nb_list /* block pointer worklist */
# define ad_state ad_list.wk_state /* block pointer state */
TAILQ_ENTRY(allocdirect) ad_next; /* inodedep's list of allocdirect's */
struct inodedep *ad_inodedep; /* associated inodedep */
ufs2_daddr_t ad_oldblkno; /* old value of block pointer */
@ -947,3 +981,106 @@ struct sbdep {
struct fs *sb_fs; /* Filesystem pointer within buf. */
struct ufsmount *sb_ump; /* Our mount structure */
};
/*
* Private journaling structures.
*/
struct jblocks {
struct jseglst jb_segs; /* TAILQ of current segments. */
struct jseg *jb_writeseg; /* Next write to complete. */
struct jseg *jb_oldestseg; /* Oldest segment with valid entries. */
struct jextent *jb_extent; /* Extent array. */
uint64_t jb_nextseq; /* Next sequence number. */
uint64_t jb_oldestwrseq; /* Oldest written sequence number. */
uint8_t jb_needseg; /* Need a forced segment. */
uint8_t jb_suspended; /* Did journal suspend writes? */
int jb_avail; /* Available extents. */
int jb_used; /* Last used extent. */
int jb_head; /* Allocator head. */
int jb_off; /* Allocator extent offset. */
int jb_blocks; /* Total disk blocks covered. */
int jb_free; /* Total disk blocks free. */
int jb_min; /* Minimum free space. */
int jb_low; /* Low on space. */
int jb_age; /* Insertion time of oldest rec. */
};
struct jextent {
ufs2_daddr_t je_daddr; /* Disk block address. */
int je_blocks; /* Disk block count. */
};
/*
* Hash table declarations.
*/
LIST_HEAD(mkdirlist, mkdir);
LIST_HEAD(pagedep_hashhead, pagedep);
LIST_HEAD(inodedep_hashhead, inodedep);
LIST_HEAD(newblk_hashhead, newblk);
LIST_HEAD(bmsafemap_hashhead, bmsafemap);
TAILQ_HEAD(indir_hashhead, freework);
/*
* Per-filesystem soft dependency data.
* Allocated at mount and freed at unmount.
*/
struct mount_softdeps {
struct rwlock *sd_fslock; /* softdep lock */
struct workhead sd_workitem_pending; /* softdep work queue */
struct worklist *sd_worklist_tail; /* Tail pointer for above */
struct workhead sd_journal_pending; /* journal work queue */
struct worklist *sd_journal_tail; /* Tail pointer for above */
struct jblocks *sd_jblocks; /* Journal block information */
struct inodedeplst sd_unlinked; /* Unlinked inodes */
struct bmsafemaphd sd_dirtycg; /* Dirty CGs */
struct mkdirlist sd_mkdirlisthd; /* Track mkdirs */
struct pagedep_hashhead *sd_pdhash; /* pagedep hash table */
u_long sd_pdhashsize; /* pagedep hash table size-1 */
long sd_pdnextclean; /* next hash bucket to clean */
struct inodedep_hashhead *sd_idhash; /* inodedep hash table */
u_long sd_idhashsize; /* inodedep hash table size-1 */
long sd_idnextclean; /* next hash bucket to clean */
struct newblk_hashhead *sd_newblkhash; /* newblk hash table */
u_long sd_newblkhashsize; /* newblk hash table size-1 */
struct bmsafemap_hashhead *sd_bmhash; /* bmsafemap hash table */
u_long sd_bmhashsize; /* bmsafemap hash table size-1*/
struct indir_hashhead *sd_indirhash; /* indir hash table */
u_long sd_indirhashsize; /* indir hash table size-1 */
long sd_numindirdeps; /* outstanding indirdeps */
int sd_on_journal; /* Items on the journal list */
int sd_on_worklist; /* Items on the worklist */
int sd_deps; /* Total dependency count */
int sd_accdeps; /* accumulated dep count */
int sd_req; /* Wakeup when deps hits 0. */
u_long sd_curdeps[D_LAST + 1]; /* count of current deps */
};
/*
* Keep the old names from when these were in the ufsmount structure.
*/
#define softdep_workitem_pending um_softdep->sd_workitem_pending
#define softdep_worklist_tail um_softdep->sd_worklist_tail
#define softdep_journal_pending um_softdep->sd_journal_pending
#define softdep_journal_tail um_softdep->sd_journal_tail
#define softdep_jblocks um_softdep->sd_jblocks
#define softdep_unlinked um_softdep->sd_unlinked
#define softdep_dirtycg um_softdep->sd_dirtycg
#define softdep_mkdirlisthd um_softdep->sd_mkdirlisthd
#define pagedep_hashtbl um_softdep->sd_pdhash
#define pagedep_hash_size um_softdep->sd_pdhashsize
#define pagedep_nextclean um_softdep->sd_pdnextclean
#define inodedep_hashtbl um_softdep->sd_idhash
#define inodedep_hash_size um_softdep->sd_idhashsize
#define inodedep_nextclean um_softdep->sd_idnextclean
#define newblk_hashtbl um_softdep->sd_newblkhash
#define newblk_hash_size um_softdep->sd_newblkhashsize
#define bmsafemap_hashtbl um_softdep->sd_bmhash
#define bmsafemap_hash_size um_softdep->sd_bmhashsize
#define indir_hashtbl um_softdep->sd_indirhash
#define indir_hash_size um_softdep->sd_indirhashsize
#define softdep_numindirdeps um_softdep->sd_numindirdeps
#define softdep_on_journal um_softdep->sd_on_journal
#define softdep_on_worklist um_softdep->sd_on_worklist
#define softdep_deps um_softdep->sd_deps
#define softdep_accdeps um_softdep->sd_accdeps
#define softdep_req um_softdep->sd_req
#define softdep_curdeps um_softdep->sd_curdeps

View File

@ -78,19 +78,7 @@ struct ufsmount {
u_long um_seqinc; /* inc between seq blocks */
struct mtx um_lock; /* Protects ufsmount & fs */
pid_t um_fsckpid; /* PID permitted fsck sysctls */
long um_numindirdeps; /* outstanding indirdeps */
struct workhead softdep_workitem_pending; /* softdep work queue */
struct worklist *softdep_worklist_tail; /* Tail pointer for above */
struct workhead softdep_journal_pending; /* journal work queue */
struct worklist *softdep_journal_tail; /* Tail pointer for above */
struct jblocks *softdep_jblocks; /* Journal block information */
struct inodedeplst softdep_unlinked; /* Unlinked inodes */
struct bmsafemaphd softdep_dirtycg; /* Dirty CGs */
int softdep_on_journal; /* Items on the journal list */
int softdep_on_worklist; /* Items on the worklist */
int softdep_deps; /* Total dependency count */
int softdep_accdeps; /* accumulated dep count */
int softdep_req; /* Wakeup when deps hits 0. */
struct mount_softdeps *um_softdep; /* softdep mgmt structure */
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
time_t um_btime[MAXQUOTAS]; /* block quota time limit */