nfs-ganesha 2.8.1 GA

Signed-off-by: Kaleb S. KEITHLEY <kkeithle@redhat.com>
This commit is contained in:
Kaleb S. KEITHLEY 2019-07-02 16:28:32 -04:00
parent 07543d66ee
commit 78e8f49df4
6 changed files with 31 additions and 2956 deletions

View File

@ -1,252 +0,0 @@
diff -u -r nfs-ganesha-2.8.0/src/CMakeLists.txt nfs-ganesha-2.8.0.1/src/CMakeLists.txt
--- nfs-ganesha-2.8.0/src/CMakeLists.txt 2019-05-31 17:37:31.000000000 -0400
+++ nfs-ganesha-2.8.0.1/src/CMakeLists.txt 2019-06-07 18:00:00.000000000 -0400
@@ -39,7 +39,7 @@
# Patch level is always ".0" for mainline (master). It is blank for development.
# When starting a stable maintenance branch, this becomes ".N"
# where N is monotonically increasing starting at 1. Remember to include the "." !!
-set(GANESHA_PATCH_LEVEL .0)
+set(GANESHA_PATCH_LEVEL .0.1)
# Extra version is for naming development/RC. It is blank in master/stable branches
# so it can be available to end-users to name local variants/versions
diff -u -r nfs-ganesha-2.8.0/src/config_parsing/config_parsing.c nfs-ganesha-2.8.0.1/src/config_parsing/config_parsing.c
--- nfs-ganesha-2.8.0/src/config_parsing/config_parsing.c 2019-05-31 17:37:31.000000000 -0400
+++ nfs-ganesha-2.8.0.1/src/config_parsing/config_parsing.c 2019-06-07 18:00:00.000000000 -0400
@@ -984,7 +984,7 @@
void *param_addr;
struct config_node *node, *term_node, *next_node = NULL;
struct glist_head *ns;
- int errors = 0;
+ int errors = 0, prev_errors = err_type->errors;
for (item = params; item->name != NULL; item++) {
uint64_t num64;
@@ -1259,6 +1259,16 @@
node = next_node;
}
}
+
+ /* Check for any errors in parsing params.
+ * It will set to default value if parsing fails.
+ * For params like Export_Id if parsing fails, we
+ * will end up setting it to 1, which could cause issue
+ * if we set it to 1 for multiple exports.
+ */
+ if (err_type->errors > prev_errors)
+ errors = err_type->errors;
+
if (relax)
return errors;
diff -u -r nfs-ganesha-2.8.0/src/FSAL/FSAL_CEPH/handle.c nfs-ganesha-2.8.0.1/src/FSAL/FSAL_CEPH/handle.c
--- nfs-ganesha-2.8.0/src/FSAL/FSAL_CEPH/handle.c 2019-05-31 17:37:31.000000000 -0400
+++ nfs-ganesha-2.8.0.1/src/FSAL/FSAL_CEPH/handle.c 2019-06-07 18:00:00.000000000 -0400
@@ -222,6 +222,13 @@
/* skip . and .. */
if ((strcmp(de.d_name, ".") == 0)
|| (strcmp(de.d_name, "..") == 0)) {
+ /* Deref inode here as we reference inode in
+ * libcephfs readdir_r_cb. The other inodes
+ * gets deref in deconstruct_handle.
+ */
+ if (i != NULL)
+ ceph_ll_put(export->cmount, i);
+
continue;
}
@@ -233,6 +240,8 @@
rc = ceph_fsal_get_sec_label(obj, &attrs);
if (rc < 0) {
fsal_status = ceph2fsal_error(rc);
+ if (i != NULL)
+ ceph_ll_put(export->cmount, i);
goto closedir;
}
diff -u -r nfs-ganesha-2.8.0/src/FSAL/FSAL_VFS/vfs/main-c.in.cmake nfs-ganesha-2.8.0.1/src/FSAL/FSAL_VFS/vfs/main-c.in.cmake
--- nfs-ganesha-2.8.0/src/FSAL/FSAL_VFS/vfs/main-c.in.cmake 2019-05-31 17:37:31.000000000 -0400
+++ nfs-ganesha-2.8.0.1/src/FSAL/FSAL_VFS/vfs/main-c.in.cmake 2019-06-07 18:00:00.000000000 -0400
@@ -129,6 +129,7 @@
{
struct vfs_fsal_module *vfs_module =
container_of(vfs_fsal_module, struct vfs_fsal_module, module);
+ int prev_errors = err_type->errors;
#ifdef F_OFD_GETLK
int fd, rc;
@@ -180,8 +181,15 @@
vfs_module,
true,
err_type);
- if (!config_error_is_harmless(err_type))
+
+ /* Check for actual errors in vfs_param parsing.
+ * err_type could have errors from previous block
+ * parsing also.
+ */
+ if ((err_type->errors > prev_errors) &&
+ !config_error_is_harmless(err_type))
return fsalstat(ERR_FSAL_INVAL, 0);
+
display_fsinfo(&vfs_module->module);
LogFullDebug(COMPONENT_FSAL,
"Supported attributes constant = 0x%" PRIx64,
diff -u -r nfs-ganesha-2.8.0/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c
--- nfs-ganesha-2.8.0/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c 2019-05-31 17:37:31.000000000 -0400
+++ nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c 2019-06-07 18:00:00.000000000 -0400
@@ -217,7 +217,29 @@
}
/**
+ * @brief Drop ref on remaining dirents in chunk
*
+ * @note content_lock of parent dir must be held for WRITE
+ *
+ * @param[in] dirent First ref'd dirent
+ */
+static void mdc_unref_chunk(struct dir_chunk *chunk,
+ mdcache_dir_entry_t *dirent)
+{
+ for (;
+ dirent != NULL;
+ dirent = glist_next_entry(&chunk->dirents,
+ mdcache_dir_entry_t,
+ chunk_list,
+ &dirent->chunk_list)) {
+ if (dirent->entry) {
+ mdcache_put(dirent->entry);
+ dirent->entry = NULL;
+ }
+ }
+}
+
+/**
* @brief Cleans up an entry so it can be reused
*
* @param[in] entry The cache entry to clean
@@ -403,17 +425,18 @@
/* entry's content_lock must not be held, this function will
get the content_lock in exclusive mode */
-void
+fsal_status_t
mdc_get_parent(struct mdcache_fsal_export *export, mdcache_entry_t *entry,
struct gsh_buffdesc *parent_out)
{
struct fsal_obj_handle *sub_handle = NULL;
- fsal_status_t status;
+ fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };
PTHREAD_RWLOCK_wrlock(&entry->content_lock);
if (entry->obj_handle.type != DIRECTORY) {
/* Parent pointer only for directories */
+ status.major = ERR_FSAL_INVAL;
goto out;
}
@@ -430,16 +453,26 @@
entry->sub_handle, "..", &sub_handle, NULL)
);
- if (FSAL_IS_ERROR(status)) {
- /* Top of filesystem */
- goto copy_parent_out;
- }
-
- mdcache_free_fh(&entry->fsobj.fsdir.parent);
- mdc_get_parent_handle(export, entry, sub_handle);
+ if (FSAL_IS_SUCCESS(status)) {
+ /* if we already had a parent handle, then we are
+ * going to refresh it.
+ */
+ mdcache_free_fh(&entry->fsobj.fsdir.parent);
+ mdc_get_parent_handle(export, entry, sub_handle);
+ } else if (entry->fsobj.fsdir.parent.len != 0) {
+ /* Lookup of (..) failed, but if we had a cached
+ * parent handle then we will keep the same and
+ * not fail this request for getting parent.
+ */
+ LogDebug(COMPONENT_CACHE_INODE,
+ "Lookup for (..) failed for entry: %p, but we have a "
+ "cached parent handle so we will keep it", entry);
+ status.major = ERR_FSAL_NO_ERROR;
+ } else
+ goto out;
copy_parent_out:
- if (parent_out != NULL && entry->fsobj.fsdir.parent.len != 0) {
+ if (parent_out != NULL) {
/* Copy the parent handle to parent_out */
mdcache_copy_fh(parent_out, &entry->fsobj.fsdir.parent);
}
@@ -453,6 +486,7 @@
sub_handle->obj_ops->release(sub_handle)
);
}
+ return status;
}
/**
@@ -1179,12 +1213,13 @@
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"Lookup parent (..) of %p", mdc_parent);
- mdc_get_parent(export, mdc_parent, &tmpfh);
+ status = mdc_get_parent(export, mdc_parent, &tmpfh);
- status = mdcache_locate_host(&tmpfh, export, new_entry,
- attrs_out);
-
- mdcache_free_fh(&tmpfh);
+ if (FSAL_IS_SUCCESS(status)) {
+ status = mdcache_locate_host(&tmpfh, export, new_entry,
+ attrs_out);
+ mdcache_free_fh(&tmpfh);
+ }
if (status.major == ERR_FSAL_STALE)
status.major = ERR_FSAL_NOENT;
@@ -3198,6 +3233,14 @@
MDCACHE_DIR_POPULATED);
}
+ if (has_write) {
+ /* We need to drop the ref on the rest of the
+ * entries in this chunk, so that they don't
+ * hang around until the directory is
+ * invalidated. */
+ mdc_unref_chunk(chunk, dirent);
+ }
+
LogDebugAlt(COMPONENT_NFS_READDIR,
COMPONENT_CACHE_INODE,
"readdir completed, eod = %s",
diff -u -r nfs-ganesha-2.8.0/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_int.h nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_int.h
--- nfs-ganesha-2.8.0/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_int.h 2019-05-31 17:37:31.000000000 -0400
+++ nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_int.h 2019-06-07 18:00:00.000000000 -0400
@@ -504,7 +504,7 @@
attrmask_t attrmask,
bool *eod_met);
-void mdc_get_parent(struct mdcache_fsal_export *exp,
+fsal_status_t mdc_get_parent(struct mdcache_fsal_export *exp,
mdcache_entry_t *entry,
struct gsh_buffdesc *parent_out);
diff -u -r nfs-ganesha-2.8.0/src/nfs-ganesha.spec-in.cmake nfs-ganesha-2.8.0.1/src/nfs-ganesha.spec-in.cmake
--- nfs-ganesha-2.8.0/src/nfs-ganesha.spec-in.cmake 2019-05-31 17:37:31.000000000 -0400
+++ nfs-ganesha-2.8.0.1/src/nfs-ganesha.spec-in.cmake 2019-06-07 18:00:00.000000000 -0400
@@ -202,6 +202,10 @@
Requires(post): psmisc
Requires(pre): shadow-utils
+%if ( 0%{?fedora} >= 30 || 0%{?rhel} >= 8 )
+Requires: nfs-ganesha-selinux = %{version}-%{release}
+%endif
+
# Use CMake variables
%description

View File

@ -0,0 +1,24 @@
--- nfs-ganesha-2.8.1/src/scripts/ganeshactl/Ganesha/glib_dbus_stats.py.orig 2019-07-02 16:15:14.081197046 -0400
+++ nfs-ganesha-2.8.1/src/scripts/ganeshactl/Ganesha/glib_dbus_stats.py 2019-07-02 16:15:55.797197046 -0400
@@ -139,9 +139,9 @@
return DumpFULLV4Stats(stats_state())
# authentication
def auth_stats(self):
- stats_state = self.exportmgrobj.get_dbus_method("GetAuthStats",
- self.dbus_exportstats_name)
- return DumpAuth(stats_state())
+ stats_state = self.exportmgrobj.get_dbus_method("GetAuthStats",
+ self.dbus_exportstats_name)
+ return DumpAuth(stats_state())
class RetrieveClientStats():
def __init__(self):
@@ -497,7 +497,7 @@
self.success = stats[0]
self.status = stats[1]
if self.success:
- self.timestamp = (stats[2][0], stats[2][1])
+ self.timestamp = (stats[2][0], stats[2][1])
self.gctotal = stats[3][0]
self.gclatency = stats[3][1]
self.gcmax = stats[3][2]

View File

@ -1,679 +0,0 @@
diff -ur nfs-ganesha-2.8.0.1/src/CMakeLists.txt nfs-ganesha-2.8.0.2/src/CMakeLists.txt
--- nfs-ganesha-2.8.0.1/src/CMakeLists.txt 2019-06-07 18:00:00.000000000 -0400
+++ nfs-ganesha-2.8.0.2/src/CMakeLists.txt 2019-06-14 18:23:42.000000000 -0400
@@ -39,7 +39,7 @@
# Patch level is always ".0" for mainline (master). It is blank for development.
# When starting a stable maintenance branch, this becomes ".N"
# where N is monotonically increasing starting at 1. Remember to include the "." !!
-set(GANESHA_PATCH_LEVEL .0.1)
+set(GANESHA_PATCH_LEVEL .0.2)
# Extra version is for naming development/RC. It is blank in master/stable branches
# so it can be available to end-users to name local variants/versions
diff -ur nfs-ganesha-2.8.0.1/src/doc/man/ganesha-cache-config.rst nfs-ganesha-2.8.0.2/src/doc/man/ganesha-cache-config.rst
--- nfs-ganesha-2.8.0.1/src/doc/man/ganesha-cache-config.rst 2019-06-07 18:00:00.000000000 -0400
+++ nfs-ganesha-2.8.0.2/src/doc/man/ganesha-cache-config.rst 2019-06-14 18:23:42.000000000 -0400
@@ -44,6 +44,9 @@
Entries_HWMark(uint32, range 1 to UINT32_MAX, default 100000)
The point at which object cache entries will start being reused.
+Chunks_HWMark(uint32, range 1 to UINT32_MAX, default 100000)
+ The point at which dirent cache chunks will start being reused.
+
LRU_Run_Interval(uint32, range 1 to 24 * 3600, default 90)
Base interval in seconds between runs of the LRU cleaner thread.
diff -ur nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c nfs-ganesha-2.8.0.2/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c
--- nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c 2019-06-07 18:00:00.000000000 -0400
+++ nfs-ganesha-2.8.0.2/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_helpers.c 2019-06-14 18:23:42.000000000 -0400
@@ -56,6 +56,28 @@
#define mdc_chunk_first_dirent(c) \
glist_first_entry(&(c)->dirents, mdcache_dir_entry_t, chunk_list)
+/**
+ * @brief Drop refs for state chunks
+ *
+ * Drop a ref from each chunk, making sure keep has one
+ *
+ * @param[in] a First chunk
+ * @param[in] b Second chunk
+ * @param[in] c Third chunk
+ * @param[in] keep Chunk to keep a ref
+ */
+static void drop_state_chunk_refs(struct dir_chunk *a, struct dir_chunk *b,
+ struct dir_chunk *c, struct dir_chunk *keep)
+{
+ if (keep) {
+ mdcache_lru_ref_chunk(keep);
+ }
+
+ mdcache_lru_unref_chunk(a);
+ mdcache_lru_unref_chunk(b);
+ mdcache_lru_unref_chunk(c);
+}
+
static inline bool trust_negative_cache(mdcache_entry_t *parent)
{
bool trust = op_ctx_export_has_option(
@@ -223,7 +245,7 @@
*
* @param[in] dirent First ref'd dirent
*/
-static void mdc_unref_chunk(struct dir_chunk *chunk,
+static void mdc_unref_chunk_dirents(struct dir_chunk *chunk,
mdcache_dir_entry_t *dirent)
{
for (;
@@ -2078,6 +2100,8 @@
*/
chunk->next_ck = here->ck;
+ mdcache_lru_unref_chunk(split);
+
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"Chunk next_ck=%"PRIx64,
chunk->next_ck);
@@ -2127,9 +2151,6 @@
fsal_cookie_t cookie)
{
struct mdcache_populate_cb_state *state = dir_state;
- struct dir_chunk *chunk = state->cur_chunk;
- mdcache_entry_t *mdc_parent = container_of(&state->dir->obj_handle,
- mdcache_entry_t, obj_handle);
struct mdcache_fsal_export *export = mdc_cur_export();
mdcache_entry_t *new_entry = NULL;
mdcache_dir_entry_t *new_dir_entry = NULL, *allocated_dir_entry = NULL;
@@ -2139,27 +2160,27 @@
enum fsal_dir_result result = DIR_CONTINUE;
#ifdef DEBUG_MDCACHE
- assert(mdc_parent->content_lock.__data.__cur_writer);
+ assert(state->dir->content_lock.__data.__cur_writer);
#endif
- if (chunk->num_entries == mdcache_param.dir.avl_chunk) {
+ if (state->cur_chunk->num_entries == mdcache_param.dir.avl_chunk) {
/* We are being called readahead. */
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"Readdir readahead first entry in new chunk %s",
name);
- state->prev_chunk = chunk;
+ mdcache_lru_unref_chunk(state->prev_chunk);
+ state->prev_chunk = state->cur_chunk;
state->prev_chunk->next_ck = cookie;
/* Chunk is added to the chunks list before being passed in */
/* Now start a new chunk, passing this chunk as prev_chunk. */
- chunk = mdcache_get_chunk(chunk->parent, chunk, 0);
-
- state->cur_chunk = chunk;
+ state->cur_chunk = mdcache_get_chunk(state->prev_chunk->parent,
+ state->prev_chunk, 0);
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"Chunk %p Prev chunk %p next_ck=%" PRIx64,
- chunk, state->prev_chunk,
+ state->cur_chunk, state->prev_chunk,
state->prev_chunk->next_ck);
/* And start accepting entries into the new chunk. */
}
@@ -2176,7 +2197,7 @@
*state->status = status;
LogInfoAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"mdcache_new_entry failed on %s in dir %p with %s",
- name, mdc_parent, fsal_err_txt(status));
+ name, state->dir, fsal_err_txt(status));
return DIR_TERMINATE;
}
@@ -2187,10 +2208,10 @@
"Add mdcache entry %p for %s for FSAL %s",
new_entry, name, new_entry->sub_handle->fsal->name);
- /* in cache avl, we always insert on mdc_parent */
+ /* in cache avl, we always insert on state->dir */
new_dir_entry = gsh_calloc(1, sizeof(mdcache_dir_entry_t) + namesize);
new_dir_entry->flags = DIR_ENTRY_FLAG_NONE;
- new_dir_entry->chunk = chunk;
+ new_dir_entry->chunk = state->cur_chunk;
new_dir_entry->ck = cookie;
allocated_dir_entry = new_dir_entry;
@@ -2207,7 +2228,7 @@
mdcache_key_dup(&new_dir_entry->ckey, &new_entry->fh_hk.key);
/* add to avl */
- code = mdcache_avl_insert(mdc_parent, &new_dir_entry);
+ code = mdcache_avl_insert(state->dir, &new_dir_entry);
if (code < 0) {
/* We can get here with the following possibilities:
@@ -2244,7 +2265,7 @@
}
/* Note that if this dirent was already in the lookup by name AVL
- * tree (mdc_parent->fsobj.fsdir.avl.t), then mdcache_avl_qp_insert
+ * tree (state->dir->fsobj.fsdir.avl.t), then mdcache_avl_qp_insert
* freed the dirent we allocated above, and returned the one that was
* in tree. It will have set chunk, ck, and nk.
*
@@ -2256,7 +2277,7 @@
"Swapped %s using %p instead of %p, new_dir_entry->chunk=%p chunk=%p",
new_dir_entry->name, new_dir_entry,
allocated_dir_entry, new_dir_entry->chunk,
- chunk);
+ state->cur_chunk);
}
assert(new_dir_entry->chunk);
@@ -2275,7 +2296,7 @@
node = avltree_inline_insert(
&new_dir_entry->node_sorted,
- &mdc_parent->fsobj.fsdir.avl.sorted,
+ &state->dir->fsobj.fsdir.avl.sorted,
avl_dirent_sorted_cmpf);
if (node != NULL) {
@@ -2313,11 +2334,12 @@
* old dirent that was not part of a chunk, but it is NOT the
* same dirent that was already part of some other chunk.
*/
- glist_add_tail(&chunk->dirents, &new_dir_entry->chunk_list);
- chunk->num_entries++;
+ glist_add_tail(&state->cur_chunk->dirents,
+ &new_dir_entry->chunk_list);
+ state->cur_chunk->num_entries++;
}
- if (new_dir_entry->chunk != chunk) {
+ if (new_dir_entry->chunk != state->cur_chunk) {
/* We have the situation where we have collided with a
* previously used chunk (and thus we have a partial chunk).
* Since dirent is pointing to the existing dirent and the one
@@ -2333,25 +2355,25 @@
"Collision old chunk %p next_ck=%"PRIx64
" new chunk %p next_ck=%"PRIx64,
new_dir_entry->chunk,
- new_dir_entry->chunk->next_ck, chunk,
- chunk->next_ck);
- if (chunk->num_entries == 0) {
+ new_dir_entry->chunk->next_ck, state->cur_chunk,
+ state->cur_chunk->next_ck);
+ if (state->cur_chunk->num_entries == 0) {
LogFullDebugAlt(COMPONENT_NFS_READDIR,
COMPONENT_CACHE_INODE,
- "Nuking empty Chunk %p", chunk);
+ "Nuking empty Chunk %p", state->cur_chunk);
/* We read-ahead into an existing chunk, and this chunk
* is empty. Just ditch it now, to avoid any issue. */
- mdcache_lru_unref_chunk(chunk);
- if (state->first_chunk == chunk) {
+ mdcache_lru_unref_chunk(state->cur_chunk);
+ if (state->first_chunk == state->cur_chunk) {
/* Drop the first_chunk ref */
mdcache_lru_unref_chunk(state->first_chunk);
state->first_chunk = new_dir_entry->chunk;
/* And take the first_chunk ref */
mdcache_lru_ref_chunk(state->first_chunk);
}
- chunk = new_dir_entry->chunk;
- state->cur_chunk = chunk;
+ state->cur_chunk = new_dir_entry->chunk;
+ mdcache_lru_ref_chunk(state->cur_chunk);
if (new_dir_entry->entry) {
/* This was ref'd already; drop extra ref */
mdcache_put(new_dir_entry->entry);
@@ -2363,10 +2385,12 @@
} else {
LogFullDebugAlt(COMPONENT_NFS_READDIR,
COMPONENT_CACHE_INODE,
- "keeping non-empty Chunk %p", chunk);
- chunk->next_ck = new_dir_entry->ck;
+ "keeping non-empty Chunk %p",
+ state->cur_chunk);
+ state->cur_chunk->next_ck = new_dir_entry->ck;
}
- } else if (chunk->num_entries == mdcache_param.dir.avl_chunk) {
+ } else if (state->cur_chunk->num_entries ==
+ mdcache_param.dir.avl_chunk) {
/* Chunk is full. Since dirent is pointing to the existing
* dirent and the one we allocated above has been freed we don't
* need to do any cleanup.
@@ -2382,7 +2406,7 @@
if (new_entry->obj_handle.type == DIRECTORY) {
/* Insert Parent's key */
PTHREAD_RWLOCK_wrlock(&new_entry->content_lock);
- mdc_dir_add_parent(new_entry, mdc_parent);
+ mdc_dir_add_parent(new_entry, state->dir);
PTHREAD_RWLOCK_unlock(&new_entry->content_lock);
}
@@ -2391,10 +2415,16 @@
new_entry,
atomic_fetch_int32_t(&new_entry->lru.refcnt));
- /* Note that this entry is ref'd, so that mdcache_readdir_chunked can
- * un-ref it. Pass this ref off to the dir_entry for this purpose. */
- assert(!new_dir_entry->entry);
- new_dir_entry->entry = new_entry;
+ if (new_dir_entry != allocated_dir_entry && new_dir_entry->entry) {
+ /* This was swapped and already has a refcounted entry. Drop our
+ * ref. */
+ mdcache_put(new_entry);
+ } else {
+ /* This is a new dirent, or doesn't have an entry. Pass our ref
+ * on entry off to mdcache_readdir_chunked */
+ assert(!new_dir_entry->entry);
+ new_dir_entry->entry = new_entry;
+ }
return result;
}
@@ -2464,10 +2494,12 @@
* @brief Read the next chunk of a directory
*
* If called for an FSAL that only supports whence as the dirent name to
- * continue from, and prev_chunk is NULL, we must scan the directory from the
- * beginning. If prev_chunk is not NULL, we can scan the directory starting with
- * the last dirent name in prev_chunk, but we must still scan the directory
- * until we find whence.
+ * continue from, and @a prev_chunk is NULL, we must scan the directory from the
+ * beginning. If @a prev_chunk is not NULL, we can scan the directory starting
+ * with the last dirent name in @a prev_chunk, but we must still scan the
+ * directory until we find whence.
+ *
+ * @a prev_chunk must have a ref taken on it, and this ref will be released
*
* @note this returns a ref on the chunk containing @a dirent
*
@@ -2489,30 +2521,30 @@
fsal_status_t status = {0, 0};
fsal_status_t readdir_status = {0, 0};
struct mdcache_populate_cb_state state;
- struct dir_chunk *chunk;
attrmask_t attrmask;
fsal_cookie_t *whence_ptr = &whence;
- chunk = mdcache_get_chunk(directory, prev_chunk, whence);
-
attrmask = op_ctx->fsal_export->exp_ops.fs_supported_attrs(
op_ctx->fsal_export) | ATTR_RDATTR_ERR;
- /* Take a ref on the first chunk */
- mdcache_lru_ref_chunk(chunk);
-
state.export = mdc_cur_export();
state.dir = directory;
state.status = &status;
state.cb = NULL; /* We don't use the call back during chunking. */
- state.first_chunk = state.cur_chunk = chunk;
- state.prev_chunk = prev_chunk;
state.cookie = whence;
state.dirent = dirent;
state.whence_is_name = op_ctx->fsal_export->exp_ops.fs_supports(
op_ctx->fsal_export, fso_whence_is_name);
- state.whence_search = state.whence_is_name && whence != 0 &&
- prev_chunk == NULL;
+ state.whence_search = state.whence_is_name && whence != 0;
+
+ /* Set up chunks */
+ state.first_chunk = mdcache_get_chunk(directory, prev_chunk, whence);
+
+ state.cur_chunk = state.first_chunk;
+ mdcache_lru_ref_chunk(state.cur_chunk);
+
+ /* prev_chunk was passed in with a ref on it */
+ state.prev_chunk = prev_chunk;
if (state.whence_is_name) {
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
@@ -2531,12 +2563,12 @@
* prev_chunk has been updated to point to the last cached chunk.
*/
if (state.whence_is_name) {
- if (prev_chunk != NULL) {
+ if (state.prev_chunk != NULL) {
/* Start from end of prev_chunk */
/* If end of directory, mark last dirent as eod. */
mdcache_dir_entry_t *last;
- last = glist_last_entry(&prev_chunk->dirents,
+ last = glist_last_entry(&state.prev_chunk->dirents,
mdcache_dir_entry_t,
chunk_list);
whence_ptr = (fsal_cookie_t *)last->name;
@@ -2590,7 +2622,8 @@
"FSAL readdir status=%s",
fsal_err_txt(readdir_status));
*dirent = NULL;
- mdcache_lru_unref_chunk(chunk);
+ drop_state_chunk_refs(state.first_chunk, state.cur_chunk,
+ state.prev_chunk, NULL);
return readdir_status;
}
@@ -2599,32 +2632,33 @@
"status=%s",
fsal_err_txt(status));
*dirent = NULL;
- mdcache_lru_unref_chunk(chunk);
+ drop_state_chunk_refs(state.first_chunk, state.cur_chunk,
+ state.prev_chunk, NULL);
return status;
}
- /* Recover the most recent chunk from cur_chunk, if we had readahead.
- * it might have changed.
- */
- chunk = state.cur_chunk;
-
- if (chunk->num_entries == 0) {
- /* Chunk is empty - should only happen for an empty directory
- * but could happen if the FSAL failed to indicate end of
- * directory. This COULD happen on a readahead chunk, but it
+ if (state.cur_chunk->num_entries == 0) {
+ /* cur_chunk is empty - should only happen for an empty
+ * directory but could happen if the FSAL failed to indicate end
+ * of directory. This COULD happen on a readahead chunk, but it
* would be unusual.
*/
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"Empty chunk");
- mdcache_lru_unref_chunk(chunk);
+ /* Put our ref */
+ mdcache_lru_unref_chunk(state.cur_chunk);
+ /* Put sentinal ref */
+ mdcache_lru_unref_chunk(state.cur_chunk);
- if (chunk == state.first_chunk) {
+ if (state.cur_chunk == state.first_chunk) {
/* We really got nothing on this readdir, so don't
* return a dirent.
*/
*dirent = NULL;
- mdcache_lru_unref_chunk(chunk);
+ mdcache_lru_unref_chunk(state.first_chunk);
+ /* cur_chunk was freed */
+ mdcache_lru_unref_chunk(state.prev_chunk);
LogDebugAlt(COMPONENT_NFS_READDIR,
COMPONENT_CACHE_INODE,
"status=%s",
@@ -2633,15 +2667,18 @@
}
/* If the empty chunk wasn't first, then prev_chunk is valid */
- chunk = state.prev_chunk;
+ state.cur_chunk = state.prev_chunk;
+ if (state.cur_chunk) {
+ mdcache_lru_ref_chunk(state.cur_chunk);
+ }
}
if (*eod_met) {
/* If end of directory, mark last dirent as eod. */
mdcache_dir_entry_t *last;
- last = glist_last_entry(&chunk->dirents, mdcache_dir_entry_t,
- chunk_list);
+ last = glist_last_entry(&state.cur_chunk->dirents,
+ mdcache_dir_entry_t, chunk_list);
last->eod = true;
}
@@ -2653,6 +2690,10 @@
if (state.whence_search && *dirent == NULL) {
if (*eod_met) {
/* Did not find cookie. */
+ drop_state_chunk_refs(state.first_chunk,
+ state.cur_chunk,
+ state.prev_chunk,
+ NULL);
status = fsalstat(ERR_FSAL_BADCOOKIE, 0);
LogDebugAlt(COMPONENT_NFS_READDIR,
COMPONENT_CACHE_INODE,
@@ -2679,34 +2720,44 @@
"Rescan dir to find cookie needs to continue search for %"
PRIx64, state.cookie);
- if (chunk->next_ck != 0) {
+ if (state.cur_chunk->next_ck != 0) {
+ fsal_cookie_t next_ck = state.cur_chunk->next_ck;
+
+ mdcache_lru_unref_chunk(state.cur_chunk);
/* In the collision case, chunk->next_ck was set,
* so now start skipping.
*/
LogFullDebugAlt(COMPONENT_NFS_READDIR,
COMPONENT_CACHE_INODE,
"Search skipping from cookie %"PRIx64,
- chunk->next_ck);
- chunk = mdcache_skip_chunks(directory, chunk->next_ck);
+ state.cur_chunk->next_ck);
+ state.cur_chunk = mdcache_skip_chunks(directory,
+ next_ck);
+ mdcache_lru_ref_chunk(state.cur_chunk);
}
+ /* drop refs on state, except cur_chunk which we're saving */
+ drop_state_chunk_refs(state.first_chunk, NULL,
+ state.prev_chunk, NULL);
+
/* We need to start a new FSAL readdir call, but we don't just
* want to call mdcache_populate_dir_chunk raw, so set up a few
* things and jump to again...
*/
+
/* The chunk we just dealt with is now prev_chunk. */
- prev_chunk = chunk;
+ state.prev_chunk = state.cur_chunk;
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"About to allocate a new chunk to continue search, prev chunk = %p",
- prev_chunk);
+ state.prev_chunk);
/* And we need to allocate a fresh chunk. */
- chunk = mdcache_get_chunk(directory, chunk, 0);
+ state.first_chunk = mdcache_get_chunk(directory,
+ state.prev_chunk, 0);
+ state.cur_chunk = state.first_chunk;
+ mdcache_lru_ref_chunk(state.cur_chunk);
- /* And switch over to new chunk. */
- state.cur_chunk = chunk;
- state.prev_chunk = prev_chunk;
/* And go start a new FSAL readdir call. */
goto again;
@@ -2721,6 +2772,14 @@
chunk_list);
}
+ /* At this point, we have ref's on first_chunk, cur_chunk, and
+ * prev_chunk. Drop the refs and make sure the chunk containing dirent
+ * is ref'd */
+ drop_state_chunk_refs(state.first_chunk, state.cur_chunk,
+ state.prev_chunk, (*dirent)->chunk);
+
+ /* At this point, only dirent->chunk should be ref'd */
+
LogDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"status=%s",
fsal_err_txt(status));
@@ -3004,12 +3063,6 @@
/* Bump the chunk in the LRU */
lru_bump_chunk(chunk);
- /* We can drop the ref now, we've bumped. This cannot be the last ref
- * drop. To get here, we had at least 2 refs, and we also hold the
- * content_lock for at least read. This means noone holds it for write,
- * and all final ref drops are done with it held for write. */
- mdcache_lru_unref_chunk(chunk);
-
LogFullDebugAlt(COMPONENT_NFS_READDIR, COMPONENT_CACHE_INODE,
"About to read directory=%p cookie=%" PRIx64,
directory, next_ck);
@@ -3076,6 +3129,7 @@
* reloading the chunk.
*/
first_pass = true;
+ mdcache_lru_unref_chunk(chunk);
chunk = NULL;
/* Now we need to look for this dirent again.
@@ -3103,6 +3157,7 @@
/* In order to get here, we passed the has_write
* check above, and took the write lock. */
mdcache_lru_unref_chunk(chunk);
+ mdcache_lru_unref_chunk(chunk);
chunk = NULL;
goto again;
}
@@ -3124,6 +3179,7 @@
if (status.major == ERR_FSAL_STALE)
mdcache_kill_entry(directory);
+ mdcache_lru_unref_chunk(chunk);
return status;
}
@@ -3134,6 +3190,7 @@
* don't match. If the new dirent couldn't be
* placed, we need to restart readdir.
*/
+ mdcache_lru_unref_chunk(chunk);
goto restart;
}
}
@@ -3192,6 +3249,7 @@
fsal_err_txt(status));
mdcache_put(entry);
+ mdcache_lru_unref_chunk(chunk);
return status;
}
@@ -3238,7 +3296,7 @@
* entries in this chunk, so that they don't
* hang around until the directory is
* invalidated. */
- mdc_unref_chunk(chunk, dirent);
+ mdc_unref_chunk_dirents(chunk, dirent);
}
LogDebugAlt(COMPONENT_NFS_READDIR,
@@ -3248,6 +3306,7 @@
PTHREAD_RWLOCK_unlock(&directory->content_lock);
+ mdcache_lru_unref_chunk(chunk);
return status;
}
@@ -3297,6 +3356,10 @@
* lock just in case the next chunk actually
* happens to be populated.
*/
+
+ /* Note: We're passing our ref on chunk into
+ * mdcache_populate_dir_chunk(), so don't drop it here.
+ */
first_pass = false;
goto again;
}
diff -ur nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.c nfs-ganesha-2.8.0.2/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.c
--- nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.c 2019-06-07 18:00:00.000000000 -0400
+++ nfs-ganesha-2.8.0.2/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.c 2019-06-14 18:23:42.000000000 -0400
@@ -869,7 +869,7 @@
* @param[in] prev_chunk If non-NULL, the previous chunk in this directory
* @param[in] whence If @a prev_chunk is NULL, the starting whence of chunk
*
- * @return reused or allocated chunk
+ * @return reused or allocated chunk with a ref taken for the caller
*/
struct dir_chunk *mdcache_get_chunk(mdcache_entry_t *parent,
struct dir_chunk *prev_chunk,
@@ -920,7 +920,7 @@
chunk->reload_ck = whence;
}
- chunk->chunk_lru.refcnt = 1;
+ chunk->chunk_lru.refcnt = 2;
chunk->chunk_lru.cf = 0;
chunk->chunk_lru.lane = lru_lane_of(chunk);
@@ -2033,7 +2033,7 @@
mdcache_clean_dirent_chunk(chunk);
}
-void mdcache_lru_ref_chunk(struct dir_chunk *chunk)
+void _mdcache_lru_ref_chunk(struct dir_chunk *chunk, const char *func, int line)
{
atomic_inc_int32_t(&chunk->chunk_lru.refcnt);
}
@@ -2043,12 +2043,17 @@
* Should be called with content_lock held in write mode.
* @param [in] chunk The chunk to unref
*/
-void mdcache_lru_unref_chunk(struct dir_chunk *chunk)
+void _mdcache_lru_unref_chunk(struct dir_chunk *chunk, const char *func,
+ int line)
{
int refcnt;
- uint32_t lane = chunk->chunk_lru.lane;
+ uint32_t lane;
struct lru_q_lane *qlane;
+ if (!chunk)
+ return;
+
+ lane = chunk->chunk_lru.lane;
qlane = &CHUNK_LRU[lane];
QLOCK(qlane);
diff -ur nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.h nfs-ganesha-2.8.0.2/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.h
--- nfs-ganesha-2.8.0.1/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.h 2019-06-07 18:00:00.000000000 -0400
+++ nfs-ganesha-2.8.0.2/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.h 2019-06-14 18:23:42.000000000 -0400
@@ -196,8 +196,14 @@
mdcache_lru_unref(entry);
}
-void mdcache_lru_ref_chunk(struct dir_chunk *chunk);
-void mdcache_lru_unref_chunk(struct dir_chunk *chunk);
+#define mdcache_lru_ref_chunk(chunk) \
+ _mdcache_lru_ref_chunk(chunk, __func__, __LINE__)
+void _mdcache_lru_ref_chunk(struct dir_chunk *chunk, const char *func,
+ int line);
+#define mdcache_lru_unref_chunk(chunk) \
+ _mdcache_lru_unref_chunk(chunk, __func__, __LINE__)
+void _mdcache_lru_unref_chunk(struct dir_chunk *chunk, const char *func,
+ int line);
struct dir_chunk *mdcache_get_chunk(mdcache_entry_t *parent,
struct dir_chunk *prev_chunk,
fsal_cookie_t whence);
diff -ur nfs-ganesha-2.8.0.1/src/Protocols/NFS/mnt_Export.c nfs-ganesha-2.8.0.2/src/Protocols/NFS/mnt_Export.c
--- nfs-ganesha-2.8.0.1/src/Protocols/NFS/mnt_Export.c 2019-06-07 18:00:00.000000000 -0400
+++ nfs-ganesha-2.8.0.2/src/Protocols/NFS/mnt_Export.c 2019-06-14 18:23:42.000000000 -0400
@@ -201,6 +201,7 @@
gsh_free(grp);
grp = next_grp;
}
+ gsh_free(exp->ex_dir);
gsh_free(exp);
exp = next_exp;
}
diff -ur nfs-ganesha-2.8.0.1/src/RPCAL/nfs_dupreq.c nfs-ganesha-2.8.0.2/src/RPCAL/nfs_dupreq.c
--- nfs-ganesha-2.8.0.1/src/RPCAL/nfs_dupreq.c 2019-06-07 18:00:00.000000000 -0400
+++ nfs-ganesha-2.8.0.2/src/RPCAL/nfs_dupreq.c 2019-06-14 18:23:42.000000000 -0400
@@ -577,6 +577,7 @@
LogFullDebug(COMPONENT_DUPREQ, "ref shared UDP DRC");
drc = &(drc_st->udp_drc);
DRC_ST_LOCK();
+ req->rq_xprt->xp_u2 = (void *)drc;
(void)nfs_dupreq_ref_drc(drc);
DRC_ST_UNLOCK();
goto out;

