cros_gralloc: Handle failure to get prime fd

... in cros_gralloc_driver::allocate().

BUG=b:178495907
TEST=Cuttlefish CFI

Change-Id: Ibb9a5e55f2d2a4bf6be71f03dfe3f0fcd55a1b55
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/2658929
Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc
index d13064b..783180f 100644
--- a/cros_gralloc/cros_gralloc_buffer.cc
+++ b/cros_gralloc/cros_gralloc_buffer.cc
@@ -26,8 +26,8 @@
 {
 	drv_bo_destroy(bo_);
 	if (hnd_) {
-		native_handle_close(&hnd_->base);
-		delete hnd_;
+		native_handle_close(hnd_);
+		native_handle_delete(hnd_);
 	}
 	if (reserved_region_addr_) {
 		munmap(reserved_region_addr_, reserved_region_size_);
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index b8eef71..b383782 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -143,10 +143,20 @@
 	return reserved_region_fd;
 }
 
+void cros_gralloc_driver::emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd)
+{
+	auto buffer = new cros_gralloc_buffer(hnd->id, bo, hnd, hnd->fds[hnd->num_planes],
+					      hnd->reserved_region_size);
+
+	std::lock_guard<std::mutex> lock(mutex_);
+	buffers_.emplace(hnd->id, buffer);
+	handles_.emplace(hnd, std::make_pair(buffer, 1));
+}
+
 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
 				      buffer_handle_t *out_handle)
 {
-	uint32_t id;
+	int ret = 0;
 	size_t num_planes;
 	size_t num_fds;
 	size_t num_ints;
@@ -154,9 +164,7 @@
 	uint32_t resolved_format;
 	uint32_t bytes_per_pixel;
 	uint64_t use_flags;
-	int32_t reserved_region_fd;
 	char *name;
-
 	struct bo *bo;
 	struct cros_gralloc_handle *hnd;
 
@@ -183,7 +191,7 @@
 	bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
 	if (!bo) {
 		drv_log("Failed to create bo.\n");
-		return -ENOMEM;
+		return -errno;
 	}
 
 	/*
@@ -192,25 +200,15 @@
 	 * send more than one fd. GL/Vulkan drivers may also have to modified.
 	 */
 	if (drv_num_buffers_per_bo(bo) != 1) {
-		drv_bo_destroy(bo);
 		drv_log("Can only support one buffer per bo.\n");
-		return -EINVAL;
+		goto destroy_bo;
 	}
 
 	num_planes = drv_bo_get_num_planes(bo);
 	num_fds = num_planes;
 
-	if (descriptor->reserved_region_size > 0) {
-		reserved_region_fd =
-		    create_reserved_region(descriptor->name, descriptor->reserved_region_size);
-		if (reserved_region_fd < 0) {
-			drv_bo_destroy(bo);
-			return reserved_region_fd;
-		}
+	if (descriptor->reserved_region_size > 0)
 		num_fds += 1;
-	} else {
-		reserved_region_fd = -1;
-	}
 
 	num_bytes = sizeof(struct cros_gralloc_handle);
 	num_bytes += (descriptor->name.size() + 1);
@@ -220,23 +218,34 @@
 	 */
 	num_bytes = ALIGN(num_bytes, sizeof(int));
 	num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
-	/*
-	 * Malloc is used as handles are ultimately destroyed via free in
-	 * native_handle_delete().
-	 */
-	hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
-	hnd->base.version = sizeof(hnd->base);
-	hnd->base.numFds = num_fds;
-	hnd->base.numInts = num_ints;
+
+	hnd =
+	    reinterpret_cast<struct cros_gralloc_handle *>(native_handle_create(num_fds, num_ints));
+
+	for (size_t i = 0; i < DRV_MAX_FDS; i++)
+		hnd->fds[i] = -1;
+
 	hnd->num_planes = num_planes;
 	for (size_t plane = 0; plane < num_planes; plane++) {
-		hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
+		ret = drv_bo_get_plane_fd(bo, plane);
+		if (ret < 0)
+			goto destroy_hnd;
+
+		hnd->fds[plane] = ret;
 		hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
 		hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
 		hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
 	}
-	hnd->fds[hnd->num_planes] = reserved_region_fd;
+
 	hnd->reserved_region_size = descriptor->reserved_region_size;
+	if (hnd->reserved_region_size > 0) {
+		ret = create_reserved_region(descriptor->name, hnd->reserved_region_size);
+		if (ret < 0)
+			goto destroy_hnd;
+
+		hnd->fds[hnd->num_planes] = ret;
+	}
+
 	static std::atomic<uint32_t> next_buffer_id{ 1 };
 	hnd->id = next_buffer_id++;
 	hnd->width = drv_bo_get_width(bo);
@@ -253,18 +262,21 @@
 	hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
 	hnd->name_offset = handle_data_size;
 
-	name = (char *)(&hnd->base.data[hnd->name_offset]);
+	name = (char *)(&hnd->data[hnd->name_offset]);
 	snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
 
-	id = hnd->id;
-	auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
-					      hnd->reserved_region_size);
+	emplace_buffer(bo, hnd);
 
-	std::lock_guard<std::mutex> lock(mutex_);
-	buffers_.emplace(id, buffer);
-	handles_.emplace(hnd, std::make_pair(buffer, 1));
 	*out_handle = reinterpret_cast<buffer_handle_t>(hnd);
 	return 0;
+
+destroy_hnd:
+	native_handle_close(hnd);
+	native_handle_delete(hnd);
+
+destroy_bo:
+	drv_bo_destroy(bo);
+	return ret;
 }
 
 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
index d444ecd..37692ac 100644
--- a/cros_gralloc/cros_gralloc_driver.h
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -50,6 +50,7 @@
 	cros_gralloc_driver(cros_gralloc_driver const &);
 	cros_gralloc_driver operator=(cros_gralloc_driver const &);
 	cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd);
+	void emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd);
 
 	struct driver *drv_;
 	std::mutex mutex_;
diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h
index b5525d1..2b70d4b 100644
--- a/cros_gralloc/cros_gralloc_handle.h
+++ b/cros_gralloc/cros_gralloc_handle.h
@@ -13,8 +13,7 @@
 #define DRV_MAX_PLANES 4
 #define DRV_MAX_FDS (DRV_MAX_PLANES + 1)
 
-struct cros_gralloc_handle {
-	native_handle_t base;
+struct cros_gralloc_handle : public native_handle_t {
 	/*
 	 * File descriptors must immediately follow the native_handle_t base and used file
 	 * descriptors must be packed at the beginning of this array to work with
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
index 31b6cab..c328f4f 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
@@ -457,7 +457,7 @@
     if (metadataType == android::gralloc4::MetadataType_BufferId) {
         status = android::gralloc4::encodeBufferId(crosHandle->id, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Name) {
-        const char* name = (const char*)(&crosHandle->base.data[crosHandle->name_offset]);
+        const char* name = (const char*)(&crosHandle->data[crosHandle->name_offset]);
         status = android::gralloc4::encodeName(name, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Width) {
         status = android::gralloc4::encodeWidth(crosHandle->width, &encodedMetadata);
diff --git a/drv.c b/drv.c
index cb51887..5489ee6 100644
--- a/drv.c
+++ b/drv.c
@@ -611,6 +611,9 @@
 	if (ret)
 		ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC, &fd);
 
+	if (ret)
+		drv_log("Failed to get plane fd: %s\n", strerror(errno));
+
 	return (ret) ? ret : fd;
 }