- Move softdep from using a global worklist to per-mount worklists. This

has many positive effects including improved smp locking, reducing
   interdependencies between mounts that can lead to deadlocks, etc.
 - Add the softdep worklist and various counters to the ufsmnt structure.
 - Add a mount pointer to the workitem and remove mount pointers from the
   various structures derived from the workitem as they are now redundant.
 - Remove the poor-man's semaphore protecting softdep_process_worklist and
   softdep_flushworklist.  Several threads may now process the list
   simultaneously.
 - Add softdep_waitidle() to block the thread until all pending
   dependencies being operated on by other threads have been flushed.
 - Use softdep_waitidle() in unmount and snapshots to block either
   operation until the fs is stable.
 - Remove softdep worklist processing from the syncer and move it into the
   softdep_flush() thread.  This thread processes all softdep mounts
   once each second and when it is called via the new softdep_speedup()
   when there is a resource shortage.  This removes the softdep hook
   from the kernel and various hacks in header files to support it.

Reviewed by/Discussed with:	tegge, truckman, mckusick
Tested by:	kris
This commit is contained in:
Jeff Roberson 2006-03-02 05:50:23 +00:00
parent 420239c773
commit eb2ea10590
9 changed files with 336 additions and 283 deletions

View File

@ -270,9 +270,6 @@ static int vnlru_nowhere;
SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW,
&vnlru_nowhere, 0, "Number of times the vnlru process ran without success");
/* Hook for calling soft updates. */
int (*softdep_process_worklist_hook)(struct mount *);
/*
* Macros to control when a vnode is freed and recycled. All require
* the vnode interlock.
@ -1675,13 +1672,6 @@ sched_sync(void)
if (syncer_state == SYNCER_FINAL_DELAY && syncer_final_iter > 0)
syncer_final_iter--;
mtx_unlock(&sync_mtx);
/*
* Do soft update processing.
*/
if (softdep_process_worklist_hook != NULL)
(*softdep_process_worklist_hook)(NULL);
/*
* The variable rushjob allows the kernel to speed up the
* processing of the filesystem syncer process. A rushjob

View File

@ -683,10 +683,6 @@ vfs_uninit_t vfs_stduninit;
vfs_extattrctl_t vfs_stdextattrctl;
vfs_sysctl_t vfs_stdsysctl;
/* XXX - these should be indirect functions!!! */
int softdep_fsync(struct vnode *);
int softdep_process_worklist(struct mount *);
#else /* !_KERNEL */
#include <sys/cdefs.h>

View File

@ -555,7 +555,6 @@ struct vattr;
struct vnode;
extern int (*lease_check_hook)(struct vop_lease_args *);
extern int (*softdep_process_worklist_hook)(struct mount *);
/* cache_* may belong in namei.h. */
void cache_enter(struct vnode *dvp, struct vnode *vp,

View File

@ -1348,7 +1348,7 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
ACTIVECLEAR(fs, cg);
UFS_UNLOCK(ump);
if (DOINGSOFTDEP(ITOV(ip)))
softdep_setup_blkmapdep(bp, fs, bprev);
softdep_setup_blkmapdep(bp, UFSTOVFS(ump), bprev);
bdwrite(bp);
return (bprev);
@ -1454,7 +1454,7 @@ ffs_alloccg(ip, cg, bpref, size)
ACTIVECLEAR(fs, cg);
UFS_UNLOCK(ump);
if (DOINGSOFTDEP(ITOV(ip)))
softdep_setup_blkmapdep(bp, fs, blkno);
softdep_setup_blkmapdep(bp, UFSTOVFS(ump), blkno);
bdwrite(bp);
return (blkno);
@ -1523,7 +1523,7 @@ gotit:
/* XXX Fixme. */
UFS_UNLOCK(ump);
if (DOINGSOFTDEP(ITOV(ip)))
softdep_setup_blkmapdep(bp, fs, blkno);
softdep_setup_blkmapdep(bp, UFSTOVFS(ump), blkno);
UFS_LOCK(ump);
return (blkno);
}

View File

