2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2008
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/>.
21 lease (oplock) implementation using fcntl F_SETLEASE on linux
26 #include "system/filesys.h"
27 #include "ntvfs/sysdep/sys_lease.h"
28 #include "ntvfs/ntvfs.h"
29 #include "librpc/gen_ndr/ndr_opendb.h"
30 #include "../lib/util/dlinklist.h"
31 #include "cluster/cluster.h"
33 NTSTATUS
sys_lease_linux_init(void);
35 #define LINUX_LEASE_RT_SIGNAL (SIGRTMIN+1)
37 struct linux_lease_pending
{
38 struct linux_lease_pending
*prev
, *next
;
39 struct sys_lease_context
*ctx
;
40 struct opendb_entry e
;
43 /* the global linked list of pending leases */
44 static struct linux_lease_pending
*leases
;
46 static void linux_lease_signal_handler(struct tevent_context
*ev_ctx
,
47 struct tevent_signal
*se
,
48 int signum
, int count
,
49 void *_info
, void *private_data
)
51 struct sys_lease_context
*ctx
= talloc_get_type(private_data
,
52 struct sys_lease_context
);
53 siginfo_t
*info
= (siginfo_t
*)_info
;
54 struct linux_lease_pending
*c
;
55 int got_fd
= info
->si_fd
;
57 for (c
= leases
; c
; c
= c
->next
) {
58 int *fd
= (int *)c
->e
.fd
;
69 ctx
->break_send(ctx
->msg_ctx
, &c
->e
, OPLOCK_BREAK_TO_NONE
);
72 static int linux_lease_pending_destructor(struct linux_lease_pending
*p
)
75 int *fd
= (int *)p
->e
.fd
;
77 DLIST_REMOVE(leases
, p
);
83 ret
= fcntl(*fd
, F_SETLEASE
, F_UNLCK
);
85 DEBUG(0,("%s: failed to remove oplock: %s\n",
86 __FUNCTION__
, strerror(errno
)));
92 static NTSTATUS
linux_lease_init(struct sys_lease_context
*ctx
)
94 struct tevent_signal
*se
;
96 se
= tevent_add_signal(ctx
->event_ctx
, ctx
,
97 LINUX_LEASE_RT_SIGNAL
, SA_SIGINFO
,
98 linux_lease_signal_handler
, ctx
);
99 NT_STATUS_HAVE_NO_MEMORY(se
);
104 static NTSTATUS
linux_lease_setup(struct sys_lease_context
*ctx
,
105 struct opendb_entry
*e
)
108 int *fd
= (int *)e
->fd
;
109 struct linux_lease_pending
*p
;
111 if (e
->oplock_level
== OPLOCK_NONE
) {
114 } else if (e
->oplock_level
== OPLOCK_LEVEL_II
) {
116 * the linux kernel doesn't support level2 oplocks
117 * so fix up the granted oplock level
119 e
->oplock_level
= OPLOCK_NONE
;
120 e
->allow_level_II_oplock
= false;
125 p
= talloc(ctx
, struct linux_lease_pending
);
126 NT_STATUS_HAVE_NO_MEMORY(p
);
131 ret
= fcntl(*fd
, F_SETSIG
, LINUX_LEASE_RT_SIGNAL
);
134 return map_nt_error_from_unix_common(errno
);
137 ret
= fcntl(*fd
, F_SETLEASE
, F_WRLCK
);
140 return map_nt_error_from_unix_common(errno
);
143 DLIST_ADD(leases
, p
);
145 talloc_set_destructor(p
, linux_lease_pending_destructor
);
150 static NTSTATUS
linux_lease_remove(struct sys_lease_context
*ctx
,
151 struct opendb_entry
*e
);
153 static NTSTATUS
linux_lease_update(struct sys_lease_context
*ctx
,
154 struct opendb_entry
*e
)
156 struct linux_lease_pending
*c
;
158 for (c
= leases
; c
; c
= c
->next
) {
159 if (c
->e
.fd
== e
->fd
) {
165 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
169 * set the fd pointer to NULL so that the caller
170 * will not call the remove function as the oplock
180 static NTSTATUS
linux_lease_remove(struct sys_lease_context
*ctx
,
181 struct opendb_entry
*e
)
183 struct linux_lease_pending
*c
;
185 for (c
= leases
; c
; c
= c
->next
) {
186 if (c
->e
.fd
== e
->fd
) {
192 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
200 static struct sys_lease_ops linux_lease_ops
= {
202 .init
= linux_lease_init
,
203 .setup
= linux_lease_setup
,
204 .update
= linux_lease_update
,
205 .remove
= linux_lease_remove
209 initialialise the linux lease module
211 NTSTATUS
sys_lease_linux_init(void)
213 /* register ourselves as a system lease module */
214 return sys_lease_register(&linux_lease_ops
);