📄 ufs_flock.c
字号:
#ifndef lintstatic char *sccsid = "@(#)ufs_flock.c 4.2 ULTRIX 11/9/90";#endif/************************************************************************ * * * Copyright (c) 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * Modification History * * 11/14/89 - prs * Unlocked file table entry lock before sleeping * in setflck(). This prevented the deadlock detection * code from executing on locking attempt. * * 09/12/88 - Condylis * Made SMP changes for UFS kernel region locking. * * 01/26/88 - Fred Glover * Move former gfs_flock routines to ufs_flock to * support the UFS kernel region locking functionality * * Stephen Reilly, 09-Sept-85 * Created to handle the lockf call. * ***********************************************************************/#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/kernel.h"#include "../h/gnode_common.h"#include "../ufs/ufs_inode.h"#include "../h/gnode.h"#include "../h/mount.h"#include "../h/proc.h"#include "../h/conf.h"#include "../h/file.h"#include "../h/flock.h"/* region types */#define S_BEFORE 010#define S_START 020#define S_MIDDLE 030#define S_END 040#define S_AFTER 050#define E_BEFORE 001#define E_START 002#define E_MIDDLE 003#define E_END 004#define E_AFTER 005#define SLEEP(ptr, pri) sleep_unlock(ptr, pri, (caddr_t)&lk_frlock)#define WAKEUP(ptr) if (ptr->stat.wakeflg) { \ wakeup((caddr_t)ptr); \ ptr->stat.wakeflg = 0 ; \ }#define l_end l_len#define MAXEND 017777777777extern struct flckinfo flckinfo; /* configuration and acct info */struct filock *frlock; /* pointer to record lock free list*/struct flino *frfid; /* file id free list */struct flino *fids; /* file id head list */struct flino sleeplcks; /* head of chain of sleeping locks*/struct filock *ufs_insflck(), *ufs_delflck(), *ufs_flckadj();struct filock *ufs_blocked(), *ufs_deadlock(), *ufs_krlock();struct _rlock { struct filock *(*function)();};struct _rlock ufs_flock_routines[] = { ufs_insflck, ufs_delflck, ufs_flckadj, ufs_blocked, ufs_deadlock};/* SMP lock for file and record locking structures */struct lock_t lk_frlock;#define RLOCKROUTINE(num) ufs_flock_routines[(num)].function/* * ufs_krlock is the entry point for all of the ufs * kernel region/file lockingroutines */struct filock *ufs_krlock(gp, cmd, flino, filock, flock) register struct gnode *gp; register int cmd; register struct flino *flino; register struct filock *filock; register struct flock *flock;{ register struct filock *(*routine)(); if((routine = RLOCKROUTINE(cmd)) == NULL) return((struct filock *)EOPNOTSUPP); return((*routine)(flino, filock, flock));}/* insert lock after given lock using locking data */struct filock *ufs_insflck(flip, lckdat, fl) register struct flino *flip; register struct filock *fl; register struct flock *lckdat;{ register struct filock *new; register struct filock *f; new = frlock; if (new != NULL) { ++flckinfo.reccnt; ++flckinfo.rectot; frlock = new->next; if (frlock != NULL) frlock->prev = NULL; new->set = *lckdat; new->set.l_pid = u.u_procp->p_pid; new->stat.wakeflg = 0; if (fl == NULL) { new->next = flip->fl_flck; if (flip->fl_flck != NULL) flip->fl_flck->prev = new; flip->fl_flck = new; } else { new->next = fl->next; if (fl->next != NULL) fl->next->prev = new; fl->next = new; } new->prev = fl; } return (new);}/* delete lock */struct filock *ufs_delflck(flip, fl) register struct flino *flip; register struct filock *fl;{ if (fl->prev != NULL) fl->prev->next = fl->next; else flip->fl_flck = fl->next; if (fl->next != NULL) fl->next->prev = fl->prev; WAKEUP(fl); --flckinfo.reccnt; if (frlock == NULL) { fl->next = fl->prev = NULL; frlock = fl; } else { fl->next = frlock; fl->prev = NULL; frlock = (frlock->prev = fl); }}/* Adjust file lock from region specified by 'ld' starting at lock 'insrtp' */struct filock *ufs_flckadj(flip, insrtp, ld) struct flino *flip; struct filock *insrtp; register struct flock *ld;{ struct flock td; /* lock data for severed lock */ register struct filock *flp, *nflp, *tdi, *tdp; int insrtflg, rv = 0; register int regtyp; insrtflg = (ld->l_type != F_UNLCK) ? 1 : 0; nflp = (insrtp == NULL) ? flip->fl_flck : insrtp; while (flp = nflp) { nflp = flp->next; if (flp->set.l_pid == u.u_procp->p_pid) { regtyp = regflck(ld, flp); /* release already locked region if necessary */ switch (regtyp) { case S_BEFORE|E_BEFORE: nflp = NULL; break; case S_BEFORE|E_START: if (ld->l_type == flp->set.l_type) { ld->l_end = flp->set.l_end; if (insrtp == flp) insrtp = flp->prev; ufs_delflck(flip, flp); } nflp = NULL; break; case S_START|E_END: /* don't bother if this is in the middle of * an already similarly set section. */ if (ld->l_type == flp->set.l_type) return((struct filock *)rv); case S_START|E_AFTER: insrtp = flp->prev; ufs_delflck(flip, flp); break; case S_BEFORE|E_END: if (ld->l_type == flp->set.l_type) nflp = NULL; case S_BEFORE|E_AFTER: if (insrtp == flp) insrtp = flp->prev; ufs_delflck(flip, flp); break; case S_BEFORE|E_MIDDLE: if (ld->l_type == flp->set.l_type) ld->l_end = flp->set.l_end; else { /* setup piece after end of (un)lock */ td = flp->set; td.l_start = ld->l_end; tdp = tdi = flp; do { if (tdp->set.l_start < ld->l_start) tdi = tdp; else break; } while (tdp = tdp->next); if (ufs_insflck(flip, &td, tdi) == NULL) return((struct filock *)ENOSPC); } if (insrtp == flp) insrtp = flp->prev; ufs_delflck(flip, flp); nflp = NULL; break; case S_START|E_MIDDLE: case S_MIDDLE|E_MIDDLE: /* don't bother if this is in the middle of * an already similarly set section. */ if (ld->l_type == flp->set.l_type) return((struct filock *)rv); /* setup piece after end of (un)lock */ td = flp->set; td.l_start = ld->l_end; tdp = tdi = flp; do { if (tdp->set.l_start < ld->l_start) tdi = tdp; else break; } while (tdp = tdp->next); if (ufs_insflck(flip, &td, tdi) == NULL) return((struct filock *)ENOSPC); if (regtyp == (S_MIDDLE|E_MIDDLE)) { /* setup piece before (un)lock */ flp->set.l_end = ld->l_start; WAKEUP(flp); insrtp = flp; } else { insrtp = flp->prev; ufs_delflck(flip, flp); } nflp = NULL; break; case S_MIDDLE|E_END: /* don't bother if this is in the middle of * an already similarly set section. */ if (ld->l_type == flp->set.l_type) return((struct filock *)rv); flp->set.l_end = ld->l_start; WAKEUP(flp); insrtp = flp; break; case S_MIDDLE|E_AFTER: case S_END|E_AFTER: if (ld->l_type == flp->set.l_type) { ld->l_start = flp->set.l_start; insrtp = flp->prev; ufs_delflck(flip, flp); } else { flp->set.l_end = ld->l_start; WAKEUP(flp); insrtp = flp; } break; case S_AFTER|E_AFTER: insrtp = flp; break; } } else { if (flp->set.l_start > ld->l_end) nflp = NULL; } } if (insrtflg) { if (flp = insrtp) { do { if (flp->set.l_start < ld->l_start) insrtp = flp; else break; } while (flp = flp->next); } if (ufs_insflck(flip, ld, insrtp) == NULL) rv = ENOSPC; } return ((struct filock *)rv);}/* blocked checks whether a new lock (lckdat) would be * blocked by a previously set lock owned by another process. * When blocked is called, 'flp' should point * to the record from which the search should begin. * Insrt is set to point to the lock before which the new lock * is to be placed. */struct filock *ufs_blocked(flp, lckdat, insrt) register struct filock *flp; register struct flock *lckdat; register struct filock **insrt;{ register struct filock *f; *insrt = NULL; for (f = flp; f != NULL; f = f->next) { if (f->set.l_start < lckdat->l_start) *insrt = f; else break; if (f->set.l_pid == u.u_procp->p_pid) { if (lckdat->l_start <= f->set.l_end && lckdat->l_end >= f->set.l_start) { *insrt = f; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -