From 40d0707827ee154bcb03013abe6f72f1026a70c9 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 22 Mar 2006 23:49:09 +0000 Subject: r14668: Set the FILE_STATUS_OFFLINE bit by observing the events a DMAPI-based HSM is interested in. Tested on both IRIX and SLES9. (This used to be commit 514a767c57f8194547e5b708ad2573ab9a0719c6) --- source3/smbd/dmapi.c | 576 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 576 insertions(+) create mode 100644 source3/smbd/dmapi.c (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c new file mode 100644 index 0000000000..0fa3a16760 --- /dev/null +++ b/source3/smbd/dmapi.c @@ -0,0 +1,576 @@ +/* + Unix SMB/CIFS implementation. + DMAPI Support routines + + Copyright (C) James Peach 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_DMAPI + +#if defined(HAVE_LIBDM) +#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) +#define USE_DMAPI 1 +#endif +#endif + +#ifndef USE_DMAPI + +int dmapi_init_session(void) { return -1; } +uint32 dmapi_file_flags(const char * const path) { return 0; } +BOOL dmapi_have_session(void) { return False; } + +#else /* USE_DMAPI */ + +#ifdef HAVE_XFS_DMAPI_H +#include +#endif + +#ifdef HAVE_SYS_DMI_H +#include +#endif + +#define DMAPI_SESSION_NAME "samba" +#define DMAPI_TRACE 10 + +static dm_sessid_t dmapi_session = DM_NO_SESSION; + +/* Initialise the DMAPI interface. Make sure that we only end up initialising + * once per process to avoid resource leaks across different DMAPI + * implementations. + */ +static int init_dmapi_service(void) +{ + static pid_t lastpid; + + pid_t mypid; + + mypid = sys_getpid(); + if (mypid != lastpid) { + char *version; + + lastpid = mypid; + if (dm_init_service(&version) < 0) { + return -1; + } + + DEBUG(0, ("Initializing DMAPI: %s\n", version)); + } + + return 0; +} + +BOOL dmapi_have_session(void) +{ + return dmapi_session != DM_NO_SESSION; +} + +static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) +{ + dm_sessid_t *nsessions; + + nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); + if (nsessions == NULL) { + TALLOC_FREE(sessions); + return NULL; + } + + return nsessions; +} + +/* Initialise DMAPI session. The session is persistant kernel state, so it + * might already exist, in which case we merely want to reconnect to it. This + * function should be called as root. + */ +int dmapi_init_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + uint nsessions = 10; + dm_sessid_t *sessions = NULL; + + int i, err; + + /* If we aren't root, something in the following will fail due to lack + * of privileges. Aborting seems a little extreme. + */ + SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); + + dmapi_session = DM_NO_SESSION; + if (init_dmapi_service() < 0) { + return -1; + } + +retry: + + if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { + return -1; + } + + err = dm_getall_sessions(nsessions, sessions, &nsessions); + if (err < 0) { + if (errno == E2BIG) { + nsessions *= 2; + goto retry; + } + + DEBUGADD(DMAPI_TRACE, + ("failed to retrieve DMAPI sessions: %s\n", + strerror(errno))); + TALLOC_FREE(sessions); + return -1; + } + + for (i = 0; i < nsessions; ++i) { + err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); + buf[sizeof(buf) - 1] = '\0'; + if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { + dmapi_session = sessions[i]; + DEBUGADD(DMAPI_TRACE, + ("attached to existing DMAPI session " + "named '%s'\n", buf)); + break; + } + } + + TALLOC_FREE(sessions); + + /* No session already defined. */ + if (dmapi_session == DM_NO_SESSION) { + err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, + &dmapi_session); + if (err < 0) { + DEBUGADD(DMAPI_TRACE, + ("failed to create new DMAPI session: %s\n", + strerror(errno))); + dmapi_session = DM_NO_SESSION; + return -1; + } + + DEBUGADD(DMAPI_TRACE, + ("created new DMAPI session named '%s'\n", + DMAPI_SESSION_NAME)); + } + + /* Note that we never end the DMAPI session. This enables child + * processes to continue to use the session after we exit. It also lets + * you run a second Samba server on different ports without any + * conflict. + */ + + return 0; +} + +/* Reattach to an existing dmapi session. Called from service processes that + * might not be running as root. + */ +static int reattach_dmapi_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + if (dmapi_session != DM_NO_SESSION ) { + become_root(); + + /* NOTE: On Linux, this call opens /dev/dmapi, costing us a + * file descriptor. Ideally, we would close this when we fork. + */ + if (init_dmapi_service() < 0) { + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + if (dm_query_session(dmapi_session, sizeof(buf), + buf, &buflen) < 0) { + /* Session is stale. Disable DMAPI. */ + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + set_effective_capability(DMAPI_ACCESS_CAPABILITY); + + DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); + unbecome_root(); + } + + return 0; +} + +uint32 dmapi_file_flags(const char * const path) +{ + static int attached = 0; + + int err; + dm_eventset_t events = {0}; + uint nevents; + + void *dm_handle; + size_t dm_handle_len; + + uint32 flags = 0; + + /* If a DMAPI session has been initialised, then we need to make sure + * we are attached to it and have the correct privileges. This is + * necessary to be able to do DMAPI operations across a fork(2). If + * it fails, there is no liklihood of that failure being transient. + * + * Note that this use of the static attached flag relies on the fact + * that dmapi_file_flags() is never called prior to forking the + * per-client server process. + */ + if (dmapi_have_session() && !attached) { + attached++; + if (reattach_dmapi_session() < 0) { + return 0; + } + } + + err = dm_path_to_handle(CONST_DISCARD(char *, path), + &dm_handle, &dm_handle_len); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n", + path, strerror(errno))); + + if (errno != EPERM) { + return 0; + } + + /* Linux capabilities are broken in that changing our + * user ID will clobber out effective capabilities irrespective + * of whether we have set PR_SET_KEEPCAPS. Fortunately, the + * capabilities are not removed from our permitted set, so we + * can re-acquire them if necessary. + */ + + set_effective_capability(DMAPI_ACCESS_CAPABILITY); + + err = dm_path_to_handle(CONST_DISCARD(char *, path), + &dm_handle, &dm_handle_len); + if (err < 0) { + DEBUG(DMAPI_TRACE, + ("retrying dm_path_to_handle(%s): %s\n", + path, strerror(errno))); + return 0; + } + } + + err = dm_get_eventlist(dmapi_session, dm_handle, dm_handle_len, + DM_NO_TOKEN, DM_EVENT_MAX, &events, &nevents); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_get_eventlist(%s): %s\n", + path, strerror(errno))); + dm_handle_free(dm_handle, dm_handle_len); + return 0; + } + + /* We figure that the only reason a DMAPI application would be + * interested in trapping read events is that part of the file is + * offline. + */ + DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", + path, events)); + if (DMEV_ISSET(DM_EVENT_READ, events)) { + flags = FILE_ATTRIBUTE_OFFLINE; + } + + dm_handle_free(dm_handle, dm_handle_len); + + if (flags & FILE_ATTRIBUTE_OFFLINE) { + DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); + } + + return flags; +} + +#endif /* USE_DMAPI */ +/* + Unix SMB/CIFS implementation. + DMAPI Support routines + + Copyright (C) Silicon Graphics, Inc. 2006. All rights reserved. + James Peach + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_DMAPI + +#if defined(HAVE_LIBDM) +#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) +#define USE_DMAPI 1 +#endif +#endif + +#ifndef USE_DMAPI + +int dmapi_init_session(void) { return -1; } +uint32 dmapi_file_flags(const char * const path) { return 0; } +BOOL dmapi_have_session(void) { return False; } + +#else /* USE_DMAPI */ + +#ifdef HAVE_XFS_DMAPI_H +#include +#endif + +#ifdef HAVE_SYS_DMI_H +#include +#endif + +#define DMAPI_SESSION_NAME "samba" +#define DMAPI_TRACE 10 + +static dm_sessid_t dmapi_session = DM_NO_SESSION; + +/* Initialise the DMAPI interface. Make sure that we only end up initialising + * once per process to avoid resource leaks across different DMAPI + * implementations. + */ +static int init_dmapi_service(void) +{ + static pid_t lastpid; + + pid_t mypid; + + mypid = sys_getpid(); + if (mypid != lastpid) { + char *version; + + lastpid = mypid; + if (dm_init_service(&version) < 0) { + return -1; + } + + DEBUG(0, ("Initializing DMAPI: %s\n", version)); + } + + return 0; +} + +BOOL dmapi_have_session(void) +{ + return dmapi_session != DM_NO_SESSION; +} + +static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) +{ + dm_sessid_t *nsessions; + + nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); + if (nsessions == NULL) { + TALLOC_FREE(sessions); + return NULL; + } + + return nsessions; +} + +/* Initialise DMAPI session. The session is persistant kernel state, so it + * might already exist, in which case we merely want to reconnect to it. This + * function should be called as root. + */ +int dmapi_init_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + uint nsessions = 10; + dm_sessid_t *sessions = NULL; + + int i, err; + + /* If we aren't root, something in the following will fail due to lack + * of privileges. Aborting seems a little extreme. + */ + SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); + + dmapi_session = DM_NO_SESSION; + if (init_dmapi_service() < 0) { + return -1; + } + +retry: + + if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { + return -1; + } + + err = dm_getall_sessions(nsessions, sessions, &nsessions); + if (err < 0) { + if (errno == E2BIG) { + nsessions *= 2; + goto retry; + } + + DEBUGADD(DMAPI_TRACE, + ("failed to retrieve DMAPI sessions: %s\n", + strerror(errno))); + TALLOC_FREE(sessions); + return -1; + } + + for (i = 0; i < nsessions; ++i) { + err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); + buf[sizeof(buf) - 1] = '\0'; + if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { + dmapi_session = sessions[i]; + DEBUGADD(DMAPI_TRACE, + ("attached to existing DMAPI session " + "named '%s'\n", buf)); + break; + } + } + + TALLOC_FREE(sessions); + + /* No session already defined. */ + if (dmapi_session == DM_NO_SESSION) { + err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, + &dmapi_session); + if (err < 0) { + DEBUGADD(DMAPI_TRACE, + ("failed to create new DMAPI session: %s\n", + strerror(errno))); + return -1; + } + + DEBUGADD(DMAPI_TRACE, + ("created new DMAPI session named '%s'\n", + DMAPI_SESSION_NAME)); + } + + /* Note that we never end the DMAPI session. This enables child + * processes to continue to use the session after we exit. It also lets + * you run a second Samba server on different ports without any + * conflict. + */ + + return 0; +} + +/* Reattach to an existing dmapi session. Called from service processes that + * might not be running as root. + */ +static int reattach_dmapi_session(void) +{ + char buf[DM_SESSION_INFO_LEN]; + size_t buflen; + + if (dmapi_session != DM_NO_SESSION ) { + become_root(); + + /* NOTE: On Linux, this call opens /dev/dmapi, costing us a + * file descriptor. Ideally, we would close this when we fork. + */ + if (init_dmapi_service() < 0) { + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + if (dm_query_session(dmapi_session, sizeof(buf), + buf, &buflen) < 0) { + /* Session is stale. Disable DMAPI. */ + dmapi_session = DM_NO_SESSION; + unbecome_root(); + return -1; + } + + set_effective_capability(DMAPI_ACCESS_CAPABILITY); + + DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); + unbecome_root(); + return 0; + } + + return 0; +} + +uint32 dmapi_file_flags(const char * const path) +{ + int err; + dm_eventset_t events = {0}; + uint nevents; + + void *dm_handle; + size_t dm_handle_len; + + uint32 flags = 0; + + if (dmapi_have_session()) { + if (reattach_dmapi_session() < 0) { + return 0; + } + } + + err = dm_path_to_handle(CONST_DISCARD(char *, path), + &dm_handle, &dm_handle_len); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n", + path, strerror(errno))); + return 0; + } + + err = dm_get_eventlist(dmapi_session, dm_handle, dm_handle_len, + DM_NO_TOKEN, DM_EVENT_MAX, &events, &nevents); + if (err < 0) { + DEBUG(DMAPI_TRACE, ("dm_get_eventlist: %s\n", + strerror(errno))); + dm_handle_free(dm_handle, dm_handle_len); + return 0; + } + + /* We figure that the only reason a DMAPI application would be + * interested in trapping read events is that part of the file is + * offline. + */ + DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", + path, events)); + if (DMEV_ISSET(DM_EVENT_READ, events)) { + flags = FILE_ATTRIBUTE_OFFLINE; + } + + dm_handle_free(dm_handle, dm_handle_len); + + if (flags & FILE_ATTRIBUTE_OFFLINE) { + DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); + } + + return flags; +} + +#endif /* USE_DMAPI */ -- cgit From a7d1a32b1470c5903ae720cfbc0f05ed2348c931 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 23 Mar 2006 00:12:37 +0000 Subject: r14669: Remove duplicate source caused by running patch(1) once too often. (This used to be commit 0ebbfc867c71002eaf921f4f4d8aa7d7b78973a7) --- source3/smbd/dmapi.c | 272 --------------------------------------------------- 1 file changed, 272 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 0fa3a16760..2188924d4b 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -302,275 +302,3 @@ uint32 dmapi_file_flags(const char * const path) } #endif /* USE_DMAPI */ -/* - Unix SMB/CIFS implementation. - DMAPI Support routines - - Copyright (C) Silicon Graphics, Inc. 2006. All rights reserved. - James Peach - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_DMAPI - -#if defined(HAVE_LIBDM) -#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) -#define USE_DMAPI 1 -#endif -#endif - -#ifndef USE_DMAPI - -int dmapi_init_session(void) { return -1; } -uint32 dmapi_file_flags(const char * const path) { return 0; } -BOOL dmapi_have_session(void) { return False; } - -#else /* USE_DMAPI */ - -#ifdef HAVE_XFS_DMAPI_H -#include -#endif - -#ifdef HAVE_SYS_DMI_H -#include -#endif - -#define DMAPI_SESSION_NAME "samba" -#define DMAPI_TRACE 10 - -static dm_sessid_t dmapi_session = DM_NO_SESSION; - -/* Initialise the DMAPI interface. Make sure that we only end up initialising - * once per process to avoid resource leaks across different DMAPI - * implementations. - */ -static int init_dmapi_service(void) -{ - static pid_t lastpid; - - pid_t mypid; - - mypid = sys_getpid(); - if (mypid != lastpid) { - char *version; - - lastpid = mypid; - if (dm_init_service(&version) < 0) { - return -1; - } - - DEBUG(0, ("Initializing DMAPI: %s\n", version)); - } - - return 0; -} - -BOOL dmapi_have_session(void) -{ - return dmapi_session != DM_NO_SESSION; -} - -static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) -{ - dm_sessid_t *nsessions; - - nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); - if (nsessions == NULL) { - TALLOC_FREE(sessions); - return NULL; - } - - return nsessions; -} - -/* Initialise DMAPI session. The session is persistant kernel state, so it - * might already exist, in which case we merely want to reconnect to it. This - * function should be called as root. - */ -int dmapi_init_session(void) -{ - char buf[DM_SESSION_INFO_LEN]; - size_t buflen; - - uint nsessions = 10; - dm_sessid_t *sessions = NULL; - - int i, err; - - /* If we aren't root, something in the following will fail due to lack - * of privileges. Aborting seems a little extreme. - */ - SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); - - dmapi_session = DM_NO_SESSION; - if (init_dmapi_service() < 0) { - return -1; - } - -retry: - - if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { - return -1; - } - - err = dm_getall_sessions(nsessions, sessions, &nsessions); - if (err < 0) { - if (errno == E2BIG) { - nsessions *= 2; - goto retry; - } - - DEBUGADD(DMAPI_TRACE, - ("failed to retrieve DMAPI sessions: %s\n", - strerror(errno))); - TALLOC_FREE(sessions); - return -1; - } - - for (i = 0; i < nsessions; ++i) { - err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); - buf[sizeof(buf) - 1] = '\0'; - if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { - dmapi_session = sessions[i]; - DEBUGADD(DMAPI_TRACE, - ("attached to existing DMAPI session " - "named '%s'\n", buf)); - break; - } - } - - TALLOC_FREE(sessions); - - /* No session already defined. */ - if (dmapi_session == DM_NO_SESSION) { - err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, - &dmapi_session); - if (err < 0) { - DEBUGADD(DMAPI_TRACE, - ("failed to create new DMAPI session: %s\n", - strerror(errno))); - return -1; - } - - DEBUGADD(DMAPI_TRACE, - ("created new DMAPI session named '%s'\n", - DMAPI_SESSION_NAME)); - } - - /* Note that we never end the DMAPI session. This enables child - * processes to continue to use the session after we exit. It also lets - * you run a second Samba server on different ports without any - * conflict. - */ - - return 0; -} - -/* Reattach to an existing dmapi session. Called from service processes that - * might not be running as root. - */ -static int reattach_dmapi_session(void) -{ - char buf[DM_SESSION_INFO_LEN]; - size_t buflen; - - if (dmapi_session != DM_NO_SESSION ) { - become_root(); - - /* NOTE: On Linux, this call opens /dev/dmapi, costing us a - * file descriptor. Ideally, we would close this when we fork. - */ - if (init_dmapi_service() < 0) { - dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - if (dm_query_session(dmapi_session, sizeof(buf), - buf, &buflen) < 0) { - /* Session is stale. Disable DMAPI. */ - dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - set_effective_capability(DMAPI_ACCESS_CAPABILITY); - - DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); - unbecome_root(); - return 0; - } - - return 0; -} - -uint32 dmapi_file_flags(const char * const path) -{ - int err; - dm_eventset_t events = {0}; - uint nevents; - - void *dm_handle; - size_t dm_handle_len; - - uint32 flags = 0; - - if (dmapi_have_session()) { - if (reattach_dmapi_session() < 0) { - return 0; - } - } - - err = dm_path_to_handle(CONST_DISCARD(char *, path), - &dm_handle, &dm_handle_len); - if (err < 0) { - DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n", - path, strerror(errno))); - return 0; - } - - err = dm_get_eventlist(dmapi_session, dm_handle, dm_handle_len, - DM_NO_TOKEN, DM_EVENT_MAX, &events, &nevents); - if (err < 0) { - DEBUG(DMAPI_TRACE, ("dm_get_eventlist: %s\n", - strerror(errno))); - dm_handle_free(dm_handle, dm_handle_len); - return 0; - } - - /* We figure that the only reason a DMAPI application would be - * interested in trapping read events is that part of the file is - * offline. - */ - DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", - path, events)); - if (DMEV_ISSET(DM_EVENT_READ, events)) { - flags = FILE_ATTRIBUTE_OFFLINE; - } - - dm_handle_free(dm_handle, dm_handle_len); - - if (flags & FILE_ATTRIBUTE_OFFLINE) { - DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); - } - - return flags; -} - -#endif /* USE_DMAPI */ -- cgit From e4878351816d7196efab22b68672430fb61e7b47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 24 Mar 2006 18:40:28 +0000 Subject: r14695: Patch from Björn Jacke: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add DMAPI/XDSM support for AIX - find JFS DMAPI libs on Linux when only they are available Volker (This used to be commit b6b72f8c6a03001ae75457c9e7a78e189bea5a3f) --- source3/smbd/dmapi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 2188924d4b..4a6cba293b 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -24,8 +24,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_DMAPI -#if defined(HAVE_LIBDM) -#if (defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H)) +#if defined(HAVE_LIBDM) || defined(HAVE_LIBJFSDM) || defined(HAVE_LIBXDSM) +#if defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H) || defined(HAVE_SYS_JFSDMAPI_H) || defined(HAVE_SYS_DMAPI_H) #define USE_DMAPI 1 #endif #endif @@ -40,10 +40,12 @@ BOOL dmapi_have_session(void) { return False; } #ifdef HAVE_XFS_DMAPI_H #include -#endif - -#ifdef HAVE_SYS_DMI_H +#elif defined(HAVE_SYS_DMI_H) #include +#elif defined(HAVE_SYS_JFSDMAPI_H) +#include +#elif defined(HAVE_SYS_DMAPI_H) +#include #endif #define DMAPI_SESSION_NAME "samba" -- cgit From 777c22b300c573e94d4dc99452575b7af7676774 Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 6 Jun 2006 07:43:17 +0000 Subject: r16057: Coalesce the DMAPI configure tests into a single macro. Add a more specific probe to try and eliminate old, incompatible DMAPI implementations provided by IRIX 6.4 and AIX 4.3. (This used to be commit aafd4db457ce8a60c628d54a3ace3b97c8885dca) --- source3/smbd/dmapi.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 4a6cba293b..a9d83c782b 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -24,12 +24,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_DMAPI -#if defined(HAVE_LIBDM) || defined(HAVE_LIBJFSDM) || defined(HAVE_LIBXDSM) -#if defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H) || defined(HAVE_SYS_JFSDMAPI_H) || defined(HAVE_SYS_DMAPI_H) -#define USE_DMAPI 1 -#endif -#endif - #ifndef USE_DMAPI int dmapi_init_session(void) { return -1; } -- cgit From 60936146d0b74315ff872da047a970fe87d0f1d3 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 24 Nov 2006 05:35:05 +0000 Subject: r19873: Make sure we are privileged when doing DMAPI operations on systems that don't have capability support. Patch by J Raynor . (This used to be commit 53fe047f35534afc4b56fcbaf135a3ca13df65bd) --- source3/smbd/dmapi.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index a9d83c782b..b42b7d51f0 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -240,6 +240,13 @@ uint32 dmapi_file_flags(const char * const path) } } + /* AIX has DMAPI but no POSIX capablities support. In this case, + * we need to be root to do DMAPI manipulations. + */ +#ifndef HAVE_POSIX_CAPABILITIES + become_root(); +#endif + err = dm_path_to_handle(CONST_DISCARD(char *, path), &dm_handle, &dm_handle_len); if (err < 0) { @@ -247,7 +254,7 @@ uint32 dmapi_file_flags(const char * const path) path, strerror(errno))); if (errno != EPERM) { - return 0; + goto done; } /* Linux capabilities are broken in that changing our @@ -265,7 +272,7 @@ uint32 dmapi_file_flags(const char * const path) DEBUG(DMAPI_TRACE, ("retrying dm_path_to_handle(%s): %s\n", path, strerror(errno))); - return 0; + goto done; } } @@ -275,7 +282,7 @@ uint32 dmapi_file_flags(const char * const path) DEBUG(DMAPI_TRACE, ("dm_get_eventlist(%s): %s\n", path, strerror(errno))); dm_handle_free(dm_handle, dm_handle_len); - return 0; + goto done; } /* We figure that the only reason a DMAPI application would be @@ -294,6 +301,12 @@ uint32 dmapi_file_flags(const char * const path) DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path)); } +done: + +#ifndef HAVE_POSIX_CAPABILITIES + unbecome_root(); +#endif + return flags; } -- cgit From 415612949005edffa3ca05133ea5f1358f578161 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 20 Feb 2007 15:55:12 +0000 Subject: r21467: Add GPFS-provided DMAPI support based on their GPL library (This used to be commit 5876bedda51fce0c932ca0cdab074629b31a9c94) --- source3/smbd/dmapi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index b42b7d51f0..b8c23c2dce 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -40,6 +40,8 @@ BOOL dmapi_have_session(void) { return False; } #include #elif defined(HAVE_SYS_DMAPI_H) #include +#elif defined(HAVE_DMAPI_H) +#include #endif #define DMAPI_SESSION_NAME "samba" -- cgit From fb5644342760cb54b4285c65ab36d693f558a289 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 5 May 2007 21:13:40 +0000 Subject: r22691: Fix a 64-bit warning and a const const discard warning (This used to be commit 3a2ca1b1b85e268928587287f61d26f992b303a5) --- source3/smbd/dmapi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index b8c23c2dce..23b5d5e947 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -152,7 +152,8 @@ retry: /* No session already defined. */ if (dmapi_session == DM_NO_SESSION) { - err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME, + err = dm_create_session(DM_NO_SESSION, + CONST_DISCARD(DMAPI_SESSION_NAME), &dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, -- cgit From c4d42829a5c0e9d2bf7d706ff627117a2c678526 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 May 2007 08:22:59 +0000 Subject: r22693: Always compile before checkin.... I've now installed dmapi on my laptop :-) (This used to be commit 7460511c4e92f6fdde430d0c56bbb72377e80b4b) --- source3/smbd/dmapi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 23b5d5e947..c433a7329e 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -153,7 +153,8 @@ retry: /* No session already defined. */ if (dmapi_session == DM_NO_SESSION) { err = dm_create_session(DM_NO_SESSION, - CONST_DISCARD(DMAPI_SESSION_NAME), + CONST_DISCARD(char *, + DMAPI_SESSION_NAME), &dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/dmapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index c433a7329e..1ad1bc3d1c 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -6,7 +6,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/dmapi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 1ad1bc3d1c..127d1627cf 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -15,8 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/dmapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 127d1627cf..05e9138ea9 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -27,7 +27,7 @@ int dmapi_init_session(void) { return -1; } uint32 dmapi_file_flags(const char * const path) { return 0; } -BOOL dmapi_have_session(void) { return False; } +bool dmapi_have_session(void) { return False; } #else /* USE_DMAPI */ @@ -73,7 +73,7 @@ static int init_dmapi_service(void) return 0; } -BOOL dmapi_have_session(void) +bool dmapi_have_session(void) { return dmapi_session != DM_NO_SESSION; } -- cgit From d86fc3ec8c99aaa5ffaa14a97525154507c39df7 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 12:17:03 +0300 Subject: Add support for offline files support, remote storage, and Async I/O force operations to VFS Offline files support and remote storage are for allowing communication with backup and archiving tools that mark files moved to a tape library as offline. We translate this info into corresponding CIFS offline file attribute and mark an exported volume as remote storage. Async I/O force is to allow selective redirection of I/O operations to asynchronous processing in case it is viable at VFS module discretion. It is needed for proper handling of offline files as performing regular I/O on offline file will block smbd. Signed-off-by: Alexander Bokovoy (This used to be commit 875208724e39564fe81385dfe36e6c963e79e101) --- source3/smbd/dmapi.c | 71 +++++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 31 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 05e9138ea9..620baf199e 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -46,7 +46,7 @@ bool dmapi_have_session(void) { return False; } #define DMAPI_SESSION_NAME "samba" #define DMAPI_TRACE 10 -static dm_sessid_t dmapi_session = DM_NO_SESSION; +static dm_sessid_t samba_dmapi_session = DM_NO_SESSION; /* Initialise the DMAPI interface. Make sure that we only end up initialising * once per process to avoid resource leaks across different DMAPI @@ -75,7 +75,7 @@ static int init_dmapi_service(void) bool dmapi_have_session(void) { - return dmapi_session != DM_NO_SESSION; + return samba_dmapi_session != DM_NO_SESSION; } static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) @@ -110,7 +110,7 @@ int dmapi_init_session(void) */ SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; if (init_dmapi_service() < 0) { return -1; } @@ -139,7 +139,7 @@ retry: err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); buf[sizeof(buf) - 1] = '\0'; if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { - dmapi_session = sessions[i]; + samba_dmapi_session = sessions[i]; DEBUGADD(DMAPI_TRACE, ("attached to existing DMAPI session " "named '%s'\n", buf)); @@ -150,16 +150,15 @@ retry: TALLOC_FREE(sessions); /* No session already defined. */ - if (dmapi_session == DM_NO_SESSION) { - err = dm_create_session(DM_NO_SESSION, - CONST_DISCARD(char *, - DMAPI_SESSION_NAME), - &dmapi_session); + if (samba_dmapi_session == DM_NO_SESSION) { + err = dm_create_session(DM_NO_SESSION, + CONST_DISCARD(char *, DMAPI_SESSION_NAME), + &samba_dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, ("failed to create new DMAPI session: %s\n", strerror(errno))); - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; return -1; } @@ -185,22 +184,22 @@ static int reattach_dmapi_session(void) char buf[DM_SESSION_INFO_LEN]; size_t buflen; - if (dmapi_session != DM_NO_SESSION ) { + if (samba_dmapi_session != DM_NO_SESSION ) { become_root(); /* NOTE: On Linux, this call opens /dev/dmapi, costing us a * file descriptor. Ideally, we would close this when we fork. */ if (init_dmapi_service() < 0) { - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; unbecome_root(); return -1; } - if (dm_query_session(dmapi_session, sizeof(buf), + if (dm_query_session(samba_dmapi_session, sizeof(buf), buf, &buflen) < 0) { /* Session is stale. Disable DMAPI. */ - dmapi_session = DM_NO_SESSION; + samba_dmapi_session = DM_NO_SESSION; unbecome_root(); return -1; } @@ -214,33 +213,42 @@ static int reattach_dmapi_session(void) return 0; } -uint32 dmapi_file_flags(const char * const path) +/* If a DMAPI session has been initialised, then we need to make sure + * we are attached to it and have the correct privileges. This is + * necessary to be able to do DMAPI operations across a fork(2). If + * it fails, there is no likelihood of that failure being transient. + * + * Note that this use of the static attached flag relies on the fact + * that dmapi_file_flags() is never called prior to forking the + * per-client server process. + */ +const void * dmapi_get_current_session(void) { static int attached = 0; + if (dmapi_have_session() && !attached) { + attached++; + if (reattach_dmapi_session() < 0) { + return DM_NO_SESSION; + } + } + return &samba_dmapi_session; +} +uint32 dmapi_file_flags(const char * const path) +{ + dm_sessid_t dmapi_session; int err; dm_eventset_t events = {0}; uint nevents; - void *dm_handle; - size_t dm_handle_len; + void *dm_handle = NULL; + size_t dm_handle_len = 0; uint32 flags = 0; - /* If a DMAPI session has been initialised, then we need to make sure - * we are attached to it and have the correct privileges. This is - * necessary to be able to do DMAPI operations across a fork(2). If - * it fails, there is no liklihood of that failure being transient. - * - * Note that this use of the static attached flag relies on the fact - * that dmapi_file_flags() is never called prior to forking the - * per-client server process. - */ - if (dmapi_have_session() && !attached) { - attached++; - if (reattach_dmapi_session() < 0) { - return 0; - } + dmapi_session = *(dm_sessid_t*) dmapi_get_current_session(); + if (dmapi_session == DM_NO_SESSION) { + return 0; } /* AIX has DMAPI but no POSIX capablities support. In this case, @@ -313,4 +321,5 @@ done: return flags; } + #endif /* USE_DMAPI */ -- cgit From c17c64530ec479334f88679ef780691e06ccd65a Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Fri, 18 Jan 2008 17:34:21 +0300 Subject: Merge DMAPI fixes from CTDB Samba (This used to be commit cf1f90ad7a79dbe5926018790bb50d4e3b36cc7b) --- source3/smbd/dmapi.c | 205 ++++++++++++++++++++------------------------------- 1 file changed, 78 insertions(+), 127 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 620baf199e..a410748ccf 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -25,9 +25,9 @@ #ifndef USE_DMAPI -int dmapi_init_session(void) { return -1; } uint32 dmapi_file_flags(const char * const path) { return 0; } bool dmapi_have_session(void) { return False; } +const void * dmapi_get_current_session(void) { return NULL; } #else /* USE_DMAPI */ @@ -48,90 +48,48 @@ bool dmapi_have_session(void) { return False; } static dm_sessid_t samba_dmapi_session = DM_NO_SESSION; -/* Initialise the DMAPI interface. Make sure that we only end up initialising - * once per process to avoid resource leaks across different DMAPI - * implementations. - */ -static int init_dmapi_service(void) -{ - static pid_t lastpid; - - pid_t mypid; - - mypid = sys_getpid(); - if (mypid != lastpid) { - char *version; - - lastpid = mypid; - if (dm_init_service(&version) < 0) { - return -1; - } - - DEBUG(0, ("Initializing DMAPI: %s\n", version)); - } - - return 0; -} - -bool dmapi_have_session(void) -{ - return samba_dmapi_session != DM_NO_SESSION; -} - -static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count) -{ - dm_sessid_t *nsessions; - - nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count); - if (nsessions == NULL) { - TALLOC_FREE(sessions); - return NULL; - } - return nsessions; -} - -/* Initialise DMAPI session. The session is persistant kernel state, so it - * might already exist, in which case we merely want to reconnect to it. This - * function should be called as root. - */ -int dmapi_init_session(void) +/* + Initialise DMAPI session. The session is persistant kernel state, + so it might already exist, in which case we merely want to + reconnect to it. This function should be called as root. +*/ +static int dmapi_init_session(void) { char buf[DM_SESSION_INFO_LEN]; size_t buflen; - - uint nsessions = 10; + uint nsessions = 5; dm_sessid_t *sessions = NULL; + char *version; int i, err; - /* If we aren't root, something in the following will fail due to lack - * of privileges. Aborting seems a little extreme. - */ - SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root"); - - samba_dmapi_session = DM_NO_SESSION; - if (init_dmapi_service() < 0) { + if (dm_init_service(&version) < 0) { + DEBUG(0, ("dm_init_service failed - disabling DMAPI\n")); return -1; } -retry: + ZERO_STRUCT(buf); - if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) { - return -1; - } - - err = dm_getall_sessions(nsessions, sessions, &nsessions); - if (err < 0) { - if (errno == E2BIG) { - nsessions *= 2; - goto retry; + do { + dm_sessid_t *new_sessions; + nsessions *= 2; + new_sessions = TALLOC_REALLOC_ARRAY(NULL, sessions, + dm_sessid_t, nsessions); + if (new_sessions == NULL) { + talloc_free(sessions); + return -1; } + sessions = new_sessions; + err = dm_getall_sessions(nsessions, sessions, &nsessions); + } while (err == -1 && errno == E2BIG); + + if (err == -1) { DEBUGADD(DMAPI_TRACE, ("failed to retrieve DMAPI sessions: %s\n", strerror(errno))); - TALLOC_FREE(sessions); + talloc_free(sessions); return -1; } @@ -147,7 +105,7 @@ retry: } } - TALLOC_FREE(sessions); + talloc_free(sessions); /* No session already defined. */ if (samba_dmapi_session == DM_NO_SESSION) { @@ -162,91 +120,84 @@ retry: return -1; } - DEBUGADD(DMAPI_TRACE, - ("created new DMAPI session named '%s'\n", - DMAPI_SESSION_NAME)); + DEBUG(0, ("created new DMAPI session named '%s' for %s\n", + DMAPI_SESSION_NAME, version)); + } + + if (samba_dmapi_session != DM_NO_SESSION) { + set_effective_capability(DMAPI_ACCESS_CAPABILITY); } - /* Note that we never end the DMAPI session. This enables child - * processes to continue to use the session after we exit. It also lets - * you run a second Samba server on different ports without any - * conflict. + /* + Note that we never end the DMAPI session. It gets re-used if possiblie. + DMAPI session is a kernel resource that is usually lives until server reboot + and doesn't get destroed when an application finishes. */ return 0; } -/* Reattach to an existing dmapi session. Called from service processes that - * might not be running as root. - */ -static int reattach_dmapi_session(void) +/* + Return a pointer to our DMAPI session, if available. + This assumes that you have called dmapi_have_session() first. +*/ +const void *dmapi_get_current_session(void) { - char buf[DM_SESSION_INFO_LEN]; - size_t buflen; - - if (samba_dmapi_session != DM_NO_SESSION ) { - become_root(); - - /* NOTE: On Linux, this call opens /dev/dmapi, costing us a - * file descriptor. Ideally, we would close this when we fork. - */ - if (init_dmapi_service() < 0) { - samba_dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - if (dm_query_session(samba_dmapi_session, sizeof(buf), - buf, &buflen) < 0) { - /* Session is stale. Disable DMAPI. */ - samba_dmapi_session = DM_NO_SESSION; - unbecome_root(); - return -1; - } - - set_effective_capability(DMAPI_ACCESS_CAPABILITY); - - DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n")); - unbecome_root(); + if (samba_dmapi_session == DM_NO_SESSION) { + return NULL; } - return 0; + return (void *)&samba_dmapi_session; } + +/* + dmapi_have_session() must be the first DMAPI call you make in Samba. It will + initialize DMAPI, if available, and tell you if you can get a DMAPI session. + This should be called in the client-specific child process. +*/ -/* If a DMAPI session has been initialised, then we need to make sure - * we are attached to it and have the correct privileges. This is - * necessary to be able to do DMAPI operations across a fork(2). If - * it fails, there is no likelihood of that failure being transient. - * - * Note that this use of the static attached flag relies on the fact - * that dmapi_file_flags() is never called prior to forking the - * per-client server process. - */ -const void * dmapi_get_current_session(void) +bool dmapi_have_session(void) { - static int attached = 0; - if (dmapi_have_session() && !attached) { - attached++; - if (reattach_dmapi_session() < 0) { - return DM_NO_SESSION; - } + static bool initialized; + if (!initialized) { + initialized = true; + + become_root(); + dmapi_init_session(); + unbecome_root(); + } - return &samba_dmapi_session; + + return samba_dmapi_session != DM_NO_SESSION; } +/* + This is default implementation of dmapi_file_flags() that is + called from VFS is_offline() call to know whether file is offline. + For GPFS-specific version see modules/vfs_tsmsm.c. It might be + that approach on quering existence of a specific attribute that + is used in vfs_tsmsm.c will work with other DMAPI-based HSM + implementations as well. +*/ uint32 dmapi_file_flags(const char * const path) { - dm_sessid_t dmapi_session; int err; dm_eventset_t events = {0}; uint nevents; + dm_sessid_t dmapi_session; + void *dmapi_session_ptr; void *dm_handle = NULL; size_t dm_handle_len = 0; uint32 flags = 0; - dmapi_session = *(dm_sessid_t*) dmapi_get_current_session(); + dmapi_session_ptr = dmapi_get_current_session(); + if (dmapi_session_ptr == NULL) { + return 0; + } + + dmapi_session = *(dm_sessid_t *)dmapi_session_ptr; if (dmapi_session == DM_NO_SESSION) { return 0; } -- cgit From 28b27bfd40d1bfbebaa9f8026efdf169d7bc6b29 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 29 Jan 2008 17:43:49 +0300 Subject: Merge DMAPI fixes from Tridge Support cases when existing DMAPI session is stale. In this case we are creating another one. The code differs from 3-0_ctdb branch in that we fail when it is not possible to create more sessions and pretend that file is offline. This allows to escape endless loop in vfs_tsmsm.c. (This used to be commit 5efb57d904e25e68b09a567e260292439ad9c095) --- source3/smbd/dmapi.c | 72 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 16 deletions(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index a410748ccf..8d43e0a9d1 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -47,7 +47,7 @@ const void * dmapi_get_current_session(void) { return NULL; } #define DMAPI_TRACE 10 static dm_sessid_t samba_dmapi_session = DM_NO_SESSION; - +static unsigned session_num; /* Initialise DMAPI session. The session is persistant kernel state, @@ -61,23 +61,41 @@ static int dmapi_init_session(void) uint nsessions = 5; dm_sessid_t *sessions = NULL; char *version; + char *session_name; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); int i, err; + if (session_num == 0) { + session_name = DMAPI_SESSION_NAME; + } else { + session_name = talloc_asprintf(tmp_ctx, "%s%u", DMAPI_SESSION_NAME, + session_num); + } + + if (session_name == NULL) { + DEBUG(0,("Out of memory in dmapi_init_session\n")); + talloc_free(tmp_ctx); + return -1; + } + + if (dm_init_service(&version) < 0) { DEBUG(0, ("dm_init_service failed - disabling DMAPI\n")); + talloc_free(tmp_ctx); return -1; } ZERO_STRUCT(buf); + /* Fetch kernel DMAPI sessions until we get any of them */ do { dm_sessid_t *new_sessions; nsessions *= 2; - new_sessions = TALLOC_REALLOC_ARRAY(NULL, sessions, + new_sessions = TALLOC_REALLOC_ARRAY(tmp_ctx, sessions, dm_sessid_t, nsessions); if (new_sessions == NULL) { - talloc_free(sessions); + talloc_free(tmp_ctx); return -1; } @@ -89,14 +107,15 @@ static int dmapi_init_session(void) DEBUGADD(DMAPI_TRACE, ("failed to retrieve DMAPI sessions: %s\n", strerror(errno))); - talloc_free(sessions); + talloc_free(tmp_ctx); return -1; } + /* Look through existing kernel DMAPI sessions to find out ours */ for (i = 0; i < nsessions; ++i) { err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen); buf[sizeof(buf) - 1] = '\0'; - if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) { + if (err == 0 && strcmp(session_name, buf) == 0) { samba_dmapi_session = sessions[i]; DEBUGADD(DMAPI_TRACE, ("attached to existing DMAPI session " @@ -105,23 +124,22 @@ static int dmapi_init_session(void) } } - talloc_free(sessions); - /* No session already defined. */ if (samba_dmapi_session == DM_NO_SESSION) { err = dm_create_session(DM_NO_SESSION, - CONST_DISCARD(char *, DMAPI_SESSION_NAME), + session_name, &samba_dmapi_session); if (err < 0) { DEBUGADD(DMAPI_TRACE, ("failed to create new DMAPI session: %s\n", strerror(errno))); samba_dmapi_session = DM_NO_SESSION; + talloc_free(tmp_ctx); return -1; } DEBUG(0, ("created new DMAPI session named '%s' for %s\n", - DMAPI_SESSION_NAME, version)); + session_name, version)); } if (samba_dmapi_session != DM_NO_SESSION) { @@ -132,8 +150,12 @@ static int dmapi_init_session(void) Note that we never end the DMAPI session. It gets re-used if possiblie. DMAPI session is a kernel resource that is usually lives until server reboot and doesn't get destroed when an application finishes. + + However, we free list of references to DMAPI sessions we've got from the kernel + as it is not needed anymore once we have found (or created) our session. */ + talloc_free(tmp_ctx); return 0; } @@ -171,6 +193,25 @@ bool dmapi_have_session(void) return samba_dmapi_session != DM_NO_SESSION; } +/* + only call this when you get back an EINVAL error indicating that the + session you are using is invalid. This destroys the existing session + and creates a new one. + */ +BOOL dmapi_new_session(void) +{ + if (dmapi_have_session()) { + /* try to destroy the old one - this may not succeed */ + dm_destroy_session(samba_dmapi_session); + } + samba_dmapi_session = DM_NO_SESSION; + become_root(); + session_num++; + dmapi_init_session(); + unbecome_root(); + return samba_dmapi_session != DM_NO_SESSION; +} + /* This is default implementation of dmapi_file_flags() that is called from VFS is_offline() call to know whether file is offline. @@ -185,12 +226,12 @@ uint32 dmapi_file_flags(const char * const path) dm_eventset_t events = {0}; uint nevents; - dm_sessid_t dmapi_session; - void *dmapi_session_ptr; - void *dm_handle = NULL; - size_t dm_handle_len = 0; + dm_sessid_t dmapi_session; + const void *dmapi_session_ptr; + void *dm_handle = NULL; + size_t dm_handle_len = 0; - uint32 flags = 0; + uint32 flags = 0; dmapi_session_ptr = dmapi_get_current_session(); if (dmapi_session_ptr == NULL) { @@ -251,8 +292,7 @@ uint32 dmapi_file_flags(const char * const path) * interested in trapping read events is that part of the file is * offline. */ - DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n", - path, events)); + DEBUG(DMAPI_TRACE, ("DMAPI event list for %s\n", path)); if (DMEV_ISSET(DM_EVENT_READ, events)) { flags = FILE_ATTRIBUTE_OFFLINE; } -- cgit From 52c16c95e6e6fa17a7e440b77afdccfd9a7295c9 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 29 Jan 2008 18:01:23 +0300 Subject: Fix BOOL introduced by last commit (This used to be commit 8afb7133e956ec963ac55720fb297b4d5b44702c) --- source3/smbd/dmapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index 8d43e0a9d1..fab0d5f9ef 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -198,7 +198,7 @@ bool dmapi_have_session(void) session you are using is invalid. This destroys the existing session and creates a new one. */ -BOOL dmapi_new_session(void) +bool dmapi_new_session(void) { if (dmapi_have_session()) { /* try to destroy the old one - this may not succeed */ -- cgit From c2bb4b51c1e660a675197063781323fe65c97135 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 8 Apr 2008 15:19:01 +0400 Subject: Destroy DMAPI session when main smbd daemon exits. DMAPI session is precious resource maintained at kernel level. We open one of them and use across multiple smbd daemons but once last of them exits, DMAPI session needs to be destroyed. There are some HSM implementations which fail to shutdown when opened DMAPI sessions left. Ensure we shutdown our session when it is really not needed anymore. This is what recommended by DMAPI specification anyway. (This used to be commit a0cefd44009d414fa00ec6e08c70d21b74acdbcb) --- source3/smbd/dmapi.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index fab0d5f9ef..fd252e980a 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -212,6 +212,30 @@ bool dmapi_new_session(void) return samba_dmapi_session != DM_NO_SESSION; } +/* + only call this when exiting from master smbd process. DMAPI sessions + are long-lived kernel resources we ought to share across smbd processes. + However, we must free them when all smbd processes are finished to + allow other subsystems clean up properly. Not freeing DMAPI session + blocks certain HSM implementations from proper shutdown. +*/ +bool dmapi_destroy_session(void) +{ + if (samba_dmapi_session != DM_NO_SESSION) { + become_root(); + if (!dm_destroy_session(samba_dmapi_session)) { + session_num--; + samba_dmapi_session = DM_NO_SESSION; + } else { + DEBUG(0,("Couldn't destroy DMAPI session: %s\n", + strerror(errno))); + } + unbecome_root(); + } + return samba_dmapi_session == DM_NO_SESSION; +} + + /* This is default implementation of dmapi_file_flags() that is called from VFS is_offline() call to know whether file is offline. -- cgit From 09c5d892201a94c8d24bc5b593942a869ece2f34 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 14 Apr 2008 13:56:36 +0400 Subject: Use more error-prone form of testing dm_destroy_session() return code after discussing with Tridge (This used to be commit 4abdbad52e456764bca1b17ead04edee1e2a2a64) --- source3/smbd/dmapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/dmapi.c') diff --git a/source3/smbd/dmapi.c b/source3/smbd/dmapi.c index fd252e980a..1049c95a39 100644 --- a/source3/smbd/dmapi.c +++ b/source3/smbd/dmapi.c @@ -223,7 +223,7 @@ bool dmapi_destroy_session(void) { if (samba_dmapi_session != DM_NO_SESSION) { become_root(); - if (!dm_destroy_session(samba_dmapi_session)) { + if (0 == dm_destroy_session(samba_dmapi_session)) { session_num--; samba_dmapi_session = DM_NO_SESSION; } else { -- cgit