diff options
-rw-r--r-- | fs/cifs/link.c | 63 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 4 |
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 | ||
404 | int | ||
405 | smb3_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, | |||
82 | extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, | 82 | extern 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 | 85 | extern 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); | ||
86 | extern int smb2_open_file(const unsigned int xid, | 88 | extern 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); |