From patchwork Wed Dec 13 03:18:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490285 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="dh35lbe9" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D68F8E for ; Tue, 12 Dec 2023 19:18:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=fx95EkwWz1mt4+AaZxFljby7hee95+tcGnGk7TC6CmE=; b=dh35lbe9Btl0zk/y86LVD1CZPd Vi8be388xwcj1YiNcROgcYguDXOiS6J3UKbvDB67aLywzJRLqTGmumY4sb24rW0C7e4on9EDAKBVy Gl+H9VQyC0qAlRdJMNW+r1BxdT2YQ4XKL+aX1KVtli4dF+qLqROKGs239fFOCMUQk5FFp6v/EGA5J +Z4rrAavQjdAHcIU7YJDCAiwiXicwFg8cdXXnlOJjxA4EFKhS4f7cdRrR8mCdlDpSoKDY5RnRFECA g/VCciOiExL1IbubSHAKB3knC4q4FzSO7gR9+89scRFIXmTAGMFEPMHPLNVgNIRjsfIZvwKk6NsF3 tX3VKJCw==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlT-00Bbxi-2f; Wed, 13 Dec 2023 03:18:27 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 01/12] fs/ufs: Use the offset_in_page() helper Date: Wed, 13 Dec 2023 03:18:16 +0000 Message-Id: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031639.GJ1674809@ZenIV> References: <20231213031639.GJ1674809@ZenIV> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro From: "Fabio M. De Francesco" Use the offset_in_page() helper because it is more suitable than doing explicit subtractions between pointers to directory entries and kernel virtual addresses of mapped pages. Cc: Ira Weiny Reviewed-by: Ira Weiny Suggested-by: Al Viro Signed-off-by: Fabio M. De Francesco Signed-off-by: Al Viro --- fs/ufs/dir.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 27c85d92d1dc..5be536fe0e3f 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -92,8 +92,7 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, struct page *page, struct inode *inode, bool update_times) { - loff_t pos = page_offset(page) + - (char *) de - (char *) page_address(page); + loff_t pos = page_offset(page) + offset_in_page(de); unsigned len = fs16_to_cpu(dir->i_sb, de->d_reclen); int err; @@ -377,8 +376,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) return -EINVAL; got_it: - pos = page_offset(page) + - (char*)de - (char*)page_address(page); + pos = page_offset(page) + offset_in_page(de); err = ufs_prepare_chunk(page, pos, rec_len); if (err) goto out_unlock; @@ -504,8 +502,8 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, { struct super_block *sb = inode->i_sb; char *kaddr = page_address(page); - unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); - unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); + unsigned int from = offset_in_page(dir) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); + unsigned int to = offset_in_page(dir) + fs16_to_cpu(sb, dir->d_reclen); loff_t pos; struct ufs_dir_entry *pde = NULL; struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); @@ -529,7 +527,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, de = ufs_next_entry(sb, de); } if (pde) - from = (char*)pde - (char*)page_address(page); + from = offset_in_page(pde); pos = page_offset(page) + from; lock_page(page); From patchwork Wed Dec 13 03:18:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490286 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="qUKiygdJ" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 811E8B0 for ; Tue, 12 Dec 2023 19:18:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=eVtucG2qVnjYKV8XnpVoXwzjFXyQmYt7Mrq5+ppPcTI=; b=qUKiygdJf2O4XhwY0lFhjHIMoK F9Qcg/QBNthaekqiISuFXl6qYFbUVFS2S/OwKutQNXK7q0C8l2SciBynvFeBfahaAKTcfAKCg2VTl G0aTftigAyyYt0/TgQvkJJJ6LtHzRHyRDA2FVPzxP2bh19XyPK+gYyFN8LiHXJ930zoqOQ7UvwB2z 248r71wvXgXQeI7lxAC+Pjbnx9Z0Z66YOJnKPXJYgfjwPtU3LbvgIrhP+cNLMSqDWZnvofPxbttht C2TR2BzaWhgirUxAPRBo2mKDGCdc6MKk5l/7QMHZshSxVKJTpvCdAKgHuYKAuLQaDqHkKAfR6mtZz lsqJ2w5A==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlU-00Bbxk-0H; Wed, 13 Dec 2023 03:18:28 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 02/12] fs/ufs: Change the signature of ufs_get_page() Date: Wed, 13 Dec 2023 03:18:17 +0000 Message-Id: <20231213031827.2767531-2-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro From: "Fabio M. De Francesco" Change the signature of ufs_get_page() in order to prepare this function to the conversion to the use of kmap_local_page(). Change also those call sites which are required to conform its invocations to the new signature. Cc: Ira Weiny Suggested-by: Al Viro Reviewed-by: Ira Weiny Signed-off-by: Fabio M. De Francesco Signed-off-by: Al Viro --- fs/ufs/dir.c | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 5be536fe0e3f..b695eab0105a 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -191,7 +191,7 @@ static bool ufs_check_page(struct page *page) return false; } -static struct page *ufs_get_page(struct inode *dir, unsigned long n) +static void *ufs_get_page(struct inode *dir, unsigned long n, struct page **p) { struct address_space *mapping = dir->i_mapping; struct page *page = read_mapping_page(mapping, n, NULL); @@ -201,8 +201,10 @@ static struct page *ufs_get_page(struct inode *dir, unsigned long n) if (!ufs_check_page(page)) goto fail; } + *p = page; + return page_address(page); } - return page; + return ERR_CAST(page); fail: ufs_put_page(page); @@ -233,15 +235,12 @@ ufs_next_entry(struct super_block *sb, struct ufs_dir_entry *p) struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct page **p) { - struct page *page = ufs_get_page(dir, 0); - struct ufs_dir_entry *de = NULL; + struct ufs_dir_entry *de = ufs_get_page(dir, 0, p); - if (!IS_ERR(page)) { - de = ufs_next_entry(dir->i_sb, - (struct ufs_dir_entry *)page_address(page)); - *p = page; - } - return de; + if (!IS_ERR(de)) + return ufs_next_entry(dir->i_sb, de); + else + return NULL; } /* @@ -279,11 +278,10 @@ struct ufs_dir_entry *ufs_find_entry(struct inode *dir, const struct qstr *qstr, start = 0; n = start; do { - char *kaddr; - page = ufs_get_page(dir, n); - if (!IS_ERR(page)) { - kaddr = page_address(page); - de = (struct ufs_dir_entry *) kaddr; + char *kaddr = ufs_get_page(dir, n, &page); + + if (!IS_ERR(kaddr)) { + de = (struct ufs_dir_entry *)kaddr; kaddr += ufs_last_byte(dir, n) - reclen; while ((char *) de <= kaddr) { if (ufs_match(sb, namelen, name, de)) @@ -334,12 +332,10 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) for (n = 0; n <= npages; n++) { char *dir_end; - page = ufs_get_page(dir, n); - err = PTR_ERR(page); - if (IS_ERR(page)) - goto out; + kaddr = ufs_get_page(dir, n, &page); + if (IS_ERR(kaddr)) + return PTR_ERR(kaddr); lock_page(page); - kaddr = page_address(page); dir_end = kaddr + ufs_last_byte(dir, n); de = (struct ufs_dir_entry *)kaddr; kaddr += PAGE_SIZE - reclen; @@ -402,7 +398,6 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) /* OFFSET_CACHE */ out_put: ufs_put_page(page); -out: return err; out_unlock: unlock_page(page); @@ -445,17 +440,16 @@ ufs_readdir(struct file *file, struct dir_context *ctx) for ( ; n < npages; n++, offset = 0) { char *kaddr, *limit; struct ufs_dir_entry *de; + struct page *page; - struct page *page = ufs_get_page(inode, n); - - if (IS_ERR(page)) { + kaddr = ufs_get_page(inode, n, &page); + if (IS_ERR(kaddr)) { ufs_error(sb, __func__, "bad page in #%lu", inode->i_ino); ctx->pos += PAGE_SIZE - offset; return -EIO; } - kaddr = page_address(page); if (unlikely(need_revalidate)) { if (offset) { offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); @@ -604,12 +598,11 @@ int ufs_empty_dir(struct inode * inode) for (i = 0; i < npages; i++) { char *kaddr; struct ufs_dir_entry *de; - page = ufs_get_page(inode, i); - if (IS_ERR(page)) + kaddr = ufs_get_page(inode, i, &page); + if (IS_ERR(kaddr)) continue; - kaddr = page_address(page); de = (struct ufs_dir_entry *)kaddr; kaddr += ufs_last_byte(inode, i) - UFS_DIR_REC_LEN(1); From patchwork Wed Dec 13 03:18:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490287 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="rAxqk4d4" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B203AB2 for ; Tue, 12 Dec 2023 19:18:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=OQP9VIwa9XhJVR5DwN/a2Z+WS205zCtcf/mrHiOcKMQ=; b=rAxqk4d4TPNFRnJFgd4uk+ypXD z+McQdavbfTxkKQcPyxvQ/RtjX9gvExaOpjlPsb09X1H1wvBWPJAX72SqHsm2qbHnwIqxl1U7K8nw cYgxpOhiiElacqk6V/04P+6a3f8FKvtX+6A4KrvPIfuVwhKhREWXeDvBdSPHRVZaoWRY4F9qRCS/z xfoAvxajlbz4+0vUdpWpwEhCm74OnC7tGTLM1LYZZQVloDeqf3j2EdkbmtDX0fQgqFKZlqYzIisf/ fjfj+mqLsHJh6NiWAH2h4iIwtNfWeyc/uPRn7a1b0HB+7m/Xgl3s5shwhZrpL9XYkWIZyPwihdIv7 E0Z9jVRQ==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlU-00Bbxo-0o; Wed, 13 Dec 2023 03:18:28 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 03/12] fs/ufs: Use ufs_put_page() in ufs_rename() Date: Wed, 13 Dec 2023 03:18:18 +0000 Message-Id: <20231213031827.2767531-3-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro From: "Fabio M. De Francesco" Use the ufs_put_page() helper in ufs_rename() instead of open-coding three kunmap() + put_page(). Cc: Al Viro Reviewed-by: Ira Weiny Suggested-by: Ira Weiny Signed-off-by: Fabio M. De Francesco Signed-off-by: Al Viro --- fs/ufs/dir.c | 2 +- fs/ufs/namei.c | 9 +++------ fs/ufs/ufs.h | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index b695eab0105a..2c9061ad3ab3 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -66,7 +66,7 @@ static int ufs_handle_dirsync(struct inode *dir) return err; } -static inline void ufs_put_page(struct page *page) +inline void ufs_put_page(struct page *page) { kunmap(page); put_page(page); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 9cad29463791..50dbe13d24d6 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -307,8 +307,7 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, if (old_dir != new_dir) ufs_set_link(old_inode, dir_de, dir_page, new_dir, 0); else { - kunmap(dir_page); - put_page(dir_page); + ufs_put_page(dir_page); } inode_dec_link_count(old_dir); } @@ -317,12 +316,10 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, out_dir: if (dir_de) { - kunmap(dir_page); - put_page(dir_page); + ufs_put_page(dir_page); } out_old: - kunmap(old_page); - put_page(old_page); + ufs_put_page(old_page); out: return err; } diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 6b499180643b..4594cbe6b2e0 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -98,6 +98,7 @@ extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, uns extern void ufs_put_cylinder (struct super_block *, unsigned); /* dir.c */ +extern void ufs_put_page(struct page *page); extern const struct inode_operations ufs_dir_inode_operations; extern int ufs_add_link (struct dentry *, struct inode *); extern ino_t ufs_inode_by_name(struct inode *, const struct qstr *); From patchwork Wed Dec 13 03:18:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490295 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="OnmCZyrD" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5178B7 for ; Tue, 12 Dec 2023 19:18:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description; bh=HHK9iip+14M2GQ6l0cD6JdJ+QVtnx8uqkwMXlEigi+Y=; b=OnmCZyrDsx3ytauLM8Ot2U83XA Kw9EiqswB39WK/qpLAA1ECWHCWAkhqyA6PZxpNaoNAEv3Nr/t2uP+n6zteRJYDONaZ44v/P6dhy7T +vpV5wLtqss3zgyxDJpOs4WePONz/HVnaDq5me5vmzpZiFXVIQb0v6q/04b9lZ0uWOSzSQ7Jfinvv lGMW4AUHxj2mctCjRQnBR9jA+X+rUvSy4blOM3U+N0ujVBqCV3kIWd/fCx94bL55ahzVoW8Hy6vrE 22/CH1pVCAkXLi63X7IdWiStqFpB39DnGaxuTxfmA1n4oEF3Ken4dJYhl2p2/Z0Vjb6FZiuEXjAT4 AWB8gKHw==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlU-00Bbxs-1U; Wed, 13 Dec 2023 03:18:28 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 04/12] fs/ufs: Replace kmap() with kmap_local_page() Date: Wed, 13 Dec 2023 03:18:19 +0000 Message-Id: <20231213031827.2767531-4-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro From: "Fabio M. De Francesco" kmap() is being deprecated in favor of kmap_local_page(). There are two main problems with kmap(): (1) It comes with an overhead as the mapping space is restricted and protected by a global lock for synchronization and (2) it also requires global TLB invalidation when the kmap’s pool wraps and it might block when the mapping space is fully utilized until a slot becomes available. With kmap_local_page() the mappings are per thread, CPU local, can take page faults, and can be called from any context (including interrupts). It is faster than kmap() in kernels with HIGHMEM enabled. Furthermore, the tasks can be preempted and, when they are scheduled to run again, the kernel virtual addresses are restored and still valid. The use of kmap_local_page() in fs/ufs is "safe" because (1) the kernel virtual addresses are exclusively re-used by the thread which established the mappings (i.e., thread locality is never violated) and (2) the nestings of mappings and un-mappings are always stack based (LIFO). Therefore, replace kmap() with kmap_local_page() in fs/ufs. kunmap_local() requires the mapping address, so return that address from ufs_get_page() and use it as parameter for the second argument of ufs_put_page(). [AV: replaced ufs_put_page() with unmap_and_put() - there's nothing ufs-specific about it] Reviewed-by: Ira Weiny Suggested-by: Al Viro Suggested-by: Ira Weiny Signed-off-by: Fabio M. De Francesco Signed-off-by: Al Viro --- fs/ufs/dir.c | 74 +++++++++++++++++++++++++++++++------------------- fs/ufs/namei.c | 11 ++++---- fs/ufs/ufs.h | 1 - 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 2c9061ad3ab3..fcf13e3ca869 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -66,12 +66,6 @@ static int ufs_handle_dirsync(struct inode *dir) return err; } -inline void ufs_put_page(struct page *page) -{ - kunmap(page); - put_page(page); -} - ino_t ufs_inode_by_name(struct inode *dir, const struct qstr *qstr) { ino_t res = 0; @@ -81,7 +75,7 @@ ino_t ufs_inode_by_name(struct inode *dir, const struct qstr *qstr) de = ufs_find_entry(dir, qstr, &page); if (de) { res = fs32_to_cpu(dir->i_sb, de->d_ino); - ufs_put_page(page); + unmap_and_put_page(page, de); } return res; } @@ -104,7 +98,7 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, ufs_set_de_type(dir->i_sb, de, inode->i_mode); ufs_commit_chunk(page, pos, len); - ufs_put_page(page); + unmap_and_put_page(page, de); if (update_times) inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); mark_inode_dirty(dir); @@ -112,11 +106,10 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, } -static bool ufs_check_page(struct page *page) +static bool ufs_check_page(struct page *page, char *kaddr) { struct inode *dir = page->mapping->host; struct super_block *sb = dir->i_sb; - char *kaddr = page_address(page); unsigned offs, rec_len; unsigned limit = PAGE_SIZE; const unsigned chunk_mask = UFS_SB(sb)->s_uspi->s_dirblksize - 1; @@ -191,23 +184,32 @@ static bool ufs_check_page(struct page *page) return false; } +/* + * Calls to ufs_get_page()/unmap_and_put_page() must be nested according to the + * rules documented in kmap_local_page()/kunmap_local(). + * + * NOTE: ufs_find_entry() and ufs_dotdot() act as calls to ufs_get_page() + * and must be treated accordingly for nesting purposes. + */ static void *ufs_get_page(struct inode *dir, unsigned long n, struct page **p) { + char *kaddr; + struct address_space *mapping = dir->i_mapping; struct page *page = read_mapping_page(mapping, n, NULL); if (!IS_ERR(page)) { - kmap(page); + kaddr = kmap_local_page(page); if (unlikely(!PageChecked(page))) { - if (!ufs_check_page(page)) + if (!ufs_check_page(page, kaddr)) goto fail; } *p = page; - return page_address(page); + return kaddr; } return ERR_CAST(page); fail: - ufs_put_page(page); + unmap_and_put_page(page, kaddr); return ERR_PTR(-EIO); } @@ -233,6 +235,13 @@ ufs_next_entry(struct super_block *sb, struct ufs_dir_entry *p) fs16_to_cpu(sb, p->d_reclen)); } +/* + * Calls to ufs_get_page()/unmap_and_put_page() must be nested according to the + * rules documented in kmap_local_page()/kunmap_local(). + * + * ufs_dotdot() acts as a call to ufs_get_page() and must be treated + * accordingly for nesting purposes. + */ struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct page **p) { struct ufs_dir_entry *de = ufs_get_page(dir, 0, p); @@ -250,6 +259,11 @@ struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct page **p) * returns the page in which the entry was found, and the entry itself * (as a parameter - res_dir). Page is returned mapped and unlocked. * Entry is guaranteed to be valid. + * + * On Success unmap_and_put_page() should be called on *res_page. + * + * ufs_find_entry() acts as a call to ufs_get_page() and must be treated + * accordingly for nesting purposes. */ struct ufs_dir_entry *ufs_find_entry(struct inode *dir, const struct qstr *qstr, struct page **res_page) @@ -288,7 +302,7 @@ struct ufs_dir_entry *ufs_find_entry(struct inode *dir, const struct qstr *qstr, goto found; de = ufs_next_entry(sb, de); } - ufs_put_page(page); + unmap_and_put_page(page, kaddr); } if (++n >= npages) n = 0; @@ -366,7 +380,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) de = (struct ufs_dir_entry *) ((char *) de + rec_len); } unlock_page(page); - ufs_put_page(page); + unmap_and_put_page(page, kaddr); } BUG(); return -EINVAL; @@ -397,7 +411,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) err = ufs_handle_dirsync(dir); /* OFFSET_CACHE */ out_put: - ufs_put_page(page); + unmap_and_put_page(page, kaddr); return err; out_unlock: unlock_page(page); @@ -475,13 +489,13 @@ ufs_readdir(struct file *file, struct dir_context *ctx) ufs_get_de_namlen(sb, de), fs32_to_cpu(sb, de->d_ino), d_type)) { - ufs_put_page(page); + unmap_and_put_page(page, kaddr); return 0; } } ctx->pos += fs16_to_cpu(sb, de->d_reclen); } - ufs_put_page(page); + unmap_and_put_page(page, kaddr); } return 0; } @@ -492,10 +506,15 @@ ufs_readdir(struct file *file, struct dir_context *ctx) * previous entry. */ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, - struct page * page) + struct page *page) { struct super_block *sb = inode->i_sb; - char *kaddr = page_address(page); + /* + * The "dir" dentry points somewhere in the same page whose we need the + * address of; therefore, we can simply get the base address "kaddr" by + * masking the previous with PAGE_MASK. + */ + char *kaddr = (char *)((unsigned long)dir & PAGE_MASK); unsigned int from = offset_in_page(dir) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); unsigned int to = offset_in_page(dir) + fs16_to_cpu(sb, dir->d_reclen); loff_t pos; @@ -535,7 +554,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, mark_inode_dirty(inode); err = ufs_handle_dirsync(inode); out: - ufs_put_page(page); + unmap_and_put_page(page, kaddr); UFSD("EXIT\n"); return err; } @@ -559,8 +578,7 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) goto fail; } - kmap(page); - base = (char*)page_address(page); + base = kmap_local_page(page); memset(base, 0, PAGE_SIZE); de = (struct ufs_dir_entry *) base; @@ -577,7 +595,7 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1)); ufs_set_de_namlen(sb, de, 2); strcpy (de->d_name, ".."); - kunmap(page); + kunmap_local(base); ufs_commit_chunk(page, 0, chunk_size); err = ufs_handle_dirsync(inode); @@ -594,9 +612,9 @@ int ufs_empty_dir(struct inode * inode) struct super_block *sb = inode->i_sb; struct page *page = NULL; unsigned long i, npages = dir_pages(inode); + char *kaddr; for (i = 0; i < npages; i++) { - char *kaddr; struct ufs_dir_entry *de; kaddr = ufs_get_page(inode, i, &page); @@ -629,12 +647,12 @@ int ufs_empty_dir(struct inode * inode) } de = ufs_next_entry(sb, de); } - ufs_put_page(page); + unmap_and_put_page(page, kaddr); } return 1; not_empty: - ufs_put_page(page); + unmap_and_put_page(page, kaddr); return 0; } diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 50dbe13d24d6..25fa97340f73 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -250,7 +250,7 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, struct inode *old_inode = d_inode(old_dentry); struct inode *new_inode = d_inode(new_dentry); struct page *dir_page = NULL; - struct ufs_dir_entry * dir_de = NULL; + struct ufs_dir_entry *dir_de = NULL; struct page *old_page; struct ufs_dir_entry *old_de; int err = -ENOENT; @@ -307,7 +307,7 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, if (old_dir != new_dir) ufs_set_link(old_inode, dir_de, dir_page, new_dir, 0); else { - ufs_put_page(dir_page); + unmap_and_put_page(dir_page, dir_de); } inode_dec_link_count(old_dir); } @@ -315,11 +315,10 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, out_dir: - if (dir_de) { - ufs_put_page(dir_page); - } + if (dir_de) + unmap_and_put_page(dir_page, dir_de); out_old: - ufs_put_page(old_page); + unmap_and_put_page(old_page, old_de); out: return err; } diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 4594cbe6b2e0..6b499180643b 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -98,7 +98,6 @@ extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, uns extern void ufs_put_cylinder (struct super_block *, unsigned); /* dir.c */ -extern void ufs_put_page(struct page *page); extern const struct inode_operations ufs_dir_inode_operations; extern int ufs_add_link (struct dentry *, struct inode *); extern ino_t ufs_inode_by_name(struct inode *, const struct qstr *); From patchwork Wed Dec 13 03:18:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490293 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="NmEGHwTF" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0E4D4BD for ; Tue, 12 Dec 2023 19:18:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=VjPK/De1gE8RmPpJweMC8W9BLYkPksaDrCLgp/sOxQA=; b=NmEGHwTFaUvziagbRrHCWdBKZw SHKHduCo4sIk7mHZY4D1qw6yYFck3A2IKx7kJhHyUgmBSkt29ZpweYifR4Z9U5cSF3I3dTTkJ8yIu UxrEzELwX6WzwX07z+j6Zetu6zfNvP6vKIRxSEiTwbpo8K/5A2ZKPoHNBV5F907TgDOFCs07Z2aaf 3qDcAuzhmuFsE6BvtX1ywBkSNNzLKHLDjkDnvoPVnfoTDYjmP7Dd+emVqY24CtgEvhkPdFMybG1nX PJUrkmKR27403+m77nzopXgcpzi9Jb285xPkmRH1ZLFmWRqXhyYXLcQKNMvKyjjK28gz/Kl5aeSRG DtOAUPjg==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlU-00Bbxx-1z; Wed, 13 Dec 2023 03:18:28 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 05/12] ufs: fix handling of delete_entry and set_link failures Date: Wed, 13 Dec 2023 03:18:20 +0000 Message-Id: <20231213031827.2767531-5-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro similar to minixfs series - make ufs_set_link() report failures, lift dir_put_page() into the callers of ufs_set_link() and ufs_delete_entry(), make ufs_rename() handle failures in both. Signed-off-by: Al Viro --- fs/ufs/dir.c | 27 ++++++++++++--------------- fs/ufs/namei.c | 40 +++++++++++++++++----------------------- fs/ufs/ufs.h | 2 +- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index fcf13e3ca869..5edacece384b 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -81,8 +81,7 @@ ino_t ufs_inode_by_name(struct inode *dir, const struct qstr *qstr) } -/* Releases the page */ -void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, +int ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, struct page *page, struct inode *inode, bool update_times) { @@ -92,17 +91,19 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, lock_page(page); err = ufs_prepare_chunk(page, pos, len); - BUG_ON(err); + if (unlikely(err)) { + unlock_page(page); + return err; + } de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); ufs_set_de_type(dir->i_sb, de, inode->i_mode); ufs_commit_chunk(page, pos, len); - unmap_and_put_page(page, de); if (update_times) inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); mark_inode_dirty(dir); - ufs_handle_dirsync(dir); + return ufs_handle_dirsync(dir); } @@ -522,8 +523,6 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); int err; - UFSD("ENTER\n"); - UFSD("ino %u, reclen %u, namlen %u, name %s\n", fs32_to_cpu(sb, de->d_ino), fs16_to_cpu(sb, de->d_reclen), @@ -533,8 +532,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, if (de->d_reclen == 0) { ufs_error(inode->i_sb, __func__, "zero-length directory entry"); - err = -EIO; - goto out; + return -EIO; } pde = de; de = ufs_next_entry(sb, de); @@ -545,18 +543,17 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, pos = page_offset(page) + from; lock_page(page); err = ufs_prepare_chunk(page, pos, to - from); - BUG_ON(err); + if (unlikely(err)) { + unlock_page(page); + return err; + } if (pde) pde->d_reclen = cpu_to_fs16(sb, to - from); dir->d_ino = 0; ufs_commit_chunk(page, pos, to - from); inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); mark_inode_dirty(inode); - err = ufs_handle_dirsync(inode); -out: - unmap_and_put_page(page, kaddr); - UFSD("EXIT\n"); - return err; + return ufs_handle_dirsync(inode); } int ufs_make_empty(struct inode * inode, struct inode *dir) diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 25fa97340f73..b8082fb53a08 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -210,20 +210,18 @@ static int ufs_unlink(struct inode *dir, struct dentry *dentry) struct inode * inode = d_inode(dentry); struct ufs_dir_entry *de; struct page *page; - int err = -ENOENT; + int err; de = ufs_find_entry(dir, &dentry->d_name, &page); if (!de) - goto out; + return -ENOENT; err = ufs_delete_entry(dir, de, page); - if (err) - goto out; - - inode_set_ctime_to_ts(inode, inode_get_ctime(dir)); - inode_dec_link_count(inode); - err = 0; -out: + if (!err) { + inode_set_ctime_to_ts(inode, inode_get_ctime(dir)); + inode_dec_link_count(inode); + } + unmap_and_put_page(page, de); return err; } @@ -253,14 +251,14 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, struct ufs_dir_entry *dir_de = NULL; struct page *old_page; struct ufs_dir_entry *old_de; - int err = -ENOENT; + int err; if (flags & ~RENAME_NOREPLACE) return -EINVAL; old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page); if (!old_de) - goto out; + return -ENOENT; if (S_ISDIR(old_inode->i_mode)) { err = -EIO; @@ -281,7 +279,10 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_page); if (!new_de) goto out_dir; - ufs_set_link(new_dir, new_de, new_page, old_inode, 1); + err = ufs_set_link(new_dir, new_de, new_page, old_inode, 1); + unmap_and_put_page(new_page, new_de); + if (err) + goto out_dir; inode_set_ctime_current(new_inode); if (dir_de) drop_nlink(new_inode); @@ -299,27 +300,20 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir, * rename. */ inode_set_ctime_current(old_inode); - - ufs_delete_entry(old_dir, old_de, old_page); mark_inode_dirty(old_inode); - if (dir_de) { + err = ufs_delete_entry(old_dir, old_de, old_page); + if (!err && dir_de) { if (old_dir != new_dir) - ufs_set_link(old_inode, dir_de, dir_page, new_dir, 0); - else { - unmap_and_put_page(dir_page, dir_de); - } + err = ufs_set_link(old_inode, dir_de, dir_page, + new_dir, 0); inode_dec_link_count(old_dir); } - return 0; - - out_dir: if (dir_de) unmap_and_put_page(dir_page, dir_de); out_old: unmap_and_put_page(old_page, old_de); -out: return err; } diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 6b499180643b..b521ab01471a 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -106,7 +106,7 @@ extern struct ufs_dir_entry *ufs_find_entry(struct inode *, const struct qstr *, extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *); extern int ufs_empty_dir (struct inode *); extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **); -extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, +extern int ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, struct page *page, struct inode *inode, bool update_times); /* file.c */ From patchwork Wed Dec 13 03:18:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490288 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="ZjCv3OKj" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E207CA for ; Tue, 12 Dec 2023 19:18:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=s8HNLzILHg37bTX0xFxBYp9QuUN74TbeU3F3jc3e1ms=; b=ZjCv3OKjDnmqAMDVKcEUtFKoQx HwyIn5p1t4JCtzNPVm22lAWRmuGMbuM0LK0IsZlPRCSHiSqtf2ElyQec+9wilghGwAZ3Ssb3nyOoy tIPOMyDxXZcFVTA8hKn/zzGqHp3FOnZGqLgoGxqArS0LtdqeLTX3JLVNhDwcapRE/hnG25EdkybZM QhYwsl4pWxeB1pbhoSU59E7VL97XLoNIMQsJz0fMzqCK1RRjDsgfBNXvluQaN9Q9klSfBtKxsM8SN qwqdXt8aAeybVFnoN+xdMyV1LeOqb63Ibk6FSa+GuRzgEsN2k4R1hlD9O1AhN97Xh8nomjM/7SKkg wfaJjaaA==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlU-00Bby1-2W; Wed, 13 Dec 2023 03:18:28 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 06/12] ufs: untangle ubh_...block...() macros, part 1 Date: Wed, 13 Dec 2023 03:18:21 +0000 Message-Id: <20231213031827.2767531-6-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro passing implicit argument to a macro by having it in a variable with special name is Not Nice(tm); just pass it explicitly. kill an unused macro, while we are at it... Signed-off-by: Al Viro --- fs/ufs/balloc.c | 10 +++++----- fs/ufs/util.h | 11 +++-------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 53c11be2b2c1..e412ddcfda03 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -95,7 +95,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) * Trying to reassemble free fragments into block */ blkno = ufs_fragstoblks (bbase); - if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { + if (ubh_isblockset(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb); uspi->cs_total.cs_nffree -= uspi->s_fpb; fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb); @@ -182,10 +182,10 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) for (i = bit; i < end_bit; i += uspi->s_fpb) { blkno = ufs_fragstoblks(i); - if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { + if (ubh_isblockset(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); } - ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); + ubh_setblock(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, 1); @@ -716,7 +716,7 @@ static u64 ufs_alloccg_block(struct inode *inode, /* * If the requested block is available, use it. */ - if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) { + if (ubh_isblockset(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) { result = goal; goto gotit; } @@ -730,7 +730,7 @@ static u64 ufs_alloccg_block(struct inode *inode, if (!try_add_frags(inode, uspi->s_fpb)) return 0; blkno = ufs_fragstoblks(result); - ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); + ubh_clrblock(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, -1); diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 0ecd2ed792f5..dc3240f0ddea 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -455,10 +455,7 @@ static inline unsigned _ubh_find_last_zero_bit_( return (base << uspi->s_bpfshift) + pos - begin; } -#define ubh_isblockclear(ubh,begin,block) (!_ubh_isblockset_(uspi,ubh,begin,block)) - -#define ubh_isblockset(ubh,begin,block) _ubh_isblockset_(uspi,ubh,begin,block) -static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, +static inline int ubh_isblockset(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned block) { u8 mask; @@ -478,8 +475,7 @@ static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, return 0; } -#define ubh_clrblock(ubh,begin,block) _ubh_clrblock_(uspi,ubh,begin,block) -static inline void _ubh_clrblock_(struct ufs_sb_private_info * uspi, +static inline void ubh_clrblock(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned block) { switch (uspi->s_fpb) { @@ -498,8 +494,7 @@ static inline void _ubh_clrblock_(struct ufs_sb_private_info * uspi, } } -#define ubh_setblock(ubh,begin,block) _ubh_setblock_(uspi,ubh,begin,block) -static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi, +static inline void ubh_setblock(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned block) { switch (uspi->s_fpb) { From patchwork Wed Dec 13 03:18:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490290 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="EE+sb2x4" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50B2ECF for ; Tue, 12 Dec 2023 19:18:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=q1e0sVyAULfkcONrOI7pHUW/iSjJQDx0jAb2enWyUV0=; b=EE+sb2x4kEr0CqfZ1jsDK82wcS 6vFYTg8QX7PJispp5huBHhAC2nQKOIKdsSRMq9ZsP5NSm5v2bORk2wv/OwHQaOQXpBJMtFD6mFm5S GiMCLeEdBz4b2oYboEOSgcfOrtQEigZH85n5EUpLZhMxoho+jum2pEKbIXuNppAgVso+CCjc1pN9k WDjeqtp7yPT8cyPRzZnFgB1OJtKoPMYoIsMmJGchku9DHr+884/MRCaD9UllA9dVA/pW0ANisTMqq 3AxXQQWnaMk4yseKzR2AJlpxWR3+EkkRFDjC4RWK24NP8G3KTwHu7kgo02EQoe42o01bcpTE4dPci 0eHx9TgA==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlU-00Bby5-2x; Wed, 13 Dec 2023 03:18:28 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 07/12] ufs: untangle ubh_...block...(), part 2 Date: Wed, 13 Dec 2023 03:18:22 +0000 Message-Id: <20231213031827.2767531-7-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro pass cylinder group descriptor instead of its buffer head (ubh, always UCPI_UBH(ucpi)) and its ->c_freeoff. Signed-off-by: Al Viro --- fs/ufs/balloc.c | 10 +++++----- fs/ufs/util.h | 16 +++++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index e412ddcfda03..d76c04fbd4fa 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -95,7 +95,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) * Trying to reassemble free fragments into block */ blkno = ufs_fragstoblks (bbase); - if (ubh_isblockset(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { + if (ubh_isblockset(uspi, ucpi, blkno)) { fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb); uspi->cs_total.cs_nffree -= uspi->s_fpb; fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb); @@ -182,10 +182,10 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) for (i = bit; i < end_bit; i += uspi->s_fpb) { blkno = ufs_fragstoblks(i); - if (ubh_isblockset(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { + if (ubh_isblockset(uspi, ucpi, blkno)) { ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); } - ubh_setblock(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); + ubh_setblock(uspi, ucpi, blkno); inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, 1); @@ -716,7 +716,7 @@ static u64 ufs_alloccg_block(struct inode *inode, /* * If the requested block is available, use it. */ - if (ubh_isblockset(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) { + if (ubh_isblockset(uspi, ucpi, ufs_fragstoblks(goal))) { result = goal; goto gotit; } @@ -730,7 +730,7 @@ static u64 ufs_alloccg_block(struct inode *inode, if (!try_add_frags(inode, uspi->s_fpb)) return 0; blkno = ufs_fragstoblks(result); - ubh_clrblock(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); + ubh_clrblock(uspi, ucpi, blkno); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, -1); diff --git a/fs/ufs/util.h b/fs/ufs/util.h index dc3240f0ddea..89c890b5c54d 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -455,9 +455,11 @@ static inline unsigned _ubh_find_last_zero_bit_( return (base << uspi->s_bpfshift) + pos - begin; } -static inline int ubh_isblockset(struct ufs_sb_private_info * uspi, - struct ufs_buffer_head * ubh, unsigned begin, unsigned block) +static inline int ubh_isblockset(struct ufs_sb_private_info *uspi, + struct ufs_cg_private_info *ucpi, unsigned block) { + struct ufs_buffer_head *ubh = UCPI_UBH(ucpi); + unsigned begin = ucpi->c_freeoff; u8 mask; switch (uspi->s_fpb) { case 8: @@ -475,9 +477,11 @@ static inline int ubh_isblockset(struct ufs_sb_private_info * uspi, return 0; } -static inline void ubh_clrblock(struct ufs_sb_private_info * uspi, - struct ufs_buffer_head * ubh, unsigned begin, unsigned block) +static inline void ubh_clrblock(struct ufs_sb_private_info *uspi, + struct ufs_cg_private_info *ucpi, unsigned block) { + struct ufs_buffer_head *ubh = UCPI_UBH(ucpi); + unsigned begin = ucpi->c_freeoff; switch (uspi->s_fpb) { case 8: *ubh_get_addr (ubh, begin + block) = 0x00; @@ -495,8 +499,10 @@ static inline void ubh_clrblock(struct ufs_sb_private_info * uspi, } static inline void ubh_setblock(struct ufs_sb_private_info * uspi, - struct ufs_buffer_head * ubh, unsigned begin, unsigned block) + struct ufs_cg_private_info *ucpi, unsigned block) { + struct ufs_buffer_head *ubh = UCPI_UBH(ucpi); + unsigned begin = ucpi->c_freeoff; switch (uspi->s_fpb) { case 8: *ubh_get_addr(ubh, begin + block) = 0xff; From patchwork Wed Dec 13 03:18:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490289 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="SLKtX9AB" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F906D0 for ; Tue, 12 Dec 2023 19:18:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=QAtV5tuB+Me1ccSVI1rSQgNFnTQhTkww+CkbPrd5hj4=; b=SLKtX9ABL/QWMalpur75MJI0nu QjR32vr8NC4uVRd/5YlOPksm3xg5gYA7X3fch1YqrXfwno+/DSr2WvGh0N3I937hn4HXM8bKuVV2k xxQPQX/So1P7NFb4CdjVtpdTTG0RuXK3JoV0WyaC2ZZdjtuyOJKoNgxZKsLb0+OtdYR8OwSvY89SR efjZ1LJwoHXZ36COEKBITDw+ITSJY1KhsIu1sOycMXHUgrz0gxMH7BFFeIdVx7GAtpIsdCZUVdwlS N+0QdEBC3hWuRucBwN3QSqan0T3KaU/WosQTQfLRivcZYy8I9pU/q+4Rv4Fo9cJ8KRw1gLhLFN+E4 F8mqWZTA==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlV-00Bby9-0D; Wed, 13 Dec 2023 03:18:29 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 08/12] ufs: untangle ubh_...block...(), part 3 Date: Wed, 13 Dec 2023 03:18:23 +0000 Message-Id: <20231213031827.2767531-8-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro Pass fragment number instead of a block one. It's available in all callers and it makes the logics inside those helpers much simpler. The bitmap they operate upon is with bit per fragment, block being an aligned group of 1, 2, 4 or 8 adjacent fragments. We still need a switch by the number of fragments in block (== number of bits to check/set/clear), but finding the byte we need to work with becomes uniform and that makes the things easier to follow. Signed-off-by: Al Viro --- fs/ufs/balloc.c | 10 +++++----- fs/ufs/util.h | 45 ++++++++++++++++++++++++--------------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index d76c04fbd4fa..7694666fac18 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -95,7 +95,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) * Trying to reassemble free fragments into block */ blkno = ufs_fragstoblks (bbase); - if (ubh_isblockset(uspi, ucpi, blkno)) { + if (ubh_isblockset(uspi, ucpi, bbase)) { fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb); uspi->cs_total.cs_nffree -= uspi->s_fpb; fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb); @@ -182,10 +182,10 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) for (i = bit; i < end_bit; i += uspi->s_fpb) { blkno = ufs_fragstoblks(i); - if (ubh_isblockset(uspi, ucpi, blkno)) { + if (ubh_isblockset(uspi, ucpi, i)) { ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); } - ubh_setblock(uspi, ucpi, blkno); + ubh_setblock(uspi, ucpi, i); inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, 1); @@ -716,7 +716,7 @@ static u64 ufs_alloccg_block(struct inode *inode, /* * If the requested block is available, use it. */ - if (ubh_isblockset(uspi, ucpi, ufs_fragstoblks(goal))) { + if (ubh_isblockset(uspi, ucpi, goal)) { result = goal; goto gotit; } @@ -730,7 +730,7 @@ static u64 ufs_alloccg_block(struct inode *inode, if (!try_add_frags(inode, uspi->s_fpb)) return 0; blkno = ufs_fragstoblks(result); - ubh_clrblock(uspi, ucpi, blkno); + ubh_clrblock(uspi, ucpi, result); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, -1); diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 89c890b5c54d..6fff3da93a66 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -456,65 +456,68 @@ static inline unsigned _ubh_find_last_zero_bit_( } static inline int ubh_isblockset(struct ufs_sb_private_info *uspi, - struct ufs_cg_private_info *ucpi, unsigned block) + struct ufs_cg_private_info *ucpi, unsigned int frag) { struct ufs_buffer_head *ubh = UCPI_UBH(ucpi); - unsigned begin = ucpi->c_freeoff; + u8 *p = ubh_get_addr(ubh, ucpi->c_freeoff + (frag >> 3)); u8 mask; + switch (uspi->s_fpb) { case 8: - return (*ubh_get_addr (ubh, begin + block) == 0xff); + return *p == 0xff; case 4: - mask = 0x0f << ((block & 0x01) << 2); - return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask; + mask = 0x0f << (frag & 4); + return (*p & mask) == mask; case 2: - mask = 0x03 << ((block & 0x03) << 1); - return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask; + mask = 0x03 << (frag & 6); + return (*p & mask) == mask; case 1: - mask = 0x01 << (block & 0x07); - return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask; + mask = 0x01 << (frag & 7); + return (*p & mask) == mask; } return 0; } static inline void ubh_clrblock(struct ufs_sb_private_info *uspi, - struct ufs_cg_private_info *ucpi, unsigned block) + struct ufs_cg_private_info *ucpi, unsigned int frag) { struct ufs_buffer_head *ubh = UCPI_UBH(ucpi); - unsigned begin = ucpi->c_freeoff; + u8 *p = ubh_get_addr(ubh, ucpi->c_freeoff + (frag >> 3)); + switch (uspi->s_fpb) { case 8: - *ubh_get_addr (ubh, begin + block) = 0x00; + *p = 0x00; return; case 4: - *ubh_get_addr (ubh, begin + (block >> 1)) &= ~(0x0f << ((block & 0x01) << 2)); + *p &= ~(0x0f << (frag & 4)); return; case 2: - *ubh_get_addr (ubh, begin + (block >> 2)) &= ~(0x03 << ((block & 0x03) << 1)); + *p &= ~(0x03 << (frag & 6)); return; case 1: - *ubh_get_addr (ubh, begin + (block >> 3)) &= ~(0x01 << ((block & 0x07))); + *p &= ~(0x01 << (frag & 7)); return; } } static inline void ubh_setblock(struct ufs_sb_private_info * uspi, - struct ufs_cg_private_info *ucpi, unsigned block) + struct ufs_cg_private_info *ucpi, unsigned int frag) { struct ufs_buffer_head *ubh = UCPI_UBH(ucpi); - unsigned begin = ucpi->c_freeoff; + u8 *p = ubh_get_addr(ubh, ucpi->c_freeoff + (frag >> 3)); + switch (uspi->s_fpb) { case 8: - *ubh_get_addr(ubh, begin + block) = 0xff; + *p = 0xff; return; case 4: - *ubh_get_addr(ubh, begin + (block >> 1)) |= (0x0f << ((block & 0x01) << 2)); + *p |= 0x0f << (frag & 4); return; case 2: - *ubh_get_addr(ubh, begin + (block >> 2)) |= (0x03 << ((block & 0x03) << 1)); + *p |= 0x03 << (frag & 6); return; case 1: - *ubh_get_addr(ubh, begin + (block >> 3)) |= (0x01 << ((block & 0x07))); + *p |= 0x01 << (frag & 7); return; } } From patchwork Wed Dec 13 03:18:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490292 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="VzPMl5HL" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E15AD3 for ; Tue, 12 Dec 2023 19:18:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=kg6auRfhHkERnlkL0+KpjMlxek7hUNOXFYFWaJTtzQ0=; b=VzPMl5HLxe+YDqNlADDyiMJszy UynBFjoR6vGV083Af67wSe7F+HhFifQG0BvqZWafpnUqxNw+GxT4YiUSXHGe+heu1K7PbnmarVfPY dMl8bDOEBgExCkUGTprCgpjuhGRS6o4AvXigUGJfn1tkwxs9EVAdpbMJGOveZo7rPhwxF2IEeFUTS TwPr7KZw+A70d/04ylghEshSVuXDVL4I8ZxXj6gxkr7wZ2acSSTrnbTlYpxG1OVcK3LQutCbjVUWm vRLFTWvTDBskkYHZUSSyItsyD5PQO2z9IuKU14c6TSzzr9Vzeh026Zo+hG5zFUbuOaDy+cayEBkD4 A8rbWDlg==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlV-00BbyD-0g; Wed, 13 Dec 2023 03:18:29 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 09/12] ufs_clusteracct(): switch to passing fragment number Date: Wed, 13 Dec 2023 03:18:24 +0000 Message-Id: <20231213031827.2767531-9-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro Signed-off-by: Al Viro --- fs/ufs/balloc.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 7694666fac18..1793ce48df0a 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -43,7 +43,6 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; unsigned cgno, bit, end_bit, bbase, blkmap, i; - u64 blkno; sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; @@ -94,13 +93,12 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) /* * Trying to reassemble free fragments into block */ - blkno = ufs_fragstoblks (bbase); if (ubh_isblockset(uspi, ucpi, bbase)) { fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb); uspi->cs_total.cs_nffree -= uspi->s_fpb; fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) - ufs_clusteracct (sb, ucpi, blkno, 1); + ufs_clusteracct(sb, ucpi, bbase, 1); fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); uspi->cs_total.cs_nbfree++; fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); @@ -139,7 +137,6 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; unsigned overflow, cgno, bit, end_bit, i; - u64 blkno; sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; @@ -181,14 +178,13 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) } for (i = bit; i < end_bit; i += uspi->s_fpb) { - blkno = ufs_fragstoblks(i); if (ubh_isblockset(uspi, ucpi, i)) { ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); } ubh_setblock(uspi, ucpi, i); inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) - ufs_clusteracct (sb, ucpi, blkno, 1); + ufs_clusteracct(sb, ucpi, i, 1); fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); uspi->cs_total.cs_nbfree++; @@ -698,7 +694,7 @@ static u64 ufs_alloccg_block(struct inode *inode, struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_cylinder_group * ucg; - u64 result, blkno; + u64 result; UFSD("ENTER, goal %llu\n", (unsigned long long)goal); @@ -729,10 +725,9 @@ static u64 ufs_alloccg_block(struct inode *inode, gotit: if (!try_add_frags(inode, uspi->s_fpb)) return 0; - blkno = ufs_fragstoblks(result); ubh_clrblock(uspi, ucpi, result); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) - ufs_clusteracct (sb, ucpi, blkno, -1); + ufs_clusteracct(sb, ucpi, result, -1); fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1); uspi->cs_total.cs_nbfree--; @@ -863,12 +858,12 @@ static u64 ufs_bitmap_search(struct super_block *sb, } static void ufs_clusteracct(struct super_block * sb, - struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt) + struct ufs_cg_private_info * ucpi, unsigned frag, int cnt) { - struct ufs_sb_private_info * uspi; + struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; int i, start, end, forw, back; + unsigned blkno = ufs_fragstoblks(frag); - uspi = UFS_SB(sb)->s_uspi; if (uspi->s_contigsumsize <= 0) return; From patchwork Wed Dec 13 03:18:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490291 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="pZDhelTM" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BA1FBD5 for ; Tue, 12 Dec 2023 19:18:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=3fE/oxeg1thLynUN0Za05MCtDcmKpfNaEwI0X2tkErY=; b=pZDhelTML+Jjel+hfkABfcAK6W e5UcLU9jZ13F8uai8/5DcQXiNGbakHfUi4hfNYVW8JRG1fO77CsGC+KGvkhopHG1KMqrhJLLeWrUH lIM+YCIg+ZzY3O2h2YhnAV1iND2I/XAnRqTYvqe10bNzLV4E+G6GcDXUBIb3BA2J3wPnAyTtGiPkV y4Q+fhdCUg06I6gLEq3yWKCVgP3HPgbdEFVUT5xQyUpcibZ8VURgyruV9vm1dLzJVOvHUFhp1eWWn bl/SdGsaZavkUrxfwaNSarfQ2AC6Iz5FwhaZuwUGjP7BCsDViumsLszlNvAYsr3mgVkS6Vzh/tZjz Twm9k1RA==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlV-00BbyH-1I; Wed, 13 Dec 2023 03:18:29 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 10/12] ufs_inode_getfrag(): remove junk comment Date: Wed, 13 Dec 2023 03:18:25 +0000 Message-Id: <20231213031827.2767531-10-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro It used to be a stubbed out beginning of ufs2 support, which had been implemented differently quite a while ago. Remove the commented-out (pseudo-)code. Signed-off-by: Al Viro --- fs/ufs/inode.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index ebce93b08281..e1c736409af8 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -263,11 +263,6 @@ ufs_inode_getfrag(struct inode *inode, unsigned index, unsigned nfrags = uspi->s_fpb; void *p; - /* TODO : to be done for write support - if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) - goto ufs2; - */ - p = ufs_get_direct_data_ptr(uspi, ufsi, index); tmp = ufs_data_ptr_to_cpu(sb, p); if (tmp) @@ -302,21 +297,6 @@ ufs_inode_getfrag(struct inode *inode, unsigned index, mark_inode_dirty(inode); out: return tmp + uspi->s_sbbase; - - /* This part : To be implemented .... - Required only for writing, not required for READ-ONLY. -ufs2: - - u2_block = ufs_fragstoblks(fragment); - u2_blockoff = ufs_fragnum(fragment); - p = ufsi->i_u1.u2_i_data + block; - goal = 0; - -repeat2: - tmp = fs32_to_cpu(sb, *p); - lastfrag = ufsi->i_lastfrag; - - */ } /** From patchwork Wed Dec 13 03:18:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490294 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="s36eGc5x" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0BC30DB for ; Tue, 12 Dec 2023 19:18:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=RH4qiGVHnQ1pbKsNUICZdDNbrbx6uDfHTHWZOsm2ZEQ=; b=s36eGc5xMiG7Q3OPVNHdfbAJYx IhAMVtRts/+ng/a+CJiMp+HMZ5kp8I2lGHfQNVXVq7wPvS/ZD2yiMoq1AM3vBM04ysWQLbmYT3sU/ gdbPXTBWBcnhtDlWMdKdmsvwcagZA6OLitNNSWc2hUPeW6K78DUh6q861uH0sUUAxGgXdYOdfOaDD fKaseZ3+H2GgVoi6x8EPuZBPY94lwD5JJRQl3fL6j+jzAy/Eh9qHAfhmGj6hUqWH1XTexaxdg3Cjf J7AQNzHA5ThdGD6WJOKH95gkFfgJjLkZgpWNVkqkq1LreA0D9TVSIEE7KKHTxo6d3wxH/ZDIp+L2n h6rsrThQ==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlV-00BbyM-1d; Wed, 13 Dec 2023 03:18:29 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 11/12] ufs: get rid of ubh_{ubhcpymem,memcpyubh}() Date: Wed, 13 Dec 2023 03:18:26 +0000 Message-Id: <20231213031827.2767531-11-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro used only in ufs_read_cylinder_structures()/ufs_put_super_internal() and there we can just as well avoid bothering with ufs_buffer_head and just deal with it fragment-by-fragment. Signed-off-by: Al Viro --- fs/ufs/super.c | 45 +++++++++++++++++---------------------------- fs/ufs/util.c | 46 ---------------------------------------------- fs/ufs/util.h | 5 ----- 3 files changed, 17 insertions(+), 79 deletions(-) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index a480810cd4e3..ccdfd4cb2682 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -505,7 +505,6 @@ static int ufs_read_cylinder_structures(struct super_block *sb) { struct ufs_sb_info *sbi = UFS_SB(sb); struct ufs_sb_private_info *uspi = sbi->s_uspi; - struct ufs_buffer_head * ubh; unsigned char * base, * space; unsigned size, blks, i; @@ -521,21 +520,13 @@ static int ufs_read_cylinder_structures(struct super_block *sb) if (!base) goto failed; sbi->s_csp = (struct ufs_csum *)space; - for (i = 0; i < blks; i += uspi->s_fpb) { - size = uspi->s_bsize; - if (i + uspi->s_fpb > blks) - size = (blks - i) * uspi->s_fsize; - - ubh = ubh_bread(sb, uspi->s_csaddr + i, size); - - if (!ubh) + for (i = 0; i < blks; i++) { + struct buffer_head *bh = sb_bread(sb, uspi->s_csaddr + i); + if (!bh) goto failed; - - ubh_ubhcpymem (space, ubh, size); - - space += size; - ubh_brelse (ubh); - ubh = NULL; + memcpy(space, bh->b_data, uspi->s_fsize); + space += uspi->s_fsize; + brelse (bh); } /* @@ -645,7 +636,6 @@ static void ufs_put_super_internal(struct super_block *sb) { struct ufs_sb_info *sbi = UFS_SB(sb); struct ufs_sb_private_info *uspi = sbi->s_uspi; - struct ufs_buffer_head * ubh; unsigned char * base, * space; unsigned blks, size, i; @@ -656,18 +646,17 @@ static void ufs_put_super_internal(struct super_block *sb) size = uspi->s_cssize; blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; base = space = (char*) sbi->s_csp; - for (i = 0; i < blks; i += uspi->s_fpb) { - size = uspi->s_bsize; - if (i + uspi->s_fpb > blks) - size = (blks - i) * uspi->s_fsize; - - ubh = ubh_bread(sb, uspi->s_csaddr + i, size); - - ubh_memcpyubh (ubh, space, size); - space += size; - ubh_mark_buffer_uptodate (ubh, 1); - ubh_mark_buffer_dirty (ubh); - ubh_brelse (ubh); + for (i = 0; i < blks; i++, space += uspi->s_fsize) { + struct buffer_head *bh = sb_bread(sb, uspi->s_csaddr + i); + + if (unlikely(!bh)) { // better than an oops... + ufs_panic(sb, __func__, + "can't write part of cylinder group summary"); + continue; + } + memcpy(bh->b_data, space, uspi->s_fsize); + mark_buffer_dirty(bh); + brelse(bh); } for (i = 0; i < sbi->s_cg_loaded; i++) { ufs_put_cylinder (sb, i); diff --git a/fs/ufs/util.c b/fs/ufs/util.c index 13ba34e6d64f..535c7ee80a10 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c @@ -99,20 +99,6 @@ void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh) mark_buffer_dirty (ubh->bh[i]); } -void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag) -{ - unsigned i; - if (!ubh) - return; - if (flag) { - for ( i = 0; i < ubh->count; i++ ) - set_buffer_uptodate (ubh->bh[i]); - } else { - for ( i = 0; i < ubh->count; i++ ) - clear_buffer_uptodate (ubh->bh[i]); - } -} - void ubh_sync_block(struct ufs_buffer_head *ubh) { if (ubh) { @@ -146,38 +132,6 @@ int ubh_buffer_dirty (struct ufs_buffer_head * ubh) return result; } -void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi, - unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size) -{ - unsigned len, bhno; - if (size > (ubh->count << uspi->s_fshift)) - size = ubh->count << uspi->s_fshift; - bhno = 0; - while (size) { - len = min_t(unsigned int, size, uspi->s_fsize); - memcpy (mem, ubh->bh[bhno]->b_data, len); - mem += uspi->s_fsize; - size -= len; - bhno++; - } -} - -void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, - struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size) -{ - unsigned len, bhno; - if (size > (ubh->count << uspi->s_fshift)) - size = ubh->count << uspi->s_fshift; - bhno = 0; - while (size) { - len = min_t(unsigned int, size, uspi->s_fsize); - memcpy (ubh->bh[bhno]->b_data, mem, len); - mem += uspi->s_fsize; - size -= len; - bhno++; - } -} - dev_t ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi) { diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 6fff3da93a66..eb6943fa7fa4 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -263,14 +263,9 @@ extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, str extern void ubh_brelse (struct ufs_buffer_head *); extern void ubh_brelse_uspi (struct ufs_sb_private_info *); extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *); -extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int); extern void ubh_sync_block(struct ufs_buffer_head *); extern void ubh_bforget (struct ufs_buffer_head *); extern int ubh_buffer_dirty (struct ufs_buffer_head *); -#define ubh_ubhcpymem(mem,ubh,size) _ubh_ubhcpymem_(uspi,mem,ubh,size) -extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struct ufs_buffer_head *, unsigned); -#define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size) -extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned); /* This functions works with cache pages*/ struct folio *ufs_get_locked_folio(struct address_space *mapping, pgoff_t index); From patchwork Wed Dec 13 03:18:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 13490296 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linux.org.uk header.i=@linux.org.uk header.b="rWS8vDRd" Received: from zeniv.linux.org.uk (zeniv.linux.org.uk [IPv6:2a03:a000:7:0:5054:ff:fe1c:15ff]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 371AADC for ; Tue, 12 Dec 2023 19:18:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=linux.org.uk; s=zeniv-20220401; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=zceKd/TlPDr/aNSNr3L/G9bEBgVSRQECu2FfNe+Vffk=; b=rWS8vDRdz9ZJh0HCqufgpseKt8 9sTeEdmGBkSEEpVzPmfU+LnTz47y/8Dm7WekVaVHFadE3Nupt4uDgk92w6R8HXNZZ0UReIDvWfSh+ uqTxdZfpf35T5uVWX/0sVQ7cMOBBkSjQRhUfN98Qm3mZK5bnqzB2WMUqUVaTWe43h3zR0+UKdDjcy 33Q+2vt6RrjDPnA3MVABjbqI1Wcp9PIthHjKeShAixCsEtRAoVLPAM1yZfA/9/YkIDBsNExxin5bn gPFXE/p6HoTIUfl0VrR0YTcKnS7zhYGdqAtS4YGnS1melyy7kBKyfcRERRErfgRSv74GPrtrysI7j PkHOM2sA==; Received: from viro by zeniv.linux.org.uk with local (Exim 4.96 #2 (Red Hat Linux)) id 1rDFlV-00BbyQ-2b; Wed, 13 Dec 2023 03:18:29 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Evgeniy Dushistov , "Fabio M. De Francesco" Subject: [PATCH 12/12] clean ufs_trunc_direct() up a bit... Date: Wed, 13 Dec 2023 03:18:27 +0000 Message-Id: <20231213031827.2767531-12-viro@zeniv.linux.org.uk> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231213031827.2767531-1-viro@zeniv.linux.org.uk> References: <20231213031639.GJ1674809@ZenIV> <20231213031827.2767531-1-viro@zeniv.linux.org.uk> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sender: Al Viro For short files (== no indirect blocks needed) UFS allows the last block to be a partial one. That creates some complications for truncation down to "short file" lengths. ufs_trunc_direct() is called when we'd already made sure that new EOF is not in a hole; nothing needs to be done if we are extending the file and in case we are shrinking the file it needs to * shrink or free the old final block. * free all full direct blocks between the new and old EOF. * possibly shrink the new final block. The logics is needlessly complicated by trying to keep all cases handled by the same sequence of operations. if not shrinking nothing to do else if number of full blocks unchanged free the tail of possibly partial last block else free the tail of (full) new last block free all present (full) blocks in between free the (possibly partial) old last block is easier to follow than the result of trying to unify these cases. Signed-off-by: Al Viro --- fs/ufs/inode.c | 124 ++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index e1c736409af8..c573f444afd4 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -875,91 +875,87 @@ static inline void free_data(struct to_free *ctx, u64 from, unsigned count) #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) +/* + * used only for truncation down to direct blocks. + */ static void ufs_trunc_direct(struct inode *inode) { struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block * sb; - struct ufs_sb_private_info * uspi; + struct super_block *sb = inode->i_sb; + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; void *p; - u64 frag1, frag2, frag3, frag4, block1, block2; + u64 frag1, frag4, block1, block2; + unsigned old_partial, new_partial, old_blocks, new_blocks; struct to_free ctx = {.inode = inode}; unsigned i, tmp; UFSD("ENTER: ino %lu\n", inode->i_ino); - sb = inode->i_sb; - uspi = UFS_SB(sb)->s_uspi; - frag1 = DIRECT_FRAGMENT; + // frag1 = first fragment past the new EOF frag4 = min_t(u64, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag); - frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1); - frag3 = frag4 & ~uspi->s_fpbmask; - block1 = block2 = 0; - if (frag2 > frag3) { - frag2 = frag4; - frag3 = frag4 = 0; - } else if (frag2 < frag3) { - block1 = ufs_fragstoblks (frag2); - block2 = ufs_fragstoblks (frag3); - } - - UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu," - " frag3 %llu, frag4 %llu\n", inode->i_ino, - (unsigned long long)frag1, (unsigned long long)frag2, - (unsigned long long)block1, (unsigned long long)block2, - (unsigned long long)frag3, (unsigned long long)frag4); - - if (frag1 >= frag2) - goto next1; + // frag4 = first fragment past the old EOF or covered by indirects - /* - * Free first free fragments - */ - p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1)); - tmp = ufs_data_ptr_to_cpu(sb, p); - if (!tmp ) - ufs_panic (sb, "ufs_trunc_direct", "internal error"); - frag2 -= frag1; - frag1 = ufs_fragnum (frag1); + if (frag1 >= frag4) // expanding - nothing to free + goto next3; - ufs_free_fragments(inode, tmp + frag1, frag2); + old_partial = ufs_fragnum(frag4); + old_blocks = ufs_fragstoblks(frag4); + new_partial = ufs_fragnum(frag1); + new_blocks = ufs_fragstoblks(frag1); -next1: - /* - * Free whole blocks - */ - for (i = block1 ; i < block2; i++) { - p = ufs_get_direct_data_ptr(uspi, ufsi, i); + if (old_blocks == new_blocks) { + p = ufs_get_direct_data_ptr(uspi, ufsi, new_blocks); tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) - continue; - write_seqlock(&ufsi->meta_lock); - ufs_data_ptr_clear(uspi, p); - write_sequnlock(&ufsi->meta_lock); + ufs_panic (sb, "ufs_trunc_direct", "internal error"); + if (!new_partial) { + write_seqlock(&ufsi->meta_lock); + ufs_data_ptr_clear(uspi, p); + write_sequnlock(&ufsi->meta_lock); + } + ufs_free_fragments(inode, tmp + new_partial, + old_partial - new_partial); + } else { + block1 = new_blocks; + block2 = old_partial ? old_blocks-1 : old_blocks; + + if (new_partial) { + p = ufs_get_direct_data_ptr(uspi, ufsi, new_blocks); + tmp = ufs_data_ptr_to_cpu(sb, p); + if (!tmp) + ufs_panic (sb, "ufs_trunc_direct", "internal error"); + ufs_free_fragments(inode, tmp + new_partial, + uspi->s_fpb - new_partial); + block1++; + } + for (i = block1 ; i < block2; i++) { + p = ufs_get_direct_data_ptr(uspi, ufsi, i); + tmp = ufs_data_ptr_to_cpu(sb, p); + if (!tmp) + continue; + write_seqlock(&ufsi->meta_lock); + ufs_data_ptr_clear(uspi, p); + write_sequnlock(&ufsi->meta_lock); - free_data(&ctx, tmp, uspi->s_fpb); - } + free_data(&ctx, tmp, uspi->s_fpb); + } - free_data(&ctx, 0, 0); + free_data(&ctx, 0, 0); - if (frag3 >= frag4) - goto next3; + if (old_partial) { + p = ufs_get_direct_data_ptr(uspi, ufsi, old_blocks); + tmp = ufs_data_ptr_to_cpu(sb, p); + if (!tmp) + ufs_panic(sb, "ufs_truncate_direct", "internal error"); + write_seqlock(&ufsi->meta_lock); + ufs_data_ptr_clear(uspi, p); + write_sequnlock(&ufsi->meta_lock); - /* - * Free last free fragments - */ - p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3)); - tmp = ufs_data_ptr_to_cpu(sb, p); - if (!tmp ) - ufs_panic(sb, "ufs_truncate_direct", "internal error"); - frag4 = ufs_fragnum (frag4); - write_seqlock(&ufsi->meta_lock); - ufs_data_ptr_clear(uspi, p); - write_sequnlock(&ufsi->meta_lock); - - ufs_free_fragments (inode, tmp, frag4); + ufs_free_fragments(inode, tmp, old_partial); + } + } next3: - UFSD("EXIT: ino %lu\n", inode->i_ino); }