~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/modules/onefs_cbrl.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Unix SMB/CIFS implementation.
 
3
 * Support for OneFS system interfaces.
 
4
 *
 
5
 * Copyright (C) Zack Kirsch, 2009
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 3 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#include "includes.h"
 
22
#include "onefs.h"
 
23
 
 
24
#include <ifs/ifs_syscalls.h>
 
25
#include <sys/isi_cifs_brl.h>
 
26
#include <isi_ecs/isi_ecs_cbrl.h>
 
27
 
 
28
#undef DBGC_CLASS
 
29
#define DBGC_CLASS DBGC_LOCKING
 
30
 
 
31
extern struct blocking_lock_record *blocking_lock_queue;
 
32
 
 
33
static uint64_t onefs_get_new_id(void) {
 
34
        static uint64_t id = 0;
 
35
 
 
36
        id++;
 
37
 
 
38
        return id;
 
39
}
 
40
 
 
41
enum onefs_cbrl_lock_state {ONEFS_CBRL_NONE, ONEFS_CBRL_ASYNC, ONEFS_CBRL_DONE,
 
42
        ONEFS_CBRL_ERROR};
 
43
 
 
44
struct onefs_cbrl_blr_state {
 
45
        uint64_t id;
 
46
        enum onefs_cbrl_lock_state state;
 
47
};
 
48
 
 
49
static char *onefs_cbrl_blr_state_str(const struct blocking_lock_record *blr)
 
50
{
 
51
        static fstring result;
 
52
        struct onefs_cbrl_blr_state *bs;
 
53
 
 
54
        SMB_ASSERT(blr);
 
55
 
 
56
        bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
 
57
 
 
58
        if (bs == NULL) {
 
59
                fstrcpy(result, "NULL CBRL BLR state - Posix lock?");
 
60
                return result;
 
61
        }
 
62
 
 
63
        switch (bs->state) {
 
64
        case ONEFS_CBRL_NONE:
 
65
                fstr_sprintf(result, "CBRL BLR id=%llu: state=NONE", bs->id);
 
66
                break;
 
67
        case ONEFS_CBRL_ASYNC:
 
68
                fstr_sprintf(result, "CBRL BLR id=%llu: state=ASYNC", bs->id);
 
69
                break;
 
70
        case ONEFS_CBRL_DONE:
 
71
                fstr_sprintf(result, "CBRL BLR id=%llu: state=DONE", bs->id);
 
72
                break;
 
73
        case ONEFS_CBRL_ERROR:
 
74
                fstr_sprintf(result, "CBRL BLR id=%llu: state=ERROR", bs->id);
 
75
                break;
 
76
        default:
 
77
                fstr_sprintf(result, "CBRL BLR id=%llu: unknown state %d",
 
78
                    bs->id, bs->state);
 
79
                break;
 
80
        }
 
81
 
 
82
        return result;
 
83
}
 
84
 
 
85
static void onefs_cbrl_enumerate_blq(const char *fn)
 
86
{
 
87
        struct blocking_lock_record *blr;
 
88
 
 
89
        if (DEBUGLVL(10))
 
90
                return;
 
91
 
 
92
        DEBUG(10, ("CBRL BLR records (%s):\n", fn));
 
93
 
 
94
        for (blr = blocking_lock_queue; blr; blr = blr->next)
 
95
                DEBUGADD(10, ("%s\n", onefs_cbrl_blr_state_str(blr)));
 
96
}
 
97
 
 
98
static struct blocking_lock_record *onefs_cbrl_find_blr(uint64_t id)
 
