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