From patchwork Wed Nov 26 08:51:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Shilong X-Patchwork-Id: 5384371 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 83F469F39B for ; Wed, 26 Nov 2014 08:53:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9093220160 for ; Wed, 26 Nov 2014 08:53:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 70DFB2015A for ; Wed, 26 Nov 2014 08:53:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751781AbaKZIxI (ORCPT ); Wed, 26 Nov 2014 03:53:08 -0500 Received: from mail-pd0-f176.google.com ([209.85.192.176]:63049 "EHLO mail-pd0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751305AbaKZIxG (ORCPT ); Wed, 26 Nov 2014 03:53:06 -0500 Received: by mail-pd0-f176.google.com with SMTP id y10so2410037pdj.7 for ; Wed, 26 Nov 2014 00:53:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id; bh=12ZNu1eHLe/xqXR64/p7BUhYVvzJBnJNoCi9se+o7TU=; b=0U/gthRTEwQ8SGLkgMTONxyPwNZ3MwrFWT0IL/uTrO36TzjRu0KLC+zchlv7pJRxAq DBkWJ18In3+h05N3BUxVOotpuSbzX944OufpBiJgonphLroSjHKC8w122bvEP/yL5nzz pmZHeVA/bmhfO3PdERaF4/E8aNwrIpO68h2EK3bHrrqet93cBFd2kvuOKhohEbNamhlK TdIPJBC02NmZNzqGsyYrfQgJ0MLmuMfQNkjaOhUKNPIxQkPUfEsrnr3o7WVSIW1CPS1r r3YLTik2ditKOo2QmGdzlxvdlDwPT4uZTYp0Vi15mPwzFeRDB/kUWDcLpMdKNOp7NMkX 4lAg== X-Received: by 10.70.100.199 with SMTP id fa7mr51598020pdb.114.1416991985884; Wed, 26 Nov 2014 00:53:05 -0800 (PST) Received: from localhost.localdomain.localdomain ([112.23.171.71]) by mx.google.com with ESMTPSA id bn13sm3671603pdb.4.2014.11.26.00.53.04 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2014 00:53:05 -0800 (PST) From: Wang Shilong To: linux-btrfs@vger.kernel.org Subject: [PATCH v3] Btrfs: deal with all 'subvol=xxx' options once Date: Wed, 26 Nov 2014 16:51:29 +0800 Message-Id: <1416991889-8403-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: avoid loop way that David addressed. --- fs/btrfs/super.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 21c60ee..cac8e36 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; + len = strlen(args) + 1; + while (p) { + len += 2; + p = strchr(p, ','); + if (!p) + break; + p = strstr(p, "subvol="); + } + buf = dst = kmalloc(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);