summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAravind Srinivasan <aravind.srinivasan@isilon.com>2009-02-18 17:36:25 -0800
committerSteven Danneman <steven.danneman@isilon.com>2009-02-18 20:49:31 -0800
commit8e8aa27e1b1366c8c4e3cf6d8a681fec80cca858 (patch)
tree944be11156941821050a504a442a7e46b87a1fd7
parentc19214424b0f8ca0dfa5970880e54807880c443c (diff)
downloadsamba-8e8aa27e1b1366c8c4e3cf6d8a681fec80cca858.tar.gz
samba-8e8aa27e1b1366c8c4e3cf6d8a681fec80cca858.tar.bz2
samba-8e8aa27e1b1366c8c4e3cf6d8a681fec80cca858.zip
s3: Fix streams enumeration bug in OneFS implementation
Previously, we didn’t call SMB_VFS_OPEN_DIR from the streams module, instead we called fdopendir(). As a result we failed to populate the dir_state list in the readdirplus module. So when we tried to view the stream data, we will always returned NULL. To solve this I separated onefs_opendir() and the initialization of the dir_state list. This is done by introducing a new utility function “onefs_rdp_add_dir_state()”, which initializes the dir_state structure and adds it to the dir_state list. This function is called from the streams module before calling readdir().
-rw-r--r--source3/modules/onefs.h3
-rw-r--r--source3/modules/onefs_dir.c70
-rw-r--r--source3/modules/onefs_streams.c13
3 files changed, 68 insertions, 18 deletions
diff --git a/source3/modules/onefs.h b/source3/modules/onefs.h
index b979cfd7eb..c002739f1f 100644
--- a/source3/modules/onefs.h
+++ b/source3/modules/onefs.h
@@ -224,6 +224,9 @@ NTSTATUS onefs_split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
bool onefs_get_config(int snum, int config_type,
struct onefs_vfs_config *cfg);
+
+int onefs_rdp_add_dir_state(connection_struct *conn, SMB_STRUCT_DIR *dirp);
+
/*
* System Interfaces
*/
diff --git a/source3/modules/onefs_dir.c b/source3/modules/onefs_dir.c
index 3c1a8364be..83622b2bcd 100644
--- a/source3/modules/onefs_dir.c
+++ b/source3/modules/onefs_dir.c
@@ -183,6 +183,54 @@ rdp_fill_cache(struct rdp_dir_state *dsp)
}
/**
+ * Create a dir_state to track an open directory that we're enumerating.
+ *
+ * This utility function is globally accessible for use by other parts of the
+ * onefs.so module to initialize a dir_state when a directory is opened through
+ * a path other than the VFS layer.
+ *
+ * @return 0 on success and errno on failure
+ *
+ * @note: Callers of this function MUST cleanup the dir_state through a proper
+ * call to VFS_CLOSEDIR().
+ */
+int
+onefs_rdp_add_dir_state(connection_struct *conn, SMB_STRUCT_DIR *dirp)
+{
+ int ret = 0;
+ struct rdp_dir_state *dsp = NULL;
+
+ /* No-op if readdirplus is disabled */
+ if (!lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+ PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
+ {
+ return 0;
+ }
+
+ /* Create a struct dir_state */
+ dsp = SMB_MALLOC_P(struct rdp_dir_state);
+ if (!dsp) {
+ DEBUG(0, ("Error allocating struct rdp_dir_state.\n"));
+ return ENOMEM;
+ }
+
+ /* Initialize the dir_state structure and add it to the list */
+ ret = rdp_init(dsp);
+ if (ret) {
+ DEBUG(0, ("Error initializing readdirplus() buffers: %s\n",
+ strerror(ret)));
+ return ret;
+ }
+
+ /* Set the SMB_STRUCT_DIR in the dsp */
+ dsp->dirp = dirp;
+
+ DLIST_ADD(dirstatelist, dsp);
+
+ return 0;
+}
+
+/**
* Open a directory for enumeration.
*
* Create a state struct to track the state of this directory for the life
@@ -201,7 +249,6 @@ onefs_opendir(vfs_handle_struct *handle, const char *fname, const char *mask,
{
int ret = 0;
SMB_STRUCT_DIR *ret_dirp;
- struct rdp_dir_state *dsp = NULL;
/* Fallback to default system routines if readdirplus is disabled */
if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
@@ -210,13 +257,6 @@ onefs_opendir(vfs_handle_struct *handle, const char *fname, const char *mask,
return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
}
- /* Create a struct dir_state */
- dsp = SMB_MALLOC_P(struct rdp_dir_state);
- if (!dsp) {
- DEBUG(0, ("Error allocating struct rdp_dir_state.\n"));
- return NULL;
- }
-
/* Open the directory */
ret_dirp = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
if (!ret_dirp) {
@@ -224,21 +264,15 @@ onefs_opendir(vfs_handle_struct *handle, const char *fname, const char *mask,
return NULL;
}
- /* Initialize the dir_state structure and add it to the list */
- ret = rdp_init(dsp);
+ /* Create the dir_state struct and add it to the list */
+ ret = onefs_rdp_add_dir_state(handle->conn, ret_dirp);
if (ret) {
- DEBUG(0, ("Error initializing readdirplus() buffers: %s\n",
- strerror(ret)));
+ DEBUG(0, ("Error adding dir_state to the list\n"));
return NULL;
}
- /* Set the SMB_STRUCT_DIR in the dsp */
- dsp->dirp = ret_dirp;
-
- DLIST_ADD(dirstatelist, dsp);
-
DEBUG(9, ("Opened handle on directory: \"%s\", DIR %p\n",
- fname, dsp->dirp));
+ fname, ret_dirp));
return ret_dirp;
}
diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c
index d0dd75f259..9616ca48d5 100644
--- a/source3/modules/onefs_streams.c
+++ b/source3/modules/onefs_streams.c
@@ -540,6 +540,19 @@ static NTSTATUS walk_onefs_streams(connection_struct *conn, files_struct *fsp,
goto out;
}
+ /* Initialize the dir state struct and add it to the list.
+ * This is a layer violation, and really should be handled by a
+ * VFS_FDOPENDIR() call which would properly setup the dir state.
+ * But since this is all within the onefs.so module, we cheat for
+ * now and call directly into the readdirplus code.
+ * NOTE: This state MUST be freed by a proper VFS_CLOSEDIR() call. */
+ ret = onefs_rdp_add_dir_state(conn, dirp);
+ if (ret) {
+ DEBUG(0, ("Error adding dir_state to the list\n"));
+ status = map_nt_error_from_unix(errno);
+ goto out;
+ }
+
fake_fs.conn = conn;
fake_fs.fh = &fake_fh;
fake_fs.fsp_name = SMB_STRDUP(fname);