From patchwork Tue Jan 22 09:11:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zheng Liu X-Patchwork-Id: 214470 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 51AD62C0084 for ; Tue, 22 Jan 2013 19:58:07 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754629Ab3AVI6E (ORCPT ); Tue, 22 Jan 2013 03:58:04 -0500 Received: from mail-pb0-f45.google.com ([209.85.160.45]:39688 "EHLO mail-pb0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754552Ab3AVI6B (ORCPT ); Tue, 22 Jan 2013 03:58:01 -0500 Received: by mail-pb0-f45.google.com with SMTP id mc8so3833505pbc.4 for ; Tue, 22 Jan 2013 00:58:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=nB7q3qvXabcudziJnkHz3KVkGKQsxw1b46JonJT/epY=; b=nEbWKVsYMpKeHngirall4AcxkoGjyfVanlzdl2Ca604RGDClkeVJ4cY2rbUmvRZk8c hxS6PJtUw33GBTK20d5XW1siyOPNHWQnqENqgdYaaeqeIHtZ/Nh6SH9RHjttFOtRkdzz f3aKdbvdetWS37JqU6CcHvs/miWNGiTo/m3Xj1vWwfmWZnjP1l/VnP8ouXnBEVvYs/NL H1txnw35yOPm9d4GbJJbqGUF0BrEsvJbS9MxWdcsW9L24y7Mi4miFrKiJLDEwv4oNZ9O YyE5fNLpjOm/WLPJ8LEwk71uOjcDgk4Kaexg5GmnQ5HNSTWUGlDhAembfX72fU2SQ5Zq e4XQ== X-Received: by 10.66.85.103 with SMTP id g7mr54407843paz.45.1358845081130; Tue, 22 Jan 2013 00:58:01 -0800 (PST) Received: from lz-desktop.taobao.ali.com ([182.92.247.2]) by mx.google.com with ESMTPS id uh9sm10366140pbc.65.2013.01.22.00.57.56 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 22 Jan 2013 00:58:00 -0800 (PST) From: Zheng Liu To: linux-ext4@vger.kernel.org Cc: "Theodore Ts'o" , Zheng Liu Subject: [PATCH 2/2 v3] debugfs: dump a sparse file Date: Tue, 22 Jan 2013 17:11:33 +0800 Message-Id: <1358845893-24640-3-git-send-email-wenqing.lz@taobao.com> X-Mailer: git-send-email 1.7.12.rc2.18.g61b472e In-Reply-To: <1358845893-24640-1-git-send-email-wenqing.lz@taobao.com> References: <1358845893-24640-1-git-send-email-wenqing.lz@taobao.com> Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org From: Zheng Liu When ext2fs_file_open() is called with EXT2_FILE_SPAESE flag, ext2fs_file_read() will return EXT2_ET_READ_HOLE_FOUND if it meets a hole/uninitialized block. The caller can handle sparse file according to this flags. CC: "Theodore Ts'o" Signed-off-by: Zheng Liu --- debugfs/dump.c | 48 +++++++++++++++++++++++++++++++++++++++-------- lib/ext2fs/ext2_err.et.in | 3 +++ lib/ext2fs/ext2fs.h | 1 + lib/ext2fs/fileio.c | 11 +++++++++-- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/debugfs/dump.c b/debugfs/dump.c index 9409ab6..3341c56 100644 --- a/debugfs/dump.c +++ b/debugfs/dump.c @@ -107,13 +107,20 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd, struct ext2_inode inode; char *buf = 0; ext2_file_t e2_file; - int nbytes; + ext2_off64_t ret_pos, offset; + int nbytes, flags = 0; unsigned int got, blocksize = current_fs->blocksize; if (debugfs_read_inode(ino, &inode, cmdname)) return; - retval = ext2fs_file_open(current_fs, ino, 0, &e2_file); + /* + * We need to handle stdout because this function is called by + * do_cat() and do_dump(). + */ + if (fd != 1) + flags = EXT2_FILE_SPARSE; + retval = ext2fs_file_open(current_fs, ino, flags, &e2_file); if (retval) { com_err(cmdname, retval, "while opening ext2 file"); return; @@ -125,13 +132,38 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd, } while (1) { retval = ext2fs_file_read(e2_file, buf, blocksize, &got); - if (retval) + if (retval && retval != EXT2_ET_READ_HOLE_FOUND) com_err(cmdname, retval, "while reading ext2 file"); - if (got == 0) - break; - nbytes = write(fd, buf, got); - if ((unsigned) nbytes != got) - com_err(cmdname, errno, "while writing file"); + if (retval == EXT2_ET_READ_HOLE_FOUND) { + if (got) { + nbytes = write(fd, buf, got); + if ((unsigned) nbytes != got) + com_err(cmdname, errno, + "while writing file"); + } + retval = ext2fs_file_llseek(e2_file, 0, EXT2_SEEK_CUR, + &offset); + if (retval) + com_err(cmdname, retval, + "while lseeking ext2 file"); + retval = ext2fs_file_llseek(e2_file, offset, + EXT2_SEEK_DATA, &ret_pos); + if (retval == EXT2_ET_SEEK_BEYOND_EOF) + break; + if (retval) + com_err(cmdname, retval, + "while lseeking ext2 file"); + ret_pos = lseek64(fd, ret_pos, SEEK_SET); + if (ret_pos < 0) + com_err(cmdname, retval, + "while lseeking target file"); + } else { + if (got == 0) + break; + nbytes = write(fd, buf, got); + if ((unsigned) nbytes != got) + com_err(cmdname, errno, "while writing file"); + } } if (buf) ext2fs_free_mem(&buf); diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in index 6e79b97..f854df0 100644 --- a/lib/ext2fs/ext2_err.et.in +++ b/lib/ext2fs/ext2_err.et.in @@ -479,4 +479,7 @@ ec EXT2_ET_FILE_EXISTS, ec EXT2_ET_SEEK_BEYOND_EOF, "lseek beyond the EOF" +ec EXT2_ET_READ_HOLE_FOUND, + "We read a hole/uninitialized block with EXT2_FILE_SPARSE flag" + end diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index ce7c38a..e757b40 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -149,6 +149,7 @@ typedef struct ext2_struct_dblist *ext2_dblist; #define EXT2_FILE_WRITE 0x0001 #define EXT2_FILE_CREATE 0x0002 +#define EXT2_FILE_SPARSE 0x0004 #define EXT2_FILE_MASK 0x00FF diff --git a/lib/ext2fs/fileio.c b/lib/ext2fs/fileio.c index 6cb2e43..be658d8 100644 --- a/lib/ext2fs/fileio.c +++ b/lib/ext2fs/fileio.c @@ -185,11 +185,12 @@ static errcode_t load_buffer(ext2_file_t file, int dontfill) { ext2_filsys fs = file->fs; errcode_t retval; + int ret_flags = 0; if (!(file->flags & EXT2_FILE_BUF_VALID)) { retval = ext2fs_bmap2(fs, file->ino, &file->inode, - BMAP_BUFFER, 0, file->blockno, 0, - &file->physblock); + BMAP_BUFFER, 0, file->blockno, + &ret_flags, &file->physblock); if (retval) return retval; if (!dontfill) { @@ -203,6 +204,12 @@ static errcode_t load_buffer(ext2_file_t file, int dontfill) memset(file->buf, 0, fs->blocksize); } file->flags |= EXT2_FILE_BUF_VALID; + if (file->flags & EXT2_FILE_SPARSE) { + if (file->physblock == 0 || + (ret_flags & BMAP_RET_UNINIT)) { + return EXT2_ET_READ_HOLE_FOUND; + } + } } return 0; }