author | ck153898 |
Mon, 29 Oct 2007 22:45:33 -0700 | |
changeset 5378 | 111aa1baa84a |
parent 5326 | 6752aa2bd5bc |
child 9981 | b4907297e740 |
permissions | -rw-r--r-- |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
1 |
/* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
2 |
* CDDL HEADER START |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
3 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
4 |
* The contents of this file are subject to the terms of the |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
5 |
* Common Development and Distribution License (the "License"). |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
6 |
* You may not use this file except in compliance with the License. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
7 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
9 |
* or http://www.opensolaris.org/os/licensing. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
10 |
* See the License for the specific language governing permissions |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
11 |
* and limitations under the License. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
12 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
15 |
* If applicable, add the following below this CDDL HEADER, with the |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
18 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
19 |
* CDDL HEADER END |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
20 |
*/ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
21 |
/* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
22 |
* Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
23 |
* Use is subject to license terms. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
24 |
*/ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
25 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
26 |
#pragma ident "%Z%%M% %I% %E% SMI" |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
27 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
28 |
#include <sys/refcount.h> |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
29 |
#include <sys/rrwlock.h> |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
30 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
31 |
/* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
32 |
* This file contains the implementation of a re-entrant read |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
33 |
* reader/writer lock (aka "rrwlock"). |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
34 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
35 |
* This is a normal reader/writer lock with the additional feature |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
36 |
* of allowing threads who have already obtained a read lock to |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
37 |
* re-enter another read lock (re-entrant read) - even if there are |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
38 |
* waiting writers. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
39 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
40 |
* Callers who have not obtained a read lock give waiting writers priority. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
41 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
42 |
* The rrwlock_t lock does not allow re-entrant writers, nor does it |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
43 |
* allow a re-entrant mix of reads and writes (that is, it does not |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
44 |
* allow a caller who has already obtained a read lock to be able to |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
45 |
* then grab a write lock without first dropping all read locks, and |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
46 |
* vice versa). |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
47 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
48 |
* The rrwlock_t uses tsd (thread specific data) to keep a list of |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
49 |
* nodes (rrw_node_t), where each node keeps track of which specific |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
50 |
* lock (rrw_node_t::rn_rrl) the thread has grabbed. Since re-entering |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
51 |
* should be rare, a thread that grabs multiple reads on the same rrwlock_t |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
52 |
* will store multiple rrw_node_ts of the same 'rrn_rrl'. Nodes on the |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
53 |
* tsd list can represent a different rrwlock_t. This allows a thread |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
54 |
* to enter multiple and unique rrwlock_ts for read locks at the same time. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
55 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
56 |
* Since using tsd exposes some overhead, the rrwlock_t only needs to |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
57 |
* keep tsd data when writers are waiting. If no writers are waiting, then |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
58 |
* a reader just bumps the anonymous read count (rr_anon_rcount) - no tsd |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
59 |
* is needed. Once a writer attempts to grab the lock, readers then |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
60 |
* keep tsd data and bump the linked readers count (rr_linked_rcount). |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
61 |
* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
62 |
* If there are waiting writers and there are anonymous readers, then a |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
63 |
* reader doesn't know if it is a re-entrant lock. But since it may be one, |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
64 |
* we allow the read to proceed (otherwise it could deadlock). Since once |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
65 |
* waiting writers are active, readers no longer bump the anonymous count, |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
66 |
* the anonymous readers will eventually flush themselves out. At this point, |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
67 |
* readers will be able to tell if they are a re-entrant lock (have a |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
68 |
* rrw_node_t entry for the lock) or not. If they are a re-entrant lock, then |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
69 |
* we must let the proceed. If they are not, then the reader blocks for the |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
70 |
* waiting writers. Hence, we do not starve writers. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
71 |
*/ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
72 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
73 |
/* global key for TSD */ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
74 |
uint_t rrw_tsd_key; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
75 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
76 |
typedef struct rrw_node { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
77 |
struct rrw_node *rn_next; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
78 |
rrwlock_t *rn_rrl; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
79 |
} rrw_node_t; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
80 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
81 |
static rrw_node_t * |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
82 |
rrn_find(rrwlock_t *rrl) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
83 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
84 |
rrw_node_t *rn; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
85 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
86 |
if (refcount_count(&rrl->rr_linked_rcount) == 0) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
87 |
return (NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
88 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
89 |
for (rn = tsd_get(rrw_tsd_key); rn != NULL; rn = rn->rn_next) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
90 |
if (rn->rn_rrl == rrl) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
91 |
return (rn); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
92 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
93 |
return (NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
94 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
95 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
96 |
/* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
97 |
* Add a node to the head of the singly linked list. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
98 |
*/ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
99 |
static void |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
100 |
rrn_add(rrwlock_t *rrl) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
101 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
102 |
rrw_node_t *rn; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
103 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
104 |
rn = kmem_alloc(sizeof (*rn), KM_SLEEP); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
105 |
rn->rn_rrl = rrl; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
106 |
rn->rn_next = tsd_get(rrw_tsd_key); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
107 |
VERIFY(tsd_set(rrw_tsd_key, rn) == 0); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
108 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
109 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
110 |
/* |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
111 |
* If a node is found for 'rrl', then remove the node from this |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
112 |
* thread's list and return TRUE; otherwise return FALSE. |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
113 |
*/ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
114 |
static boolean_t |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
115 |
rrn_find_and_remove(rrwlock_t *rrl) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
116 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
117 |
rrw_node_t *rn; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
118 |
rrw_node_t *prev = NULL; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
119 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
120 |
if (refcount_count(&rrl->rr_linked_rcount) == 0) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
121 |
return (NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
122 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
123 |
for (rn = tsd_get(rrw_tsd_key); rn != NULL; rn = rn->rn_next) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
124 |
if (rn->rn_rrl == rrl) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
125 |
if (prev) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
126 |
prev->rn_next = rn->rn_next; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
127 |
else |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
128 |
VERIFY(tsd_set(rrw_tsd_key, rn->rn_next) == 0); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
129 |
kmem_free(rn, sizeof (*rn)); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
130 |
return (B_TRUE); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
131 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
132 |
prev = rn; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
133 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
134 |
return (B_FALSE); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
135 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
136 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
137 |
void |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
138 |
rrw_init(rrwlock_t *rrl) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
139 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
140 |
mutex_init(&rrl->rr_lock, NULL, MUTEX_DEFAULT, NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
141 |
cv_init(&rrl->rr_cv, NULL, CV_DEFAULT, NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
142 |
rrl->rr_writer = NULL; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
143 |
refcount_create(&rrl->rr_anon_rcount); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
144 |
refcount_create(&rrl->rr_linked_rcount); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
145 |
rrl->rr_writer_wanted = B_FALSE; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
146 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
147 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
148 |
void |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
149 |
rrw_destroy(rrwlock_t *rrl) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
150 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
151 |
mutex_destroy(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
152 |
cv_destroy(&rrl->rr_cv); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
153 |
ASSERT(rrl->rr_writer == NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
154 |
refcount_destroy(&rrl->rr_anon_rcount); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
155 |
refcount_destroy(&rrl->rr_linked_rcount); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
156 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
157 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
158 |
static void |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
159 |
rrw_enter_read(rrwlock_t *rrl, void *tag) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
160 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
161 |
mutex_enter(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
162 |
ASSERT(rrl->rr_writer != curthread); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
163 |
ASSERT(refcount_count(&rrl->rr_anon_rcount) >= 0); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
164 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
165 |
while (rrl->rr_writer || (rrl->rr_writer_wanted && |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
166 |
refcount_is_zero(&rrl->rr_anon_rcount) && |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
167 |
rrn_find(rrl) == NULL)) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
168 |
cv_wait(&rrl->rr_cv, &rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
169 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
170 |
if (rrl->rr_writer_wanted) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
171 |
/* may or may not be a re-entrant enter */ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
172 |
rrn_add(rrl); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
173 |
(void) refcount_add(&rrl->rr_linked_rcount, tag); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
174 |
} else { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
175 |
(void) refcount_add(&rrl->rr_anon_rcount, tag); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
176 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
177 |
ASSERT(rrl->rr_writer == NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
178 |
mutex_exit(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
179 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
180 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
181 |
static void |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
182 |
rrw_enter_write(rrwlock_t *rrl) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
183 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
184 |
mutex_enter(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
185 |
ASSERT(rrl->rr_writer != curthread); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
186 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
187 |
while (refcount_count(&rrl->rr_anon_rcount) > 0 || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
188 |
refcount_count(&rrl->rr_linked_rcount) > 0 || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
189 |
rrl->rr_writer != NULL) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
190 |
rrl->rr_writer_wanted = B_TRUE; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
191 |
cv_wait(&rrl->rr_cv, &rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
192 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
193 |
rrl->rr_writer_wanted = B_FALSE; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
194 |
rrl->rr_writer = curthread; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
195 |
mutex_exit(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
196 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
197 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
198 |
void |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
199 |
rrw_enter(rrwlock_t *rrl, krw_t rw, void *tag) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
200 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
201 |
if (rw == RW_READER) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
202 |
rrw_enter_read(rrl, tag); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
203 |
else |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
204 |
rrw_enter_write(rrl); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
205 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
206 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
207 |
void |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
208 |
rrw_exit(rrwlock_t *rrl, void *tag) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
209 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
210 |
mutex_enter(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
211 |
ASSERT(!refcount_is_zero(&rrl->rr_anon_rcount) || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
212 |
!refcount_is_zero(&rrl->rr_linked_rcount) || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
213 |
rrl->rr_writer != NULL); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
214 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
215 |
if (rrl->rr_writer == NULL) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
216 |
if (rrn_find_and_remove(rrl)) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
217 |
if (refcount_remove(&rrl->rr_linked_rcount, tag) == 0) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
218 |
cv_broadcast(&rrl->rr_cv); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
219 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
220 |
} else { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
221 |
if (refcount_remove(&rrl->rr_anon_rcount, tag) == 0) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
222 |
cv_broadcast(&rrl->rr_cv); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
223 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
224 |
} else { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
225 |
ASSERT(rrl->rr_writer == curthread); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
226 |
ASSERT(refcount_is_zero(&rrl->rr_anon_rcount) && |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
227 |
refcount_is_zero(&rrl->rr_linked_rcount)); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
228 |
rrl->rr_writer = NULL; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
229 |
cv_broadcast(&rrl->rr_cv); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
230 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
231 |
mutex_exit(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
232 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
233 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
234 |
boolean_t |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
235 |
rrw_held(rrwlock_t *rrl, krw_t rw) |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
236 |
{ |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
237 |
boolean_t held; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
238 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
239 |
mutex_enter(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
240 |
if (rw == RW_WRITER) { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
241 |
held = (rrl->rr_writer == curthread); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
242 |
} else { |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
243 |
held = (!refcount_is_zero(&rrl->rr_anon_rcount) || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
244 |
!refcount_is_zero(&rrl->rr_linked_rcount)); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
245 |
} |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
246 |
mutex_exit(&rrl->rr_lock); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
247 |
|
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
248 |
return (held); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
diff
changeset
|
249 |
} |