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) ));
106 /****************************************************************************
107 * Deal with the IRIX kernel <--> smbd
108 * oplock break protocol.
109 ****************************************************************************/
111 static files_struct *irix_oplock_receive_message(struct kernel_oplocks *_ctx)
113 struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data,
114 struct irix_oplocks_context);
117 struct file_id fileid;
121 * TODO: is it correct to assume we only get one
122 * oplock break, for each byte we read from the pipe?
124 ctx->pending = false;
127 * Read one byte of zero to clear the
128 * kernel break notify message.
131 if(read(ctx->read_fd, &dummy, 1) != 1) {
132 DEBUG(0,("irix_oplock_receive_message: read of kernel "
133 "notification failed. Error was %s.\n",
139 * Do a query to get the
140 * device and inode of the file that has the break
141 * request outstanding.
144 if(sys_fcntl_ptr(ctx->read_fd, F_OPLKSTAT, &os) < 0) {
145 DEBUG(0,("irix_oplock_receive_message: fcntl of kernel "
146 "notification failed. Error was %s.\n",
148 if(errno == EAGAIN) {
150 * Duplicate kernel break message - ignore.
158 * We only have device and inode info here - we have to guess that this
159 * is the first fsp open with this dev,ino pair.
161 * NOTE: this doesn't work if any VFS modules overloads
162 * the file_id_create() hook!
165 fileid = file_id_create_dev((SMB_DEV_T)os.os_dev,
166 (SMB_INO_T)os.os_ino);
167 if ((fsp = file_find_di_first(fileid)) == NULL) {
168 DEBUG(0,("irix_oplock_receive_message: unable to find open "
169 "file with dev = %x, inode = %.0f\n",
170 (unsigned int)os.os_dev, (double)os.os_ino ));
174 DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
175 "received for file_id %s gen_id = %ul",
176 file_id_string_tos(&fsp->file_id),
182 /****************************************************************************
183 Attempt to set an kernel oplock on a file.
184 ****************************************************************************/
186 static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx,
187 files_struct *fsp, int oplock_type)
189 struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data,
190 struct irix_oplocks_context);
192 if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, ctx->write_fd) == -1) {
193 if(errno != EAGAIN) {
194 DEBUG(0,("irix_set_kernel_oplock: Unable to get "
195 "kernel oplock on file %s, file_id %s "
196 "gen_id = %ul. Error was %s\n",
197 fsp->fsp_name, file_id_string_tos(&fsp->file_id),
201 DEBUG(5,("irix_set_kernel_oplock: Refused oplock on "
202 "file %s, fd = %d, file_id = %s, "
203 "gen_id = %ul. Another process had the file "
205 fsp->fsp_name, fsp->fh->fd,
206 file_id_string_tos(&fsp->file_id),
212 DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s "
214 fsp->fsp_name, file_id_string_tos(&fsp->file_id),
220 /****************************************************************************
221 Release a kernel oplock on a file.
222 ****************************************************************************/
224 static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx,
229 * Check and print out the current kernel
230 * oplock state of this file.
232 int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
233 dbgtext("irix_release_kernel_oplock: file %s, file_id = %s"
234 "gen_id = %ul, has kernel oplock state "
235 "of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id),
236 fsp->fh->gen_id, state );
240 * Remove the kernel oplock on this file.
242 if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) {
244 dbgtext("irix_release_kernel_oplock: Error when "
245 "removing kernel oplock on file " );
246 dbgtext("%s, file_id = %s gen_id = %ul. "
248 fsp->fsp_name, file_id_string_tos(&fsp->file_id),
255 static void irix_oplocks_read_fde_handler(struct event_context *ev,
256 struct fd_event *fde,
260 struct irix_oplocks_context *ctx = talloc_get_type(private_data,
261 struct irix_oplocks_context);
264 fsp = irix_oplock_receive_message(ctx->ctx);
265 break_kernel_oplock(smbd_messaging_context(), fsp);
268 /****************************************************************************
269 Setup kernel oplocks.
270 ****************************************************************************/
272 static const struct kernel_oplocks_ops irix_koplocks = {
273 .set_oplock = irix_set_kernel_oplock,
274 .release_oplock = irix_release_kernel_oplock,
277 struct kernel_oplocks *irix_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
279 struct kernel_oplocks *_ctx;
280 struct irix_oplocks_context *ctx;
283 if (!irix_oplocks_available())
286 _ctx = talloc_zero(mem_ctx, struct kernel_oplocks);
291 ctx = talloc_zero(_ctx, struct irix_oplocks_context);
296 _ctx->ops = &irix_koplocks;
297 _ctx->private_data = ctx;
302 DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. "
303 "Error was %s\n", strerror(errno) ));
307 ctx->read_fd = pfd[0];
308 ctx->write_fd = pfd[1];
310 ctx->read_fde = event_add_fd(smbd_event_context(),
314 irix_oplocks_read_fde_handler,
319 void oplock_irix_dummy(void);
320 void oplock_irix_dummy(void) {}
321 #endif /* HAVE_KERNEL_OPLOCKS_IRIX */