Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp8359354ybi; Tue, 9 Jul 2019 14:11:59 -0700 (PDT) X-Google-Smtp-Source: APXvYqw99/aoRIpeGc6ygb/JfFTfUahxU63iX9pxjm39P3njcU2chpjofZHusKjQI4YSPpqjjw5t X-Received: by 2002:a17:90a:9903:: with SMTP id b3mr2367468pjp.80.1562706719701; Tue, 09 Jul 2019 14:11:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1562706719; cv=none; d=google.com; s=arc-20160816; b=Elc8LIbVu6PW6FlXh4lbpdvtgIlrkAFg7yw4G2DFDf1rQfpmISbiDo4SaLOY4UD2Fw TuX9xYtDde6cswRtXQmjquEdSM2t3QWbD0FV8/tPRR/6mSY8hHJZNLaKx9DP265ZSZWa 7V+lDPiCKCBD3HrhBg4tEvGHl63N6ya0fgoPncdI+hlIPXnluQULHVr8uVM9mY7zuTOp 9UwTEPa4SV/z66j3Km16oZ0tmNB/f5/Je/gP/OCn6UkaRW3yxF6QKAm0Has0I0AEa3dJ VDDXS1cMpQqnZvlVffU9wIG1BgPgnWMeKo74is4Aba5/8DP4Wh6tPs47+Nx6+Mpi96Qu D+9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=qdaw5a08/aRKbRJszXbt7VZHy0EbA8IPJU2/RYpmVg4=; b=FWyx4SZiXQ/AQ8yY+KT1vFTAZh7AXxz/my57A5TIAsTVBhnfRvpNZKSttYBP9wGD5P Q08gaOIvmwoHTERdTCH+Shqa3GY2r9z8EF5GHtlsv62lDqrXHrUMRIQp0/uFP+4RmYJC a2bocu+ptps+qUnMJRUhFxm0oU4R9EjN3hjA6cRoKgrBjVimpE3CvhtOAUUws+qDU1jS UBXq5decReA4+PLnkOp1fnL3WoCM3g+fh9HzSOGGI24OEhvuzCrfmg/S6bTe5yX4/HEv 6U2MBZ8CffbvGC8Ciq6TMirRBiZJZbDsfSYRkxUWdKKtJJSrC+Z2W6QC4T0aAsgKiP+w 6hhw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k192si13607pge.222.2019.07.09.14.11.44; Tue, 09 Jul 2019 14:11:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729452AbfGIVDq (ORCPT + 99 others); Tue, 9 Jul 2019 17:03:46 -0400 Received: from mx2.suse.de ([195.135.220.15]:34454 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728998AbfGIVDq (ORCPT ); Tue, 9 Jul 2019 17:03:46 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 374FAAEE9; Tue, 9 Jul 2019 21:03:44 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id 90CEB1E4376; Tue, 9 Jul 2019 23:03:43 +0200 (CEST) Date: Tue, 9 Jul 2019 23:03:43 +0200 From: Jan Kara To: " Steven J. Magnani " Cc: Jan Kara , "Steven J . Magnani" , linux-kernel@vger.kernel.org Subject: Re: [PATCH v2] udf: Fix incorrect final NOT_ALLOCATED (hole) extent length Message-ID: <20190709210343.GA2517@quack2.suse.cz> References: <1561948775-5878-1-git-send-email-steve@digidescorp.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1561948775-5878-1-git-send-email-steve@digidescorp.com> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sun 30-06-19 21:39:35, Steven J. Magnani wrote: > In some cases, using the 'truncate' command to extend a UDF file results > in a mismatch between the length of the file's extents (specifically, due > to incorrect length of the final NOT_ALLOCATED extent) and the information > (file) length. The discrepancy can prevent other operating systems > (i.e., Windows 10) from opening the file. > > Two particular errors have been observed when extending a file: > > 1. The final extent is larger than it should be, having been rounded up > to a multiple of the block size. > > B. The final extent is not shorter than it should be, due to not having > been updated when the file's information length was increased. > > Change since v1: > Simplified udf_do_extend_file() API, partially by factoring out its > handling of the "extending within the last file block" corner case. > > Fixes: 2c948b3f86e5 ("udf: Avoid IO in udf_clear_inode") > Signed-off-by: Steven J. Magnani Thanks for the patch! I have added it with some small modifications to my tree. Below are the changes I did. > --- a/fs/udf/inode.c 2019-05-24 21:17:33.659704533 -0500 > +++ b/fs/udf/inode.c 2019-06-29 21:10:48.938562957 -0500 > @@ -470,13 +470,15 @@ static struct buffer_head *udf_getblk(st > return NULL; > } > > -/* Extend the file by 'blocks' blocks, return the number of extents added */ > +/* Extend the file with new blocks totaling 'new_block_bytes', > + * return the number of extents added > + */ > static int udf_do_extend_file(struct inode *inode, > struct extent_position *last_pos, > struct kernel_long_ad *last_ext, > - sector_t blocks) > + loff_t new_block_bytes) > { > - sector_t add; > + unsigned long add; I've changed the type here to uint32_t since that's what we usually use for extent size. > +/* Extend the final block of the file to final_block_len bytes */ > +static int udf_do_extend_final_block(struct inode *inode, Changed return type to void since the function doesn't return anything useful. > + struct extent_position *last_pos, > + struct kernel_long_ad *last_ext, > + unsigned long final_block_len) > +{ > + struct super_block *sb = inode->i_sb; > + struct kernel_lb_addr tmploc; > + uint32_t tmplen; > + struct udf_inode_info *iinfo; > + unsigned long added_bytes; > + > + iinfo = UDF_I(inode); > + > + added_bytes = final_block_len - > + (last_ext->extLength & (sb->s_blocksize - 1)); > + last_ext->extLength += added_bytes; > + iinfo->i_lenExtents += added_bytes; > + > + udf_write_aext(inode, last_pos, &last_ext->extLocation, > + last_ext->extLength, 1); > + /* > + * We've rewritten the last extent but there may be empty > + * indirect extent after it - enter it. > + */ > + udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0); > + > + /* last_pos should point to the last written extent... */ > + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) > + last_pos->offset -= sizeof(struct short_ad); > + else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) > + last_pos->offset -= sizeof(struct long_ad); > + else > + return -EIO; I've dropped the updates of last_pos here. This function is used from a single place and passed epos isn't used in any way after the function returns. > + > + return 0; > +} > + > static int udf_extend_file(struct inode *inode, loff_t newsize) > { > > @@ -605,10 +643,12 @@ static int udf_extend_file(struct inode > int8_t etype; > struct super_block *sb = inode->i_sb; > sector_t first_block = newsize >> sb->s_blocksize_bits, offset; > + unsigned long partial_final_block; Again uint32_t here. > @@ -643,7 +673,22 @@ static int udf_extend_file(struct inode > &extent.extLength, 0); > extent.extLength |= etype << 30; > } > - err = udf_do_extend_file(inode, &epos, &extent, offset); > + > + partial_final_block = newsize & (sb->s_blocksize - 1); > + > + /* File has extent covering the new size (could happen when extending > + * inside a block)? > + */ > + if (within_final_block) { > + /* Extending file within the last file block */ > + err = udf_do_extend_final_block(inode, &epos, &extent, > + partial_final_block); > + } else { > + loff_t add = (offset << sb->s_blocksize_bits) | Typed 'offset' to loff_t before shifting. Otherwise the shift could overflow for systems with 32-bit sector_t. > + partial_final_block; > + err = udf_do_extend_file(inode, &epos, &extent, add); > + } > + > if (err < 0) > goto out; > err = 0; ... > @@ -760,7 +806,8 @@ static sector_t inode_getblk(struct inod > startnum = (offset > 0); > } > /* Create extents for the hole between EOF and offset */ > - ret = udf_do_extend_file(inode, &prev_epos, laarr, offset); > + hole_len = offset << inode->i_sb->s_blocksize_bits; The same as above. > + ret = udf_do_extend_file(inode, &prev_epos, laarr, hole_len); > if (ret < 0) { > *err = ret; > newblock = 0; Honza -- Jan Kara SUSE Labs, CR