Commit 52939f25 authored by LiYankun's avatar LiYankun Committed by Tomasz Zawadzki
Browse files

lib/blobfs: fix memory error for spdk_file_write

After calling tree_free_buffers, if the
file->tree->present_mask is not equal to 0, the
cache_buffer pointed to by file->last may have been freed,
because there may be a cache_buffer->in_progress = true.
so we must check that the last cache_buffer release has
been released, otherwise spdk_file_write will be affected.
memory error

issue: https://github.com/spdk/spdk/issues/2849



Change-Id: I815708952903a99487adeb3bbc45be7e5563634f
Signed-off-by: default avatarLiYankun <liyankun01@58.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16763


Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 235c4c53
Loading
Loading
Loading
Loading
+41 −32
Original line number Diff line number Diff line
@@ -2024,9 +2024,16 @@ reclaim_cache_buffers(struct spdk_file *file)
	/* If not freed, put it in the end of the queue */
	if (file->tree->present_mask != 0) {
		TAILQ_INSERT_TAIL(&g_caches, file, cache_tailq);
	} else {
	}

	/* tree_free_buffers() may have freed the buffer pointed to by file->last.
	 * So check if current append_pos is still in the cache, and if not, clear
	 * file->last.
	 */
	if (tree_find_buffer(file->tree, file->append_pos) == NULL) {
		file->last = NULL;
	}

	pthread_spin_unlock(&file->lock);

	return 0;
@@ -2431,6 +2438,7 @@ spdk_file_write(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx,
	pthread_spin_lock(&file->lock);
	file->open_for_writing = true;

	do {
		if ((file->last == NULL) && (file->append_pos % CACHE_BUFFER_SIZE == 0)) {
			cache_append_buffer(file);
		}
@@ -2469,6 +2477,7 @@ spdk_file_write(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx,
			}
			pthread_spin_lock(&file->lock);
		}
	} while (file->last == NULL);

	flush_req = alloc_fs_request(channel);
	if (flush_req == NULL) {