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