99
{
 
100
        struct blocking_lock_record *blr;
 
101
        struct onefs_cbrl_blr_state *bs;
 
102
 
 
103
        onefs_cbrl_enumerate_blq("onefs_cbrl_find_blr");
 
104
 
 
105
        for (blr = blocking_lock_queue; blr; blr = blr->next) {
 
106
                bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
 
107
 
 
108
                /* We don't control all of the BLRs on the BLQ. */
 
109
                if (bs == NULL)
 
110
                        continue;
 
111
 
 
112
                if (bs->id == id) {
 
113
                        DEBUG(10, ("found %s\n",
 
114
                            onefs_cbrl_blr_state_str(blr)));
 
115
                        break;
 
116
                }
 
117
        }
 
118
 
 
119
        if (blr == NULL) {
 
120
                DEBUG(5, ("Could not find CBRL BLR for id %llu\n", id));
 
121
                return NULL;
 
122
        }
 
123
 
 
124
        return blr;
 
125
}
 
126
 
 
127
static void onefs_cbrl_async_success(uint64_t id)
 
128
{
 
129
        struct blocking_lock_record *blr;
 
130
        struct onefs_cbrl_blr_state *bs;
 
131
        uint16 num_locks;
 
132
 
 
133
        DEBUG(10, ("CBRL async success!\n"));
 
134
 
 
135
        /* Find BLR with id. Its okay not to find one (race with cancel) */
 
136
        blr = onefs_cbrl_find_blr(id);
 
137
        if (blr == NULL)
 
138
                return;
 
139
 
 
140
        bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
 
141
        SMB_ASSERT(bs);
 
142
        SMB_ASSERT(bs->state == ONEFS_CBRL_ASYNC);
 
143
 
 
144
        blr->lock_num++;
 
145
 
 
146
        num_locks = SVAL(blr->req->vwv+7, 0);
 
147
 
 
148
        if (blr->lock_num == num_locks)
 
149
                bs->state = ONEFS_CBRL_DONE;
 
150
        else
 
151
                bs->state = ONEFS_CBRL_NONE;
 
152
 
 
153
        /* Self contend our own level 2 oplock. The kernel handles
 
154
         * contention of other opener's level 2 oplocks. */
 
155
        contend_level2_oplocks_begin(blr->fsp,
 
156
            LEVEL2_CONTEND_WINDOWS_BRL);
 
157
 
 
158
        /* Process the queue, to try the next lock or finish up. */
 
159
        process_blocking_lock_queue();
 
160
}
 
161
 
 
162
static void onefs_cbrl_async_failure(uint64_t id)
 
163
{
 
164
        struct blocking_lock_record *blr;
 
165
        struct onefs_cbrl_blr_state *bs;
 
166
 
 
167
        DEBUG(10, ("CBRL async failure!\n"));
 
168
 
 
169
        /* Find BLR with id. Its okay not to find one (race with cancel) */
 
170
        blr = onefs_cbrl_find_blr(id);
 
171
        if (blr == NULL)
 
172
                return;
 
173
 
 
174
        bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
 
175
        SMB_ASSERT(bs);
 
176
 
 
177
        SMB_ASSERT(bs->state == ONEFS_CBRL_ASYNC);
 
178
        bs->state = ONEFS_CBRL_ERROR;
 
179
 
 
180
        /* Process the queue. It will end up trying to retake the same lock,
 
181
         * see the error in onefs_cbrl_lock_windows() and fail. */
 
182
        process_blocking_lock_queue();
 
183
}
 
184
 
 
185
static struct cbrl_event_ops cbrl_ops =
 
186
    {.cbrl_async_success = onefs_cbrl_async_success,
 
187
     .cbrl_async_failure = onefs_cbrl_async_failure};
 
188
 
 
189
static void onefs_cbrl_events_handler(struct event_context *ev,
 
190
                                        struct fd_event *fde,
 
191
                                        uint16_t flags,
 
192
                                        void *private_data)
 
193
{
 
194
        DEBUG(10, ("onefs_cbrl_events_handler\n"));
 
195
 
 
196
        if (cbrl_event_dispatcher(&cbrl_ops)) {
 
197
                DEBUG(0, ("cbrl_event_dispatcher failed: %s\n",
 
198
                        strerror(errno)));
 
199
        }
 
200
}
 