File diff suppressed because it is too large Load Diff

View File

@ -130,16 +130,14 @@ Requires: openSUSE-release
#%%global dash_dev_version 2.8-rc1
Name: nfs-ganesha
Version: 2.8.0
Release: 4%{?dev:%{dev}}%{?dist}
Version: 2.8.1
Release: 1%{?dev:%{dev}}%{?dist}
Summary: NFS-Ganesha is a NFS Server running in user space
License: LGPLv3+
Url: https://github.com/nfs-ganesha/nfs-ganesha/wiki
Source0: https://github.com/%{name}/%{name}/archive/V%{version}/%{name}-%{version}.tar.gz
Patch1: 0001-nfs-ganesha_2801.patch
Patch2: 0002-nfs-ganesha_2802.patch
Patch3: 0003-nfs-ganesha_2803.patch
Patch1: 0001-src-scripts-ganeshactl-Ganesha-glib_dbus_stats.py.patch
BuildRequires: cmake
BuildRequires: bison
@ -500,8 +498,6 @@ Development headers and auxiliary files for developing with %{name}.
%prep
%setup -q -n %{name}-%{version}
%patch1 -p1
%patch2 -p1
%patch3 -p1
%build
cd src && %cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo \
@ -877,6 +873,9 @@ exit 0
%endif
%changelog
* Tue Jul 2 2019 Kaleb S. KEITHLEY <kkeithle at redhat.com> - 2.8.1-1
- nfs-ganesha 2.8.1 GA
* Mon Jul 1 2019 Kaleb S. KEITHLEY <kkeithle at redhat.com> - 2.8.0-4
- nfs-ganesha 2.8.0, 2.8.0.3

View File

@ -1 +1 @@
SHA512 (nfs-ganesha-2.8.0.tar.gz) = 8b15f1240047c17f061b149e4dbb311164f6a5f4dc782a353600932f69d8b505f120508bc45500d44de721b39bc7ebba46bb3e375b041634b92a407204d3656d
SHA512 (nfs-ganesha-2.8.1.tar.gz) = 0b3d1551258dcf2a9c838cd425c98c07cbf14fa256741bda45c8ce4749e80d43ac9e1547d300e8378351ed7fd1acae929a4d9df1d79f8a67132d23cec0fb6172