From patchwork Mon Sep 15 18:39:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 4907351 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 20BE7BEEA6 for ; Mon, 15 Sep 2014 18:39:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1F70F201BF for ; Mon, 15 Sep 2014 18:39:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C8B932017D for ; Mon, 15 Sep 2014 18:39:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754383AbaIOSjl (ORCPT ); Mon, 15 Sep 2014 14:39:41 -0400 Received: from mail-qc0-f173.google.com ([209.85.216.173]:43120 "EHLO mail-qc0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753780AbaIOSjl (ORCPT ); Mon, 15 Sep 2014 14:39:41 -0400 Received: by mail-qc0-f173.google.com with SMTP id i8so4314836qcq.18 for ; Mon, 15 Sep 2014 11:39:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:cc:content-type; bh=WjoienQaP/Mnm3AHG/YpgKNeTboQrIcco2wg+cy28GU=; b=uG/I50813ytzOw0IdUYitkmh/U05GQ+xjq3aoFxGhxlCcEWsmlLcxe+tLZrlZjuL9T cqq6WzoWCkFxwcaVNFXxXldmcWQSbDJa3yE0yDy6M/xQwdT/QBLlmP9/TnmifxBGdrsy 7G4bMbbfs0yXh3m88eciGLwiDXqgiywoZfLGFM19zHUaUjpyDMZahB7P/GVkj91iz5Uv e5I4w1x2ukJFccneDhK/4QCBIyiubEYIC5jYK/x5/lw8wonD48I4CzHJ6ERUKsvSBcs2 8yZ2Mh4mJAYYNx151ehWs+Qe4gN5a1mSB7JZZ7bnKTICywtCCW/YMGKK1ssk5uTvZkQN 63wg== X-Received: by 10.140.97.247 with SMTP id m110mr39929819qge.80.1410806376867; Mon, 15 Sep 2014 11:39:36 -0700 (PDT) MIME-Version: 1.0 Received: by 10.140.32.116 with HTTP; Mon, 15 Sep 2014 11:39:16 -0700 (PDT) From: Steve French Date: Mon, 15 Sep 2014 13:39:16 -0500 Message-ID: Subject: [PATCH] [SMB3] Add mfsymlinks support for SMB2.1/SMB3. Part 1 create symlink To: "linux-cifs@vger.kernel.org" Cc: samba-technical , linux-fsdevel Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 Adds support on SMB2.1 and SMB3 mounts for emulation of symlinks via the "Minshall/French" symlink format already used for cifs mounts when mfsymlinks mount option is used (and also used by Apple). http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks This first patch adds support to create them. The next patch will add support for recognizing them and reading them. Although CIFS/SMB3 have other types of symlinks, in the many use cases they aren't practical (e.g. either require cifs only mounts with unix extensions to Samba, or require the user to be Administrator to Windows for SMB3). This also helps enable running additional xfstests over SMB3 (since some xfstests directly or indirectly require symlink support). Signed-off-by: Steve French CC: Stefan Metzmacher --- fs/cifs/link.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/smb2ops.c | 2 ++ fs/cifs/smb2proto.h | 4 +++- 3 files changed, 68 insertions(+), 1 deletion(-) __u32 *oplock, FILE_ALL_INFO *buf); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index a5c2812..11657f6 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -28,6 +28,7 @@ #include "cifsproto.h" #include "cifs_debug.h" #include "cifs_fs_sb.h" +#include "smb2proto.h" /* * M-F Symlink Functions - Begin @@ -398,6 +399,68 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, return rc; } +int +smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, const unsigned char *path, + char *pbuf, unsigned int *pbytes_written) +{ + int rc; + struct cifs_fid fid; + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms; + int create_options = CREATE_NOT_DIR; + __le16 *utf16_path; + __u8 oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; + struct kvec iov[2]; + + if (backup_cred(cifs_sb)) + create_options |= CREATE_OPEN_BACKUP_INTENT; + + cifs_dbg(FYI, "%s: path: %s\n", __func__, path); + + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); + if (!utf16_path) + return -ENOMEM; + + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; + oparms.create_options = create_options; + oparms.disposition = FILE_CREATE; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); + if (rc) { + kfree(utf16_path); + return rc; + } + + io_parms.netfid = fid.netfid; + io_parms.pid = current->tgid; + io_parms.tcon = tcon; + io_parms.offset = 0; + io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; + io_parms.persistent_fid = fid.persistent_fid; + io_parms.volatile_fid = fid.volatile_fid; + + /* iov[0] is reserved for smb header */ + iov[1].iov_base = pbuf; + iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE; + + rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1); + + /* Make sure we wrote all of the symlink data */ + if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE)) + rc = -EIO; + + SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); + + kfree(utf16_path); + return rc; +} + + /* * M-F Symlink Functions - End */ diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f522193..7d3fa29 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1452,6 +1452,7 @@ struct smb_version_operations smb21_operations = { .rename = smb2_rename_path, .create_hardlink = smb2_create_hardlink, .query_symlink = smb2_query_symlink, + .create_mf_symlink = smb3_create_mf_symlink, .open = smb2_open_file, .set_fid = smb2_set_fid, .close = smb2_close_file, @@ -1531,6 +1532,7 @@ struct smb_version_operations smb30_operations = { .rename = smb2_rename_path, .create_hardlink = smb2_create_hardlink, .query_symlink = smb2_query_symlink, + .create_mf_symlink = smb3_create_mf_symlink, .open = smb2_open_file, .set_fid = smb2_set_fid, .close = smb2_close_file, diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 67e8ce8..e144ecf 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -82,7 +82,9 @@ extern int smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon, extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, const char *from_name, const char *to_name, struct cifs_sb_info *cifs_sb); - +extern int smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, const unsigned char *path, + char *pbuf, unsigned int *pbytes_written); extern int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,