From patchwork Sat Nov 5 17:26:35 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Mahoney X-Patchwork-Id: 9413777 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1FBED60573 for ; Sat, 5 Nov 2016 17:26:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0EB3A293BF for ; Sat, 5 Nov 2016 17:26:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 03DF7293D0; Sat, 5 Nov 2016 17:26:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 605F9293CB for ; Sat, 5 Nov 2016 17:26:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754987AbcKER0o (ORCPT ); Sat, 5 Nov 2016 13:26:44 -0400 Received: from mx2.suse.de ([195.135.220.15]:59006 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753211AbcKER0n (ORCPT ); Sat, 5 Nov 2016 13:26:43 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id AB9BEAD16 for ; Sat, 5 Nov 2016 17:26:41 +0000 (UTC) Received: by starscream.home.jeffm.io (Postfix, from userid 1000) id 19F448554C; Sat, 5 Nov 2016 13:26:39 -0400 (EDT) From: jeffm@suse.com To: linux-btrfs@vger.kernel.org Cc: Jeff Mahoney Subject: [PATCH 2/2] btrfs: increment ctx->pos for every emitted or skipped dirent in readdir Date: Sat, 5 Nov 2016 13:26:35 -0400 Message-Id: <1478366795-27009-2-git-send-email-jeffm@suse.com> X-Mailer: git-send-email 2.7.1 In-Reply-To: <1478366795-27009-1-git-send-email-jeffm@suse.com> References: <1478366795-27009-1-git-send-email-jeffm@suse.com> Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jeff Mahoney If we process the last item in the leaf and hit an I/O error while reading the next leaf, we return -EIO without having adjusted the position. Since we have emitted dirents, getdents() will return the byte count to the user instead of the error. Subsequent callers will emit the last successful dirent again, and return -EIO again, with the same result. Callers loop forever. Instead, if we always increment ctx->pos after emitting or skipping the dirent, we'll be sure that we won't hit the same one again. When we go to process the next leaf, we won't have emitted any dirents and the -EIO will be returned to the user properly. We also don't need to track if we've emitted a dirent already or if we've changed the position yet. Signed-off-by: Jeff Mahoney Reviewed-by: David Sterba --- fs/btrfs/delayed-inode.c | 3 +-- fs/btrfs/delayed-inode.h | 2 +- fs/btrfs/inode.c | 21 ++------------------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 0fcf5f2..d90d444 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1686,7 +1686,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list, * */ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, - struct list_head *ins_list, bool *emitted) + struct list_head *ins_list) { struct btrfs_dir_item *di; struct btrfs_delayed_item *curr, *next; @@ -1730,7 +1730,6 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, if (over) return 1; - *emitted = true; } return 0; } diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 2495b3d..2c1cbe2 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -146,7 +146,7 @@ void btrfs_readdir_put_delayed_items(struct inode *inode, int btrfs_should_delete_dir_index(struct list_head *del_list, u64 index); int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, - struct list_head *ins_list, bool *emitted); + struct list_head *ins_list); /* for init */ int __init btrfs_delayed_inode_init(void); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c52239d..d8834bc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5808,8 +5808,6 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) char tmp_name[32]; char *name_ptr; int name_len; - int is_curr = 0; /* ctx->pos points to the current index? */ - bool emitted; bool put = false; struct btrfs_key location; @@ -5834,7 +5832,6 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) if (ret < 0) goto err; - emitted = false; while (1) { leaf = path->nodes[0]; slot = path->slots[0]; @@ -5860,7 +5857,6 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) goto next; ctx->pos = found_key.offset; - is_curr = 1; di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); if (verify_dir_item(root, leaf, di)) @@ -5890,29 +5886,16 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) if (over) goto nopos; + ctx->pos++; next: path->slots[0]++; } - if (is_curr) - ctx->pos++; - ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted); + ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list); if (ret) goto nopos; /* - * If we haven't emitted any dir entry, we must not touch ctx->pos as - * it was was set to the termination value in previous call. We assume - * that "." and ".." were emitted if we reach this point and set the - * termination value as well for an empty directory. - */ - if (ctx->pos > 2 && !emitted) - goto nopos; - - /* Reached end of directory/root. Bump pos past the last item. */ - ctx->pos++; - - /* * Stop new entries from being returned after we return the last * entry. *