From patchwork Thu Jul 31 06:58:52 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pu Hou X-Patchwork-Id: 375146 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 0ECAD140179 for ; Thu, 31 Jul 2014 16:59:01 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753711AbaGaG7A (ORCPT ); Thu, 31 Jul 2014 02:59:00 -0400 Received: from m12-17.163.com ([220.181.12.17]:58086 "EHLO m12-17.163.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752901AbaGaG67 (ORCPT ); Thu, 31 Jul 2014 02:58:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-Id; bh=343TK/e+53LkDyRoJ6 c43g7q5+yzJEj8gPBJUcteew8=; b=Cm5W8O8AH3h/dB9AFfKI3qBscEmzWReDeW QTWmvSr+xNZ/UVwtvj+GN4GEm3d/pv0PoQlpmNsXpAd7eVzQv4ubEgBfDXBAbhHL gOpKAssn4LNSYt0H9Qct5lv+t1+3HRF6bOMluENlQQ+9NshzDomxtBpjXC74c5QL +WhgBaUDE= Received: from localhost (unknown [182.92.253.16]) by smtp13 (Coremail) with SMTP id EcCowEApHgsu6dlTODjLBg--.403S2; Thu, 31 Jul 2014 14:58:55 +0800 (CST) From: Pu Hou To: linux-ext4@vger.kernel.org Cc: boyu.mt@taobao.com, wenqing.lz@taobao.com, Pu Hou Subject: [PATCH] debugfs: Add inline data feature for symlink. Date: Thu, 31 Jul 2014 14:58:52 +0800 Message-Id: <1406789932-13770-1-git-send-email-houpu.hp@alibaba-inc.com> X-Mailer: git-send-email 1.9.1 X-CM-TRANSID: EcCowEApHgsu6dlTODjLBg--.403S2 X-Coremail-Antispam: 1Uf129KBjvJXoW3Ary7XF4fKF4rKw1DtF4Dtwb_yoW7Cw4DpF 1UJF98Wr4UGFyI9FWSyw4jqr1Sg3WI9rs8uFWxKFn5Aa43X34fKF4rJFy3JFyUtr4vy34j grW2yF1UurnxJrJanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jM1v-UUUUU= X-Originating-IP: [182.92.253.16] X-CM-SenderInfo: hvwd21qrsyqiywtou0bp/1tbiDRHZg1D+QKGEGQAAsU Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Symlink in debugfs can take advantage of inline data feature. The path name of the target of the symbol link which is longer than 60 byte and shorter than 132 byte can stay in inline data area. Signed-off-by: Pu Hou --- lib/ext2fs/ext2fs.h | 3 +++ lib/ext2fs/inline_data.c | 26 +++++++++++++++++++++++ lib/ext2fs/symlink.c | 55 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 7812956..8268d96 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -1401,6 +1401,9 @@ extern errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino, extern errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, void *buf, size_t size); +extern errcode_t ext2fs_symlink_inline_data_set(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + void *buf, size_t size); /* inode.c */ extern errcode_t ext2fs_create_inode_cache(ext2_filsys fs, diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c index 19248a0..ed82a32 100644 --- a/lib/ext2fs/inline_data.c +++ b/lib/ext2fs/inline_data.c @@ -585,6 +585,32 @@ errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino, return ext2fs_inline_data_ea_set(&data); } +errcode_t ext2fs_symlink_inline_data_set(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + void *buf, size_t size) +{ + struct ext2_inode inode_buf; + struct ext2_inline_data data; + errcode_t retval; + size_t free_ea_size, existing_size, free_inode_size; + + if (!inode) { + retval = ext2fs_read_inode(fs, ino, &inode_buf); + if (retval) + return retval; + inode = &inode_buf; + } + memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE); + retval = ext2fs_write_inode(fs, ino, inode); + if (retval) + return retval; + data.fs = fs; + data.ino = ino; + data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE; + data.ea_data = buf + EXT4_MIN_INLINE_DATA_SIZE; + return ext2fs_inline_data_ea_set(&data); +} + #ifdef DEBUG #include "e2p/e2p.h" diff --git a/lib/ext2fs/symlink.c b/lib/ext2fs/symlink.c index ba8ed8e..a31912d 100644 --- a/lib/ext2fs/symlink.c +++ b/lib/ext2fs/symlink.c @@ -27,6 +27,7 @@ #include "ext2_fs.h" #include "ext2fs.h" +#include "ext2_ext_attr.h" errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, const char *name, char *target) @@ -36,6 +37,8 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, ext2_ino_t scratch_ino; blk64_t blk; int fastlink; + int inline_link = 0; + int max_inline; unsigned int target_len; char *block_buf = 0; @@ -53,12 +56,27 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, */ fastlink = (target_len < sizeof(inode.i_block)); if (!fastlink) { - retval = ext2fs_new_block2(fs, 0, 0, &blk); - if (retval) - goto cleanup; - retval = ext2fs_get_mem(fs->blocksize, &block_buf); - if (retval) - goto cleanup; + if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, + EXT4_FEATURE_INCOMPAT_INLINE_DATA)) { + /* whether target string can be stored + in inline data area */ + max_inline = EXT2_INODE_SIZE(fs->super) - + sizeof(struct ext2_inode_large)- + sizeof(__u32)- + sizeof(struct ext2_ext_attr_entry)- + strlen("data")- + sizeof(__u32)+ + EXT4_MIN_INLINE_DATA_SIZE; + inline_link = (target_len < max_inline); + } + if (!inline_link) { + retval = ext2fs_new_block2(fs, 0, 0, &blk); + if (retval) + goto cleanup; + retval = ext2fs_get_mem(fs->blocksize, &block_buf); + if (retval) + goto cleanup; + } } /* @@ -77,7 +95,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, memset(&inode, 0, sizeof(struct ext2_inode)); inode.i_mode = LINUX_S_IFLNK | 0777; inode.i_uid = inode.i_gid = 0; - ext2fs_iblk_set(fs, &inode, fastlink ? 0 : 1); + ext2fs_iblk_set(fs, &inode, (fastlink || inline_link) ? 0 : 1); inode.i_links_count = 1; ext2fs_inode_size_set(fs, &inode, target_len); /* The time fields are set by ext2fs_write_new_inode() */ @@ -85,6 +103,8 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, if (fastlink) { /* Fast symlinks, target stored in inode */ strcpy((char *)&inode.i_block, target); + } else if (inline_link) { + inode.i_flags |= EXT4_INLINE_DATA_FL; } else { /* Slow symlinks, target stored in the first block */ memset(block_buf, 0, fs->blocksize); @@ -109,14 +129,19 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, goto cleanup; if (!fastlink) { - retval = ext2fs_bmap2(fs, ino, &inode, NULL, BMAP_SET, 0, NULL, - &blk); - if (retval) - goto cleanup; + if (inline_link) { + retval = ext2fs_symlink_inline_data_set(fs, ino, 0, + target, target_len); + } else { + retval = ext2fs_bmap2(fs, ino, &inode, NULL, + BMAP_SET, 0, NULL, &blk); + if (retval) + goto cleanup; - retval = io_channel_write_blk64(fs->io, blk, 1, block_buf); - if (retval) - goto cleanup; + retval = io_channel_write_blk64(fs->io, blk, 1, block_buf); + if (retval) + goto cleanup; + } } /* @@ -139,7 +164,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, /* * Update accounting.... */ - if (!fastlink) + if ((!fastlink) && (!inline_link)) ext2fs_block_alloc_stats2(fs, blk, +1); ext2fs_inode_alloc_stats2(fs, ino, +1, 0);