@ -107,7 +107,7 @@ void softdep_freefile(struct vnode *, ino_t, int);
int softdep_request_cleanup(struct fs *, struct vnode *);
void softdep_setup_freeblocks(struct inode *, off_t, int);
void softdep_setup_inomapdep(struct buf *, struct inode *, ino_t);
void softdep_setup_blkmapdep(struct buf *, struct fs *, ufs2_daddr_t);
void softdep_setup_blkmapdep(struct buf *, struct mount *, ufs2_daddr_t);
void softdep_setup_allocdirect(struct inode *, ufs_lbn_t, ufs2_daddr_t,
ufs2_daddr_t, long, long, struct buf *);
void softdep_setup_allocext(struct inode *, ufs_lbn_t, ufs2_daddr_t,
@ -118,9 +118,8 @@ void softdep_setup_allocindir_page(struct inode *, ufs_lbn_t,
struct buf *, int, ufs2_daddr_t, ufs2_daddr_t, struct buf *);
void softdep_fsync_mountdev(struct vnode *);
int softdep_sync_metadata(struct vnode *);
/* XXX incorrectly moved to mount.h - should be indirect function */
#if 0
int softdep_fsync(struct vnode *vp);
#endif
int softdep_process_worklist(struct mount *, int);
int softdep_fsync(struct vnode *);
int softdep_waitidle(struct mount *);
#endif /* !_UFS_FFS_EXTERN_H */

View File

@ -401,7 +401,14 @@ restart:
break;
vn_start_write(NULL, &wrtmp, V_WAIT);
}
/*
* Wait for all dependency processing to finish after the sync
* triggered by vfs_write_suspend().
*/
error = softdep_waitidle(vp->v_mount);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (error)
goto out1;
if (collectsnapstats)
nanotime(&starttime);
/*

File diff suppressed because it is too large Load Diff

View File

@ -135,6 +135,7 @@
* and the macros below changed to use it.
*/
struct worklist {
struct mount *wk_mp; /* Mount we live in */
LIST_ENTRY(worklist) wk_list; /* list of work requests */
unsigned short wk_type; /* type of request */
unsigned short wk_state; /* state flags */
@ -142,7 +143,6 @@ struct worklist {
#define WK_DATA(wk) ((void *)(wk))
#define WK_PAGEDEP(wk) ((struct pagedep *)(wk))
#define WK_INODEDEP(wk) ((struct inodedep *)(wk))
#define WK_NEWBLK(wk) ((struct newblk *)(wk))
#define WK_BMSAFEMAP(wk) ((struct bmsafemap *)(wk))
#define WK_ALLOCDIRECT(wk) ((struct allocdirect *)(wk))
#define WK_INDIRDEP(wk) ((struct indirdep *)(wk))
@ -190,7 +190,6 @@ struct pagedep {
struct worklist pd_list; /* page buffer */
# define pd_state pd_list.wk_state /* check for multiple I/O starts */
LIST_ENTRY(pagedep) pd_hash; /* hashed lookup */
struct mount *pd_mnt; /* associated mount point */
ino_t pd_ino; /* associated file */
ufs_lbn_t pd_lbn; /* block within file */
struct dirremhd pd_dirremhd; /* dirrem's waiting for page */
@ -415,7 +414,6 @@ struct allocindir {
struct freefrag {
struct worklist ff_list; /* id_inowait or delayed worklist */
# define ff_state ff_list.wk_state /* owning user; should be uid_t */
struct mount *ff_mnt; /* associated mount point */
ufs2_daddr_t ff_blkno; /* fragment physical block number */
long ff_fragsize; /* size of fragment being deleted */
ino_t ff_inum; /* owning inode number */
@ -433,7 +431,6 @@ struct freeblks {
ino_t fb_previousinum; /* inode of previous owner of blocks */
uid_t fb_uid; /* uid of previous owner of blocks */
struct vnode *fb_devvp; /* filesystem device vnode */
struct mount *fb_mnt; /* associated mount point */
long fb_oldextsize; /* previous ext data size */
off_t fb_oldsize; /* previous file size */
ufs2_daddr_t fb_chkcnt; /* used to check cnt of blks released */
@ -453,7 +450,6 @@ struct freefile {
mode_t fx_mode; /* mode of inode */
ino_t fx_oldinum; /* inum of the unlinked file */
struct vnode *fx_devvp; /* filesystem device vnode */
struct mount *fx_mnt; /* associated mount point */
};
/*
@ -555,7 +551,6 @@ struct dirrem {
struct worklist dm_list; /* delayed worklist */
# define dm_state dm_list.wk_state /* state of the old directory entry */
LIST_ENTRY(dirrem) dm_next; /* pagedep's list of dirrem's */
struct mount *dm_mnt; /* associated mount point */
ino_t dm_oldinum; /* inum of the removed dir entry */
union {
struct pagedep *dmu_pagedep; /* pagedep dependency for remove */

View File

@ -33,6 +33,8 @@
#ifndef _UFS_UFS_UFSMOUNT_H_
#define _UFS_UFS_UFSMOUNT_H_
#include <sys/buf.h> /* XXX For struct workhead. */
/*
* Arguments to mount UFS-based filesystems
*/
@ -71,6 +73,11 @@ struct ufsmount {
u_long um_seqinc; /* inc between seq blocks */
struct mtx um_lock; /* Protects ufsmount & fs */
long um_numindirdeps; /* outstanding indirdeps */
struct workhead softdep_workitem_pending; /* softdep work queue */
struct worklist *softdep_worklist_tail; /* Tail pointer for above */
int softdep_on_worklist; /* Items on the worklist */
int softdep_deps; /* Total dependency count */
int softdep_req; /* Wakeup when deps hits 0. */
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 */
@ -112,6 +119,7 @@ struct ufsmount {
/* Convert mount ptr to ufsmount ptr. */
#define VFSTOUFS(mp) ((struct ufsmount *)((mp)->mnt_data))
#define UFSTOVFS(ump) (ump)->um_mountp
/*
* Macros to access filesystem parameters in the ufsmount structure.