static int inodedep_lookup(struct fs *, ino_t, int, struct inodedep **);
static int pagedep_lookup(struct inode *, ufs_lbn_t, int,
struct pagedep **);
-static void pause_timer(void *);
static int request_cleanup(int, int);
-static int process_worklist_item(struct mount *, int);
+static int process_worklist_item(struct mount *);
static void add_to_worklist(struct worklist *);
/*
#ifdef INVARIANTS
static int lock_held(struct lock *);
#endif
-static int interlocked_sleep(struct lock *, void *, int,
- const char *, int);
static struct lock lk;
}
#endif
-static int
-interlocked_sleep(struct lock *lkp, void *ident, int flags,
- const char *wmesg, int timo)
-{
- int retval;
-
- KKASSERT(lock_held(lkp) > 0);
- retval = lksleep(ident, lkp, flags, wmesg, timo);
- return (retval);
-}
-
/*
* Place holder for real semaphores.
*/
int value;
thread_t holder;
char *name;
- int prio;
int timo;
};
-static void sema_init(struct sema *, char *, int, int);
+static void sema_init(struct sema *, char *, int);
static int sema_get(struct sema *, struct lock *);
static void sema_release(struct sema *);
#define NOHOLDER ((struct thread *) -1)
static void
-sema_init(struct sema *semap, char *name, int prio, int timo)
+sema_init(struct sema *semap, char *name, int timo)
{
-
semap->holder = NOHOLDER;
semap->value = 0;
semap->name = name;
- semap->prio = prio;
semap->timo = timo;
}
static int
sema_get(struct sema *semap, struct lock *interlock)
{
-
if (semap->value++ > 0) {
- if (interlock != NULL) {
- interlocked_sleep(interlock, (caddr_t)semap,
- semap->prio, semap->name, semap->timo);
- FREE_LOCK(interlock);
- } else {
- tsleep((caddr_t)semap, semap->prio, semap->name,
- semap->timo);
- }
+ if (interlock)
+ lksleep(semap, interlock, 0, semap->name, semap->timo);
+ else
+ tsleep(semap, 0, semap->name, semap->timo);
return (0);
}
semap->holder = curthread;
- if (interlock != NULL)
- FREE_LOCK(interlock);
return (1);
}
static void
sema_release(struct sema *semap)
{
-
if (semap->value <= 0 || semap->holder != curthread) {
panic("sema_release: not held");
}
static void
worklist_insert(struct workhead *head, struct worklist *item)
{
-
KKASSERT(lock_held(&lk) > 0);
if (item->wk_state & ONWORKLIST) {
static int tickdelay = 2; /* number of ticks to pause during slowdown */
static int *stat_countp; /* statistic to count in proc_waiting timeout */
static int proc_waiting; /* tracks whether we have a timeout posted */
-static struct callout handle; /* handle on posted proc_waiting timeout */
static struct thread *filesys_syncer; /* proc of filesystem syncer process */
static int req_clear_inodedeps; /* syncer process flush some inodedeps */
#define FLUSH_INODES 1
return(1);
if ((flags & DEPALLOC) == 0)
return (0);
- if (sema_get(&pagedep_in_progress, &lk) == 0) {
- ACQUIRE_LOCK(&lk);
+ if (sema_get(&pagedep_in_progress, &lk) == 0)
goto top;
- }
+
+ FREE_LOCK(&lk);
pagedep = kmalloc(sizeof(struct pagedep), M_PAGEDEP,
M_SOFTDEP_FLAGS | M_ZERO);
-
+ ACQUIRE_LOCK(&lk);
if (pagedep_find(pagedephd, ip->i_number, lbn, mp)) {
kprintf("pagedep_lookup: blocking race avoided\n");
- ACQUIRE_LOCK(&lk);
sema_release(&pagedep_in_progress);
kfree(pagedep, M_PAGEDEP);
goto top;
LIST_INIT(&pagedep->pd_pendinghd);
for (i = 0; i < DAHASHSZ; i++)
LIST_INIT(&pagedep->pd_diraddhd[i]);
- ACQUIRE_LOCK(&lk);
LIST_INSERT_HEAD(pagedephd, pagedep, pd_hash);
sema_release(&pagedep_in_progress);
*pagedeppp = pagedep;
firsttry = 0;
goto top;
}
- if (sema_get(&inodedep_in_progress, &lk) == 0) {
- ACQUIRE_LOCK(&lk);
+ if (sema_get(&inodedep_in_progress, &lk) == 0)
goto top;
- }
+
+ FREE_LOCK(&lk);
inodedep = kmalloc(sizeof(struct inodedep), M_INODEDEP,
M_SOFTDEP_FLAGS | M_ZERO);
+ ACQUIRE_LOCK(&lk);
if (inodedep_find(inodedephd, fs, inum)) {
kprintf("inodedep_lookup: blocking race avoided\n");
- ACQUIRE_LOCK(&lk);
sema_release(&inodedep_in_progress);
kfree(inodedep, M_INODEDEP);
goto top;
LIST_INIT(&inodedep->id_bufwait);
TAILQ_INIT(&inodedep->id_inoupdt);
TAILQ_INIT(&inodedep->id_newinoupdt);
- ACQUIRE_LOCK(&lk);
num_inodedep += 1;
LIST_INSERT_HEAD(inodedephd, inodedep, id_hash);
sema_release(&inodedep_in_progress);
return(1);
if ((flags & DEPALLOC) == 0)
return (0);
- if (sema_get(&newblk_in_progress, 0) == 0)
+ if (sema_get(&newblk_in_progress, NULL) == 0)
goto top;
+
newblk = kmalloc(sizeof(struct newblk), M_NEWBLK,
M_SOFTDEP_FLAGS | M_ZERO);
void
softdep_initialize(void)
{
- callout_init(&handle);
-
LIST_INIT(&mkdirlisthd);
LIST_INIT(&softdep_workitem_pending);
max_softdeps = min(desiredvnodes * 8,
pagedep_hashtbl = hashinit(desiredvnodes / 5, M_PAGEDEP,
&pagedep_hash);
lockinit(&lk, "ffs_softdep", 0, LK_CANRECURSE);
- sema_init(&pagedep_in_progress, "pagedep", 0, 0);
+ sema_init(&pagedep_in_progress, "pagedep", 0);
inodedep_hashtbl = hashinit(desiredvnodes, M_INODEDEP, &inodedep_hash);
- sema_init(&inodedep_in_progress, "inodedep", 0, 0);
+ sema_init(&inodedep_in_progress, "inodedep", 0);
newblk_hashtbl = hashinit(64, M_NEWBLK, &newblk_hash);
- sema_init(&newblk_in_progress, "newblk", 0, 0);
+ sema_init(&newblk_in_progress, "newblk", 0);
add_bio_ops(&softdep_bioops);
}
*/
ACQUIRE_LOCK(&lk);
if ((inodedep_lookup(ip->i_fs, newinum, DEPALLOC|NODELAY, &inodedep))) {
- FREE_LOCK(&lk);
panic("softdep_setup_inomapdep: found inode");
}
inodedep->id_buf = bp;
if (lbn >= NDADDR) {
/* allocating an indirect block */
if (oldblkno != 0) {
- FREE_LOCK(&lk);
panic("softdep_setup_allocdirect: non-zero indir");
}
} else {
break;
}
if (oldadp == NULL) {
- FREE_LOCK(&lk);
panic("softdep_setup_allocdirect: lost entry");
}
/* insert in middle of list */
if (newadp->ad_oldblkno != oldadp->ad_newblkno ||
newadp->ad_oldsize != oldadp->ad_newsize ||
newadp->ad_lbn >= NDADDR) {
- FREE_LOCK(&lk);
panic("allocdirect_check: old %d != new %d || lbn %ld >= %d",
newadp->ad_oldblkno, oldadp->ad_newblkno, newadp->ad_lbn,
NDADDR);
break;
if (oldaip != NULL) {
if (oldaip->ai_newblkno != aip->ai_oldblkno) {
- FREE_LOCK(&lk);
panic("setup_allocindir_phase2: blkno");
}
aip->ai_oldblkno = oldaip->ai_oldblkno;
ACQUIRE_LOCK(&lk);
(void) inodedep_lookup(fs, ip->i_number, DEPALLOC, &inodedep);
if ((inodedep->id_state & IOSTARTED) != 0) {
- FREE_LOCK(&lk);
panic("softdep_setup_freeblocks: inode busy");
}
/*
* so b_bio1 contains the device block number.
*/
if (indirdep->ir_state & GOINGAWAY) {
- FREE_LOCK(&lk);
panic("deallocate_dependencies: already gone");
}
indirdep->ir_state |= GOINGAWAY;
free_allocindir(aip, inodedep);
if (bp->b_bio1.bio_offset >= 0 ||
bp->b_bio2.bio_offset != indirdep->ir_savebp->b_bio1.bio_offset) {
- FREE_LOCK(&lk);
panic("deallocate_dependencies: not indir");
}
bcopy(bp->b_data, indirdep->ir_savebp->b_data,
case D_ALLOCDIRECT:
case D_INODEDEP:
- FREE_LOCK(&lk);
panic("deallocate_dependencies: Unexpected type %s",
TYPENAME(wk->wk_type));
/* NOTREACHED */
default:
- FREE_LOCK(&lk);
panic("deallocate_dependencies: Unknown type %s",
TYPENAME(wk->wk_type));
/* NOTREACHED */
inodedep->id_savedino = NULL;
}
if (free_inodedep(inodedep) == 0) {
- FREE_LOCK(&lk);
panic("check_inode_unwritten: busy inode");
}
return (1);
if (wk->wk_type != D_INDIRDEP ||
(indirdep = WK_INDIRDEP(wk))->ir_savebp != bp ||
(indirdep->ir_state & GOINGAWAY) == 0) {
- FREE_LOCK(&lk);
panic("indir_trunc: lost indirdep");
}
WORKLIST_REMOVE(wk);
WORKITEM_FREE(indirdep, D_INDIRDEP);
if (LIST_FIRST(&bp->b_dep) != NULL) {
- FREE_LOCK(&lk);
panic("indir_trunc: dangling dep");
}
FREE_LOCK(&lk);
WORKITEM_FREE(mkdir, D_MKDIR);
}
if ((dap->da_state & (MKDIR_PARENT | MKDIR_BODY)) != 0) {
- FREE_LOCK(&lk);
panic("free_diradd: unfound ref");
}
}
* Must be ATTACHED at this point.
*/
if ((dap->da_state & ATTACHED) == 0) {
- FREE_LOCK(&lk);
panic("newdirrem: not ATTACHED");
}
if (dap->da_newinum != ip->i_number) {
- FREE_LOCK(&lk);
panic("newdirrem: inum %"PRId64" should be %"PRId64,
ip->i_number, dap->da_newinum);
}
ACQUIRE_LOCK(&lk);
(void) inodedep_lookup(ip->i_fs, ip->i_number, DEPALLOC, &inodedep);
if (ip->i_nlink < ip->i_effnlink) {
- FREE_LOCK(&lk);
panic("softdep_change_linkcnt: bad delta");
}
inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
ip = VTOI(vp);
ACQUIRE_LOCK(&lk);
if ((inodedep_lookup(ip->i_fs, dirrem->dm_oldinum, 0, &inodedep)) == 0){
- FREE_LOCK(&lk);
panic("handle_workitem_remove: lost inodedep");
}
/*
ip->i_nlink--;
ip->i_flag |= IN_CHANGE;
if (ip->i_nlink < ip->i_effnlink) {
- FREE_LOCK(&lk);
panic("handle_workitem_remove: bad file delta");
}
inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
ip->i_nlink -= 2;
ip->i_flag |= IN_CHANGE;
if (ip->i_nlink < ip->i_effnlink) {
- FREE_LOCK(&lk);
panic("handle_workitem_remove: bad dir delta");
}
inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
ep = (struct direct *)
((char *)bp->b_data + dap->da_offset);
if (ep->d_ino != dap->da_newinum) {
- FREE_LOCK(&lk);
panic("%s: dir inum %d != new %"PRId64,
"initiate_write_filepage",
ep->d_ino, dap->da_newinum);
adp = TAILQ_NEXT(adp, ad_next)) {
#ifdef DIAGNOSTIC
if (deplist != 0 && prevlbn >= adp->ad_lbn) {
- FREE_LOCK(&lk);
panic("softdep_write_inodeblock: lbn order");
}
prevlbn = adp->ad_lbn;
if (adp->ad_lbn < NDADDR &&
dp->di_db[adp->ad_lbn] != adp->ad_newblkno) {
- FREE_LOCK(&lk);
panic("%s: direct pointer #%ld mismatch %d != %d",
"softdep_write_inodeblock", adp->ad_lbn,
dp->di_db[adp->ad_lbn], adp->ad_newblkno);
}
if (adp->ad_lbn >= NDADDR &&
dp->di_ib[adp->ad_lbn - NDADDR] != adp->ad_newblkno) {
- FREE_LOCK(&lk);
panic("%s: indirect pointer #%ld mismatch %d != %d",
"softdep_write_inodeblock", adp->ad_lbn - NDADDR,
dp->di_ib[adp->ad_lbn - NDADDR], adp->ad_newblkno);
}
deplist |= 1 << adp->ad_lbn;
if ((adp->ad_state & ATTACHED) == 0) {
- FREE_LOCK(&lk);
panic("softdep_write_inodeblock: Unknown state 0x%x",
adp->ad_state);
}
for (i = adp->ad_lbn + 1; i < NDADDR; i++) {
#ifdef DIAGNOSTIC
if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0) {
- FREE_LOCK(&lk);
panic("softdep_write_inodeblock: lost dep1");
}
#endif /* DIAGNOSTIC */
#ifdef DIAGNOSTIC
if (dp->di_ib[i] != 0 &&
(deplist & ((1 << NDADDR) << i)) == 0) {
- FREE_LOCK(&lk);
panic("softdep_write_inodeblock: lost dep2");
}
#endif /* DIAGNOSTIC */
{
struct inodedep *inodedep;
struct worklist *wk;
+ struct buf *ibp;
int error, gotit;
/*
return;
}
if (inodedep->id_nlinkdelta != ip->i_nlink - ip->i_effnlink) {
- FREE_LOCK(&lk);
panic("softdep_update_inodeblock: bad delta");
}
/*
FREE_LOCK(&lk);
return;
}
+ ibp = inodedep->id_buf;
FREE_LOCK(&lk);
- if ((error = bwrite(inodedep->id_buf)) != 0)
+ if ((error = bwrite(ibp)) != 0)
softdep_error("softdep_update_inodeblock: bwrite", error);
}
LIST_FIRST(&inodedep->id_bufwait) != NULL ||
TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL) {
- FREE_LOCK(&lk);
panic("softdep_fsync: pending ops");
}
for (error = 0, flushparent = 0; ; ) {
if ((wk = LIST_FIRST(&inodedep->id_pendinghd)) == NULL)
break;
if (wk->wk_type != D_DIRADD) {
- FREE_LOCK(&lk);
panic("softdep_fsync: Unexpected type %s",
TYPENAME(wk->wk_type));
}
parentino = pagedep->pd_ino;
lbn = pagedep->pd_lbn;
if ((dap->da_state & (MKDIR_BODY | COMPLETE)) != COMPLETE) {
- FREE_LOCK(&lk);
panic("softdep_fsync: dirty");
}
flushparent = dap->da_state & MKDIR_PARENT;
break;
default:
- FREE_LOCK(&lk);
panic("softdep_sync_metadata: Unknown type %s",
TYPENAME(wk->wk_type));
/* NOTREACHED */
if (dap != LIST_FIRST(diraddhdp))
continue;
if (dap->da_state & MKDIR_PARENT) {
- FREE_LOCK(&lk);
panic("flush_pagedep_deps: MKDIR_PARENT");
}
}
if (dap != LIST_FIRST(diraddhdp))
continue;
if (dap->da_state & MKDIR_BODY) {
- FREE_LOCK(&lk);
panic("flush_pagedep_deps: MKDIR_BODY");
}
}
* caused by a bitmap dependency, then write the inode buffer.
*/
if (inodedep_lookup(ump->um_fs, inum, 0, &inodedep) == 0) {
- FREE_LOCK(&lk);
panic("flush_pagedep_deps: lost inode");
}
/*
* then something is seriously wrong.
*/
if (dap == LIST_FIRST(diraddhdp)) {
- FREE_LOCK(&lk);
panic("flush_pagedep_deps: flush failed");
}
}
break;
default:
- if (islocked)
- FREE_LOCK(&lk);
panic("request_cleanup: unknown type");
}
/*
*/
if (islocked == 0)
ACQUIRE_LOCK(&lk);
- proc_waiting += 1;
- if (!callout_active(&handle))
- callout_reset(&handle, tickdelay > 2 ? tickdelay : 2,
- pause_timer, NULL);
- interlocked_sleep(&lk, (caddr_t)&proc_waiting, 0,
- "softupdate", 0);
- proc_waiting -= 1;
+ lksleep(&proc_waiting, &lk, 0, "softupdate",
+ tickdelay > 2 ? tickdelay : 2);
if (islocked == 0)
FREE_LOCK(&lk);
return (1);
}
/*
- * Awaken processes pausing in request_cleanup and clear proc_waiting
- * to indicate that there is no longer a timer running.
- */
-void
-pause_timer(void *arg)
-{
- *stat_countp += 1;
- wakeup_one(&proc_waiting);
- if (proc_waiting > 0)
- callout_reset(&handle, tickdelay > 2 ? tickdelay : 2,
- pause_timer, NULL);
- else
- callout_deactivate(&handle);
-}
-
-/*
* Flush out a directory with at least one removal dependency in an effort to
* reduce the number of dirrem, freefile, and freeblks dependency structures.
*/
continue;
default:
- FREE_LOCK(&lk);
panic("softdep_check_for_rollback: Unexpected type %s",
TYPENAME(wk->wk_type));
/* NOTREACHED */
void
softdep_error(char *func, int error)
{
-
/* XXX should do something better! */
kprintf("%s: got error %d while accessing filesystem\n", func, error);
}