201
 
 
202
static void onefs_init_cbrl(void)
 
203
{
 
204
        static bool init_done = false;
 
205
        static int cbrl_event_fd;
 
206
        static struct fd_event *cbrl_fde;
 
207
 
 
208
        if (init_done)
 
209
                return;
 
210
 
 
211
        DEBUG(10, ("onefs_init_cbrl\n"));
 
212
 
 
213
        /* Register the event channel for CBRL. */
 
214
        cbrl_event_fd = cbrl_event_register();
 
215
        if (cbrl_event_fd == -1) {
 
216
                DEBUG(0, ("cbrl_event_register failed: %s\n",
 
217
                        strerror(errno)));
 
218
                return;
 
219
        }
 
220
 
 
221
        DEBUG(10, ("cbrl_event_fd = %d\n", cbrl_event_fd));
 
222
 
 
223
        /* Register the CBRL event_fd with samba's event system */
 
224
        cbrl_fde = event_add_fd(smbd_event_context(),
 
225
                                     NULL,
 
226
                                     cbrl_event_fd,
 
227
                                     EVENT_FD_READ,
 
228
                                     onefs_cbrl_events_handler,
 
229
                                     NULL);
 
230
 
 
231
        init_done = true;
 
232
        return;
 
233
}
 
234
 
 
235
/**
 
236
 * Blocking PID. As far as I can tell, the blocking_pid is only used to tell
 
237
 * whether a posix lock or a CIFS lock blocked us. If it was a posix lock,
 
238
 * Samba polls every 10 seconds, which we don't want. -zkirsch
 
239
 */
 
240
#define ONEFS_BLOCKING_PID 0xABCDABCD
 
241
 
 
242
/**
 
243
 * @param[in]     br_lck        Contains the fsp.
 
244
 * @param[in]     plock         Lock request.
 
245
 * @param[in]     blocking_lock Only used for figuring out the error.
 
246
 * @param[in,out] blr           The BLR for the already-deferred operation.
 
247
 */
 
248
NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
 
249
                                struct byte_range_lock *br_lck,
 
250
                                struct lock_struct *plock,
 
251
                                bool blocking_lock,
 
252
                                struct blocking_lock_record *blr)
 
