2
Unix SMB/CIFS implementation.
3
IRIX kernel oplock processing
4
Copyright (C) Andrew Tridgell 1992-1998
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 3 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#define DBGC_CLASS DBGC_LOCKING
22
#include "smbd/globals.h"
24
#if HAVE_KERNEL_OPLOCKS_IRIX
26
struct irix_oplocks_context {
27
struct kernel_oplocks *ctx;
30
struct fd_event *read_fde;
34
/****************************************************************************
35
Test to see if IRIX kernel oplocks work.
36
****************************************************************************/
38
static bool irix_oplocks_available(void)
42
TALLOC_CTX *ctx = talloc_stackframe();
45
set_effective_capability(KERNEL_OPLOCK_CAPABILITY);
47
tmpname = talloc_asprintf(ctx,
57
DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error "
64
if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) {
65
DEBUG(0,("check_kernel_oplocks: Unable to open temp test file "
67
tmpname, strerror(errno) ));
79
if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) {
80
DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not "
81
"available on this machine. Disabling kernel oplock "
89
if(sys_fcntl_long(fd, F_OPLKACK, OP_REVOKE) < 0 ) {
90
DEBUG(0,("check_kernel_oplocks: Error when removing kernel "
91
"oplock. Error was %s. Disabling kernel oplock "
92
"support.\n", strerror(errno) ));
107
* This is bad because the file_id should always be created through the vfs
108
* layer! Unfortunately, a conn struct isn't available here.
110
static struct file_id file_id_create_dev(SMB_DEV_T dev, SMB_INO_T inode)
114
/* the ZERO_STRUCT ensures padding doesn't break using the key as a
124
/****************************************************************************
125
* Deal with the IRIX kernel <--> smbd
126
* oplock break protocol.
127
****************************************************************************/
129
static files_struct *irix_oplock_receive_message(struct kernel_oplocks *_ctx)
131
struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data,
132
struct irix_oplocks_context);
135
struct file_id fileid;
139
* TODO: is it correct to assume we only get one
140
* oplock break, for each byte we read from the pipe?
142
ctx->pending = false;
145
* Read one byte of zero to clear the
146
* kernel break notify message.
149
if(read(ctx->read_fd, &dummy, 1) != 1) {
150
DEBUG(0,("irix_oplock_receive_message: read of kernel "
151
"notification failed. Error was %s.\n",
157
* Do a query to get the
158
* device and inode of the file that has the break
159
* request outstanding.
162
if(sys_fcntl_ptr(ctx->read_fd, F_OPLKSTAT, &os) < 0) {
163
DEBUG(0,("irix_oplock_receive_message: fcntl of kernel "
164
"notification failed. Error was %s.\n",
166
if(errno == EAGAIN) {
168
* Duplicate kernel break message - ignore.
176
* We only have device and inode info here - we have to guess that this
177
* is the first fsp open with this dev,ino pair.
179
* NOTE: this doesn't work if any VFS modules overloads
180
* the file_id_create() hook!
183
fileid = file_id_create_dev((SMB_DEV_T)os.os_dev,
184
(SMB_INO_T)os.os_ino);
185
if ((fsp = file_find_di_first(fileid)) == NULL) {
186
DEBUG(0,("irix_oplock_receive_message: unable to find open "
187
"file with dev = %x, inode = %.0f\n",
188
(unsigned int)os.os_dev, (double)os.os_ino ));
192
DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
193
"received for file_id %s gen_id = %ul",
194
file_id_string_tos(&fsp->file_id),
200
/****************************************************************************
201
Attempt to set an kernel oplock on a file.
202
****************************************************************************/
204
static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx,
205
files_struct *fsp, int oplock_type)
207
struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data,
208
struct irix_oplocks_context);
210
if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, ctx->write_fd) == -1) {
211
if(errno != EAGAIN) {
212
DEBUG(0,("irix_set_kernel_oplock: Unable to get "
213
"kernel oplock on file %s, file_id %s "
214
"gen_id = %ul. Error was %s\n",
215
fsp->fsp_name, file_id_string_tos(&fsp->file_id),
219
DEBUG(5,("irix_set_kernel_oplock: Refused oplock on "
220
"file %s, fd = %d, file_id = %s, "
221
"gen_id = %ul. Another process had the file "
223
fsp->fsp_name, fsp->fh->fd,
224
file_id_string_tos(&fsp->file_id),
230
DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s "
232
fsp->fsp_name, file_id_string_tos(&fsp->file_id),
238
/****************************************************************************
239
Release a kernel oplock on a file.
240
****************************************************************************/
242
static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx,
243
files_struct *fsp, int oplock_type)
247
* Check and print out the current kernel
248
* oplock state of this file.
250
int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
251
dbgtext("irix_release_kernel_oplock: file %s, file_id = %s"
252
"gen_id = %ul, has kernel oplock state "
253
"of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id),
254
fsp->fh->gen_id, state );
258
* Remove the kernel oplock on this file.
260
if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) {
262
dbgtext("irix_release_kernel_oplock: Error when "
263
"removing kernel oplock on file " );
264
dbgtext("%s, file_id = %s gen_id = %ul. "
266
fsp->fsp_name, file_id_string_tos(&fsp->file_id),
273
static void irix_oplocks_read_fde_handler(struct event_context *ev,
274
struct fd_event *fde,
278
struct irix_oplocks_context *ctx = talloc_get_type(private_data,
279
struct irix_oplocks_context);
282
fsp = irix_oplock_receive_message(ctx->ctx);
283
break_kernel_oplock(smbd_messaging_context(), fsp);
286
/****************************************************************************
287
Setup kernel oplocks.
288
****************************************************************************/
290
static const struct kernel_oplocks_ops irix_koplocks = {
291
.set_oplock = irix_set_kernel_oplock,
292
.release_oplock = irix_release_kernel_oplock,
293
.contend_level2_oplocks_begin = NULL,
294
.contend_level2_oplocks_end = NULL,
297
struct kernel_oplocks *irix_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
299
struct kernel_oplocks *_ctx;
300
struct irix_oplocks_context *ctx;
303
if (!irix_oplocks_available())
306
_ctx = talloc_zero(mem_ctx, struct kernel_oplocks);
311
ctx = talloc_zero(_ctx, struct irix_oplocks_context);
316
_ctx->ops = &irix_koplocks;
317
_ctx->private_data = ctx;
322
DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. "
323
"Error was %s\n", strerror(errno) ));
327
ctx->read_fd = pfd[0];
328
ctx->write_fd = pfd[1];
330
ctx->read_fde = event_add_fd(smbd_event_context(),
334
irix_oplocks_read_fde_handler,
339
void oplock_irix_dummy(void);
340
void oplock_irix_dummy(void) {}
341
#endif /* HAVE_KERNEL_OPLOCKS_IRIX */