#include "smbd/smbd.h"
#include "smbd/globals.h"
-#if HAVE_KERNEL_OPLOCKS_LINUX
+#ifdef HAVE_KERNEL_OPLOCKS_LINUX
#ifndef F_SETLEASE
#define F_SETLEASE 1024
#define F_GETLEASE 1025
#endif
-#ifndef CAP_LEASE
-#define CAP_LEASE 28
-#endif
-
#ifndef RT_SIGNAL_LEASE
#define RT_SIGNAL_LEASE (SIGRTMIN+1)
#endif
#define F_SETSIG 10
#endif
-/*
- * public function to get linux lease capability. Needed by some VFS modules (eg. gpfs.c)
- */
-void linux_set_lease_capability(void)
-{
- set_effective_capability(LEASE_CAPABILITY);
-}
-
/*
* Call to set the kernel lease signal handler
*/
int linux_setlease(int fd, int leasetype)
{
int ret;
+ int saved_errno;
+
+ /*
+ * Ensure the lease owner is root to allow
+ * correct delivery of lease-break signals.
+ */
+
+ become_root();
/* First set the signal handler. */
if (linux_set_lease_sighandler(fd) == -1) {
- return -1;
+ saved_errno = errno;
+ ret = -1;
+ goto out;
}
ret = fcntl(fd, F_SETLEASE, leasetype);
- if (ret == -1 && errno == EACCES) {
- set_effective_capability(LEASE_CAPABILITY);
- /*
- * Bug 8974 - work around Linux kernel bug
- * https://bugzilla.kernel.org/show_bug.cgi?id=43336.
- * "fcntl(F_SETLEASE) resets signal number when
- * called multiple times"
- */
- if (linux_set_lease_sighandler(fd) == -1) {
- return -1;
- }
- ret = fcntl(fd, F_SETLEASE, leasetype);
+ if (ret == -1) {
+ saved_errno = errno;
}
+ out:
+
+ unbecome_root();
+
+ if (ret == -1) {
+ errno = saved_errno;
+ }
return ret;
}
static bool linux_set_kernel_oplock(struct kernel_oplocks *ctx,
files_struct *fsp, int oplock_type)
{
+ struct file_id_buf idbuf;
+
if ( SMB_VFS_LINUX_SETLEASE(fsp, F_WRLCK) == -1) {
- DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, "
- "fd = %d, file_id = %s. (%s)\n",
- fsp_str_dbg(fsp), fsp->fh->fd,
- file_id_string_tos(&fsp->file_id),
- strerror(errno)));
+ DBG_NOTICE("Refused oplock on file %s, "
+ "fd = %d, file_id = %s. (%s)\n",
+ fsp_str_dbg(fsp),
+ fsp->fh->fd,
+ file_id_str_buf(fsp->file_id, &idbuf),
+ strerror(errno));
return False;
}
- DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, "
- "file_id = %s gen_id = %lu\n",
- fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id),
- fsp->fh->gen_id));
+ DBG_NOTICE("got kernel oplock on file %s, "
+ "file_id = %s gen_id = %"PRIu64"\n",
+ fsp_str_dbg(fsp),
+ file_id_str_buf(fsp->file_id, &idbuf),
+ fsp->fh->gen_id);
return True;
}
static void linux_release_kernel_oplock(struct kernel_oplocks *ctx,
files_struct *fsp, int oplock_type)
{
+ struct file_id_buf idbuf;
+
if (DEBUGLVL(10)) {
/*
* Check and print out the current kernel
*/
int state = fcntl(fsp->fh->fd, F_GETLEASE, 0);
dbgtext("linux_release_kernel_oplock: file %s, file_id = %s "
- "gen_id = %lu has kernel oplock state "
- "of %x.\n", fsp_str_dbg(fsp),
- file_id_string_tos(&fsp->file_id),
- fsp->fh->gen_id, state );
+ "gen_id = %"PRIu64" has kernel oplock state "
+ "of %x.\n",
+ fsp_str_dbg(fsp),
+ file_id_str_buf(fsp->file_id, &idbuf),
+ fsp->fh->gen_id,
+ state);
}
/*
if (DEBUGLVL(0)) {
dbgtext("linux_release_kernel_oplock: Error when "
"removing kernel oplock on file " );
- dbgtext("%s, file_id = %s, gen_id = %lu. "
- "Error was %s\n", fsp_str_dbg(fsp),
- file_id_string_tos(&fsp->file_id),
- fsp->fh->gen_id, strerror(errno) );
+ dbgtext("%s, file_id = %s, gen_id = %"PRIu64". "
+ "Error was %s\n",
+ fsp_str_dbg(fsp),
+ file_id_str_buf(fsp->file_id, &idbuf),
+ fsp->fh->gen_id,
+ strerror(errno));
}
}
}
static const struct kernel_oplocks_ops linux_koplocks = {
.set_oplock = linux_set_kernel_oplock,
.release_oplock = linux_release_kernel_oplock,
- .contend_level2_oplocks_begin = NULL,
- .contend_level2_oplocks_end = NULL,
};
struct kernel_oplocks *linux_init_kernel_oplocks(struct smbd_server_connection *sconn)