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 #define LINUX_LEASE_RT_SIGNAL (SIGRTMIN+1)
35 struct linux_lease_pending
{
36 struct linux_lease_pending
*prev
, *next
;
37 struct sys_lease_context
*ctx
;
38 struct opendb_entry e
;
41 /* the global linked list of pending leases */
42 static struct linux_lease_pending
*leases
;
44 static void linux_lease_signal_handler(struct tevent_context
*ev_ctx
,
45 struct tevent_signal
*se
,
46 int signum
, int count
,
47 void *_info
, void *private_data
)
49 struct sys_lease_context
*ctx
= talloc_get_type(private_data
,
50 struct sys_lease_context
);
51 siginfo_t
*info
= (siginfo_t
*)_info
;
52 struct linux_lease_pending
*c
;
53 int got_fd
= info
->si_fd
;
55 for (c
= leases
; c
; c
= c
->next
) {
56 int *fd
= (int *)c
->e
.fd
;
67 ctx
->break_send(ctx
->msg_ctx
, &c
->e
, OPLOCK_BREAK_TO_NONE
);
70 static int linux_lease_pending_destructor(struct linux_lease_pending
*p
)
73 int *fd
= (int *)p
->e
.fd
;
75 DLIST_REMOVE(leases
, p
);
81 ret
= fcntl(*fd
, F_SETLEASE
, F_UNLCK
);
83 DEBUG(0,("%s: failed to remove oplock: %s\n",
84 __FUNCTION__
, strerror(errno
)));
90 static NTSTATUS
linux_lease_init(struct sys_lease_context
*ctx
)
92 struct tevent_signal
*se
;
94 se
= tevent_add_signal(ctx
->event_ctx
, ctx
,
95 LINUX_LEASE_RT_SIGNAL
, SA_SIGINFO
,
96 linux_lease_signal_handler
, ctx
);
97 NT_STATUS_HAVE_NO_MEMORY(se
);
102 static NTSTATUS
linux_lease_setup(struct sys_lease_context
*ctx
,
103 struct opendb_entry
*e
)
106 int *fd
= (int *)e
->fd
;
107 struct linux_lease_pending
*p
;
109 if (e
->oplock_level
== OPLOCK_NONE
) {
112 } else if (e
->oplock_level
== OPLOCK_LEVEL_II
) {
114 * the linux kernel doesn't support level2 oplocks
115 * so fix up the granted oplock level
117 e
->oplock_level
= OPLOCK_NONE
;
118 e
->allow_level_II_oplock
= false;
123 p
= talloc(ctx
, struct linux_lease_pending
);
124 NT_STATUS_HAVE_NO_MEMORY(p
);
129 ret
= fcntl(*fd
, F_SETSIG
, LINUX_LEASE_RT_SIGNAL
);
132 return map_nt_error_from_unix(errno
);
135 ret
= fcntl(*fd
, F_SETLEASE
, F_WRLCK
);
138 return map_nt_error_from_unix(errno
);
141 DLIST_ADD(leases
, p
);
143 talloc_set_destructor(p
, linux_lease_pending_destructor
);
148 static NTSTATUS
linux_lease_remove(struct sys_lease_context
*ctx
,
149 struct opendb_entry
*e
);
151 static NTSTATUS
linux_lease_update(struct sys_lease_context
*ctx
,
152 struct opendb_entry
*e
)
154 struct linux_lease_pending
*c
;
156 for (c
= leases
; c
; c
= c
->next
) {
157 if (c
->e
.fd
== e
->fd
) {
163 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
167 * set the fd pointer to NULL so that the caller
168 * will not call the remove function as the oplock
178 static NTSTATUS
linux_lease_remove(struct sys_lease_context
*ctx
,
179 struct opendb_entry
*e
)
181 struct linux_lease_pending
*c
;
183 for (c
= leases
; c
; c
= c
->next
) {
184 if (c
->e
.fd
== e
->fd
) {
190 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
198 static struct sys_lease_ops linux_lease_ops
= {
200 .init
= linux_lease_init
,
201 .setup
= linux_lease_setup
,
202 .update
= linux_lease_update
,
203 .remove
= linux_lease_remove
207 initialialise the linux lease module
209 NTSTATUS
sys_lease_linux_init(void)
211 /* register ourselves as a system lease module */
212 return sys_lease_register(&linux_lease_ops
);