"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/xlators/features/locks/src/reservelk.c" (16 Sep 2020, 10627 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "reservelk.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2    Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com>
    3    This file is part of GlusterFS.
    4 
    5    This file is licensed to you under your choice of the GNU Lesser
    6    General Public License, version 3 or any later version (LGPLv3 or
    7    later), or the GNU General Public License, version 2 (GPLv2), in all
    8    cases as published by the Free Software Foundation.
    9 */
   10 #include <glusterfs/glusterfs.h>
   11 #include <glusterfs/compat.h>
   12 #include <glusterfs/xlator.h>
   13 #include <glusterfs/logging.h>
   14 #include <glusterfs/common-utils.h>
   15 #include <glusterfs/list.h>
   16 
   17 #include "locks.h"
   18 #include "common.h"
   19 
   20 /* Return true if the two reservelks have exactly same lock boundaries */
   21 int
   22 reservelks_equal(posix_lock_t *l1, posix_lock_t *l2)
   23 {
   24     if ((l1->fl_start == l2->fl_start) && (l1->fl_end == l2->fl_end))
   25         return 1;
   26 
   27     return 0;
   28 }
   29 
   30 /* Determine if lock is grantable or not */
   31 static posix_lock_t *
   32 __reservelk_grantable(pl_inode_t *pl_inode, posix_lock_t *lock)
   33 {
   34     xlator_t *this = THIS;
   35     posix_lock_t *l = NULL;
   36     posix_lock_t *ret_lock = NULL;
   37 
   38     if (list_empty(&pl_inode->reservelk_list)) {
   39         gf_log(this->name, GF_LOG_TRACE, "No reservelks in list");
   40         goto out;
   41     }
   42     list_for_each_entry(l, &pl_inode->reservelk_list, list)
   43     {
   44         if (reservelks_equal(lock, l)) {
   45             ret_lock = l;
   46             break;
   47         }
   48     }
   49 out:
   50     return ret_lock;
   51 }
   52 
   53 static int
   54 __same_owner_reservelk(posix_lock_t *l1, posix_lock_t *l2)
   55 {
   56     return (is_same_lkowner(&l1->owner, &l2->owner));
   57 }
   58 
   59 static posix_lock_t *
   60 __matching_reservelk(pl_inode_t *pl_inode, posix_lock_t *lock)
   61 {
   62     posix_lock_t *l = NULL;
   63 
   64     if (list_empty(&pl_inode->reservelk_list)) {
   65         gf_log("posix-locks", GF_LOG_TRACE, "reservelk list empty");
   66         return NULL;
   67     }
   68 
   69     list_for_each_entry(l, &pl_inode->reservelk_list, list)
   70     {
   71         if (reservelks_equal(l, lock)) {
   72             gf_log("posix-locks", GF_LOG_TRACE, "equal reservelk found");
   73             break;
   74         }
   75     }
   76 
   77     return l;
   78 }
   79 
   80 static int
   81 __reservelk_conflict(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock)
   82 {
   83     int ret = 0;
   84 
   85     posix_lock_t *conf = __matching_reservelk(pl_inode, lock);
   86     if (conf) {
   87         gf_log(this->name, GF_LOG_TRACE, "Matching reservelk found");
   88         if (__same_owner_reservelk(lock, conf)) {
   89             list_del_init(&conf->list);
   90             gf_log(this->name, GF_LOG_TRACE,
   91                    "Removing the matching reservelk for setlk to progress");
   92             __destroy_lock(conf);
   93             ret = 0;
   94         } else {
   95             gf_log(this->name, GF_LOG_TRACE, "Conflicting reservelk found");
   96             ret = 1;
   97         }
   98     }
   99     return ret;
  100 }
  101 
  102 int
  103 pl_verify_reservelk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock,
  104                     const int can_block)
  105 {
  106     int ret = 0;
  107 
  108     pthread_mutex_lock(&pl_inode->mutex);
  109     {
  110         if (__reservelk_conflict(this, pl_inode, lock)) {
  111             lock->blocked = can_block;
  112             list_add_tail(&lock->list, &pl_inode->blocked_calls);
  113             pthread_mutex_unlock(&pl_inode->mutex);
  114             gf_log(this->name, GF_LOG_TRACE,
  115                    "Found conflicting reservelk. Blocking until reservelk is "
  116                    "unlocked.");
  117             ret = -1;
  118             goto out;
  119         }
  120     }
  121     pthread_mutex_unlock(&pl_inode->mutex);
  122     gf_log(this->name, GF_LOG_TRACE,
  123            "no conflicting reservelk found. Call continuing");
  124     ret = 0;
  125 out:
  126     return ret;
  127 }
  128 
  129 /* Determines if lock can be granted and adds the lock. If the lock
  130  * is blocking, adds it to the blocked_reservelks.
  131  */
  132 static int
  133 __lock_reservelk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock,
  134                  const int can_block)
  135 {
  136     int ret = -EINVAL;
  137 
  138     posix_lock_t *conf = __reservelk_grantable(pl_inode, lock);
  139     if (conf) {
  140         ret = -EAGAIN;
  141         if (can_block == 0)
  142             goto out;
  143 
  144         list_add_tail(&lock->list, &pl_inode->blocked_reservelks);
  145 
  146         gf_log(this->name, GF_LOG_TRACE,
  147                "%s (pid=%d) lk-owner:%s %" PRId64 " - %" PRId64 " => Blocked",
  148                lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid,
  149                lkowner_utoa(&lock->owner), lock->user_flock.l_start,
  150                lock->user_flock.l_len);
  151 
  152         goto out;
  153     }
  154 
  155     list_add(&lock->list, &pl_inode->reservelk_list);
  156 
  157     ret = 0;
  158 
  159 out:
  160     return ret;
  161 }
  162 
  163 static posix_lock_t *
  164 find_matching_reservelk(posix_lock_t *lock, pl_inode_t *pl_inode)
  165 {
  166     posix_lock_t *l = NULL;
  167     list_for_each_entry(l, &pl_inode->reservelk_list, list)
  168     {
  169         if (reservelks_equal(l, lock))
  170             return l;
  171     }
  172     return NULL;
  173 }
  174 
  175 /* Set F_UNLCK removes a lock which has the exact same lock boundaries
  176  * as the UNLCK lock specifies. If such a lock is not found, returns invalid
  177  */
  178 static posix_lock_t *
  179 __reserve_unlock_lock(xlator_t *this, posix_lock_t *lock, pl_inode_t *pl_inode)
  180 {
  181     posix_lock_t *conf = find_matching_reservelk(lock, pl_inode);
  182     if (!conf) {
  183         gf_log(this->name, GF_LOG_DEBUG, " Matching lock not found for unlock");
  184         goto out;
  185     }
  186     __delete_lock(conf);
  187     gf_log(this->name, GF_LOG_DEBUG, " Matching lock found for unlock");
  188 
  189 out:
  190     return conf;
  191 }
  192 
  193 static void
  194 __grant_blocked_reserve_locks(xlator_t *this, pl_inode_t *pl_inode,
  195                               struct list_head *granted)
  196 {
  197     int bl_ret = 0;
  198     posix_lock_t *bl = NULL;
  199     posix_lock_t *tmp = NULL;
  200 
  201     struct list_head blocked_list;
  202 
  203     INIT_LIST_HEAD(&blocked_list);
  204     list_splice_init(&pl_inode->blocked_reservelks, &blocked_list);
  205 
  206     list_for_each_entry_safe(bl, tmp, &blocked_list, list)
  207     {
  208         list_del_init(&bl->list);
  209 
  210         bl_ret = __lock_reservelk(this, pl_inode, bl, 1);
  211 
  212         if (bl_ret == 0) {
  213             list_add(&bl->list, granted);
  214         }
  215     }
  216     return;
  217 }
  218 
  219 /* Grant all reservelks blocked on lock(s) */
  220 void
  221 grant_blocked_reserve_locks(xlator_t *this, pl_inode_t *pl_inode)
  222 {
  223     struct list_head granted;
  224     posix_lock_t *lock = NULL;
  225     posix_lock_t *tmp = NULL;
  226 
  227     INIT_LIST_HEAD(&granted);
  228 
  229     if (list_empty(&pl_inode->blocked_reservelks)) {
  230         gf_log(this->name, GF_LOG_TRACE, "No blocked locks to be granted");
  231         return;
  232     }
  233 
  234     pthread_mutex_lock(&pl_inode->mutex);
  235     {
  236         __grant_blocked_reserve_locks(this, pl_inode, &granted);
  237     }
  238     pthread_mutex_unlock(&pl_inode->mutex);
  239 
  240     list_for_each_entry_safe(lock, tmp, &granted, list)
  241     {
  242         gf_log(this->name, GF_LOG_TRACE,
  243                "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => Granted",
  244                lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid,
  245                lkowner_utoa(&lock->owner), lock->user_flock.l_start,
  246                lock->user_flock.l_len);
  247 
  248         STACK_UNWIND_STRICT(lk, lock->frame, 0, 0, &lock->user_flock, NULL);
  249     }
  250 }
  251 
  252 static void
  253 __grant_blocked_lock_calls(xlator_t *this, pl_inode_t *pl_inode,
  254                            struct list_head *granted)
  255 {
  256     int bl_ret = 0;
  257     posix_lock_t *bl = NULL;
  258     posix_lock_t *tmp = NULL;
  259 
  260     struct list_head blocked_list;
  261 
  262     INIT_LIST_HEAD(&blocked_list);
  263     list_splice_init(&pl_inode->blocked_reservelks, &blocked_list);
  264 
  265     list_for_each_entry_safe(bl, tmp, &blocked_list, list)
  266     {
  267         list_del_init(&bl->list);
  268 
  269         bl_ret = pl_verify_reservelk(this, pl_inode, bl, bl->blocked);
  270 
  271         if (bl_ret == 0) {
  272             list_add_tail(&bl->list, granted);
  273         }
  274     }
  275     return;
  276 }
  277 
  278 void
  279 grant_blocked_lock_calls(xlator_t *this, pl_inode_t *pl_inode)
  280 {
  281     struct list_head granted;
  282     posix_lock_t *lock = NULL;
  283     posix_lock_t *tmp = NULL;
  284     fd_t *fd = NULL;
  285 
  286     int can_block = 0;
  287     int32_t cmd = 0;
  288     int ret = 0;
  289 
  290     if (list_empty(&pl_inode->blocked_calls)) {
  291         gf_log(this->name, GF_LOG_TRACE, "No blocked lock calls to be granted");
  292         return;
  293     }
  294 
  295     pthread_mutex_lock(&pl_inode->mutex);
  296     {
  297         __grant_blocked_lock_calls(this, pl_inode, &granted);
  298     }
  299     pthread_mutex_unlock(&pl_inode->mutex);
  300 
  301     list_for_each_entry_safe(lock, tmp, &granted, list)
  302     {
  303         fd = fd_from_fdnum(lock);
  304 
  305         if (lock->blocked) {
  306             can_block = 1;
  307             cmd = F_SETLKW;
  308         } else
  309             cmd = F_SETLK;
  310 
  311         lock->blocked = 0;
  312         ret = pl_setlk(this, pl_inode, lock, can_block);
  313         if (ret == -1) {
  314             if (can_block) {
  315                 continue;
  316             } else {
  317                 gf_log(this->name, GF_LOG_DEBUG, "returning EAGAIN");
  318                 pl_trace_out(this, lock->frame, fd, NULL, cmd,
  319                              &lock->user_flock, -1, EAGAIN, NULL);
  320                 pl_update_refkeeper(this, fd->inode);
  321                 STACK_UNWIND_STRICT(lk, lock->frame, -1, EAGAIN,
  322                                     &lock->user_flock, NULL);
  323                 __destroy_lock(lock);
  324             }
  325         }
  326     }
  327 }
  328 
  329 int
  330 pl_reserve_unlock(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock)
  331 {
  332     posix_lock_t *retlock = NULL;
  333     int ret = -1;
  334 
  335     pthread_mutex_lock(&pl_inode->mutex);
  336     {
  337         retlock = __reserve_unlock_lock(this, lock, pl_inode);
  338         if (!retlock) {
  339             pthread_mutex_unlock(&pl_inode->mutex);
  340             gf_log(this->name, GF_LOG_DEBUG, "Bad Unlock issued on Inode lock");
  341             ret = -EINVAL;
  342             goto out;
  343         }
  344 
  345         gf_log(this->name, GF_LOG_TRACE, "Reservelk Unlock successful");
  346         __destroy_lock(retlock);
  347         ret = 0;
  348     }
  349     pthread_mutex_unlock(&pl_inode->mutex);
  350 out:
  351     grant_blocked_reserve_locks(this, pl_inode);
  352     grant_blocked_lock_calls(this, pl_inode);
  353 
  354     return ret;
  355 }
  356 
  357 int
  358 pl_reserve_setlk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock,
  359                  int can_block)
  360 {
  361     int ret = -EINVAL;
  362 
  363     pthread_mutex_lock(&pl_inode->mutex);
  364     {
  365         ret = __lock_reservelk(this, pl_inode, lock, can_block);
  366     }
  367     pthread_mutex_unlock(&pl_inode->mutex);
  368 
  369     if (ret < 0)
  370         gf_log(this->name, GF_LOG_TRACE,
  371                "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => NOK",
  372                lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid,
  373                lkowner_utoa(&lock->owner), lock->user_flock.l_start,
  374                lock->user_flock.l_len);
  375     else
  376         gf_log(this->name, GF_LOG_TRACE,
  377                "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => OK",
  378                lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid,
  379                lkowner_utoa(&lock->owner), lock->fl_start, lock->fl_end);
  380 
  381     return ret;
  382 }