📄 ufs_flock.c
字号:
} } else if (lckdat->l_start < f->set.l_end && lckdat->l_end > f->set.l_start && (f->set.l_type == F_WRLCK || (f->set.l_type == F_RDLCK && lckdat->l_type == F_WRLCK))) return(f); } for ( ; f != NULL; f = f->next) { if (lckdat->l_start < f->set.l_end && lckdat->l_end > f->set.l_start && f->set.l_pid != u.u_procp->p_pid && (f->set.l_type == F_WRLCK || (f->set.l_type == F_RDLCK && lckdat->l_type == F_WRLCK))) return(f); if (f->set.l_start > lckdat->l_end) break; } return(NULL);}/* deadflck does the deadlock detection for the given record */struct filock *ufs_deadlock(flp) register struct filock *flp;{ register struct filock *blck, *sf; register int blckpid; blck = flp; /* current blocking lock pointer */ blckpid = blck->set.l_pid; do { if (blckpid == u.u_procp->p_pid) return((struct filock *)1); /* if the blocking process is sleeping on a locked region, * change the blocked lock to this one. */ for (sf = sleeplcks.fl_flck; sf != NULL; sf = sf->next) { if (blckpid == sf->set.l_pid) { blckpid = sf->stat.blkpid; break; } } blck = sf; } while (blck != NULL); return((struct filock*) 0);}/* find file id */struct flino *findfid(fp) register struct file *fp;{ register struct flino *flip; dev_t d; register gno_t n; register struct gnode *gp = (struct gnode *)fp->f_data; d = gp->g_dev; n = gp->g_number; flip = fids; while (flip != NULL) { if (flip->fl_dev == d && flip->fl_number == n) { flip->fl_refcnt++; break; } flip = flip->next; } return (flip);}struct flino *allocfid(fp) register struct file *fp;{ register struct flino *flip; register struct gnode *gp = (struct gnode *)fp->f_data; flip = frfid; if (flip != NULL) { ++flckinfo.filcnt; ++flckinfo.filtot; /* remove from free list */ frfid = flip->next; if (frfid != NULL) frfid->prev = NULL; /* insert into allocated file identifier list */ if (fids != NULL) fids->prev = flip; flip->next = fids; fids = flip; /* set up file identifier info */ ++flip->fl_refcnt; flip->fl_dev = gp->g_dev; flip->fl_number = gp->g_number; } return (flip);}freefid(flip) register struct flino *flip;{ if (--flip->fl_refcnt <= 0 && flip->fl_flck == NULL) { --flckinfo.filcnt; if (flip->prev != NULL) flip->prev->next = flip->next; else fids = flip->next; if (flip->next != NULL) flip->next->prev = flip->prev; flip->fl_dev = 0; flip->fl_number = 0; flip->fl_refcnt = 0; if (frfid != NULL) frfid->prev = flip; flip->next = frfid; flip->prev = NULL; frfid = flip; }} /* build file lock free list */flckinit(){ register int i; /* Initialize file and record locking lock */ lockinit(&lk_frlock, &lock_frlock_d); for (i=0; i<flckinfo.fils; i++) { freefid(&flinotab[i]); } flckinfo.filcnt = 0; for (i=0; i<flckinfo.recs; i++) { if (frlock == NULL) { flox[i].next = flox[i].prev = NULL; frlock = &flox[i]; } else { flox[i].next = frlock; flox[i].prev = NULL; frlock = (frlock->prev = &flox[i]); } } flckinfo.reccnt = 0;}/* regflck sets the type of span of this (un)lock relative to the specified * already existing locked section. * There are five regions: * * S_BEFORE S_START S_MIDDLE S_END S_AFTER * 010 020 030 040 050 * E_BEFORE E_START E_MIDDLE E_END E_AFTER * 01 02 03 04 05 * |-------------------------------| * * relative to the already locked section. The type is two octal digits, * the 8's digit is the start type and the 1's digit is the end type. */intregflck(ld, flp) register struct flock *ld; register struct filock *flp;{ register int regntype; if (ld->l_start > flp->set.l_start) { if (ld->l_start > flp->set.l_end) return(S_AFTER|E_AFTER); else if (ld->l_start == flp->set.l_end) return(S_END|E_AFTER); else regntype = S_MIDDLE; } else if (ld->l_start == flp->set.l_start) regntype = S_START; else regntype = S_BEFORE; if (ld->l_end > flp->set.l_start) { if (ld->l_end > flp->set.l_end) regntype |= E_AFTER; else if (ld->l_end == flp->set.l_end) regntype |= E_END; else regntype |= E_MIDDLE; } else if (ld->l_end == flp->set.l_start) regntype |= E_START; else regntype |= E_BEFORE; return (regntype);}/* locate overlapping file locks */getflck(fp, lckdat) register struct file *fp; register struct flock *lckdat;{ register struct flino *flip; struct filock *found, *insrt = NULL; /* get file identifier and file lock list pointer if there is one */ /* SMP lock operations on file and record locking linked lists */ smp_lock(&lk_frlock, LK_RETRY); flip = findfid(fp); if (flip == NULL) { smp_unlock(&lk_frlock); lckdat->l_type = F_UNLCK; return (0); } if (lckdat->l_len == 0) lckdat->l_end = MAXEND; else lckdat->l_end += lckdat->l_start; /* find overlapping lock */ found = ufs_krlock((struct gnode *)fp->f_data, BLOCKLOCK, (struct flino *) flip->fl_flck, (struct filock *) lckdat, (struct flock *) &insrt); if (found != NULL) *lckdat = found->set; else lckdat->l_type = F_UNLCK; freefid(flip); smp_unlock(&lk_frlock); /* restore length */ if (lckdat->l_end == MAXEND) lckdat->l_len = 0; else lckdat->l_len -= lckdat->l_start; return (0);}/* clear and set file locks */setflck(fp, lckdat, slpflg) register struct file *fp; struct flock *lckdat; int slpflg;{ register struct flino *flip; register struct filock *found, *sf; struct filock *insrt = NULL; register int retval = 0; register int contflg = 0; if (lckdat->l_len == 0) lckdat->l_end = MAXEND; else lckdat->l_end += lckdat->l_start; /* get or create a file/inode record lock header */ /* SMP lock operations on file and record locking linked lists */ smp_lock(&lk_frlock, LK_RETRY); flip = findfid(fp); if (flip == NULL) { if (lckdat->l_type == F_UNLCK) { smp_unlock(&lk_frlock); return (0); } if ((flip=allocfid(fp)) == NULL) { smp_unlock(&lk_frlock); return (EMFILE); } } do { contflg = 0; switch (lckdat->l_type) { case F_RDLCK: case F_WRLCK: if((found = (struct filock *)ufs_krlock((struct gnode *) fp->f_data, BLOCKLOCK, (struct flino *) flip->fl_flck, (struct filock *) lckdat, (struct flock *) &insrt)) == NULL) retval = (int)ufs_krlock((struct gnode *) fp->f_data, ADJLOCK, flip, insrt, lckdat); else if (slpflg) { /* do deadlock detection here */ if(ufs_krlock((struct gnode *)fp->f_data, DEADLOCK, (struct flino *) found, (struct filock *) 0, (struct flock *) 0)) retval = EDEADLK; else if((sf = ufs_krlock((struct gnode *) fp->f_data, MAKELOCK, &sleeplcks, lckdat, NULL)) == NULL) retval = ENOSPC; else { found->stat.wakeflg++; sf->stat.blkpid = found->set.l_pid; smp_unlock(&fp->f_lk); if (SLEEP(found, PCATCH|(PZERO+1))) retval = EINTR; else contflg = 1; smp_lock(&fp->f_lk, LK_RETRY); smp_lock(&lk_frlock, LK_RETRY); sf->stat.blkpid = 0; (void) ufs_krlock((struct gnode *) fp->f_data, DELLOCK, &sleeplcks, sf, (struct flock *)NULL); } } else retval = EACCES; break; case F_UNLCK: /* removing a file record lock */ retval = (int) ufs_krlock((struct gnode *)fp->f_data, ADJLOCK, flip, flip->fl_flck, lckdat); break; default: retval = EINVAL; /* invalid lock type */ break; } } while (contflg); freefid(flip); smp_unlock(&lk_frlock); return(retval);}/* Clean up record locks left around by process (called in closef) */cleanlocks(fp) register struct file *fp;{ register struct filock *flp, *nflp; register struct flino *flip; /* * Locks can only happen to disk inodes. */ if ( fp->f_type != DTYPE_INODE ) return; /* * Make sure the inode pointer is valid */ if ( fp->f_data == NULL ) return; /* SMP lock operations on file and record locking linked lists */ smp_lock(&lk_frlock, LK_RETRY); flip = findfid(fp); if (flip == NULL) { smp_unlock(&lk_frlock); return; } for (flp=flip->fl_flck; flp!=NULL; flp=nflp) { nflp = flp->next; if (flp->set.l_pid == u.u_procp->p_pid) ufs_krlock((struct gnode *)fp->f_data, DELLOCK, flip, flp,(struct flock *) 0); } freefid(flip); smp_unlock(&lk_frlock); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -