aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2014-09-15 05:49:28 -0400
committerSteve French <smfrench@gmail.com>2014-10-16 16:20:20 -0400
commit5ab97578cbb3bf9a28dec4534cb86fbc35e600bb (patch)
tree1eaf7d9abbf28446519f3a4196fa4835da9286ec /fs/cifs
parentdb8b631d4bc4eaa9f7e13a6b0a287306cac0cb72 (diff)
Add mfsymlinks support for SMB2.1/SMB3. Part 1 create symlink
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 <smfrench@gmail.com> CC: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/link.c63
-rw-r--r--fs/cifs/smb2ops.c2
-rw-r--r--fs/cifs/smb2proto.h4
3 files changed, 68 insertions, 1 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 5657416d3483..1216f4f1c6c9 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -28,6 +28,7 @@
28#include "cifsproto.h" 28#include "cifsproto.h"
29#include "cifs_debug.h" 29#include "cifs_debug.h"
30#include "cifs_fs_sb.h" 30#include "cifs_fs_sb.h"
31#include "smb2proto.h"
31 32
32/* 33/*
33 * M-F Symlink Functions - Begin 34 * M-F Symlink Functions - Begin
@@ -400,6 +401,68 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
400 return rc; 401 return rc;
401} 402}
402 403
404int
405smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
406 struct cifs_sb_info *cifs_sb, const unsigned char *path,
407 char *pbuf, unsigned int *pbytes_written)
408{
409 int rc;
410 struct cifs_fid fid;
411 struct cifs_open_parms oparms;
412 struct cifs_io_parms io_parms;
413 int create_options = CREATE_NOT_DIR;
414 __le16 *utf16_path;
415 __u8 oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
416 struct kvec iov[2];
417
418 if (backup_cred(cifs_sb))
419 create_options |= CREATE_OPEN_BACKUP_INTENT;
420
421 cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
422
423 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
424 if (!utf16_path)
425 return -ENOMEM;
426
427 oparms.tcon = tcon;
428 oparms.cifs_sb = cifs_sb;
429 oparms.desired_access = GENERIC_WRITE;
430 oparms.create_options = create_options;
431 oparms.disposition = FILE_CREATE;
432 oparms.fid = &fid;
433 oparms.reconnect = false;
434
435 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
436 if (rc) {
437 kfree(utf16_path);
438 return rc;
439 }
440
441 io_parms.netfid = fid.netfid;
442 io_parms.pid = current->tgid;
443 io_parms.tcon = tcon;
444 io_parms.offset = 0;
445 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
446 io_parms.persistent_fid = fid.persistent_fid;
447 io_parms.volatile_fid = fid.volatile_fid;
448
449 /* iov[0] is reserved for smb header */
450 iov[1].iov_base = pbuf;
451 iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
452
453 rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
454
455 /* Make sure we wrote all of the symlink data */
456 if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
457 rc = -EIO;
458
459 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
460
461 kfree(utf16_path);
462 return rc;
463}
464
465
403/* 466/*
404 * M-F Symlink Functions - End 467 * M-F Symlink Functions - End
405 */ 468 */
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index ea158c9dea15..5e35d51504fd 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1452,6 +1452,7 @@ struct smb_version_operations smb21_operations = {
1452 .rename = smb2_rename_path, 1452 .rename = smb2_rename_path,
1453 .create_hardlink = smb2_create_hardlink, 1453 .create_hardlink = smb2_create_hardlink,
1454 .query_symlink = smb2_query_symlink, 1454 .query_symlink = smb2_query_symlink,
1455 .create_mf_symlink = smb3_create_mf_symlink,
1455 .open = smb2_open_file, 1456 .open = smb2_open_file,
1456 .set_fid = smb2_set_fid, 1457 .set_fid = smb2_set_fid,
1457 .close = smb2_close_file, 1458 .close = smb2_close_file,
@@ -1531,6 +1532,7 @@ struct smb_version_operations smb30_operations = {
1531 .rename = smb2_rename_path, 1532 .rename = smb2_rename_path,
1532 .create_hardlink = smb2_create_hardlink, 1533 .create_hardlink = smb2_create_hardlink,
1533 .query_symlink = smb2_query_symlink, 1534 .query_symlink = smb2_query_symlink,
1535 .create_mf_symlink = smb3_create_mf_symlink,
1534 .open = smb2_open_file, 1536 .open = smb2_open_file,
1535 .set_fid = smb2_set_fid, 1537 .set_fid = smb2_set_fid,
1536 .close = smb2_close_file, 1538 .close = smb2_close_file,
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 67e8ce8055de..e144ecfaa797 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,
82extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, 82extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
83 const char *from_name, const char *to_name, 83 const char *from_name, const char *to_name,
84 struct cifs_sb_info *cifs_sb); 84 struct cifs_sb_info *cifs_sb);
85 85extern int smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
86 struct cifs_sb_info *cifs_sb, const unsigned char *path,
87 char *pbuf, unsigned int *pbytes_written);
86extern int smb2_open_file(const unsigned int xid, 88extern int smb2_open_file(const unsigned int xid,
87 struct cifs_open_parms *oparms, 89 struct cifs_open_parms *oparms,
88 __u32 *oplock, FILE_ALL_INFO *buf); 90 __u32 *oplock, FILE_ALL_INFO *buf);