From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9361E7718B for ; Mon, 23 Dec 2024 14:17:38 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 602486B00B3; Mon, 23 Dec 2024 09:17:38 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 5B2466B00B4; Mon, 23 Dec 2024 09:17:38 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 42C606B00B5; Mon, 23 Dec 2024 09:17:38 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 2426C6B00B3 for ; Mon, 23 Dec 2024 09:17:38 -0500 (EST) Received: from smtpin09.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 909571C71F3 for ; Mon, 23 Dec 2024 14:17:37 +0000 (UTC) X-FDA: 82926424728.09.5380428 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) by imf08.hostedemail.com (Postfix) with ESMTP id A1925160004 for ; Mon, 23 Dec 2024 14:17:09 +0000 (UTC) Authentication-Results: imf08.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf08.hostedemail.com: domain of yangerkun@huaweicloud.com designates 45.249.212.51 as permitted sender) smtp.mailfrom=yangerkun@huaweicloud.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1734963420; a=rsa-sha256; cv=none; b=iPIbC9110wicDvUh3JgNviqFIJWWVzJHZf60ogh3KcwyPVp7rdhiNRXi+ZPoP9BNTYYeXp 1Mta4a5P4YdNthOXwrj0qPgKTzwKuR92hra8gR29/u7HAOe4h+gbN90e8T4TvjU4Vj+Mms tMAAwkxCpzvjdwmzqaHzD8YmmLuvO18= ARC-Authentication-Results: i=1; imf08.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf08.hostedemail.com: domain of yangerkun@huaweicloud.com designates 45.249.212.51 as permitted sender) smtp.mailfrom=yangerkun@huaweicloud.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1734963420; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MeZ1CHllY0yzol73hkXyaLC0hcmGCHvPW68qCPprVrU=; b=YQqc7v+hUTje5JTE33/meSTZQitchALt0JOPo1d7uIk0uZGOtO73C+06Vr1G2UB2/bOmIb v9ic8GgDW/qSUjr57exUF99CmqqKq60shoIZY/bbOYENH8hY4QRfktoj2ifUDUXxGYGM1G rzGgNQFlqRK1iQ08h+3K8FsMNppjwp8= Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4YH0TL0BGQz4f3lg6 for ; Mon, 23 Dec 2024 22:17:10 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id BAC331A092F for ; Mon, 23 Dec 2024 22:17:30 +0800 (CST) Received: from [10.174.177.210] (unknown [10.174.177.210]) by APP4 (Coremail) with SMTP id gCh0CgBHIob6cGlnfvyuFQ--.54478S3; Mon, 23 Dec 2024 22:17:30 +0800 (CST) Message-ID: Date: Mon, 23 Dec 2024 22:17:29 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.5.1 Subject: Re: [PATCH v6 4/5] libfs: Replace simple_offset end-of-directory detection To: cel@kernel.org, Hugh Dickins , Christian Brauner , Al Viro Cc: linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, yukuai3@huawei.com, Chuck Lever References: <20241220153314.5237-1-cel@kernel.org> <20241220153314.5237-5-cel@kernel.org> From: yangerkun In-Reply-To: <20241220153314.5237-5-cel@kernel.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-CM-TRANSID:gCh0CgBHIob6cGlnfvyuFQ--.54478S3 X-Coremail-Antispam: 1UD129KBjvJXoW3AFW8tF1xur4kKw17urW5GFg_yoW7Xw13pF Z8G3ZxKrs3Xw1j9F40vF4DZ34F9wnagrWxGr1Fgwn8A3sIqrsrKasFyr1Yka40kr4kCr12 vF45Kr13uw4UJrDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUvjb4IE77IF4wAFF20E14v26r4j6ryUM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4 vEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x 0267AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG 6I80ewAv7VC0I7IYx2IY67AKxVWUXVWUAwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFV Cjc4AY6r1j6r4UM4x0Y48IcVAKI48JMxk0xIA0c2IEe2xFo4CEbIxvr21lc7CjxVAaw2AF wI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I 0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWU JVW8JwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxUFB T5DUUUU X-CM-SenderInfo: 51dqwvhunx0q5kxd4v5lfo033gof0z/ X-Stat-Signature: n1hdgx96esmttwda45c7xfsor9a53xdz X-Rspam-User: X-Rspamd-Queue-Id: A1925160004 X-Rspamd-Server: rspam08 X-HE-Tag: 1734963429-884748 X-HE-Meta: U2FsdGVkX1+VL+KgUh986wPzYMF6lsiOOzTlmtyy3XZ2lDccTuRSYtVKCZ8g5IJD1/2uWakb26b2nQr+Quh7r0geSKY14srJZSP2mJse4cEuvIkpK+mIaRzYCVWUty4R44RdPftwmwP5oahVoXsIC2bBT6hvh/EekUsMVLCnzzx9uwfPd9fM8bwjl8nWBw7q1NBAnS89lEB2oGByeVTojLUlHFCpGqs5sF5jmLbdfQvN1t1Bw8WmLIQbxkY5/Rdz8qqKx9jRK7aRpgNs849ROLnxmgiw5roT94P42ByOFsXOCs2wI60ZVkP+JLvAllHd5rRiUj2AWvNiE6dSJUQiqgrlty70l4AwhPpT1u8S5b0Uae5yN/OWcuRNkypD2KvZRA539g9LY3hPxGJZHQuqYRCy6/XJ/RHDeBPUVSSeLjp2LLNcdDsruxVQLHquXfRME9B2En9iIaCto9HD/yQaEuX/1Fl1R4x4kfi2AdZVw4YIwGgE8CWiDPeIKQjBUIpPjcthMAhOkwl2EBoH7ca6kA4Ak9HsvgZZXKdRztx2rP0CjTDdfrHJJM0ZiGNNfTCKuu93fLsTkjnoRHm3oTtWIb9ZmsOq+tjm8D0Qai+4c1voWHFvQJ4px6C7yzuoTIfcUzkdoyvZClwolTePpPc7D7bPqoam0/rEYrj2I0iSMvw22sP25o8pIeLdJj6JfKTv8bVo5/wFuH7iMkrnh/FmNJw5BmCrgzuYVV6mRWeUGegrv1VAiObi4XRRQtfH4tf+pzxQmyCs1zXnctzic6Wv5S0wYzcS0A2oQZXPh3KV5klbilgvzqD2+O2pjIZkC0vXakP13ERyHwY/HGuXeKfO6Wn7Fq6dfx5t03l7osalV36g/i2PnWdl5sSUTgWCoVww1MH7YcobkY5R3xN+FzdhwdhSkW8/Kuo8odCA/+0bq4QWAa57BwgPSTGTLsk9Te3dQbVCTsXudL0xI+DJNc/ 2Rle9KAM HfA4k3a7NCMwnqmlkmopSpj3eRcxlevHwGUUbkwqDjxS0j/zwKIQqM1I3/u/nZAbw8nb2ZcdLp/TOMwg42Sp+raWPjeDFlY7a/pemEwT6F432zFRZBlYFncQDvvrv8xOtgfu4/y149jvWLMLmhpv+cFumfbh3YH+n2b19tN+YCf8ZB7yELQsTJBnwF+lIT6OtujjxD7e98D6vzLwYwZiCnoubU06DE2Ym2MlqI8v8KdBMXwjyNJcqTUqaZcyfmMymmIBarxNhMQYHoNU= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: LGTM Reviewed-by: Yang Erkun 在 2024/12/20 23:33, cel@kernel.org 写道: > From: Chuck Lever > > According to getdents(3), the d_off field in each returned directory > entry points to the next entry in the directory. The d_off field in > the last returned entry in the readdir buffer must contain a valid > offset value, but if it points to an actual directory entry, then > readdir/getdents can loop. > > This patch introduces a specific fixed offset value that is placed > in the d_off field of the last entry in a directory. Some user space > applications assume that the EOD offset value is larger than the > offsets of real directory entries, so the largest possible offset > value is reserved for this purpose. This new value is never > allocated by simple_offset_add(). > > When ->iterate_dir() returns, getdents{64} inserts the ctx->pos > value into the d_off field of the last valid entry in the readdir > buffer. When it hits EOD, offset_readdir() sets ctx->pos to the EOD > offset value so the last entry is updated to point to the EOD marker. > > When trying to read the entry at the EOD offset, offset_readdir() > terminates immediately. > > It is worth noting that using a Maple tree for directory offset > value allocation does not guarantee a 63-bit range of values -- > on platforms where "long" is a 32-bit type, the directory offset > value range is still 0..(2^31 - 1). > > Fixes: 796432efab1e ("libfs: getdents() should return 0 after reaching EOD") > Signed-off-by: Chuck Lever > --- > fs/libfs.c | 38 ++++++++++++++++++++++---------------- > 1 file changed, 22 insertions(+), 16 deletions(-) > > diff --git a/fs/libfs.c b/fs/libfs.c > index 8c9364a0174c..5c56783c03a5 100644 > --- a/fs/libfs.c > +++ b/fs/libfs.c > @@ -245,9 +245,16 @@ const struct inode_operations simple_dir_inode_operations = { > }; > EXPORT_SYMBOL(simple_dir_inode_operations); > > -/* 0 is '.', 1 is '..', so always start with offset 2 or more */ > +/* simple_offset_add() allocation range */ > enum { > - DIR_OFFSET_MIN = 2, > + DIR_OFFSET_MIN = 2, > + DIR_OFFSET_MAX = LONG_MAX - 1, > +}; > + > +/* simple_offset_add() never assigns these to a dentry */ > +enum { > + DIR_OFFSET_EOD = LONG_MAX, /* Marks EOD */ > + > }; > > static void offset_set(struct dentry *dentry, long offset) > @@ -291,7 +298,8 @@ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry) > return -EBUSY; > > ret = mtree_alloc_cyclic(&octx->mt, &offset, dentry, DIR_OFFSET_MIN, > - LONG_MAX, &octx->next_offset, GFP_KERNEL); > + DIR_OFFSET_MAX, &octx->next_offset, > + GFP_KERNEL); > if (unlikely(ret < 0)) > return ret == -EBUSY ? -ENOSPC : ret; > > @@ -447,8 +455,6 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) > return -EINVAL; > } > > - /* In this case, ->private_data is protected by f_pos_lock */ > - file->private_data = NULL; > return vfs_setpos(file, offset, LONG_MAX); > } > > @@ -458,7 +464,7 @@ static struct dentry *offset_find_next(struct offset_ctx *octx, loff_t offset) > struct dentry *child, *found = NULL; > > rcu_read_lock(); > - child = mas_find(&mas, LONG_MAX); > + child = mas_find(&mas, DIR_OFFSET_MAX); > if (!child) > goto out; > spin_lock(&child->d_lock); > @@ -479,7 +485,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) > inode->i_ino, fs_umode_to_dtype(inode->i_mode)); > } > > -static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) > +static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx) > { > struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode); > struct dentry *dentry; > @@ -487,7 +493,7 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) > while (true) { > dentry = offset_find_next(octx, ctx->pos); > if (!dentry) > - return ERR_PTR(-ENOENT); > + goto out_eod; > > if (!offset_dir_emit(ctx, dentry)) { > dput(dentry); > @@ -497,7 +503,10 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) > ctx->pos = dentry2offset(dentry) + 1; > dput(dentry); > } > - return NULL; > + return; > + > +out_eod: > + ctx->pos = DIR_OFFSET_EOD; > } > > /** > @@ -517,6 +526,8 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) > * > * On return, @ctx->pos contains an offset that will read the next entry > * in this directory when offset_readdir() is called again with @ctx. > + * Caller places this value in the d_off field of the last entry in the > + * user's buffer. > * > * Return values: > * %0 - Complete > @@ -529,13 +540,8 @@ static int offset_readdir(struct file *file, struct dir_context *ctx) > > if (!dir_emit_dots(file, ctx)) > return 0; > - > - /* In this case, ->private_data is protected by f_pos_lock */ > - if (ctx->pos == DIR_OFFSET_MIN) > - file->private_data = NULL; > - else if (file->private_data == ERR_PTR(-ENOENT)) > - return 0; > - file->private_data = offset_iterate_dir(d_inode(dir), ctx); > + if (ctx->pos != DIR_OFFSET_EOD) > + offset_iterate_dir(d_inode(dir), ctx); > return 0; > } >