253
{
 
254
        int fd = br_lck->fsp->fh->fd;
 
255
        uint64_t id = 0;
 
256
        enum cbrl_lock_type type;
 
257
        bool async = false;
 
258
        bool pending = false;
 
259
        bool pending_async = false;
 
260
        int error;
 
261
        struct onefs_cbrl_blr_state *bs;
 
262
        NTSTATUS status;
 
263
 
 
264
        START_PROFILE(syscall_brl_lock);
 
265
 
 
266
        SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
 
267
        SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
 
268
 
 
269
        onefs_cbrl_enumerate_blq("onefs_brl_lock_windows");
 
270
 
 
271
        /* Will only initialize the first time its called. */
 
272
        onefs_init_cbrl();
 
273
 
 
274
        switch (plock->lock_type) {
 
275
                case WRITE_LOCK:
 
276
                        type = CBRL_LK_EX;
 
277
                        break;
 
278
                case READ_LOCK:
 
279
                        type = CBRL_LK_SH;
 
280
                        break;
 
281
                case PENDING_WRITE_LOCK:
 
282
                        /* Called when a blocking lock request is added - do an
 
283
                         * async lock. */
 
284
                        type = CBRL_LK_EX;
 
285
                        pending = true;
 
286
                        async = true;
 
287
                        break;
 
288
                case PENDING_READ_LOCK:
 
289
                        /* Called when a blocking lock request is added - do an
 
290
                         * async lock. */
 
291
                        type = CBRL_LK_SH;
 
292
                        pending = true;
 
293
                        async = true;
 
294
                        break;
 
295
                default:
 
296
                        /* UNLOCK_LOCK: should only be used for a POSIX_LOCK */
 
297
                        smb_panic("Invalid plock->lock_type passed in to "
 
298
                            "onefs_brl_lock_windows");
 
299
        }
 
300
 
 
301
        /* Figure out if we're actually doing the lock or a no-op. We need to
 
302
         * do a no-op when process_blocking_lock_queue calls back into us.
 
303
         *
 
304
         * We know process_* is calling into us if a blr is passed in and
 
305
         * pending is false. */
 
306
        if (!pending && blr) {
 
307
                /* Check the BLR state. */
 
308
                bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
 
309
                SMB_ASSERT(bs);
 
310
 
 
311
                /* ASYNC still in progress: The process_* calls will keep
 
312
                 * calling even if we haven't gotten the lock. Keep erroring
 
313
                 * without calling ifs_cbrl, or getting/setting an id. */
 
314
                if (bs->state == ONEFS_CBRL_ASYNC) {
 
315
                        goto failure;
 
316
                }
 
317
                else if (bs->state == ONEFS_CBRL_ERROR) {
 
318
                        END_PROFILE(syscall_brl_lock);
 
319
                        return NT_STATUS_NO_MEMORY;
 
320
                }
 
321
 
 
322
                SMB_ASSERT(bs->state == ONEFS_CBRL_NONE);
 
323
                async = true;
 
324
        }
 
325
 
 
326
        if (async) {
 
327
                SMB_ASSERT(blocking_lock);
 
328
                SMB_ASSERT(blr);
 
329
                id = onefs_get_new_id();
 
330
        }
 
331
 
 
332
        DEBUG(10, ("Calling ifs_cbrl(LOCK)...\n"));
 
333
        error = ifs_cbrl(fd, CBRL_OP_LOCK, type, plock->start,
 
334
            plock->size, async, id, plock->context.smbpid, plock->context.tid,
 
335
            plock->fnum);
 
336
        if (!error) {
 
337
                goto success;
 
338
        } else if (errno == EWOULDBLOCK) {
 
339
                SMB_ASSERT(!async);
 
340
        } else if (errno == EINPROGRESS) {
 
341
                SMB_ASSERT(async);
 
342
 
 
343
                if (pending) {
 
344
                        /* Talloc a new BLR private state. */
 
345
                        blr->blr_private = talloc(blr, struct onefs_cbrl_blr_state);
 
346
                        pending_async = true;
 
347
                }
 
348
 
 
349
                /* Store the new id in the BLR private state. */
 
350
                bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
 
351
                bs->id = id;
 
352
                bs->state = ONEFS_CBRL_ASYNC;
 
353
        } else {
 
354
                DEBUG(0, ("onefs_brl_lock_windows failure: error=%d (%s).\n",
 
355
                        errno, strerror(errno)));
 
356
        }
 
357
 
 
358
failure:
 
359
 
 
360
        END_PROFILE(syscall_brl_lock);
 
361
 
 
362
        /* Failure - error or async. */
 
363
        plock->context.smbpid = (uint32) ONEFS_BLOCKING_PID;
 
364
 
 
365
        if (pending_async)
 
366
                status = NT_STATUS_OK;
 
367
        else
 
368
                status = brl_lock_failed(br_lck->fsp, plock, blocking_lock);
 
369
 
 
370
        DEBUG(10, ("returning %s.\n", nt_errstr(status)));
 
371
        return status;
 
372
 
 
373
success:
 
374
        /* Self contend our own level 2 oplock. The kernel handles
 
375
         * contention of other opener's level 2 oplocks. */
 
376
        contend_level2_oplocks_begin(br_lck->fsp,
 
377
            LEVEL2_CONTEND_WINDOWS_BRL);
 
378
 
 
379
        END_PROFILE(syscall_brl_lock);
 
380
 
 
381
        /* Success. */
 
382
        onefs_cbrl_enumerate_blq("onefs_brl_unlock_windows");
 
383
        DEBUG(10, ("returning NT_STATUS_OK.\n"));
 
384
        return NT_STATUS_OK;
 
385
}
 
