[BACK]Return to vfs_lockf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/vfs_lockf.c between version 1.48 and 1.48.4.1

version 1.48, 2005/12/24 19:12:23 version 1.48.4.1, 2006/09/09 02:57:17
Line 46  __KERNEL_RCSID(0, "$NetBSD$");
Line 46  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/pool.h>  #include <sys/pool.h>
 #include <sys/fcntl.h>  #include <sys/fcntl.h>
 #include <sys/lockf.h>  #include <sys/lockf.h>
   #include <sys/kauth.h>
   
 POOL_INIT(lockfpool, sizeof(struct lockf), 0, 0, 0, "lockfpl",  /*
    * The lockf structure is a kernel structure which contains the information
    * associated with a byte range lock.  The lockf structures are linked into
    * the inode structure. Locks are sorted by the starting byte of the lock for
    * efficiency.
    *
    * lf_next is used for two purposes, depending on whether the lock is
    * being held, or is in conflict with an existing lock.  If this lock
    * is held, it indicates the next lock on the same vnode.
    * For pending locks, if lock->lf_next is non-NULL, then lock->lf_block
    * must be queued on the lf_blkhd TAILQ of lock->lf_next.
    */
   
   TAILQ_HEAD(locklist, lockf);
   
   struct lockf {
           short   lf_flags;        /* Lock semantics: F_POSIX, F_FLOCK, F_WAIT */
           short   lf_type;         /* Lock type: F_RDLCK, F_WRLCK */
           off_t   lf_start;        /* The byte # of the start of the lock */
           off_t   lf_end;          /* The byte # of the end of the lock (-1=EOF)*/
           void    *lf_id;          /* process or file description holding lock */
           struct  lockf **lf_head; /* Back pointer to the head of lockf list */
           struct  lockf *lf_next;  /* Next lock on this vnode, or blocking lock */
           struct  locklist lf_blkhd; /* List of requests blocked on this lock */
           TAILQ_ENTRY(lockf) lf_block;/* A request waiting for a lock */
           uid_t   lf_uid;          /* User ID responsible */
   };
   
   /* Maximum length of sleep chains to traverse to try and detect deadlock. */
   #define MAXDEPTH 50
   
   static POOL_INIT(lockfpool, sizeof(struct lockf), 0, 0, 0, "lockfpl",
     &pool_allocator_nointr);      &pool_allocator_nointr);
   
 /*  /*
Line 60  int maxlockdepth = MAXDEPTH;
Line 92  int maxlockdepth = MAXDEPTH;
 int     lockf_debug = 0;  int     lockf_debug = 0;
 #endif  #endif
   
 #define NOLOCKF (struct lockf *)0  
 #define SELF    0x1  #define SELF    0x1
 #define OTHERS  0x2  #define OTHERS  0x2
   
Line 95  int maxlocksperuid = 1024;
Line 126  int maxlocksperuid = 1024;
  * Print out a lock.   * Print out a lock.
  */   */
 static void  static void
 lf_print(char *tag, struct lockf *lock)  lf_print(const char *tag, struct lockf *lock)
 {  {
   
         printf("%s: lock %p for ", tag, lock);          printf("%s: lock %p for ", tag, lock);
Line 115  lf_print(char *tag, struct lockf *lock)
Line 146  lf_print(char *tag, struct lockf *lock)
 }  }
   
 static void  static void
 lf_printlist(char *tag, struct lockf *lock)  lf_printlist(const char *tag, struct lockf *lock)
 {  {
         struct lockf *lf, *blk;          struct lockf *lf, *blk;
   
Line 202  lf_findoverlap(struct lockf *lf, struct 
Line 233  lf_findoverlap(struct lockf *lf, struct 
         off_t start, end;          off_t start, end;
   
         *overlap = lf;          *overlap = lf;
         if (lf == NOLOCKF)          if (lf == NULL)
                 return 0;                  return 0;
 #ifdef LOCKF_DEBUG  #ifdef LOCKF_DEBUG
         if (lockf_debug & 2)          if (lockf_debug & 2)
Line 210  lf_findoverlap(struct lockf *lf, struct 
Line 241  lf_findoverlap(struct lockf *lf, struct 
 #endif /* LOCKF_DEBUG */  #endif /* LOCKF_DEBUG */
         start = lock->lf_start;          start = lock->lf_start;
         end = lock->lf_end;          end = lock->lf_end;
         while (lf != NOLOCKF) {          while (lf != NULL) {
                 if (((type == SELF) && lf->lf_id != lock->lf_id) ||                  if (((type == SELF) && lf->lf_id != lock->lf_id) ||
                     ((type == OTHERS) && lf->lf_id == lock->lf_id)) {                      ((type == OTHERS) && lf->lf_id == lock->lf_id)) {
                         *prev = &lf->lf_next;                          *prev = &lf->lf_next;
Line 355  lf_wakelock(struct lockf *listhead)
Line 386  lf_wakelock(struct lockf *listhead)
         while ((wakelock = TAILQ_FIRST(&listhead->lf_blkhd))) {          while ((wakelock = TAILQ_FIRST(&listhead->lf_blkhd))) {
                 KASSERT(wakelock->lf_next == listhead);                  KASSERT(wakelock->lf_next == listhead);
                 TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block);                  TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block);
                 wakelock->lf_next = NOLOCKF;                  wakelock->lf_next = NULL;
 #ifdef LOCKF_DEBUG  #ifdef LOCKF_DEBUG
                 if (lockf_debug & 2)                  if (lockf_debug & 2)
                         lf_print("lf_wakelock: awakening", wakelock);                          lf_print("lf_wakelock: awakening", wakelock);
Line 378  lf_clearlock(struct lockf *unlock, struc
Line 409  lf_clearlock(struct lockf *unlock, struc
         struct lockf *overlap, **prev;          struct lockf *overlap, **prev;
         int ovcase;          int ovcase;
   
         if (lf == NOLOCKF)          if (lf == NULL)
                 return 0;                  return 0;
 #ifdef LOCKF_DEBUG  #ifdef LOCKF_DEBUG
         if (unlock->lf_type != F_UNLCK)          if (unlock->lf_type != F_UNLCK)
Line 457  lf_getblock(struct lockf *lock)
Line 488  lf_getblock(struct lockf *lock)
                  */                   */
                 lf = overlap->lf_next;                  lf = overlap->lf_next;
         }          }
         return NOLOCKF;          return NULL;
 }  }
   
 /*  /*
Line 511  lf_setlock(struct lockf *lock, struct lo
Line 542  lf_setlock(struct lockf *lock, struct lo
                         struct lwp *wlwp;                          struct lwp *wlwp;
                         volatile const struct lockf *waitblock;                          volatile const struct lockf *waitblock;
                         int i = 0;                          int i = 0;
                           struct proc *p;
   
                         /*                          p = (struct proc *)block->lf_id;
                          * The block is waiting on something.  if_lwp will be                          KASSERT(p != NULL);
                          * 0 once the lock is granted, so we terminate the                          while (i++ < maxlockdepth) {
                          * loop if we find this.                                  simple_lock(&p->p_lock);
                          */                                  if (p->p_nlwps > 1) {
                         wlwp = block->lf_lwp;                                          simple_unlock(&p->p_lock);
                         while (wlwp && (i++ < maxlockdepth)) {                                          break;
                                   }
                                   wlwp = LIST_FIRST(&p->p_lwps);
                                   if (wlwp->l_wmesg != lockstr) {
                                           simple_unlock(&p->p_lock);
                                           break;
                                   }
                                   simple_unlock(&p->p_lock);
                                 waitblock = wlwp->l_wchan;                                  waitblock = wlwp->l_wchan;
                                   if (waitblock == NULL) {
                                           /*
                                            * this lwp just got up but
                                            * not returned from ltsleep yet.
                                            */
                                           break;
                                   }
                                 /* Get the owner of the blocking lock */                                  /* Get the owner of the blocking lock */
                                 waitblock = waitblock->lf_next;                                  waitblock = waitblock->lf_next;
                                 if ((waitblock->lf_flags & F_POSIX) == 0)                                  if ((waitblock->lf_flags & F_POSIX) == 0)
                                         break;                                          break;
                                 wlwp = waitblock->lf_lwp;                                  p = (struct proc *)waitblock->lf_id;
                                 if (wlwp == lock->lf_lwp) {                                  if (p == curproc) {
                                         lf_free(lock);                                          lf_free(lock);
                                         return EDEADLK;                                          return EDEADLK;
                                 }                                  }
Line 571  lf_setlock(struct lockf *lock, struct lo
Line 617  lf_setlock(struct lockf *lock, struct lo
                  * blocked list) and/or by another process                   * blocked list) and/or by another process
                  * releasing a lock (in which case we have already                   * releasing a lock (in which case we have already
                  * been removed from the blocked list and our                   * been removed from the blocked list and our
                  * lf_next field set to NOLOCKF).                   * lf_next field set to NULL).
                  */                   */
                 if (lock->lf_next != NOLOCKF) {                  if (lock->lf_next != NULL) {
                         TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, lf_block);                          TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, lf_block);
                         lock->lf_next = NOLOCKF;                          lock->lf_next = NULL;
                 }                  }
                 if (error) {                  if (error) {
                         lf_free(lock);                          lf_free(lock);
Line 590  lf_setlock(struct lockf *lock, struct lo
Line 636  lf_setlock(struct lockf *lock, struct lo
          * Skip over locks owned by other processes.           * Skip over locks owned by other processes.
          * Handle any locks that overlap and are owned by ourselves.           * Handle any locks that overlap and are owned by ourselves.
          */           */
         lock->lf_lwp = 0;  
         prev = head;          prev = head;
         block = *head;          block = *head;
         needtolink = 1;          needtolink = 1;
Line 750  lf_getlock(struct lockf *lock, struct fl
Line 795  lf_getlock(struct lockf *lock, struct fl
 int  int
 lf_advlock(struct vop_advlock_args *ap, struct lockf **head, off_t size)  lf_advlock(struct vop_advlock_args *ap, struct lockf **head, off_t size)
 {  {
         struct proc *p = curproc;          struct lwp *l = curlwp;
         struct flock *fl = ap->a_fl;          struct flock *fl = ap->a_fl;
         struct lockf *lock = NULL;          struct lockf *lock = NULL;
         struct lockf *sparelock;          struct lockf *sparelock;
Line 782  lf_advlock(struct vop_advlock_args *ap, 
Line 827  lf_advlock(struct vop_advlock_args *ap, 
                 return EINVAL;                  return EINVAL;
   
         /*          /*
          * allocate locks before acquire simple lock.           * Allocate locks before acquiring the simple lock.  We need two
          * we need two locks in the worst case.           * locks in the worst case.
          */           */
         switch (ap->a_op) {          switch (ap->a_op) {
         case F_SETLK:          case F_SETLK:
         case F_UNLCK:          case F_UNLCK:
                 /*                  /*
                  * XXX for F_UNLCK case, we can re-use lock.                   * XXX For F_UNLCK case, we can re-use the lock.
                  */                   */
                 if ((ap->a_flags & F_FLOCK) == 0) {                  if ((ap->a_flags & F_FLOCK) == 0) {
                         /*                          /*
                          * byte-range lock might need one more lock.                           * Byte-range lock might need one more lock.
                          */                           */
                         sparelock = lf_alloc(p->p_ucred->cr_uid, 0);                          sparelock = lf_alloc(kauth_cred_geteuid(l->l_cred), 0);
                         if (sparelock == NULL) {                          if (sparelock == NULL) {
                                 error = ENOMEM;                                  error = ENOMEM;
                                 goto quit;                                  goto quit;
Line 812  lf_advlock(struct vop_advlock_args *ap, 
Line 857  lf_advlock(struct vop_advlock_args *ap, 
                 return EINVAL;                  return EINVAL;
         }          }
   
         lock = lf_alloc(p->p_ucred->cr_uid, ap->a_op != F_UNLCK ? 1 : 2);          lock = lf_alloc(kauth_cred_geteuid(l->l_cred),
               ap->a_op != F_UNLCK ? 1 : 2);
         if (lock == NULL) {          if (lock == NULL) {
                 error = ENOMEM;                  error = ENOMEM;
                 goto quit;                  goto quit;
Line 855  lf_advlock(struct vop_advlock_args *ap, 
Line 901  lf_advlock(struct vop_advlock_args *ap, 
                 KASSERT(curproc == (struct proc *)ap->a_id);                  KASSERT(curproc == (struct proc *)ap->a_id);
         }          }
         lock->lf_id = (struct proc *)ap->a_id;          lock->lf_id = (struct proc *)ap->a_id;
         lock->lf_lwp = curlwp;  
   
         /*          /*
          * Do the requested operation.           * Do the requested operation.

Legend:
Removed from v.1.48  
changed lines
  Added in v.1.48.4.1

CVSweb <webmaster@jp.NetBSD.org>