From patchwork Wed Dec 3 18:42:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Shilong X-Patchwork-Id: 5432751 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7CA019F319 for ; Wed, 3 Dec 2014 18:44:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E99402022A for ; Wed, 3 Dec 2014 18:44:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1A88A200E0 for ; Wed, 3 Dec 2014 18:44:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751241AbaLCSoK (ORCPT ); Wed, 3 Dec 2014 13:44:10 -0500 Received: from mail-pa0-f46.google.com ([209.85.220.46]:35517 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750798AbaLCSoJ (ORCPT ); Wed, 3 Dec 2014 13:44:09 -0500 Received: by mail-pa0-f46.google.com with SMTP id lj1so16310469pab.33 for ; Wed, 03 Dec 2014 10:44:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=T5VZL3OFZZY+3dUv5cbyvDahxbDbL35qFVlI38PpTE8=; b=ukI3T6xjL6RrY3Sp5g1eBk3nSph/2+PdAp11rMigG96siiyaM52Ytqri1ToWwUxieK lBfkS4HpJGKayOBQ6ZqmeocunHmdNgRjWeD7RlWmqDXlk7CkwcM8NUgHKUEbmSYkPCbI bSuzcT/91u1eycWw8YPHchuPttZesCd/Rch60aKNh35ZOropgITCrydaTKywwu6hZlPN zO3HBzyXvRWAEGsmZhfxRv0lKyKysgZ+lftzJzGm4YhFOFE+hJJURYxX+WLwwrDQw+5E bIsY7hJwDwq4Dp431Bic/U1Sncy8Id6tzo0m0fidgMDgvBNVC2eSh5N1R5/Cs7KeNaKq nzrA== X-Received: by 10.68.203.161 with SMTP id kr1mr18772933pbc.78.1417632249177; Wed, 03 Dec 2014 10:44:09 -0800 (PST) Received: from localhost.localdomain.localdomain ([112.21.55.126]) by mx.google.com with ESMTPSA id pd9sm23714667pbb.7.2014.12.03.10.44.07 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 03 Dec 2014 10:44:08 -0800 (PST) From: Wang Shilong To: linux-btrfs@vger.kernel.org Cc: dsterba@suse.cz Subject: [PATCH v4] Btrfs: deal with all 'subvol=xxx' options once Date: Thu, 4 Dec 2014 02:42:21 +0800 Message-Id: <1417632141-26815-1-git-send-email-wangshilong1991@gmail.com> X-Mailer: git-send-email 1.7.12.4 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Steps to reproduce: # mkfs.btrfs -f /dev/sdb # mount -t btrfs /dev/sdb /mnt # btrfs sub create /mnt/dir # mount -t btrfs /dev/sdb /mnt -o subvol=dir,subvol=dir It fails with: mount: mount(2) failed: No such file or directory Btrfs deal with subvolume mounting in a recursive way, to avoid looping, it will stripe out 'subvol=xxxx' string, then next loop will stop.Problem here is it only deal one string once, if users specify mount option multiple times. It will loop several times which is not good, and above reproducing steps will also return confusing results. Fix this problem by striping out all 'subvol=xxx' options, only last is valid. Signed-off-by: Wang Shilong --- v3->v4: zero buffer to make sure strncat() work... --- fs/btrfs/super.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 21c60ee..cf3faf5 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1117,44 +1117,50 @@ static inline int is_subvolume_inode(struct inode *inode) */ static char *setup_root_args(char *args) { - unsigned len = strlen(args) + 2 + 1; - char *src, *dst, *buf; + unsigned len; + char *src = args; + char *p = args; + char *dst, *buf; /* * We need the same args as before, but with this substitution: * s!subvol=[^,]+!subvolid=0! * * Since the replacement string is up to 2 bytes longer than the - * original, allocate strlen(args) + 2 + 1 bytes. + * original, allocate strlen(args) + 2 * N + 1 bytes. */ - - src = strstr(args, "subvol="); + p = strstr(src, "subvol="); /* This shouldn't happen, but just in case.. */ - if (!src) + if (!p) return NULL; - buf = dst = kmalloc(len, GFP_NOFS); + len = strlen(args) + 1; + while (p) { + len += 2; + p = strchr(p, ','); + if (!p) + break; + p = strstr(p, "subvol="); + } + + buf = dst = kzalloc(len, GFP_NOFS); if (!buf) return NULL; - /* - * If the subvol= arg is not at the start of the string, - * copy whatever precedes it into buf. - */ - if (src != args) { - *src++ = '\0'; - strcpy(buf, args); - dst += strlen(args); + /* loop and replace all subvol=xxx string */ + while ((p = strstr(src, "subvol="))) { + strncat(dst, src, p - src); + dst += p - src; + strcpy(dst, "subvolid=0"); + dst += strlen("subvolid=0"); + src = p = strchr(p, ','); + if (!src) + break; } - - strcpy(dst, "subvolid=0"); - dst += strlen("subvolid=0"); - /* * If there is a "," after the original subvol=... string, * copy that suffix into our buffer. Otherwise, we're done. */ - src = strchr(src, ','); if (src) strcpy(dst, src);