386
 
 
387
bool onefs_brl_unlock_windows(vfs_handle_struct *handle,
 
388
                              struct messaging_context *msg_ctx,
 
389
                              struct byte_range_lock *br_lck,
 
390
                              const struct lock_struct *plock)
 
391
{
 
392
        int error;
 
393
        int fd = br_lck->fsp->fh->fd;
 
394
 
 
395
        START_PROFILE(syscall_brl_unlock);
 
396
 
 
397
        SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
 
398
        SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
 
399
 
 
400
        DEBUG(10, ("Calling ifs_cbrl(UNLOCK)...\n"));
 
401
        error = ifs_cbrl(fd, CBRL_OP_UNLOCK, CBRL_LK_SH,
 
402
            plock->start, plock->size, false, 0, plock->context.smbpid,
 
403
            plock->context.tid, plock->fnum);
 
404
 
 
405
        END_PROFILE(syscall_brl_unlock);
 
406
 
 
407
        if (error) {
 
408
                DEBUG(10, ("returning false.\n"));
 
409
                return false;
 
410
        }
 
411
 
 
412
        /* For symmetry purposes, end our oplock contention even though its
 
413
         * currently a no-op. */
 
414
        contend_level2_oplocks_end(br_lck->fsp, LEVEL2_CONTEND_WINDOWS_BRL);
 
415
 
 
416
        DEBUG(10, ("returning true.\n"));
 
417
        return true;
 
418
 
 
419
        /* Problem with storing things in TDB: I won't know what BRL to unlock in the TDB.
 
420
         *  - I could fake it?
 
421
         *  - I could send Samba a message with which lock is being unlocked?
 
422
         *  - I could *easily* make the "id" something you always pass in to
 
423
         *  lock, unlock or cancel -- it identifies a lock. Makes sense!
 
424
         */
 
425
}
 
426
 
 
427
/* Default implementation only calls this on PENDING locks. */
 
428
bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
 
429
                              struct byte_range_lock *br_lck,
 
430
                              struct lock_struct *plock,
 
431
                              struct blocking_lock_record *blr)
 
432
{
 
433
        int error;
 
434
        int fd = br_lck->fsp->fh->fd;
 
435
        struct onefs_cbrl_blr_state *bs;
 
436
 
 
437
        START_PROFILE(syscall_brl_cancel);
 
438
 
 
439
        SMB_ASSERT(plock);
 
440
        SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
 
441
        SMB_ASSERT(blr);
 
442
 
 
443
        onefs_cbrl_enumerate_blq("onefs_brl_cancel_windows");
 
444
 
 
445
        bs = ((struct onefs_cbrl_blr_state *)blr->blr_private);
 
446
        SMB_ASSERT(bs);
 
447
 
 
448
        if (bs->state == ONEFS_CBRL_DONE || bs->state == ONEFS_CBRL_ERROR) {
 
449
                /* No-op. */
 
450
                DEBUG(10, ("State=%d, returning true\n", bs->state));
 
451
                END_PROFILE(syscall_brl_cancel);
 
452
                return true;
 
453
        }
 
454
 
 
455
        SMB_ASSERT(bs->state == ONEFS_CBRL_NONE ||
 
456
            bs->state == ONEFS_CBRL_ASYNC);
 
457
 
 
458
        /* A real cancel. */
 
459
        DEBUG(10, ("Calling ifs_cbrl(CANCEL)...\n"));
 
460
        error = ifs_cbrl(fd, CBRL_OP_CANCEL, CBRL_LK_UNSPEC, plock->start,
 
461
            plock->size, false, bs->id, plock->context.smbpid,
 
462
            plock->context.tid, plock->fnum);
 
463
 
 
464
        END_PROFILE(syscall_brl_cancel);
 
465
 
 
466
        if (error) {
 
467
                DEBUG(10, ("returning false\n"));
 
468
                bs->state = ONEFS_CBRL_ERROR;
 
469
                return false;
 
470
        }
 
471
 
 
472
        bs->state = ONEFS_CBRL_DONE;
 
473
        onefs_cbrl_enumerate_blq("onefs_brl_cancel_windows");
 
474
        DEBUG(10, ("returning true\n"));
 
475
        return true;
 
476
}
 
