The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/hfs/hfs_lockf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1999,2001-2002 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 
   26 /*      (c) 1997-1998,2001 Apple Computer, Inc.  All Rights Reserved */
   27 /*
   28  * Copyright (c) 1982, 1986, 1989, 1993
   29  *      The Regents of the University of California.  All rights reserved.
   30  *
   31  * This code is derived from software contributed to Berkeley by
   32  * Scooter Morris at Genentech Inc.
   33  *
   34  * Redistribution and use in source and binary forms, with or without
   35  * modification, are permitted provided that the following conditions
   36  * are met:
   37  * 1. Redistributions of source code must retain the above copyright
   38  *    notice, this list of conditions and the following disclaimer.
   39  * 2. Redistributions in binary form must reproduce the above copyright
   40  *    notice, this list of conditions and the following disclaimer in the
   41  *    documentation and/or other materials provided with the distribution.
   42  * 3. All advertising materials mentioning features or use of this software
   43  *    must display the following acknowledgement:
   44  *      This product includes software developed by the University of
   45  *      California, Berkeley and its contributors.
   46  * 4. Neither the name of the University nor the names of its contributors
   47  *    may be used to endorse or promote products derived from this software
   48  *    without specific prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   60  * SUCH DAMAGE.
   61  *
   62  *      @(#)hfs_lockf.c 1.0
   63  *      derived from @(#)ufs_lockf.c    8.4 (Berkeley) 10/26/94
   64  */
   65 
   66 #include <sys/param.h>
   67 #include <sys/systm.h>
   68 #include <sys/kernel.h>
   69 #include <sys/file.h>
   70 #include <sys/proc.h>
   71 #include <sys/vnode.h>
   72 #include <sys/malloc.h>
   73 #include <sys/fcntl.h>
   74 
   75 #include "hfs_cnode.h"
   76 #include "hfs_lockf.h"
   77 
   78 /*
   79  * This variable controls the maximum number of processes that will
   80  * be checked in doing deadlock detection.
   81  */
   82 int hfsmaxlockdepth = MAXDEPTH;
   83 
   84 #ifdef LOCKF_DEBUG
   85 #include <vm/vm.h>
   86 #include <sys/sysctl.h>
   87 int     lockf_debug = 0;
   88 struct ctldebug debug4 = { "lockf_debug", &lockf_debug };
   89 #endif
   90 
   91 #define NOLOCKF (struct hfslockf *)0
   92 #define SELF    0x1
   93 #define OTHERS  0x2
   94 
   95 /*
   96  * Set a byte-range lock.
   97  */
   98 int
   99 hfs_setlock(lock)
  100         register struct hfslockf *lock;
  101 {
  102         register struct hfslockf *block;
  103         struct filefork *fork = lock->lf_fork;
  104         struct hfslockf **prev, *overlap, *ltmp;
  105         static char lockstr[] = "hfslockf";
  106         int ovcase, priority, needtolink, error;
  107 
  108 #ifdef LOCKF_DEBUG
  109         if (lockf_debug & 1)
  110                 hfs_lprint("hfs_setlock", lock);
  111 #endif /* LOCKF_DEBUG */
  112 
  113         /*
  114          * Set the priority
  115          */
  116         priority = PLOCK;
  117         if (lock->lf_type == F_WRLCK)
  118                 priority += 4;
  119         priority |= PCATCH;
  120         /*
  121          * Scan lock list for this file looking for locks that would block us.
  122          */
  123         while ((block = hfs_getblock(lock))) {
  124                 /*
  125                  * Free the structure and return if nonblocking.
  126                  */
  127                 if ((lock->lf_flags & F_WAIT) == 0) {
  128                         FREE(lock, M_LOCKF);
  129                         return (EAGAIN);
  130                 }
  131                 /*
  132                  * We are blocked. Since flock style locks cover
  133                  * the whole file, there is no chance for deadlock.
  134                  * For byte-range locks we must check for deadlock.
  135                  *
  136                  * Deadlock detection is done by looking through the
  137                  * wait channels to see if there are any cycles that
  138                  * involve us. MAXDEPTH is set just to make sure we
  139                  * do not go off into neverland.
  140                  */
  141                 if ((lock->lf_flags & F_POSIX) &&
  142                     (block->lf_flags & F_POSIX)) {
  143                         register struct proc *wproc;
  144                         register struct hfslockf *waitblock;
  145                         int i = 0;
  146 
  147                         /* The block is waiting on something */
  148                         wproc = (struct proc *)block->lf_id;
  149                         while (wproc->p_wchan &&
  150                                (wproc->p_wmesg == lockstr) &&
  151                                (i++ < hfsmaxlockdepth)) {
  152                                 waitblock = (struct hfslockf *)wproc->p_wchan;
  153                                 /* Get the owner of the blocking lock */
  154                                 waitblock = waitblock->lf_next;
  155                                 if ((waitblock->lf_flags & F_POSIX) == 0)
  156                                         break;
  157                                 wproc = (struct proc *)waitblock->lf_id;
  158                                 if (wproc == (struct proc *)lock->lf_id) {
  159                                         _FREE(lock, M_LOCKF);
  160                                         return (EDEADLK);
  161                                 }
  162                         }
  163                 }
  164                 /*
  165                  * For flock type locks, we must first remove
  166                  * any shared locks that we hold before we sleep
  167                  * waiting for an exclusive lock.
  168                  */
  169                 if ((lock->lf_flags & F_FLOCK) &&
  170                     lock->lf_type == F_WRLCK) {
  171                         lock->lf_type = F_UNLCK;
  172                         (void) hfs_clearlock(lock);
  173                         lock->lf_type = F_WRLCK;
  174                 }
  175                 /*
  176                  * Add our lock to the blocked list and sleep until we're free.
  177                  * Remember who blocked us (for deadlock detection).
  178                  */
  179                 lock->lf_next = block;
  180                 TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block);
  181 #ifdef LOCKF_DEBUG
  182                 if (lockf_debug & 1) {
  183                         hfs_lprint("hfs_setlock: blocking on", block);
  184                         hfs_lprintlist("hfs_setlock", block);
  185                 }
  186 #endif /* LOCKF_DEBUG */
  187                 if ((error = tsleep((caddr_t)lock, priority, lockstr, 0))) {
  188                         /*
  189                          * We may have been awakened by a signal (in
  190                          * which case we must remove ourselves from the
  191                          * blocked list) and/or by another process
  192                          * releasing a lock (in which case we have already
  193                          * been removed from the blocked list and our
  194                          * lf_next field set to NOLOCKF).
  195                          */
  196                         if (lock->lf_next)
  197                                 TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock,
  198                                     lf_block);
  199                         _FREE(lock, M_LOCKF);
  200                         return (error);
  201                 }
  202         }
  203         /*
  204          * No blocks!!  Add the lock.  Note that we will
  205          * downgrade or upgrade any overlapping locks this
  206          * process already owns.
  207          *
  208          * Skip over locks owned by other processes.
  209          * Handle any locks that overlap and are owned by ourselves.
  210          */
  211         prev = &fork->ff_lockf;
  212         block = fork->ff_lockf;
  213         needtolink = 1;
  214         for (;;) {
  215                 if ((ovcase = hfs_findoverlap(block, lock, SELF, &prev, &overlap)))
  216                         block = overlap->lf_next;
  217                 /*
  218                  * Six cases:
  219                  *      0) no overlap
  220                  *      1) overlap == lock
  221                  *      2) overlap contains lock
  222                  *      3) lock contains overlap
  223                  *      4) overlap starts before lock
  224                  *      5) overlap ends after lock
  225                  */
  226                 switch (ovcase) {
  227                 case 0: /* no overlap */
  228                         if (needtolink) {
  229                                 *prev = lock;
  230                                 lock->lf_next = overlap;
  231                         }
  232                         break;
  233 
  234                 case 1: /* overlap == lock */
  235                         /*
  236                          * If downgrading lock, others may be
  237                          * able to acquire it.
  238                          */
  239                         if (lock->lf_type == F_RDLCK &&
  240                             overlap->lf_type == F_WRLCK)
  241                                 hfs_wakelock(overlap);
  242                         overlap->lf_type = lock->lf_type;
  243                         FREE(lock, M_LOCKF);
  244                         lock = overlap; /* for debug output below */
  245                         break;
  246 
  247                 case 2: /* overlap contains lock */
  248                         /*
  249                          * Check for common starting point and different types.
  250                          */
  251                         if (overlap->lf_type == lock->lf_type) {
  252                                 _FREE(lock, M_LOCKF);
  253                                 lock = overlap; /* for debug output below */
  254                                 break;
  255                         }
  256                         if (overlap->lf_start == lock->lf_start) {
  257                                 *prev = lock;
  258                                 lock->lf_next = overlap;
  259                                 overlap->lf_start = lock->lf_end + 1;
  260                         } else
  261                                 hfs_split(overlap, lock);
  262                         hfs_wakelock(overlap);
  263                         break;
  264 
  265                 case 3: /* lock contains overlap */
  266                         /*
  267                          * If downgrading lock, others may be able to
  268                          * acquire it, otherwise take the list.
  269                          */
  270                         if (lock->lf_type == F_RDLCK &&
  271                             overlap->lf_type == F_WRLCK) {
  272                                 hfs_wakelock(overlap);
  273                         } else {
  274                                 while ((ltmp = overlap->lf_blkhd.tqh_first)) {
  275                                         TAILQ_REMOVE(&overlap->lf_blkhd, ltmp,
  276                                             lf_block);
  277                                         TAILQ_INSERT_TAIL(&lock->lf_blkhd,
  278                                             ltmp, lf_block);
  279                                 }
  280                         }
  281                         /*
  282                          * Add the new lock if necessary and delete the overlap.
  283                          */
  284                         if (needtolink) {
  285                                 *prev = lock;
  286                                 lock->lf_next = overlap->lf_next;
  287                                 prev = &lock->lf_next;
  288                                 needtolink = 0;
  289                         } else
  290                                 *prev = overlap->lf_next;
  291                         _FREE(overlap, M_LOCKF);
  292                         continue;
  293 
  294                 case 4: /* overlap starts before lock */
  295                         /*
  296                          * Add lock after overlap on the list.
  297                          */
  298                         lock->lf_next = overlap->lf_next;
  299                         overlap->lf_next = lock;
  300                         overlap->lf_end = lock->lf_start - 1;
  301                         prev = &lock->lf_next;
  302                         hfs_wakelock(overlap);
  303                         needtolink = 0;
  304                         continue;
  305 
  306                 case 5: /* overlap ends after lock */
  307                         /*
  308                          * Add the new lock before overlap.
  309                          */
  310                         if (needtolink) {
  311                                 *prev = lock;
  312                                 lock->lf_next = overlap;
  313                         }
  314                         overlap->lf_start = lock->lf_end + 1;
  315                         hfs_wakelock(overlap);
  316                         break;
  317                 }
  318                 break;
  319         }
  320 #ifdef LOCKF_DEBUG
  321         if (lockf_debug & 1) {
  322                 hfs_lprint("hfs_setlock: got the lock", lock);
  323                 hfs_lprintlist("hfs_setlock", lock);
  324         }
  325 #endif /* LOCKF_DEBUG */
  326         return (0);
  327 }
  328 
  329 /*
  330  * Remove a file fork's byte-range lock.
  331  *
  332  * Generally, find the lock (or an overlap to that lock)
  333  * and remove it (or shrink it), then wakeup anyone we can.
  334  */
  335 int
  336 hfs_clearlock(unlock)
  337         register struct hfslockf *unlock;
  338 {
  339         struct filefork *fork = unlock->lf_fork;
  340         register struct hfslockf *lf = fork->ff_lockf;
  341         struct hfslockf *overlap, **prev;
  342         int ovcase;
  343 
  344         if (lf == NOLOCKF)
  345                 return (0);
  346 #ifdef LOCKF_DEBUG
  347         if (unlock->lf_type != F_UNLCK)
  348                 panic("hfs_clearlock: bad type");
  349         if (lockf_debug & 1)
  350                 hfs_lprint("hfs_clearlock", unlock);
  351 #endif /* LOCKF_DEBUG */
  352         prev = &fork->ff_lockf;
  353         while ((ovcase = hfs_findoverlap(lf, unlock, SELF, &prev, &overlap))) {
  354                 /*
  355                  * Wakeup the list of locks to be retried.
  356                  */
  357                 hfs_wakelock(overlap);
  358 
  359                 switch (ovcase) {
  360 
  361                 case 1: /* overlap == lock */
  362                         *prev = overlap->lf_next;
  363                         FREE(overlap, M_LOCKF);
  364                         break;
  365 
  366                 case 2: /* overlap contains lock: split it */
  367                         if (overlap->lf_start == unlock->lf_start) {
  368                                 overlap->lf_start = unlock->lf_end + 1;
  369                                 break;
  370                         }
  371                         hfs_split(overlap, unlock);
  372                         overlap->lf_next = unlock->lf_next;
  373                         break;
  374 
  375                 case 3: /* lock contains overlap */
  376                         *prev = overlap->lf_next;
  377                         lf = overlap->lf_next;
  378                         _FREE(overlap, M_LOCKF);
  379                         continue;
  380 
  381                 case 4: /* overlap starts before lock */
  382                         overlap->lf_end = unlock->lf_start - 1;
  383                         prev = &overlap->lf_next;
  384                         lf = overlap->lf_next;
  385                         continue;
  386 
  387                 case 5: /* overlap ends after lock */
  388                         overlap->lf_start = unlock->lf_end + 1;
  389                         break;
  390                 }
  391                 break;
  392         }
  393 #ifdef LOCKF_DEBUG
  394         if (lockf_debug & 1)
  395                 hfs_lprintlist("hfs_clearlock", unlock);
  396 #endif /* LOCKF_DEBUG */
  397         return (0);
  398 }
  399 
  400 /*
  401  * Check whether there is a blocking lock,
  402  * and if so return its process identifier.
  403  */
  404 int
  405 hfs_getlock(lock, fl)
  406         register struct hfslockf *lock;
  407         register struct flock *fl;
  408 {
  409         register struct hfslockf *block;
  410 
  411 #ifdef LOCKF_DEBUG
  412         if (lockf_debug & 1)
  413                 hfs_lprint("hfs_getlock", lock);
  414 #endif /* LOCKF_DEBUG */
  415 
  416         if ((block = hfs_getblock(lock))) {
  417                 fl->l_type = block->lf_type;
  418                 fl->l_whence = SEEK_SET;
  419                 fl->l_start = block->lf_start;
  420                 if (block->lf_end == -1)
  421                         fl->l_len = 0;
  422                 else
  423                         fl->l_len = block->lf_end - block->lf_start + 1;
  424                 if (block->lf_flags & F_POSIX)
  425                         fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;
  426                 else
  427                         fl->l_pid = -1;
  428         } else {
  429                 fl->l_type = F_UNLCK;
  430         }
  431         return (0);
  432 }
  433 
  434 /*
  435  * Walk a file fork's list of locks and
  436  * return the first blocking lock.
  437  */
  438 struct hfslockf *
  439 hfs_getblock(lock)
  440         register struct hfslockf *lock;
  441 {
  442         struct hfslockf **prev, *overlap, *lf = lock->lf_fork->ff_lockf;
  443         int ovcase;
  444 
  445         prev = &lock->lf_fork->ff_lockf;
  446         while ((ovcase = hfs_findoverlap(lf, lock, OTHERS, &prev, &overlap))) {
  447                 /*
  448                  * We've found an overlap, see if it blocks us
  449                  */
  450                 if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
  451                         return (overlap);
  452                 /*
  453                  * Nope, point to the next one on the list and
  454                  * see if it blocks us
  455                  */
  456                 lf = overlap->lf_next;
  457         }
  458         return (NOLOCKF);
  459 }
  460 
  461 /*
  462  * Walk a file fork's list of locks to
  463  * find an overlapping lock (if any).
  464  *
  465  * NOTE: this returns only the FIRST overlapping lock.  There
  466  *       may be more than one.
  467  */
  468 int
  469 hfs_findoverlap(lf, lock, type, prev, overlap)
  470         register struct hfslockf *lf;
  471         struct hfslockf *lock;
  472         int type;
  473         struct hfslockf ***prev;
  474         struct hfslockf **overlap;
  475 {
  476         off_t start, end;
  477 
  478         *overlap = lf;
  479         if (lf == NOLOCKF)
  480                 return (0);
  481 #ifdef LOCKF_DEBUG
  482         if (lockf_debug & 2)
  483                 hfs_lprint("hfs_findoverlap: looking for overlap in", lock);
  484 #endif /* LOCKF_DEBUG */
  485         start = lock->lf_start;
  486         end = lock->lf_end;
  487         while (lf != NOLOCKF) {
  488                 if (((type & SELF) && lf->lf_id != lock->lf_id) ||
  489                     ((type & OTHERS) && lf->lf_id == lock->lf_id)) {
  490                         *prev = &lf->lf_next;
  491                         *overlap = lf = lf->lf_next;
  492                         continue;
  493                 }
  494 #ifdef LOCKF_DEBUG
  495                 if (lockf_debug & 2)
  496                         hfs_lprint("\tchecking", lf);
  497 #endif /* LOCKF_DEBUG */
  498                 /*
  499                  * OK, check for overlap
  500                  *
  501                  * Six cases:
  502                  *      0) no overlap
  503                  *      1) overlap == lock
  504                  *      2) overlap contains lock
  505                  *      3) lock contains overlap
  506                  *      4) overlap starts before lock
  507                  *      5) overlap ends after lock
  508                  */
  509                 if ((lf->lf_end != -1 && start > lf->lf_end) ||
  510                     (end != -1 && lf->lf_start > end)) {
  511                         /* Case 0 */
  512 #ifdef LOCKF_DEBUG
  513                         if (lockf_debug & 2)
  514                                 printf("no overlap\n");
  515 #endif /* LOCKF_DEBUG */
  516                         if ((type & SELF) && end != -1 && lf->lf_start > end)
  517                                 return (0);
  518                         *prev = &lf->lf_next;
  519                         *overlap = lf = lf->lf_next;
  520                         continue;
  521                 }
  522                 if ((lf->lf_start == start) && (lf->lf_end == end)) {
  523                         /* Case 1 */
  524 #ifdef LOCKF_DEBUG
  525                         if (lockf_debug & 2)
  526                                 printf("overlap == lock\n");
  527 #endif /* LOCKF_DEBUG */
  528                         return (1);
  529                 }
  530                 if ((lf->lf_start <= start) &&
  531                     (end != -1) &&
  532                     ((lf->lf_end >= end) || (lf->lf_end == -1))) {
  533                         /* Case 2 */
  534 #ifdef LOCKF_DEBUG
  535                         if (lockf_debug & 2)
  536                                 printf("overlap contains lock\n");
  537 #endif /* LOCKF_DEBUG */
  538                         return (2);
  539                 }
  540                 if (start <= lf->lf_start &&
  541                            (end == -1 ||
  542                            (lf->lf_end != -1 && end >= lf->lf_end))) {
  543                         /* Case 3 */
  544 #ifdef LOCKF_DEBUG
  545                         if (lockf_debug & 2)
  546                                 printf("lock contains overlap\n");
  547 #endif /* LOCKF_DEBUG */
  548                         return (3);
  549                 }
  550                 if ((lf->lf_start < start) &&
  551                         ((lf->lf_end >= start) || (lf->lf_end == -1))) {
  552                         /* Case 4 */
  553 #ifdef LOCKF_DEBUG
  554                         if (lockf_debug & 2)
  555                                 printf("overlap starts before lock\n");
  556 #endif /* LOCKF_DEBUG */
  557                         return (4);
  558                 }
  559                 if ((lf->lf_start > start) &&
  560                         (end != -1) &&
  561                         ((lf->lf_end > end) || (lf->lf_end == -1))) {
  562                         /* Case 5 */
  563 #ifdef LOCKF_DEBUG
  564                         if (lockf_debug & 2)
  565                                 printf("overlap ends after lock\n");
  566 #endif /* LOCKF_DEBUG */
  567                         return (5);
  568                 }
  569                 panic("hfs_findoverlap: default");
  570         }
  571         return (0);
  572 }
  573 
  574 /*
  575  * Split a lock and a contained region into
  576  * two or three locks as necessary.
  577  */
  578 void
  579 hfs_split(lock1, lock2)
  580         register struct hfslockf *lock1;
  581         register struct hfslockf *lock2;
  582 {
  583         register struct hfslockf *splitlock;
  584 
  585 #ifdef LOCKF_DEBUG
  586         if (lockf_debug & 2) {
  587                 hfs_lprint("hfs_split", lock1);
  588                 hfs_lprint("splitting from", lock2);
  589         }
  590 #endif /* LOCKF_DEBUG */
  591         /*
  592          * Check to see if spliting into only two pieces.
  593          */
  594         if (lock1->lf_start == lock2->lf_start) {
  595                 lock1->lf_start = lock2->lf_end + 1;
  596                 lock2->lf_next = lock1;
  597                 return;
  598         }
  599         if (lock1->lf_end == lock2->lf_end) {
  600                 lock1->lf_end = lock2->lf_start - 1;
  601                 lock2->lf_next = lock1->lf_next;
  602                 lock1->lf_next = lock2;
  603                 return;
  604         }
  605         /*
  606          * Make a new lock consisting of the last part of
  607          * the encompassing lock
  608          */
  609         MALLOC(splitlock, struct hfslockf *, sizeof *splitlock, M_LOCKF, M_WAITOK);
  610         bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock);
  611         splitlock->lf_start = lock2->lf_end + 1;
  612         TAILQ_INIT(&splitlock->lf_blkhd);
  613         lock1->lf_end = lock2->lf_start - 1;
  614         /*
  615          * OK, now link it in
  616          */
  617         splitlock->lf_next = lock1->lf_next;
  618         lock2->lf_next = splitlock;
  619         lock1->lf_next = lock2;
  620 }
  621 
  622 /*
  623  * Wakeup a blocklist
  624  */
  625 void
  626 hfs_wakelock(listhead)
  627         struct hfslockf *listhead;
  628 {
  629         register struct hfslockf *wakelock;
  630 
  631         while ((wakelock = listhead->lf_blkhd.tqh_first)) {
  632                 TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block);
  633                 wakelock->lf_next = NOLOCKF;
  634 #ifdef LOCKF_DEBUG
  635                 if (lockf_debug & 2)
  636                         hfs_lprint("hfs_wakelock: awakening", wakelock);
  637 #endif /* LOCKF_DEBUG */
  638                 wakeup((caddr_t)wakelock);
  639         }
  640 }
  641 
  642 #ifdef LOCKF_DEBUG
  643 /*
  644  * Print out a lock.
  645  */
  646 hfs_lprint(tag, lock)
  647         char *tag;
  648         register struct hfslockf *lock;
  649 {
  650         
  651         printf("%s: lock 0x%lx for ", tag, lock);
  652         if (lock->lf_flags & F_POSIX)
  653                 printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid);
  654         else
  655                 printf("id 0x%x", lock->lf_id);
  656         printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d",
  657                 FTOC(lock->lf_fork)->c_fileid,
  658                 major(FTOC(lock->lf_fork)->c_dev),
  659                 minor(FTOC(lock->lf_fork)->c_dev),
  660                 lock->lf_type == F_RDLCK ? "shared" :
  661                 lock->lf_type == F_WRLCK ? "exclusive" :
  662                 lock->lf_type == F_UNLCK ? "unlock" :
  663                 "unknown", lock->lf_start, lock->lf_end);
  664         if (lock->lf_blkhd.tqh_first)
  665                 printf(" block 0x%x\n", lock->lf_blkhd.tqh_first);
  666         else
  667                 printf("\n");
  668 }
  669 
  670 hfs_lprintlist(tag, lock)
  671         char *tag;
  672         struct hfslockf *lock;
  673 {
  674         register struct hfslockf *lf, *blk;
  675 
  676         printf("%s: Lock list for ino %d on dev <%d, %d>:\n",
  677                 tag, FTOC(lock->lf_fork)->i_number,
  678                 major(FTOC(lock->lf_fork)->c_dev),
  679                 minor(FTOC(lock->lf_fork)->c_dev));
  680         for (lf = lock->lf_fork->ff_lockf; lf; lf = lf->lf_next) {
  681                 printf("\tlock 0x%lx for ", lf);
  682                 if (lf->lf_flags & F_POSIX)
  683                         printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid);
  684                 else
  685                         printf("id 0x%x", lf->lf_id);
  686                 printf(", %s, start %d, end %d",
  687                         lf->lf_type == F_RDLCK ? "shared" :
  688                         lf->lf_type == F_WRLCK ? "exclusive" :
  689                         lf->lf_type == F_UNLCK ? "unlock" :
  690                         "unknown", lf->lf_start, lf->lf_end);
  691                 for (blk = lf->lf_blkhd.tqh_first; blk;
  692                      blk = blk->lf_block.tqe_next) {
  693                         printf("\n\t\tlock request 0x%lx for ", blk);
  694                         if (blk->lf_flags & F_POSIX)
  695                                 printf("proc %d",
  696                                     ((struct proc *)(blk->lf_id))->p_pid);
  697                         else
  698                                 printf("id 0x%x", blk->lf_id);
  699                         printf(", %s, start %d, end %d",
  700                                 blk->lf_type == F_RDLCK ? "shared" :
  701                                 blk->lf_type == F_WRLCK ? "exclusive" :
  702                                 blk->lf_type == F_UNLCK ? "unlock" :
  703                                 "unknown", blk->lf_start, blk->lf_end);
  704                         if (blk->lf_blkhd.tqh_first)
  705                                 panic("hfs_lprintlist: bad list");
  706                 }
  707                 printf("\n");
  708         }
  709 }
  710 #endif /* LOCKF_DEBUG */

Cache object: 3d6821e022b5c737b87a188af82cedb2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.