summaryrefslogtreecommitdiff
path: root/source3/modules
diff options
context:
space:
mode:
Diffstat (limited to 'source3/modules')
-rw-r--r--source3/modules/gpfs.c6
-rw-r--r--source3/modules/onefs.h8
-rw-r--r--source3/modules/onefs_cbrl.c93
-rw-r--r--source3/modules/onefs_config.h2
-rw-r--r--source3/modules/onefs_open.c115
-rw-r--r--source3/modules/onefs_streams.c7
-rw-r--r--source3/modules/onefs_system.c14
-rw-r--r--source3/modules/vfs_acl_tdb.c4
-rw-r--r--source3/modules/vfs_acl_xattr.c2
-rw-r--r--source3/modules/vfs_default.c24
-rw-r--r--source3/modules/vfs_full_audit.c40
-rw-r--r--source3/modules/vfs_gpfs.c5
-rw-r--r--source3/modules/vfs_onefs.c13
-rw-r--r--source3/modules/vfs_preopen.c456
14 files changed, 654 insertions, 135 deletions
diff --git a/source3/modules/gpfs.c b/source3/modules/gpfs.c
index 16599005b9..9fc4524654 100644
--- a/source3/modules/gpfs.c
+++ b/source3/modules/gpfs.c
@@ -26,6 +26,7 @@
static bool gpfs_share_modes;
static bool gpfs_leases;
+static bool gpfs_getrealfilename;
static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny);
static int (*gpfs_set_lease_fn)(int fd, unsigned int leaseType);
@@ -139,7 +140,8 @@ int smbd_gpfs_putacl(char *pathname, int flags, void *acl)
int smbd_gpfs_get_realfilename_path(char *pathname, char *filenamep,
int *buflen)
{
- if (gpfs_get_realfilename_path_fn == NULL) {
+ if ((!gpfs_getrealfilename)
+ || (gpfs_get_realfilename_path_fn == NULL)) {
errno = ENOSYS;
return -1;
}
@@ -208,6 +210,8 @@ void init_gpfs(void)
gpfs_share_modes = lp_parm_bool(-1, "gpfs", "sharemodes", True);
gpfs_leases = lp_parm_bool(-1, "gpfs", "leases", True);
+ gpfs_getrealfilename = lp_parm_bool(-1, "gpfs", "getrealfilename",
+ True);
return;
}
diff --git a/source3/modules/onefs.h b/source3/modules/onefs.h
index ebeece40ad..bb7695800e 100644
--- a/source3/modules/onefs.h
+++ b/source3/modules/onefs.h
@@ -106,6 +106,14 @@ bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
struct lock_struct *plock,
struct blocking_lock_record *blr);
+bool onefs_strict_lock(vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct lock_struct *plock);
+
+void onefs_strict_unlock(vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct lock_struct *plock);
+
NTSTATUS onefs_notify_watch(vfs_handle_struct *vfs_handle,
struct sys_notify_context *ctx,
struct notify_entry *e,
diff --git a/source3/modules/onefs_cbrl.c b/source3/modules/onefs_cbrl.c
index 7311e1961e..a6178a9751 100644
--- a/source3/modules/onefs_cbrl.c
+++ b/source3/modules/onefs_cbrl.c
@@ -248,7 +248,7 @@ NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
{
int fd = br_lck->fsp->fh->fd;
uint64_t id = 0;
- bool exclusive = false;
+ enum cbrl_lock_type type;
bool async = false;
bool pending = false;
bool pending_async = false;
@@ -268,20 +268,22 @@ NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
switch (plock->lock_type) {
case WRITE_LOCK:
- exclusive = true;
+ type = CBRL_LK_EX;
break;
case READ_LOCK:
+ type = CBRL_LK_SH;
break;
case PENDING_WRITE_LOCK:
/* Called when a blocking lock request is added - do an
* async lock. */
+ type = CBRL_LK_EX;
pending = true;
async = true;
- exclusive = true;
break;
case PENDING_READ_LOCK:
/* Called when a blocking lock request is added - do an
* async lock. */
+ type = CBRL_LK_SH;
pending = true;
async = true;
break;
@@ -323,7 +325,7 @@ NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
}
DEBUG(10, ("Calling ifs_cbrl(LOCK)..."));
- error = ifs_cbrl(fd, CBRL_OP_LOCK, exclusive, plock->start,
+ error = ifs_cbrl(fd, CBRL_OP_LOCK, type, plock->start,
plock->size, async, id, plock->context.smbpid, plock->context.tid,
plock->fnum);
if (!error) {
@@ -373,8 +375,6 @@ success:
return NT_STATUS_OK;
}
-#define CBRL_NOTYPE true
-
bool onefs_brl_unlock_windows(vfs_handle_struct *handle,
struct messaging_context *msg_ctx,
struct byte_range_lock *br_lck,
@@ -389,8 +389,8 @@ bool onefs_brl_unlock_windows(vfs_handle_struct *handle,
SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
DEBUG(10, ("Calling ifs_cbrl(UNLOCK)..."));
- error = ifs_cbrl(fd, CBRL_OP_UNLOCK, CBRL_NOTYPE,
- plock->start, plock->size, CBRL_NOTYPE, 0, plock->context.smbpid,
+ error = ifs_cbrl(fd, CBRL_OP_UNLOCK, CBRL_LK_SH,
+ plock->start, plock->size, false, 0, plock->context.smbpid,
plock->context.tid, plock->fnum);
END_PROFILE(syscall_brl_unlock);
@@ -444,8 +444,8 @@ bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
/* A real cancel. */
DEBUG(10, ("Calling ifs_cbrl(CANCEL)..."));
- error = ifs_cbrl(fd, CBRL_OP_CANCEL, CBRL_NOTYPE, plock->start,
- plock->size, CBRL_NOTYPE, bs->id, plock->context.smbpid,
+ error = ifs_cbrl(fd, CBRL_OP_CANCEL, CBRL_LK_UNSPEC, plock->start,
+ plock->size, false, bs->id, plock->context.smbpid,
plock->context.tid, plock->fnum);
END_PROFILE(syscall_brl_cancel);
@@ -462,6 +462,79 @@ bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
return true;
}
+bool onefs_strict_lock(vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct lock_struct *plock)
+{
+ int error;
+
+ START_PROFILE(syscall_strict_lock);
+
+ SMB_ASSERT(plock->lock_type == READ_LOCK ||
+ plock->lock_type == WRITE_LOCK);
+
+ if (!lp_locking(handle->conn->params) ||
+ !lp_strict_locking(handle->conn->params)) {
+ END_PROFILE(syscall_strict_lock);
+ return True;
+ }
+
+ if (plock->lock_flav == POSIX_LOCK) {
+ END_PROFILE(syscall_strict_lock);
+ return SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
+ }
+
+ if (plock->size == 0) {
+ END_PROFILE(syscall_strict_lock);
+ return True;
+ }
+
+ error = ifs_cbrl(fsp->fh->fd, CBRL_OP_LOCK,
+ plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR,
+ plock->start, plock->size, 0, 0, plock->context.smbpid,
+ plock->context.tid, plock->fnum);
+
+ END_PROFILE(syscall_strict_lock);
+
+ return (error == 0);
+}
+
+void onefs_strict_unlock(vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct lock_struct *plock)
+{
+ START_PROFILE(syscall_strict_unlock);
+
+ SMB_ASSERT(plock->lock_type == READ_LOCK ||
+ plock->lock_type == WRITE_LOCK);
+
+ if (!lp_locking(handle->conn->params) ||
+ !lp_strict_locking(handle->conn->params)) {
+ END_PROFILE(syscall_strict_unlock);
+ return;
+ }
+
+ if (plock->lock_flav == POSIX_LOCK) {
+ SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
+ END_PROFILE(syscall_strict_unlock);
+ return;
+ }
+
+ if (plock->size == 0) {
+ END_PROFILE(syscall_strict_unlock);
+ return;
+ }
+
+ if (fsp->fh) {
+ ifs_cbrl(fsp->fh->fd, CBRL_OP_UNLOCK,
+ plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR,
+ plock->start, plock->size, 0, 0, plock->context.smbpid,
+ plock->context.tid, plock->fnum);
+ }
+
+ END_PROFILE(syscall_strict_unlock);
+}
+
/* TODO Optimization: Abstract out brl_get_locks() in the Windows case.
* We'll malloc some memory or whatever (can't return NULL), but not actually
* touch the TDB. */
diff --git a/source3/modules/onefs_config.h b/source3/modules/onefs_config.h
index 27cbb0ad74..f0f48e6379 100644
--- a/source3/modules/onefs_config.h
+++ b/source3/modules/onefs_config.h
@@ -64,6 +64,8 @@ enum onefs_acl_wire_format
#define PARM_DOT_SNAP_TILDE_DEFAULT true
#define PARM_IGNORE_SACLS "ignore sacls"
#define PARM_IGNORE_SACLS_DEFAULT false
+#define PARM_IGNORE_STREAMS "ignore streams"
+#define PARM_IGNORE_STREAMS_DEFAULT false
#define PARM_MTIME_NOW "mtime now files"
#define PARM_MTIME_NOW_DEFAULT NULL
#define PARM_MTIME_STATIC "mtime static files"
diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c
index 9043be8e19..c5030f4ab8 100644
--- a/source3/modules/onefs_open.c
+++ b/source3/modules/onefs_open.c
@@ -196,7 +196,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp,
&base, &stream);
}
/* It's a stream, so pass in the base_fd */
- if (stream != NULL) {
+ if ((conn->fs_capabilities & FILE_NAMED_STREAMS) && stream != NULL) {
SMB_ASSERT(fsp->base_fsp);
/*
@@ -1649,119 +1649,6 @@ static NTSTATUS onefs_open_directory(connection_struct *conn,
}
/*
- * If a main file is opened for delete, all streams need to be checked for
- * !FILE_SHARE_DELETE. Do this by opening with DELETE_ACCESS.
- * If that works, delete them all by setting the delete on close and close.
- */
-
-static NTSTATUS open_streams_for_delete(connection_struct *conn,
- const char *fname)
-{
- struct stream_struct *stream_info;
- files_struct **streams;
- int i;
- unsigned int num_streams;
- TALLOC_CTX *frame = talloc_stackframe();
- NTSTATUS status;
-
- status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
- &num_streams, &stream_info);
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)
- || NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
- DEBUG(10, ("no streams around\n"));
- TALLOC_FREE(frame);
- return NT_STATUS_OK;
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
- nt_errstr(status)));
- goto fail;
- }
-
- DEBUG(10, ("open_streams_for_delete found %d streams\n",
- num_streams));
-
- if (num_streams == 0) {
- TALLOC_FREE(frame);
- return NT_STATUS_OK;
- }
-
- streams = TALLOC_ARRAY(talloc_tos(), files_struct *, num_streams);
- if (streams == NULL) {
- DEBUG(0, ("talloc failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
-
- /* Open the base file */
-
- for (i=0; i<num_streams; i++) {
- char *streamname;
-
- if (strequal(stream_info[i].name, "::$DATA")) {
- streams[i] = NULL;
- continue;
- }
-
- streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
- stream_info[i].name);
-
- if (streamname == NULL) {
- DEBUG(0, ("talloc_aprintf failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
-
- status = onefs_create_file_unixpath
- (conn, /* conn */
- NULL, /* req */
- streamname, /* fname */
- DELETE_ACCESS, /* access_mask */
- FILE_SHARE_READ | FILE_SHARE_WRITE
- | FILE_SHARE_DELETE, /* share_access */
- FILE_OPEN, /* create_disposition*/
- NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE, /* create_options */
- FILE_ATTRIBUTE_NORMAL, /* file_attributes */
- 0, /* oplock_request */
- 0, /* allocation_size */
- NULL, /* sd */
- NULL, /* ea_list */
- &streams[i], /* result */
- NULL, /* pinfo */
- NULL, /* fsp_data */
- NULL); /* psbuf */
-
- TALLOC_FREE(streamname);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("Could not open stream %s: %s\n",
- streamname, nt_errstr(status)));
- break;
- }
- }
-
- /*
- * don't touch the variable "status" beyond this point :-)
- */
-
- for (i -= 1 ; i >= 0; i--) {
- if (streams[i] == NULL) {
- continue;
- }
-
- DEBUG(10, ("Closing stream # %d, %s\n", i,
- streams[i]->fsp_name));
- close_file(NULL, streams[i], NORMAL_CLOSE);
- }
-
- fail:
- TALLOC_FREE(frame);
- return status;
-}
-
-/*
* Wrapper around onefs_open_file_ntcreate and onefs_open_directory.
*/
static NTSTATUS onefs_create_file_unixpath(connection_struct *conn,
diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c
index 9f5d5e2284..05b36d7d3c 100644
--- a/source3/modules/onefs_streams.c
+++ b/source3/modules/onefs_streams.c
@@ -671,6 +671,11 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle,
state.streams = NULL;
state.num_streams = 0;
+ if (lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
+ PARM_IGNORE_STREAMS, PARM_IGNORE_STREAMS_DEFAULT)) {
+ goto out;
+ }
+
/* Add the default stream. */
if (S_ISREG(sbuf.st_mode)) {
if (!add_one_stream(mem_ctx,
@@ -702,7 +707,7 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle,
return state.status;
}
}
-
+ out:
*num_streams = state.num_streams;
*streams = state.streams;
return NT_STATUS_OK;
diff --git a/source3/modules/onefs_system.c b/source3/modules/onefs_system.c
index b8b059bce9..46f38265b1 100644
--- a/source3/modules/onefs_system.c
+++ b/source3/modules/onefs_system.c
@@ -591,8 +591,8 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
*/
while (total_rbytes < count) {
- DEBUG(0, ("shallow recvfile, reading %llu\n",
- count - total_rbytes));
+ DEBUG(0, ("shallow recvfile (%s), reading %llu\n",
+ strerror(errno), count - total_rbytes));
/*
* Read the remaining data into the spill buffer. recvfile
@@ -603,9 +603,13 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
spill_buffer + (total_rbytes - total_wbytes),
count - total_rbytes);
- if (ret == -1) {
- DEBUG(0, ("shallow recvfile read failed: %s\n",
- strerror(errno)));
+ if (ret <= 0) {
+ if (ret == 0) {
+ DEBUG(0, ("shallow recvfile read: EOF\n"));
+ } else {
+ DEBUG(0, ("shallow recvfile read failed: %s\n",
+ strerror(errno)));
+ }
/* Socket is dead, so treat as if it were drained. */
socket_drained = true;
goto out;
diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c
index 73dbca4809..a77f6d60f4 100644
--- a/source3/modules/vfs_acl_tdb.c
+++ b/source3/modules/vfs_acl_tdb.c
@@ -195,7 +195,7 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
if (fsp && fsp->fh->fd != -1) {
ret = SMB_VFS_FSTAT(fsp, &sbuf);
} else {
- if (fsp->posix_open) {
+ if (fsp && fsp->posix_open) {
ret = SMB_VFS_LSTAT(handle->conn, name, &sbuf);
} else {
ret = SMB_VFS_STAT(handle->conn, name, &sbuf);
@@ -513,7 +513,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
ret = SMB_VFS_FSTAT(fsp, &sbuf);
} else {
- if (fsp->posix_open) {
+ if (fsp && fsp->posix_open) {
ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
} else {
ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c
index 039e469426..49e4899879 100644
--- a/source3/modules/vfs_acl_xattr.c
+++ b/source3/modules/vfs_acl_xattr.c
@@ -381,7 +381,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
ret = SMB_VFS_FSTAT(fsp, &sbuf);
} else {
- if (fsp->posix_open) {
+ if (fsp && fsp->posix_open) {
ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
} else {
ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 7384268dae..bb01f98588 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1157,6 +1157,26 @@ static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
return brl_lock_cancel_default(br_lck, plock);
}
+static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct lock_struct *plock)
+{
+ SMB_ASSERT(plock->lock_type == READ_LOCK ||
+ plock->lock_type == WRITE_LOCK);
+
+ return strict_lock_default(fsp, plock);
+}
+
+static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct lock_struct *plock)
+{
+ SMB_ASSERT(plock->lock_type == READ_LOCK ||
+ plock->lock_type == WRITE_LOCK);
+
+ strict_unlock_default(fsp, plock);
+}
+
/* NT ACL operations. */
static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
@@ -1592,6 +1612,10 @@ static vfs_op_tuple vfs_default_ops[] = {
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(vfswrap_brl_cancel_windows),SMB_VFS_OP_BRL_CANCEL_WINDOWS,
SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_strict_lock), SMB_VFS_OP_STRICT_LOCK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_strict_unlock), SMB_VFS_OP_STRICT_UNLOCK,
+ SMB_VFS_LAYER_OPAQUE},
/* NT ACL operations. */
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 3c159f10eb..ebe89ec5fd 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -234,6 +234,12 @@ static bool smb_full_audit_brl_cancel_windows(struct vfs_handle_struct *handle,
struct byte_range_lock *br_lck,
struct lock_struct *plock,
struct blocking_lock_record *blr);
+static bool smb_full_audit_strict_lock(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ struct lock_struct *plock);
+static void smb_full_audit_strict_unlock(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ struct lock_struct *plock);
static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
uint32 security_info,
SEC_DESC **ppdesc);
@@ -483,6 +489,10 @@ static vfs_op_tuple audit_op_tuples[] = {
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_brl_cancel_windows), SMB_VFS_OP_BRL_CANCEL_WINDOWS,
SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_strict_lock), SMB_VFS_OP_STRICT_LOCK,
+ SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_strict_unlock), SMB_VFS_OP_STRICT_UNLOCK,
+ SMB_VFS_LAYER_LOGGER},
/* NT ACL operations. */
@@ -660,6 +670,8 @@ static struct {
{ SMB_VFS_OP_BRL_LOCK_WINDOWS, "brl_lock_windows" },
{ SMB_VFS_OP_BRL_UNLOCK_WINDOWS, "brl_unlock_windows" },
{ SMB_VFS_OP_BRL_CANCEL_WINDOWS, "brl_cancel_windows" },
+ { SMB_VFS_OP_STRICT_LOCK, "strict_lock" },
+ { SMB_VFS_OP_STRICT_UNLOCK, "strict_unlock" },
{ SMB_VFS_OP_FGET_NT_ACL, "fget_nt_acl" },
{ SMB_VFS_OP_GET_NT_ACL, "get_nt_acl" },
{ SMB_VFS_OP_FSET_NT_ACL, "fset_nt_acl" },
@@ -1766,6 +1778,34 @@ static bool smb_full_audit_brl_cancel_windows(struct vfs_handle_struct *handle,
return result;
}
+static bool smb_full_audit_strict_lock(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ struct lock_struct *plock)
+{
+ bool result;
+
+ result = SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
+
+ do_log(SMB_VFS_OP_STRICT_LOCK, result, handle,
+ "%s:%llu-%llu:%d", fsp->fsp_name, plock->start,
+ plock->size);
+
+ return result;
+}
+
+static void smb_full_audit_strict_unlock(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ struct lock_struct *plock)
+{
+ SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
+
+ do_log(SMB_VFS_OP_STRICT_UNLOCK, true, handle,
+ "%s:%llu-%llu:%d", fsp->fsp_name, plock->start,
+ plock->size);
+
+ return;
+}
+
static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
uint32 security_info,
SEC_DESC **ppdesc)
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 1d7cdba014..3c061ece79 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -96,6 +96,11 @@ static int vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
TALLOC_FREE(full_path);
+ if ((result == -1) && (errno == ENOSYS)) {
+ return SMB_VFS_NEXT_GET_REAL_FILENAME(
+ handle, path, name, mem_ctx, found_name);
+ }
+
if (result == -1) {
DEBUG(10, ("smbd_gpfs_get_realfilename_path returned %s\n",
strerror(errno)));
diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c
index f277245bdc..ad59c2b32d 100644
--- a/source3/modules/vfs_onefs.c
+++ b/source3/modules/vfs_onefs.c
@@ -222,7 +222,14 @@ static int onefs_ntimes(vfs_handle_struct *handle, const char *fname,
static uint32_t onefs_fs_capabilities(struct vfs_handle_struct *handle)
{
- return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_NAMED_STREAMS;
+ uint32_t result = 0;
+
+ if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
+ PARM_IGNORE_STREAMS, PARM_IGNORE_STREAMS_DEFAULT)) {
+ result |= FILE_NAMED_STREAMS;
+ }
+
+ return result | SMB_VFS_NEXT_FS_CAPABILITIES(handle);
}
static vfs_op_tuple onefs_ops[] = {
@@ -282,6 +289,10 @@ static vfs_op_tuple onefs_ops[] = {
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(onefs_brl_cancel_windows), SMB_VFS_OP_BRL_CANCEL_WINDOWS,
SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(onefs_strict_lock), SMB_VFS_OP_STRICT_LOCK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(onefs_strict_unlock), SMB_VFS_OP_STRICT_UNLOCK,
+ SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(onefs_notify_watch), SMB_VFS_OP_NOTIFY_WATCH,
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(onefs_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL,
diff --git a/source3/modules/vfs_preopen.c b/source3/modules/vfs_preopen.c
new file mode 100644
index 0000000000..25b9e7f3e4
--- /dev/null
+++ b/source3/modules/vfs_preopen.c
@@ -0,0 +1,456 @@
+/*
+ * Force a readahead of files by opening them and reading the first bytes
+ *
+ * Copyright (C) Volker Lendecke 2008
+ *
+ * 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"
+
+struct preopen_state;
+
+struct preopen_helper {
+ struct preopen_state *state;
+ struct fd_event *fde;
+ pid_t pid;
+ int fd;
+ bool busy;
+};
+
+struct preopen_state {
+ int num_helpers;
+ struct preopen_helper *helpers;
+
+ size_t to_read; /* How many bytes to read in children? */
+ int queue_max;
+
+ char *template_fname; /* Filename to be sent to children */
+ size_t number_start; /* start offset into "template_fname" */
+ int num_digits; /* How many digits is the number long? */
+
+ int fnum_sent; /* last fname sent to children */
+
+ int fnum_queue_end; /* last fname to be sent, based on
+ * last open call + preopen:queuelen
+ */
+
+ name_compare_entry *preopen_names;
+};
+
+static void preopen_helper_destroy(struct preopen_helper *c)
+{
+ int status;
+ close(c->fd);
+ c->fd = -1;
+ kill(c->pid, SIGKILL);
+ waitpid(c->pid, &status, 0);
+ c->busy = true;
+}
+
+static void preopen_queue_run(struct preopen_state *state)
+{
+ char *pdelimiter;
+ char delimiter;
+
+ pdelimiter = state->template_fname + state->number_start
+ + state->num_digits;
+ delimiter = *pdelimiter;
+
+ while (state->fnum_sent < state->fnum_queue_end) {
+
+ ssize_t written;
+ size_t to_write;
+ int helper;
+
+ for (helper=0; helper<state->num_helpers; helper++) {
+ if (state->helpers[helper].busy) {
+ continue;
+ }
+ break;
+ }
+ if (helper == state->num_helpers) {
+ /* everyone is busy */
+ return;
+ }
+
+ snprintf(state->template_fname + state->number_start,
+ state->num_digits + 1,
+ "%.*lu", state->num_digits,
+ (long unsigned int)(state->fnum_sent + 1));
+ *pdelimiter = delimiter;
+
+ to_write = talloc_get_size(state->template_fname);
+ written = write_data(state->helpers[helper].fd,
+ state->template_fname, to_write);
+ state->helpers[helper].busy = true;
+
+ if (written != to_write) {
+ preopen_helper_destroy(&state->helpers[helper]);
+ }
+ state->fnum_sent += 1;
+ }
+}
+
+static void preopen_helper_readable(struct event_context *ev,
+ struct fd_event *fde, uint16_t flags,
+ void *priv)
+{
+ struct preopen_helper *helper = (struct preopen_helper *)priv;
+ struct preopen_state *state = helper->state;
+ ssize_t nread;
+ char c;
+
+ if ((flags & EVENT_FD_READ) == 0) {
+ return;
+ }
+
+ nread = read(helper->fd, &c, 1);
+ if (nread <= 0) {
+ preopen_helper_destroy(helper);
+ return;
+ }
+
+ helper->busy = false;
+
+ preopen_queue_run(state);
+}
+
+static int preopen_helpers_destructor(struct preopen_state *c)
+{
+ int i;
+
+ for (i=0; i<c->num_helpers; i++) {
+ if (c->helpers[i].fd == -1) {
+ continue;
+ }
+ preopen_helper_destroy(&c->helpers[i]);
+ }
+
+ return 0;
+}
+
+static bool preopen_helper_open_one(int sock_fd, char **pnamebuf,
+ size_t to_read, void *filebuf)
+{
+ char *namebuf = *pnamebuf;
+ ssize_t nwritten, nread;
+ char c = 0;
+ int fd;
+
+ nread = 0;
+
+ while ((nread == 0) || (namebuf[nread-1] != '\0')) {
+ ssize_t thistime;
+
+ thistime = read(sock_fd, namebuf + nread,
+ talloc_get_size(namebuf) - nread);
+ if (thistime <= 0) {
+ return false;
+ }
+
+ nread += thistime;
+
+ if (nread == talloc_get_size(namebuf)) {
+ namebuf = TALLOC_REALLOC_ARRAY(
+ NULL, namebuf, char,
+ talloc_get_size(namebuf) * 2);
+ if (namebuf == NULL) {
+ return false;
+ }
+ *pnamebuf = namebuf;
+ }
+ }
+
+ fd = open(namebuf, O_RDONLY);
+ if (fd == -1) {
+ goto done;
+ }
+ nread = read(fd, filebuf, to_read);
+ close(fd);
+
+ done:
+ nwritten = write(sock_fd, &c, 1);
+ return true;
+}
+
+static bool preopen_helper(int fd, size_t to_read)
+{
+ char *namebuf;
+ void *readbuf;
+
+ namebuf = TALLOC_ARRAY(NULL, char, 1024);
+ if (namebuf == NULL) {
+ return false;
+ }
+
+ readbuf = talloc_size(NULL, to_read);
+ if (readbuf == NULL) {
+ TALLOC_FREE(namebuf);
+ return false;
+ }
+
+ while (preopen_helper_open_one(fd, &namebuf, to_read, readbuf)) {
+ ;
+ }
+
+ TALLOC_FREE(readbuf);
+ TALLOC_FREE(namebuf);
+ return false;
+}
+
+static NTSTATUS preopen_init_helper(struct preopen_helper *h)
+{
+ int fdpair[2];
+ NTSTATUS status;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) == -1) {
+ status = map_nt_error_from_unix(errno);
+ DEBUG(10, ("socketpair() failed: %s\n", strerror(errno)));
+ return status;
+ }
+
+ h->pid = sys_fork();
+
+ if (h->pid == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (h->pid == 0) {
+ close(fdpair[0]);
+ preopen_helper(fdpair[1], h->state->to_read);
+ exit(0);
+ }
+ close(fdpair[1]);
+ h->fd = fdpair[0];
+ h->fde = event_add_fd(smbd_event_context(), h->state, h->fd,
+ EVENT_FD_READ, preopen_helper_readable, h);
+ if (h->fde == NULL) {
+ close(h->fd);
+ h->fd = -1;
+ return NT_STATUS_NO_MEMORY;
+ }
+ h->busy = false;
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS preopen_init_helpers(TALLOC_CTX *mem_ctx, size_t to_read,
+ int num_helpers, int queue_max,
+ struct preopen_state **presult)
+{
+ struct preopen_state *result;
+ int i;
+
+ result = talloc(mem_ctx, struct preopen_state);
+ if (result == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result->num_helpers = num_helpers;
+ result->helpers = TALLOC_ARRAY(result, struct preopen_helper,
+ num_helpers);
+ if (result->helpers == NULL) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result->to_read = to_read;
+ result->queue_max = queue_max;
+ result->template_fname = NULL;
+ result->fnum_sent = 0;
+
+ for (i=0; i<num_helpers; i++) {
+ result->helpers[i].state = result;
+ result->helpers[i].fd = -1;
+ }
+
+ talloc_set_destructor(result, preopen_helpers_destructor);
+
+ for (i=0; i<num_helpers; i++) {
+ preopen_init_helper(&result->helpers[i]);
+ }
+
+ *presult = result;
+ return NT_STATUS_OK;
+}
+
+static void preopen_free_helpers(void **ptr)
+{
+ TALLOC_FREE(*ptr);
+}
+
+static struct preopen_state *preopen_state_get(vfs_handle_struct *handle)
+{
+ struct preopen_state *state;
+ NTSTATUS status;
+ const char *namelist;
+
+ if (SMB_VFS_HANDLE_TEST_DATA(handle)) {
+ SMB_VFS_HANDLE_GET_DATA(handle, state, struct preopen_state,
+ return NULL);
+ return state;
+ }
+
+ namelist = lp_parm_const_string(SNUM(handle->conn), "preopen", "names",
+ NULL);
+
+ if (namelist == NULL) {
+ return NULL;
+ }
+
+ status = preopen_init_helpers(
+ NULL,
+ lp_parm_int(SNUM(handle->conn), "preopen", "num_bytes", 1),
+ lp_parm_int(SNUM(handle->conn), "preopen", "helpers", 1),
+ lp_parm_int(SNUM(handle->conn), "preopen", "queuelen", 10),
+ &state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+
+ set_namearray(&state->preopen_names, (char *)namelist);
+
+ if (state->preopen_names == NULL) {
+ TALLOC_FREE(state);
+ return NULL;
+ }
+
+ if (!SMB_VFS_HANDLE_TEST_DATA(handle)) {
+ SMB_VFS_HANDLE_SET_DATA(handle, state, preopen_free_helpers,
+ struct preopen_state, return NULL);
+ }
+
+ return state;
+}
+
+static bool preopen_parse_fname(const char *fname, unsigned long *pnum,
+ size_t *pstart_idx, int *pnum_digits)
+{
+ const char *p, *q;
+ unsigned long num;
+
+ p = strrchr_m(fname, '/');
+ if (p == NULL) {
+ p = fname;
+ }
+
+ p += 1;
+ while (p[0] != '\0') {
+ if (isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2])) {
+ break;
+ }
+ p += 1;
+ }
+ if (*p == '\0') {
+ /* no digits around */
+ return false;
+ }
+
+ num = strtoul(p, (char **)&q, 10);
+
+ if (num+1 < num) {
+ /* overflow */
+ return false;
+ }
+
+ *pnum = num;
+ *pstart_idx = (p - fname);
+ *pnum_digits = (q - p);
+ return true;
+}
+
+static int preopen_open(vfs_handle_struct *handle, const char *fname,
+ files_struct *fsp, int flags, mode_t mode)
+{
+ struct preopen_state *state;
+ int res;
+ unsigned long num;
+
+ DEBUG(10, ("preopen_open called on %s\n", fname));
+
+ state = preopen_state_get(handle);
+ if (state == NULL) {
+ return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+ }
+
+ res = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+ if (res == -1) {
+ return -1;
+ }
+
+ if (flags != O_RDONLY) {
+ return res;
+ }
+
+ if (!is_in_path(fname, state->preopen_names, true)) {
+ DEBUG(10, ("%s does not match the preopen:names list\n",
+ fname));
+ return res;
+ }
+
+ TALLOC_FREE(state->template_fname);
+ state->template_fname = talloc_asprintf(
+ state, "%s/%s", fsp->conn->connectpath, fname);
+
+ if (state->template_fname == NULL) {
+ return res;
+ }
+
+ if (!preopen_parse_fname(state->template_fname, &num,
+ &state->number_start, &state->num_digits)) {
+ TALLOC_FREE(state->template_fname);
+ return res;
+ }
+
+ if (num > state->fnum_sent) {
+ /*
+ * Helpers were too slow, there's no point in reading
+ * files in helpers that we already read in the
+ * parent.
+ */
+ state->fnum_sent = num;
+ }
+
+ if ((state->fnum_queue_end != 0) /* Something was started earlier */
+ && (num < (state->fnum_queue_end - state->queue_max))) {
+ /*
+ * "num" is before the queue we announced. This means
+ * a new run is started.
+ */
+ state->fnum_sent = num;
+ }
+
+ state->fnum_queue_end = num + state->queue_max;
+
+ preopen_queue_run(state);
+
+ return res;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple preopen_ops[] = {
+ {SMB_VFS_OP(preopen_open), SMB_VFS_OP_OPEN,
+ SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_preopen_init(void);
+NTSTATUS vfs_preopen_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+ "preopen", preopen_ops);
+}