477
 
 
478
bool onefs_strict_lock(vfs_handle_struct *handle,
 
479
                        files_struct *fsp,
 
480
                        struct lock_struct *plock)
 
481
{
 
482
        int error;
 
483
 
 
484
        START_PROFILE(syscall_strict_lock);
 
485
 
 
486
        SMB_ASSERT(plock->lock_type == READ_LOCK ||
 
487
            plock->lock_type == WRITE_LOCK);
 
488
 
 
489
        if (!lp_locking(handle->conn->params) ||
 
490
            !lp_strict_locking(handle->conn->params)) {
 
491
                END_PROFILE(syscall_strict_lock);
 
492
                return True;
 
493
        }
 
494
 
 
495
        if (plock->lock_flav == POSIX_LOCK) {
 
496
                END_PROFILE(syscall_strict_lock);
 
497
                return SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
 
498
        }
 
499
 
 
500
        if (plock->size == 0) {
 
501
                END_PROFILE(syscall_strict_lock);
 
502
                return True;
 
503
        }
 
504
 
 
505
        error = ifs_cbrl(fsp->fh->fd, CBRL_OP_LOCK,
 
506
            plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR,
 
507
            plock->start, plock->size, 0, 0, plock->context.smbpid,
 
508
            plock->context.tid, plock->fnum);
 
509
 
 
510
        END_PROFILE(syscall_strict_lock);
 
511
 
 
512
        return (error == 0);
 
513
}
 
514
 
 
515
void onefs_strict_unlock(vfs_handle_struct *handle,
 
516
                        files_struct *fsp,
 
517
                        struct lock_struct *plock)
 
518
{
 
519
        START_PROFILE(syscall_strict_unlock);
 
520
 
 
521
        SMB_ASSERT(plock->lock_type == READ_LOCK ||
 
522
            plock->lock_type == WRITE_LOCK);
 
523
 
 
524
        if (!lp_locking(handle->conn->params) ||
 
525
            !lp_strict_locking(handle->conn->params)) {
 
526
                END_PROFILE(syscall_strict_unlock);
 
527
                return;
 
528
        }
 
529
 
 
530
        if (plock->lock_flav == POSIX_LOCK) {
 
531
                SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
 
532
                END_PROFILE(syscall_strict_unlock);
 
533
                return;
 
534
        }
 
535
 
 
536
        if (plock->size == 0) {
 
537
                END_PROFILE(syscall_strict_unlock);
 
538
                return;
 
539
        }
 
540
 
 
541
        if (fsp->fh) {
 
542
                ifs_cbrl(fsp->fh->fd, CBRL_OP_UNLOCK,
 
543
                    plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR,
 
544
                    plock->start, plock->size, 0, 0, plock->context.smbpid,
 
545
                    plock->context.tid, plock->fnum);
 
546
        }
 
547
 
 
548
        END_PROFILE(syscall_strict_unlock);
 
549
}
 
550
 
 
551
/* TODO Optimization: Abstract out brl_get_locks() in the Windows case.
 
552
 * We'll malloc some memory or whatever (can't return NULL), but not actually
 
553
 * touch the TDB. */
 
554
 
 
555
/* XXX brl_locktest: CBRL does not support calling this, but its only for
 
556
 * strict locking. Add empty VOP? */
 
557
 
 
558
/* XXX brl_lockquery: CBRL does not support calling this for WINDOWS LOCKS, but
 
559
 * its only called for POSIX LOCKS. Add empty VOP? */
 
560
 
 
561
/* XXX brl_close_fnum: CBRL will do this automatically. I think this is a NO-OP
 
562
 * for us, we could add an empty VOP. */
 
563