Print this page
6367 spa_config_tryenter incorrectly handles the multiple-lock case
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Prashanth Sreenivasa <prashksp@gmail.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Steven Hartland <steven.hartland@multiplay.co.uk>
Approved by: Matthew Ahrens <mahrens@delphix.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
  24  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.

  26  */
  27 
  28 #include <sys/zfs_context.h>
  29 #include <sys/spa_impl.h>
  30 #include <sys/spa_boot.h>
  31 #include <sys/zio.h>
  32 #include <sys/zio_checksum.h>
  33 #include <sys/zio_compress.h>
  34 #include <sys/dmu.h>
  35 #include <sys/dmu_tx.h>
  36 #include <sys/zap.h>
  37 #include <sys/zil.h>
  38 #include <sys/vdev_impl.h>
  39 #include <sys/metaslab.h>
  40 #include <sys/uberblock_impl.h>
  41 #include <sys/txg.h>
  42 #include <sys/avl.h>
  43 #include <sys/unique.h>
  44 #include <sys/dsl_pool.h>
  45 #include <sys/dsl_dir.h>


 368                 spa_config_lock_t *scl = &spa->spa_config_lock[i];
 369                 mutex_destroy(&scl->scl_lock);
 370                 cv_destroy(&scl->scl_cv);
 371                 refcount_destroy(&scl->scl_count);
 372                 ASSERT(scl->scl_writer == NULL);
 373                 ASSERT(scl->scl_write_wanted == 0);
 374         }
 375 }
 376 
 377 int
 378 spa_config_tryenter(spa_t *spa, int locks, void *tag, krw_t rw)
 379 {
 380         for (int i = 0; i < SCL_LOCKS; i++) {
 381                 spa_config_lock_t *scl = &spa->spa_config_lock[i];
 382                 if (!(locks & (1 << i)))
 383                         continue;
 384                 mutex_enter(&scl->scl_lock);
 385                 if (rw == RW_READER) {
 386                         if (scl->scl_writer || scl->scl_write_wanted) {
 387                                 mutex_exit(&scl->scl_lock);
 388                                 spa_config_exit(spa, locks ^ (1 << i), tag);

 389                                 return (0);
 390                         }
 391                 } else {
 392                         ASSERT(scl->scl_writer != curthread);
 393                         if (!refcount_is_zero(&scl->scl_count)) {
 394                                 mutex_exit(&scl->scl_lock);
 395                                 spa_config_exit(spa, locks ^ (1 << i), tag);

 396                                 return (0);
 397                         }
 398                         scl->scl_writer = curthread;
 399                 }
 400                 (void) refcount_add(&scl->scl_count, tag);
 401                 mutex_exit(&scl->scl_lock);
 402         }
 403         return (1);
 404 }
 405 
 406 void
 407 spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
 408 {
 409         int wlocks_held = 0;
 410 
 411         ASSERT3U(SCL_LOCKS, <, sizeof (wlocks_held) * NBBY);
 412 
 413         for (int i = 0; i < SCL_LOCKS; i++) {
 414                 spa_config_lock_t *scl = &spa->spa_config_lock[i];
 415                 if (scl->scl_writer == curthread)




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
  24  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  25  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
  26  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  27  */
  28 
  29 #include <sys/zfs_context.h>
  30 #include <sys/spa_impl.h>
  31 #include <sys/spa_boot.h>
  32 #include <sys/zio.h>
  33 #include <sys/zio_checksum.h>
  34 #include <sys/zio_compress.h>
  35 #include <sys/dmu.h>
  36 #include <sys/dmu_tx.h>
  37 #include <sys/zap.h>
  38 #include <sys/zil.h>
  39 #include <sys/vdev_impl.h>
  40 #include <sys/metaslab.h>
  41 #include <sys/uberblock_impl.h>
  42 #include <sys/txg.h>
  43 #include <sys/avl.h>
  44 #include <sys/unique.h>
  45 #include <sys/dsl_pool.h>
  46 #include <sys/dsl_dir.h>


 369                 spa_config_lock_t *scl = &spa->spa_config_lock[i];
 370                 mutex_destroy(&scl->scl_lock);
 371                 cv_destroy(&scl->scl_cv);
 372                 refcount_destroy(&scl->scl_count);
 373                 ASSERT(scl->scl_writer == NULL);
 374                 ASSERT(scl->scl_write_wanted == 0);
 375         }
 376 }
 377 
 378 int
 379 spa_config_tryenter(spa_t *spa, int locks, void *tag, krw_t rw)
 380 {
 381         for (int i = 0; i < SCL_LOCKS; i++) {
 382                 spa_config_lock_t *scl = &spa->spa_config_lock[i];
 383                 if (!(locks & (1 << i)))
 384                         continue;
 385                 mutex_enter(&scl->scl_lock);
 386                 if (rw == RW_READER) {
 387                         if (scl->scl_writer || scl->scl_write_wanted) {
 388                                 mutex_exit(&scl->scl_lock);
 389                                 spa_config_exit(spa, locks & ((1 << i) - 1),
 390                                     tag);
 391                                 return (0);
 392                         }
 393                 } else {
 394                         ASSERT(scl->scl_writer != curthread);
 395                         if (!refcount_is_zero(&scl->scl_count)) {
 396                                 mutex_exit(&scl->scl_lock);
 397                                 spa_config_exit(spa, locks & ((1 << i) - 1),
 398                                     tag);
 399                                 return (0);
 400                         }
 401                         scl->scl_writer = curthread;
 402                 }
 403                 (void) refcount_add(&scl->scl_count, tag);
 404                 mutex_exit(&scl->scl_lock);
 405         }
 406         return (1);
 407 }
 408 
 409 void
 410 spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
 411 {
 412         int wlocks_held = 0;
 413 
 414         ASSERT3U(SCL_LOCKS, <, sizeof (wlocks_held) * NBBY);
 415 
 416         for (int i = 0; i < SCL_LOCKS; i++) {
 417                 spa_config_lock_t *scl = &spa->spa_config_lock[i];
 418                 if (scl->scl_writer == curthread)