r15446: Tidy up the formatting of locking debug messages and make it more
[samba.git] / source3 / smbd / oplock_irix.c
1 /*
2    Unix SMB/CIFS implementation.
3    IRIX kernel oplock processing
4    Copyright (C) Andrew Tridgell 1992-1998
5    
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 2 of the License, or
9    (at your option) any later version.
10    
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.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #define DBGC_CLASS DBGC_LOCKING
22 #include "includes.h"
23
24 #if HAVE_KERNEL_OPLOCKS_IRIX
25
26 static int oplock_pipe_write = -1;
27 static int oplock_pipe_read = -1;
28
29 /****************************************************************************
30  Test to see if IRIX kernel oplocks work.
31 ****************************************************************************/
32
33 static BOOL irix_oplocks_available(void)
34 {
35         int fd;
36         int pfd[2];
37         pstring tmpname;
38
39         set_effective_capability(KERNEL_OPLOCK_CAPABILITY);
40
41         slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid());
42
43         if(pipe(pfd) != 0) {
44                 DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n",
45                          strerror(errno) ));
46                 return False;
47         }
48
49         if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) {
50                 DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n",
51                          tmpname, strerror(errno) ));
52                 unlink( tmpname );
53                 close(pfd[0]);
54                 close(pfd[1]);
55                 return False;
56         }
57
58         unlink(tmpname);
59
60         if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) {
61                 DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \
62 Disabling kernel oplock support.\n" ));
63                 close(pfd[0]);
64                 close(pfd[1]);
65                 close(fd);
66                 return False;
67         }
68
69         if(sys_fcntl_long(fd, F_OPLKACK, OP_REVOKE) < 0 ) {
70                 DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \
71 Disabling kernel oplock support.\n", strerror(errno) ));
72                 close(pfd[0]);
73                 close(pfd[1]);
74                 close(fd);
75                 return False;
76         }
77
78         close(pfd[0]);
79         close(pfd[1]);
80         close(fd);
81
82         return True;
83 }
84
85 /****************************************************************************
86  * Deal with the IRIX kernel <--> smbd
87  * oplock break protocol.
88 ****************************************************************************/
89
90 static files_struct *irix_oplock_receive_message(fd_set *fds)
91 {
92         extern int smb_read_error;
93         oplock_stat_t os;
94         char dummy;
95         files_struct *fsp;
96
97         /* Ensure we only get one call per select fd set. */
98         FD_CLR(oplock_pipe_read, fds);
99
100         /*
101          * Read one byte of zero to clear the
102          * kernel break notify message.
103          */
104
105         if(read(oplock_pipe_read, &dummy, 1) != 1) {
106                 DEBUG(0,("irix_oplock_receive_message: read of kernel "
107                          "notification failed. Error was %s.\n",
108                          strerror(errno) ));
109                 smb_read_error = READ_ERROR;
110                 return NULL;
111         }
112
113         /*
114          * Do a query to get the
115          * device and inode of the file that has the break
116          * request outstanding.
117          */
118
119         if(sys_fcntl_ptr(oplock_pipe_read, F_OPLKSTAT, &os) < 0) {
120                 DEBUG(0,("irix_oplock_receive_message: fcntl of kernel "
121                          "notification failed. Error was %s.\n",
122                          strerror(errno) ));
123                 if(errno == EAGAIN) {
124                         /*
125                          * Duplicate kernel break message - ignore.
126                          */
127                         return NULL;
128                 }
129                 smb_read_error = READ_ERROR;
130                 return NULL;
131         }
132
133         /*
134          * We only have device and inode info here - we have to guess that this
135          * is the first fsp open with this dev,ino pair.
136          */
137
138         if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev,
139                                       (SMB_INO_T)os.os_ino)) == NULL) {
140                 DEBUG(0,("irix_oplock_receive_message: unable to find open "
141                          "file with dev = %x, inode = %.0f\n",
142                          (unsigned int)os.os_dev, (double)os.os_ino ));
143                 return NULL;
144         }
145      
146         DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
147                  "received for dev = %x, inode = %.0f\n, file_id = %ul",
148                  (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id ));
149
150         return fsp;
151 }
152
153 /****************************************************************************
154  Attempt to set an kernel oplock on a file.
155 ****************************************************************************/
156
157 static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type)
158 {
159         if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) {
160                 if(errno != EAGAIN) {
161                         DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \
162 inode = %.0f, file_id = %ul. Error was %s\n", 
163                                  fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id,
164                                  strerror(errno) ));
165                 } else {
166                         DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
167 inode = %.0f, file_id = %ul. Another process had the file open.\n",
168                                  fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id ));
169                 }
170                 return False;
171         }
172         
173         DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n",
174                   fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id));
175
176         return True;
177 }
178
179 /****************************************************************************
180  Release a kernel oplock on a file.
181 ****************************************************************************/
182
183 static void irix_release_kernel_oplock(files_struct *fsp)
184 {
185         if (DEBUGLVL(10)) {
186                 /*
187                  * Check and print out the current kernel
188                  * oplock state of this file.
189                  */
190                 int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
191                 dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \
192 oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
193                         (double)fsp->inode, fsp->file_id, state );
194         }
195
196         /*
197          * Remove the kernel oplock on this file.
198          */
199         if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) {
200                 if( DEBUGLVL( 0 )) {
201                         dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " );
202                         dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n",
203                                 fsp->fsp_name, (unsigned int)fsp->dev, 
204                                 (double)fsp->inode, fsp->file_id, strerror(errno) );
205                 }
206         }
207 }
208
209 /****************************************************************************
210  See if there is a message waiting in this fd set.
211  Note that fds MAY BE NULL ! If so we must do our own select.
212 ****************************************************************************/
213
214 static BOOL irix_oplock_msg_waiting(fd_set *fds)
215 {
216         int selrtn;
217         fd_set myfds;
218         struct timeval to;
219
220         if (oplock_pipe_read == -1)
221                 return False;
222
223         if (fds) {
224                 return FD_ISSET(oplock_pipe_read, fds);
225         }
226
227         /* Do a zero-time select. We just need to find out if there
228          * are any outstanding messages. We use sys_select_intr as
229          * we need to ignore any signals. */
230
231         FD_ZERO(&myfds);
232         FD_SET(oplock_pipe_read, &myfds);
233
234         to = timeval_set(0, 0);
235         selrtn = sys_select_intr(oplock_pipe_read+1,&myfds,NULL,NULL,&to);
236         return (selrtn == 1) ? True : False;
237 }
238
239 /****************************************************************************
240  Setup kernel oplocks.
241 ****************************************************************************/
242
243 struct kernel_oplocks *irix_init_kernel_oplocks(void) 
244 {
245         int pfd[2];
246         static struct kernel_oplocks koplocks;
247
248         if (!irix_oplocks_available())
249                 return NULL;
250
251         if(pipe(pfd) != 0) {
252                 DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n",
253                          strerror(errno) ));
254                 return False;
255         }
256
257         oplock_pipe_read = pfd[0];
258         oplock_pipe_write = pfd[1];
259
260         koplocks.receive_message = irix_oplock_receive_message;
261         koplocks.set_oplock = irix_set_kernel_oplock;
262         koplocks.release_oplock = irix_release_kernel_oplock;
263         koplocks.msg_waiting = irix_oplock_msg_waiting;
264         koplocks.notification_fd = oplock_pipe_read;
265
266         return &koplocks;
267 }
268 #else
269  void oplock_irix_dummy(void) {}
270 #endif /* HAVE_KERNEL_OPLOCKS_IRIX */