summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2000-04-24 20:48:40 +0000
committerJeremy Allison <jra@samba.org>2000-04-24 20:48:40 +0000
commit644f22ac6141f58f2badd3a9761ac156831c16a3 (patch)
tree772d24c3d12fd37ce3401cca60887e25b42c0de0 /source3/smbd
parente82dbfcbe97c79b1c81915ae949bb2b1763970ba (diff)
downloadsamba-644f22ac6141f58f2badd3a9761ac156831c16a3.tar.gz
samba-644f22ac6141f58f2badd3a9761ac156831c16a3.tar.bz2
samba-644f22ac6141f58f2badd3a9761ac156831c16a3.zip
Added the code that keeps fd's open across a close if there are other fsp's
open on the same dev/inode pair with existing POSIX locks. This is done at the smbd/open layer, so smbd just calls fd_close() and the transfer of any open fd's is done under the covers of fd_close(). When an fsp is closed and no other fsp's open on the same dev/inode pair have existing POSIX locks then all fd's associated with this fsp are closed. Now only the hard part of doing the POSIX range unlock code when read locks overlap remains for full POSIX/SMB lock integration.... Jeremy. (This used to be commit 1df48ed55ee303b6d84d7277fd79761cfe5f7052)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/open.c120
1 files changed, 119 insertions, 1 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 353e20df8a..44bb6ebaf7 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -50,13 +50,125 @@ static int fd_open(struct connection_struct *conn, char *fname,
}
/****************************************************************************
+ Take care of moving any POSIX pending close fd's to another fsp.
+****************************************************************************/
+
+static BOOL fd_close_posix_locks(files_struct *fsp)
+{
+ files_struct *other_fsp;
+
+ DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u.\n", fsp->fsp_name,
+ (unsigned int)fsp->num_posix_pending_closes ));
+
+ for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp;
+ other_fsp = file_find_di_next(other_fsp)) {
+
+ if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) {
+
+ /*
+ * POSIX locks pending on another fsp held open, transfer
+ * the fd in this fsp and all the pending fd's in this fsp pending close array
+ * to the other_fsp pending close array.
+ */
+
+ unsigned int extra_fds = fsp->num_posix_pending_closes + 1;
+
+ DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \
+file %s, other_fsp->num_posix_pending_closes = %u.\n",
+ fsp->fsp_name, other_fsp->fsp_name, (unsigned int)other_fsp->num_posix_pending_closes ));
+
+ other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds,
+ (other_fsp->num_posix_pending_closes +
+ extra_fds)*sizeof(int));
+
+ if(other_fsp->posix_pending_close_fds == NULL) {
+ DEBUG(0,("fd_close_posix_locks: Unable to increase posix_pending_close_fds array size !\n"));
+ return False;
+ }
+
+ /*
+ * Copy over any fd's in the existing fsp's pending array.
+ */
+
+ if(fsp->posix_pending_close_fds) {
+ memcpy(&other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes],
+ &fsp->posix_pending_close_fds[0], fsp->num_posix_pending_closes * sizeof(int) );
+
+ free((char *)fsp->posix_pending_close_fds);
+ fsp->posix_pending_close_fds = NULL;
+ fsp->num_posix_pending_closes = 0;
+ }
+
+ other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes+extra_fds-1] = fsp->fd;
+ other_fsp->num_posix_pending_closes += extra_fds;
+
+ fsp->fd = -1; /* We have moved this fd to other_fsp's pending close array.... */
+
+ break;
+ }
+ }
+
+ return True;
+}
+
+/****************************************************************************
Close the file associated with a fsp.
+
+ This is where we must deal with POSIX "first close drops all locks"
+ locking braindamage. We do this by searching for any other fsp open
+ on the same dev/inode with open POSIX locks, and then transferring this
+ fd (and all pending fd's attached to this fsp) to the posix_pending_close_fds
+ array in that fsp.
+
+ If there are no open fsp's on the same dev/inode then we close all the
+ fd's in the posix_pending_close_fds array and then close the fd.
+
****************************************************************************/
int fd_close(struct connection_struct *conn, files_struct *fsp)
{
- int ret = conn->vfs_ops.close(fsp->fd);
+ int ret = 0;
+ int saved_errno = 0;
+ unsigned int i;
+
+ /*
+ * Deal with transferring any pending fd's if there
+ * are POSIX locks outstanding.
+ */
+
+ if(!fd_close_posix_locks(fsp))
+ return -1;
+
+ /*
+ * Close and free any pending closes given to use from
+ * other fsp's.
+ */
+
+ if (fsp->posix_pending_close_fds) {
+
+ for(i = 0; i < fsp->num_posix_pending_closes; i++) {
+ if (fsp->posix_pending_close_fds[i] != -1) {
+ if (conn->vfs_ops.close(fsp->posix_pending_close_fds[i]) == -1) {
+ saved_errno = errno;
+ }
+ }
+ }
+
+ free((char *)fsp->posix_pending_close_fds);
+ fsp->posix_pending_close_fds = NULL;
+ fsp->num_posix_pending_closes = 0;
+ }
+
+ if(fsp->fd != -1)
+ ret = conn->vfs_ops.close(fsp->fd);
+
fsp->fd = -1;
+
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ ret = -1;
+ }
+
return ret;
}
@@ -163,6 +275,8 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
fsp->oplock_type = NO_OPLOCK;
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->num_posix_locks = 0;
+ fsp->num_posix_pending_closes = 0;
+ fsp->posix_pending_close_fds = NULL;
fsp->is_directory = False;
fsp->stat_open = False;
fsp->directory_delete_on_close = False;
@@ -797,6 +911,8 @@ files_struct *open_file_stat(connection_struct *conn,
fsp->oplock_type = NO_OPLOCK;
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->num_posix_locks = 0;
+ fsp->num_posix_pending_closes = 0;
+ fsp->posix_pending_close_fds = NULL;
fsp->is_directory = False;
fsp->stat_open = True;
fsp->directory_delete_on_close = False;
@@ -921,6 +1037,8 @@ files_struct *open_directory(connection_struct *conn,
fsp->oplock_type = NO_OPLOCK;
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->num_posix_locks = 0;
+ fsp->num_posix_pending_closes = 0;
+ fsp->posix_pending_close_fds = NULL;
fsp->is_directory = True;
fsp->directory_delete_on_close = False;
fsp->conn = conn;