From patchwork Sat Mar 31 23:17:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 893896 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ofMR8Rfs"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40DDsp1kfGz9s19 for ; Sun, 1 Apr 2018 09:17:33 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752268AbeCaXRc (ORCPT ); Sat, 31 Mar 2018 19:17:32 -0400 Received: from mail-pl0-f47.google.com ([209.85.160.47]:46350 "EHLO mail-pl0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752247AbeCaXRb (ORCPT ); Sat, 31 Mar 2018 19:17:31 -0400 Received: by mail-pl0-f47.google.com with SMTP id 60-v6so72240plc.13 for ; Sat, 31 Mar 2018 16:17:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=M8OFevl0TM4V/ixGcBigCrsoK4vxdWMkE6weUY19FYQ=; b=ofMR8RfsDr6qnxYLkTbPDv4tiOmeiUY1eRsFQ8XxgO1xUCthqhMIZ6HyCaEvvgI5nR OGUK1nE0Q6SfHQ3EqkXwlCVkVq+F3fVl+6pYuXiwuynBhqK7uS7/KEvtgU9OPCuDRcUB hh93RGimyqHEIRDiRkFnhpXqhx3HVUuEWCH2ZupFF5bHWDwP+l2dJau09TrQFOJKaySt MqxP3vld6QhbKSOhC9PaAlgL7A0Vt1i8CeTFDFLHbwDvcQJpjov8rSR8pA7HnBLiyWd+ I2DqGGZXDuZCzeZSrk/nygE3vnrJdNpuJE/Ro3dQhz6UbtuGISG2UqwfgtWAnGmnS/oQ FYKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=M8OFevl0TM4V/ixGcBigCrsoK4vxdWMkE6weUY19FYQ=; b=Mpl6vcI+0E0yQEECDsDPtWPjTnXe02BhjwGvmesBBQlEbRbOHLdNpI+0Q7In4o4+6B oWDevzq9AmGw0zaEiMyWZ3tyTnmkPX4rqCzUAFXhheP11lrZnBHwZxdRk9wng/R5vdCJ PqK+qhr+4/VIQW7Am7Z/g7jqFfqmp80el2iv2/x9JGBmSKytQIvJ/LVkTVpAo8YdP5KI +5l4eVcsOuOHiw9Krn+efTN7Uf4od8CZqogUpnuHdqmkqHnVUnrbqPuDYwMNakPZDGxL mrYKkCDQK4UlYn1IZBikOxaq9MnTv3gYenk740Z5xSZivVwvZY5gOQjCNnTo+DEjUahe IQrQ== X-Gm-Message-State: AElRT7HqRLLyciByd6K7H+af6m+1pMBmQUfUtzkgU2fvUGKywOmFRR1U i+18M+5drE5+8gOeyOfB5IBxZsR9lCxD1E5KuxN8og== X-Google-Smtp-Source: AIpwx4+WWV4Qy6YHj37Glj5fjuWOyjqVnQMW38PWmjUcejnZo07wi8+lc2jMBKlaD82xIs315W4rBa+yj4O1FDNP7/8= X-Received: by 2002:a17:902:1006:: with SMTP id b6-v6mr4468296pla.252.1522538250513; Sat, 31 Mar 2018 16:17:30 -0700 (PDT) MIME-Version: 1.0 Received: by 10.100.152.97 with HTTP; Sat, 31 Mar 2018 16:17:09 -0700 (PDT) From: Steve French Date: Sat, 31 Mar 2018 18:17:09 -0500 Message-ID: Subject: [SMB3][PATCH] Fake an inode number when server returns inode number zero for the root To: CIFS Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Some servers return inode number zero for the root (ok for all other inodes), if so we need to create a non-zero hash instead for it and use that. Reviewed-by: Pavel Shilovsky From 773dc281d36640be88a43194d8f3b799436999fe Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 31 Mar 2018 18:13:38 -0500 Subject: [PATCH] [SMB3] Fix root directory when server returns inode number of zero Some servers return inode number zero for the root directory, which causes ls to display incorrect data (missing "." and ".."). If the server returns zero for the inode number of the root directory, fake an inode number for it. Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 2 ++ fs/cifs/inode.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 3e3f86841372..4c6953705eb0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1240,6 +1240,7 @@ struct cifsInodeInfo { #define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */ #define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */ #define CIFS_INO_LOCK (5) /* lock bit for synchronization */ +#define CIFS_FAKE_ROOT_INODE_NUM (6) /* inode has fake inode number */ unsigned long flags; spinlock_t writers_lock; unsigned int writers; /* Number of writers on this inode */ @@ -1470,6 +1471,7 @@ struct dfs_info3_param { #define CIFS_FATTR_NEED_REVAL 0x4 #define CIFS_FATTR_INO_COLLISION 0x8 #define CIFS_FATTR_UNKNOWN_NLINK 0x10 +#define CIFS_FATTR_FAKE_ROOT_INO 0x20 struct cifs_fattr { u32 cf_flags; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index c98a852180b1..2f97f4f75d7d 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -707,6 +707,18 @@ cifs_get_file_info(struct file *filp) return rc; } +/* Simple function to return a 64 bit hash of string. Rarely called */ +static __u64 simple_hashstr(const char *str) +{ + const __u64 hash_mult = 1125899906842597; /* a big enough prime */ + __u64 hash = 0; + + while (*str) + hash = (hash + (__u64) *str++) * hash_mult; + + return hash; +} + int cifs_get_inode_info(struct inode **inode, const char *full_path, FILE_ALL_INFO *data, struct super_block *sb, int xid, @@ -816,6 +828,14 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, tmprc); fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); + } else if ((fattr.cf_uniqueid == 0) && + strlen(full_path) == 0) { + /* some servers ret bad root ino ie 0 */ + cifs_dbg(FYI, "Invalid (0) inodenum\n"); + fattr.cf_flags |= + CIFS_FATTR_FAKE_ROOT_INO; + fattr.cf_uniqueid = + simple_hashstr(tcon->treeName); } } } else @@ -832,6 +852,16 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, &fattr.cf_uniqueid, data); if (tmprc) fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; + else if ((fattr.cf_uniqueid == 0) && + strlen(full_path) == 0) { + /* + * Reuse existing root inode num since + * inum zero for root causes ls of . and .. to + * not be returned + */ + cifs_dbg(FYI, "Srv ret 0 inode num for root\n"); + fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; + } } else fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; } @@ -893,6 +923,9 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, } cgii_exit: + if (inode && ((*inode)->i_ino == 0)) + cifs_dbg(FYI, "inode number of zero returned\n"); + kfree(buf); cifs_put_tlink(tlink); return rc; @@ -987,6 +1020,8 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) cifs_fattr_to_inode(inode, fattr); if (sb->s_flags & SB_NOATIME) inode->i_flags |= S_NOATIME | S_NOCMTIME; + if (fattr->cf_flags & CIFS_FATTR_FAKE_ROOT_INO) + set_bit(CIFS_FAKE_ROOT_INODE_NUM, &CIFS_I(inode)->flags); if (inode->i_state & I_NEW) { inode->i_ino = hash; #ifdef CONFIG_CIFS_FSCACHE -- 2.14.1