2 * Copyright (c) 1995 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <nnpfs/nnpfs_locl.h>
36 #include <nnpfs/nnpfs_message.h>
37 #include <nnpfs/nnpfs_msg_locl.h>
38 #include <nnpfs/nnpfs_fs.h>
39 #include <nnpfs/nnpfs_dev.h>
40 #include <nnpfs/nnpfs_deb.h>
44 #define NNPFS_FBSD_DEVLOCK
48 nnpfs_dev_lock(struct nnpfs
*chan
)
50 d_thread_t
*me
= curthread
;
52 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_lock, me=%p\n", me
));
54 mtx_lock(&chan
->lock
.lock
);
56 while (chan
->lock
.recurse
> 0 && chan
->lock
.locker
!= me
) {
59 (void)nnpfs_msleep(&chan
->lock
, &chan
->lock
.lock
, (PZERO
+ 1), "nnpfslock");
62 while msleep(&chan
->lock
, &chan
->lock
.lock
, (PZERO
+ 1), "nnpfslock", 7 * hz
);
67 chan
->lock
.locker
= me
;
68 nnpfs_assert(chan
->lock
.recurse
>= 0);
71 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_lock, locker %p\n", chan
->lock
.locker
));
73 mtx_unlock(&chan
->lock
.lock
);
77 nnpfs_dev_unlock(struct nnpfs
*chan
)
79 d_thread_t
*me
= curthread
;
81 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_unlock, me=%p locker=%p r=%d\n", me
,
82 chan
->lock
.locker
, chan
->lock
.recurse
));
84 mtx_lock(&chan
->lock
.lock
);
87 nnpfs_assert(chan
->lock
.recurse
>= 0);
88 nnpfs_assert(chan
->lock
.locker
== me
);
90 if (chan
->lock
.recurse
== 0) {
91 chan
->lock
.locker
= NULL
;
95 mtx_unlock(&chan
->lock
.lock
);
99 nnpfs_dev_msleep(struct nnpfs
*chan
, caddr_t waitobj
, int flags
, const char *msg
)
101 d_thread_t
*me
= curthread
;
104 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_msleep %p %x %s, me %p\n", waitobj
, flags
, msg
, me
));
106 mtx_lock(&chan
->lock
.lock
);
107 nlocks
= chan
->lock
.recurse
;
108 nnpfs_assert(chan
->lock
.recurse
>= 0);
109 nnpfs_assert(chan
->lock
.locker
== me
);
111 chan
->lock
.recurse
= 0;
112 chan
->lock
.locker
= NULL
;
115 ret
= nnpfs_msleep(waitobj
, &chan
->lock
.lock
, flags
, msg
);
117 while (chan
->lock
.recurse
> 0)
118 /* XXX PCATCH, flags, ret? */
119 (void)nnpfs_msleep(&chan
->lock
, &chan
->lock
.lock
, (PZERO
+ 1), "nnpfslock");
121 nnpfs_assert(chan
->lock
.recurse
== 0);
122 chan
->lock
.locker
= me
;
123 chan
->lock
.recurse
= nlocks
;
125 mtx_unlock(&chan
->lock
.lock
);
130 nnpfs_dev_initlock(struct nnpfs
*chan
)
132 d_thread_t
*me
= curthread
;
134 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_initlock\n"));
136 if (mtx_initialized(&chan
->lock
.lock
))
137 panic("nnpfs_dev_initlock: already inited!");
139 mtx_init(&chan
->lock
.lock
, "nnpfsdevlock", NULL
, MTX_DEF
);
141 mtx_lock(&chan
->lock
.lock
);
142 chan
->lock
.locker
= me
;
143 chan
->lock
.recurse
= 1;
144 mtx_unlock(&chan
->lock
.lock
);
150 nnpfs_dev_uninitlock(struct nnpfs
*chan
)
152 d_thread_t
*me
= curthread
;
154 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_uninitlock\n"));
156 if (!mtx_initialized(&chan
->lock
.lock
))
157 printf("nnpfs_dev_uninitlock: not inited!\n");
159 mtx_lock(&chan
->lock
.lock
);
160 nnpfs_assert(chan
->lock
.recurse
== 1);
161 nnpfs_assert(chan
->lock
.locker
== me
);
163 chan
->lock
.recurse
= 0;
164 chan
->lock
.locker
= NULL
;
167 * contrary to man page, it seems we need to unlock the mutex before
168 * destroying it if we use spinlocks. Default mutexes are ok.
171 mtx_destroy(&chan
->lock
.lock
);
176 nnpfs_dev_lock(struct nnpfs
*chan
)
179 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_lock\n"));
180 ret
= lockmgr(&chan
->dev_lock
, LK_EXCLUSIVE
| LK_CANRECURSE
, NULL
);
185 nnpfs_dev_unlock(struct nnpfs
*chan
)
188 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_unlock\n"));
189 ret
= lockmgr(&chan
->dev_lock
, LK_RELEASE
, NULL
);
194 nnpfs_dev_msleep(struct nnpfs
*chan
, caddr_t waitobj
, int flags
, const char *msg
)
196 d_thread_t
*td
= curthread
;
199 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_msleep %p %x %s\n", waitobj
, flags
, msg
));
201 ret
= lockstatus(&chan
->dev_lock
, td
);
202 nnpfs_assert(ret
== LK_EXCLUSIVE
);
204 nlocks
= lockcount(&chan
->dev_lock
);
206 for (i
= nlocks
; i
> 0 ; i
--) {
207 ret
= lockmgr(&chan
->dev_lock
, LK_RELEASE
, NULL
);
211 ret
= nnpfs_msleep(waitobj
, &chan
->dev_lock
, flags
, msg
);
216 nnpfs_dev_initlock(struct nnpfs
*chan
)
218 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_initlock\n"));
219 lockinit(&chan
->dev_lock
, PRIBIO
/* XXX */, "nnpfsdevlock", NULL
, LK_CANRECURSE
| LK_NOSHARE
);
220 return lockmgr(&chan
->dev_lock
, LK_EXCLUSIVE
, NULL
);
224 nnpfs_dev_uninitlock(struct nnpfs
*chan
)
226 NNPFSDEB(XDEBDEV
, ("nnpfs_dev_uninitlock\n"));
227 lockdestroy(&chan
->dev_lock
);
232 #ifndef NNPFS_FBSD_DEVLOCK
235 #define D_NEEDGIANT 0
240 struct cdevsw nnpfs_cdev
= {
241 #if __FreeBSD_version >= 502103
242 d_version
: D_VERSION
,
245 d_open
: nnpfs_devopen
,
246 d_close
: nnpfs_devclose
,
247 d_read
: nnpfs_devread
,
248 d_write
: nnpfs_devwrite
,
249 d_ioctl
: nnpfs_devioctl
,
250 #ifdef HAVE_STRUCT_CDEVSW_D_MMAP
253 #ifdef HAVE_STRUCT_CDEVSW_D_STRATEGY
254 d_strategy
: nostrategy
,
257 * Giant is no longer needed, nnpfs_node_find & friends are locked
258 * now, verify correctness before removing.
260 #ifdef NNPFS_FBSD_DEVLOCK
263 d_flags
: D_NEEDGIANT
,
266 #ifdef HAVE_STRUCT_CDEVSW_D_STOP
269 #ifdef HAVE_STRUCT_CDEVSW_D_RESET
272 #ifdef HAVE_STRUCT_CDEVSW_D_BOGORESET
273 d_bogoreset
: noreset
,
275 #ifdef HAVE_STRUCT_CDEVSW_D_DEVTOTTY
276 d_devtotty
: nodevtotty
,
278 #if defined(HAVE_VOP_SELECT)
279 d_select
: nnpfs_devselect
,
280 #elif defined(HAVE_VOP_POLL)
281 d_poll
: nnpfs_devpoll
,
283 #error select or poll: that is the question
285 #ifdef HAVE_STRUCT_CDEVSW_D_BOGOPARMS
286 d_bogoparms
: noparms
,
288 #ifdef HAVE_STRUCT_CDEVSW_D_SPARE
291 #if __FreeBSD_version < 600007
292 d_maj
: 128, /* XXX */
294 #ifdef HAVE_STRUCT_CDEVSW_D_DUMP
297 #ifdef HAVE_STRUCT_CDEVSW_D_PSIZE
300 #ifdef HAVE_STRUCT_CDEVSW_D_MAXIO
303 #ifdef HAVE_STRUCT_CDEVSW_D_BMAJ
309 #endif /* HAVE_STRUCT_CDEVSW_D_BMAJ */