LCOV - code coverage report
Current view: top level - source4/ntvfs/sysdep - sys_lease_linux.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 2 68 2.9 %
Date: 2021-09-23 10:06:22 Functions: 1 7 14.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher 2008
       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             : /*
      21             :   lease (oplock) implementation using fcntl F_SETLEASE on linux
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include <tevent.h>
      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"
      32             : 
      33             : NTSTATUS sys_lease_linux_init(TALLOC_CTX *);
      34             : 
      35             : #define LINUX_LEASE_RT_SIGNAL (SIGRTMIN+1)
      36             : 
      37             : struct linux_lease_pending {
      38             :         struct linux_lease_pending *prev, *next;
      39             :         struct sys_lease_context *ctx;
      40             :         struct opendb_entry e;
      41             : };
      42             : 
      43             : /* the global linked list of pending leases */
      44             : static struct linux_lease_pending *leases;
      45             : 
      46           0 : 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)
      50             : {
      51           0 :         struct sys_lease_context *ctx = talloc_get_type(private_data,
      52             :                                         struct sys_lease_context);
      53           0 :         siginfo_t *info = (siginfo_t *)_info;
      54             :         struct linux_lease_pending *c;
      55           0 :         int got_fd = info->si_fd;
      56             : 
      57           0 :         for (c = leases; c; c = c->next) {
      58           0 :                 int *fd = (int *)c->e.fd;
      59             : 
      60           0 :                 if (got_fd == *fd) {
      61           0 :                         break;
      62             :                 }
      63             :         }
      64             : 
      65           0 :         if (!c) {
      66           0 :                 return;
      67             :         }
      68             : 
      69           0 :         ctx->break_send(ctx->msg_ctx, &c->e, OPLOCK_BREAK_TO_NONE);
      70             : }
      71             : 
      72           0 : static int linux_lease_pending_destructor(struct linux_lease_pending *p)
      73             : {
      74             :         int ret;
      75           0 :         int *fd = (int *)p->e.fd;
      76             : 
      77           0 :         DLIST_REMOVE(leases, p);
      78             : 
      79           0 :         if (*fd == -1) {
      80           0 :                 return 0;
      81             :         }
      82             : 
      83           0 :         ret = fcntl(*fd, F_SETLEASE, F_UNLCK);
      84           0 :         if (ret == -1) {
      85           0 :                 DEBUG(0,("%s: failed to remove oplock: %s\n",
      86             :                         __FUNCTION__, strerror(errno)));
      87             :         }
      88             : 
      89           0 :         return 0;
      90             : }
      91             : 
      92           0 : static NTSTATUS linux_lease_init(struct sys_lease_context *ctx)
      93             : {
      94             :         struct tevent_signal *se;
      95             : 
      96           0 :         se = tevent_add_signal(ctx->event_ctx, ctx,
      97             :                                LINUX_LEASE_RT_SIGNAL, SA_SIGINFO,
      98             :                                linux_lease_signal_handler, ctx);
      99           0 :         NT_STATUS_HAVE_NO_MEMORY(se);
     100             : 
     101           0 :         return NT_STATUS_OK;
     102             : }
     103             : 
     104           0 : static NTSTATUS linux_lease_setup(struct sys_lease_context *ctx,
     105             :                                   struct opendb_entry *e)
     106             : {
     107             :         int ret;
     108           0 :         int *fd = (int *)e->fd;
     109             :         struct linux_lease_pending *p;
     110             : 
     111           0 :         if (e->oplock_level == OPLOCK_NONE) {
     112           0 :                 e->fd = NULL;
     113           0 :                 return NT_STATUS_OK;
     114           0 :         } else if (e->oplock_level == OPLOCK_LEVEL_II) {
     115             :                 /*
     116             :                  * the linux kernel doesn't support level2 oplocks
     117             :                  * so fix up the granted oplock level
     118             :                  */
     119           0 :                 e->oplock_level = OPLOCK_NONE;
     120           0 :                 e->allow_level_II_oplock = false;
     121           0 :                 e->fd = NULL;
     122           0 :                 return NT_STATUS_OK;
     123             :         }
     124             : 
     125           0 :         p = talloc(ctx, struct linux_lease_pending);
     126           0 :         NT_STATUS_HAVE_NO_MEMORY(p);
     127             : 
     128           0 :         p->ctx = ctx;
     129           0 :         p->e = *e;
     130             : 
     131           0 :         ret = fcntl(*fd, F_SETSIG, LINUX_LEASE_RT_SIGNAL);
     132           0 :         if (ret == -1) {
     133           0 :                 talloc_free(p);
     134           0 :                 return map_nt_error_from_unix_common(errno);
     135             :         }
     136             : 
     137           0 :         ret = fcntl(*fd, F_SETLEASE, F_WRLCK);
     138           0 :         if (ret == -1) {
     139           0 :                 talloc_free(p);
     140           0 :                 return map_nt_error_from_unix_common(errno);
     141             :         }
     142             : 
     143           0 :         DLIST_ADD(leases, p);
     144             : 
     145           0 :         talloc_set_destructor(p, linux_lease_pending_destructor);
     146             : 
     147           0 :         return NT_STATUS_OK;
     148             : }
     149             : 
     150             : static NTSTATUS linux_lease_remove(struct sys_lease_context *ctx,
     151             :                                    struct opendb_entry *e);
     152             : 
     153           0 : static NTSTATUS linux_lease_update(struct sys_lease_context *ctx,
     154             :                                    struct opendb_entry *e)
     155             : {
     156             :         struct linux_lease_pending *c;
     157             : 
     158           0 :         for (c = leases; c; c = c->next) {
     159           0 :                 if (c->e.fd == e->fd) {
     160           0 :                         break;
     161             :                 }
     162             :         }
     163             : 
     164           0 :         if (!c) {
     165           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     166             :         }
     167             : 
     168             :         /*
     169             :          * set the fd pointer to NULL so that the caller
     170             :          * will not call the remove function as the oplock
     171             :          * is already removed
     172             :          */
     173           0 :         e->fd = NULL;
     174             : 
     175           0 :         talloc_free(c);
     176             : 
     177           0 :         return NT_STATUS_OK;
     178             : }
     179             : 
     180           0 : static NTSTATUS linux_lease_remove(struct sys_lease_context *ctx,
     181             :                                    struct opendb_entry *e)
     182             : {
     183             :         struct linux_lease_pending *c;
     184             : 
     185           0 :         for (c = leases; c; c = c->next) {
     186           0 :                 if (c->e.fd == e->fd) {
     187           0 :                         break;
     188             :                 }
     189             :         }
     190             : 
     191           0 :         if (!c) {
     192           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     193             :         }
     194             : 
     195           0 :         talloc_free(c);
     196             : 
     197           0 :         return NT_STATUS_OK;
     198             : }
     199             : 
     200             : static struct sys_lease_ops linux_lease_ops = {
     201             :         .name   = "linux",
     202             :         .init   = linux_lease_init,
     203             :         .setup  = linux_lease_setup,
     204             :         .update = linux_lease_update,
     205             :         .remove = linux_lease_remove
     206             : };
     207             : 
     208             : /*
     209             :   initialialise the linux lease module
     210             :  */
     211           4 : NTSTATUS sys_lease_linux_init(TALLOC_CTX *ctx)
     212             : {
     213             :         /* register ourselves as a system lease module */
     214           4 :         return sys_lease_register(ctx, &linux_lease_ops);
     215             : }

Generated by: LCOV version 1.13