From patchwork Tue Aug 29 06:25:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Bur X-Patchwork-Id: 806972 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xhJwq5ws0z9ryr for ; Tue, 29 Aug 2017 16:42:51 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3xhJwq4HXQzDqZB for ; Tue, 29 Aug 2017 16:42:51 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3xhJY65Y3yzDqb5 for ; Tue, 29 Aug 2017 16:25:46 +1000 (AEST) Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v7T6OWCG120155 for ; Tue, 29 Aug 2017 02:25:41 -0400 Received: from e23smtp04.au.ibm.com (e23smtp04.au.ibm.com [202.81.31.146]) by mx0a-001b2d01.pphosted.com with ESMTP id 2cn1kje0kp-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 29 Aug 2017 02:25:40 -0400 Received: from localhost by e23smtp04.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 29 Aug 2017 16:25:38 +1000 Received: from d23relay07.au.ibm.com (202.81.31.226) by e23smtp04.au.ibm.com (202.81.31.210) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 29 Aug 2017 16:25:37 +1000 Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay07.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v7T6Pabe37355602 for ; Tue, 29 Aug 2017 16:25:36 +1000 Received: from d23av04.au.ibm.com (localhost [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v7T6PbgY017789 for ; Tue, 29 Aug 2017 16:25:37 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v7T6PaBg017744; Tue, 29 Aug 2017 16:25:36 +1000 Received: from camb691.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) (using TLSv1.2 with cipher DHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.au.ibm.com (Postfix) with ESMTPSA id 9C76DA0259; Tue, 29 Aug 2017 16:25:35 +1000 (AEST) From: Cyril Bur To: skiboot@lists.ozlabs.org, stewart@linux.vnet.ibm.com Date: Tue, 29 Aug 2017 16:25:04 +1000 X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170829062506.8317-1-cyril.bur@au1.ibm.com> References: <20170829062506.8317-1-cyril.bur@au1.ibm.com> X-TM-AS-MML: disable x-cbid: 17082906-0012-0000-0000-0000025A9F5B X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17082906-0013-0000-0000-0000077669DE Message-Id: <20170829062506.8317-12-cyril.bur@au1.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-08-29_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1708290096 Subject: [Skiboot] [RFC PATCH 11/13] libflash/libffs: Refcount ffs entries X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Currently consumers can add an new ffs entry to multiple headers, this is fine but freeing any of the headers will cause the entry to be freed, this causes double free problems. Even if only one header is uses, the consumer of the library still has a reference to the entry, which they may well reuse at some other point. libffs will now refcount entries and only free when there are no more references. This patch also removes the pointless return value of ffs_hdr_free() Signed-off-by: Cyril Bur --- external/ffspart/ffspart.c | 2 +- external/pflash/pflash.c | 2 ++ libflash/ffs.h | 2 ++ libflash/libffs.c | 38 +++++++++++++++++++++++++++++++------- libflash/libffs.h | 4 +++- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/external/ffspart/ffspart.c b/external/ffspart/ffspart.c index 74e12ff6..cd944651 100644 --- a/external/ffspart/ffspart.c +++ b/external/ffspart/ffspart.c @@ -338,7 +338,7 @@ out_if: continue; out_while: - free(new_entry); + ffs_entry_put(new_entry); goto out_close_bl; } diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c index 3be43ac0..f7610710 100644 --- a/external/pflash/pflash.c +++ b/external/pflash/pflash.c @@ -116,6 +116,7 @@ static uint32_t print_ffs_info(struct ffs_handle *ffsh, uint32_t toc) } user = ffs_entry_user_get(ent); + ffs_entry_put(ent); flags = ffs_entry_user_to_string(&user); if (!flags) goto out; @@ -567,6 +568,7 @@ static void print_partition_detail(struct ffs_handle *ffsh, uint32_t part_id) has_flag(ent, FFS_MISCFLAGS_BACKUP) ? "BACKUP [B]\n" : "", has_flag(ent, FFS_MISCFLAGS_REPROVISION) ? "REPROVISION [F]\n" : ""); + ffs_entry_put(ent); if (l < 0) { fprintf(stderr, "Memory allocation failure printing flags!\n"); goto out; diff --git a/libflash/ffs.h b/libflash/ffs.h index 7a362215..6a5ad49f 100644 --- a/libflash/ffs.h +++ b/libflash/ffs.h @@ -149,6 +149,7 @@ struct __ffs_entry { * @type: Describe type of partition * @flags: Partition attributes (optional) * @user: User data (optional) + * @ref: Refcount */ struct ffs_entry { char name[FFS_PART_NAME_MAX + 1]; @@ -159,6 +160,7 @@ struct ffs_entry { enum ffs_type type; uint32_t flags; struct ffs_entry_user user; + unsigned int ref; }; diff --git a/libflash/libffs.c b/libflash/libffs.c index 8c46ce7e..a9a2b961 100644 --- a/libflash/libffs.c +++ b/libflash/libffs.c @@ -268,13 +268,35 @@ bool has_flag(struct ffs_entry *ent, uint16_t flag) return ((ent->user.miscflags & flag) != 0); } -struct ffs_entry *ffs_entry_get(struct ffs_handle *ffs, uint32_t index) +static struct ffs_entry *__ffs_entry_get(struct ffs_handle *ffs, uint32_t index) { - if (!ffs || index >= ffs->hdr.count) + if (index >= ffs->hdr.count) return NULL; return ffs->hdr.entries[index]; } +struct ffs_entry *ffs_entry_get(struct ffs_handle *ffs, uint32_t index) +{ + struct ffs_entry *ret = __ffs_entry_get(ffs, index); + if (ret) + ret->ref++; + return ret; +} + +struct ffs_entry *ffs_entry_put(struct ffs_entry *ent) +{ + if (!ent) + return NULL; + + ent->ref--; + if (ent->ref == 0) { + free(ent); + ent = NULL; + } + + return ent; +} + bool has_ecc(struct ffs_entry *ent) { return ((ent->user.datainteg & FFS_ENRY_INTEG_ECC) != 0); @@ -390,6 +412,7 @@ int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl, } f->hdr.entries[f->hdr.count++] = ent; + ent->ref = 1; rc = ffs_entry_to_cpu(&f->hdr, ent, &f->cache->entries[i]); if (rc) { FL_DBG("FFS: Failed checksum for partition %s\n", @@ -424,15 +447,14 @@ static void __hdr_free(struct ffs_hdr *hdr) return; for (i = 0; i < hdr->count; i++) - free(hdr->entries[i]); + ffs_entry_put(hdr->entries[i]); free(hdr->entries); } -int ffs_hdr_free(struct ffs_hdr *hdr) +void ffs_hdr_free(struct ffs_hdr *hdr) { __hdr_free(hdr); free(hdr); - return 0; } void ffs_close(struct ffs_handle *ffs) @@ -471,7 +493,7 @@ int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx, struct ffs_entry *ent; char *n; - ent = ffs_entry_get(ffs, part_idx); + ent = __ffs_entry_get(ffs, part_idx); if (!ent) return FFS_ERR_PART_NOT_FOUND; @@ -597,6 +619,7 @@ int ffs_entry_add(struct ffs_hdr *hdr, struct ffs_entry *entry) } hdr->entries_size += HDR_ENTRIES_NUM; } + entry->ref++; hdr->entries[hdr->count++] = entry; return 0; @@ -714,6 +737,7 @@ int ffs_entry_new(const char *name, uint32_t base, uint32_t size, struct ffs_ent ret->actual = size; ret->pid = FFS_PID_TOPLEVEL; ret->type = FFS_TYPE_DATA; + ret->ref = 1; *r = ret; return 0; @@ -776,7 +800,7 @@ int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx, uint32_t offset; int rc; - ent = ffs_entry_get(ffs, part_idx); + ent = __ffs_entry_get(ffs, part_idx); if (!ent) { FL_DBG("FFS: Entry not found\n"); return FFS_ERR_PART_NOT_FOUND; diff --git a/libflash/libffs.h b/libflash/libffs.h index 56428a2c..eabca23a 100644 --- a/libflash/libffs.h +++ b/libflash/libffs.h @@ -145,6 +145,8 @@ int ffs_hdr_add_side(struct ffs_hdr *hdr); int ffs_entry_new(const char *name, uint32_t base, uint32_t size, struct ffs_entry **r); +struct ffs_entry *ffs_entry_put(struct ffs_entry *ent); + int ffs_entry_user_set(struct ffs_entry *ent, struct ffs_entry_user *user); int ffs_entry_set_act_size(struct ffs_entry *ent, uint32_t actual_size); @@ -156,5 +158,5 @@ int ffs_entry_add(struct ffs_hdr *hdr, struct ffs_entry *entry); int ffs_hdr_finalise(struct blocklevel_device *bl, struct ffs_hdr *hdr); -int ffs_hdr_free(struct ffs_hdr *hdr); +void ffs_hdr_free(struct ffs_hdr *hdr); #endif /* __LIBFFS_H */