summaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 15:27:35 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 15:27:35 -0700
commit797b9e5ae93270ec27a1f1ed48cd697d01b2269f (patch)
tree4e44ba1535a243e834bc7268486efcf83ba4e6cd /fs/cifs/smb2inode.c
parent9c0ece069b32e8e122aea71aa47181c10eb85ba7 (diff)
parent1d4ab9077681b7cce60ff46e3a42fe2dafa0b83d (diff)
downloadlinux-797b9e5ae93270ec27a1f1ed48cd697d01b2269f.tar.bz2
Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS updates from Steve French: "This patchset is the final section of the SMB2.1 support merge for cifs.ko. It also includes improvements to the cifs socket handling from Jeff, and also fixes a few cifs bug fixes. It adds SMB2 support for file and inode operations as well as moves some existing cifs code to use ops server struct of protocol specific callbacks. Most of this code is SMB2 specific. When enabled SMB2.1 does pass various functional tests including most of the connectathon test suite, For SMB2.1, Connectathon test 4 and some related tests fail due to not updating mode bits remotely (cifsacl support where mode bits are approximated with the cifs acl is not enable for smb2), and test8 (symlink) support is not completed for SMB2 yet (note that we will likely have a "Unix Extensions" eventually, at least for Samba, so in the long run posix locks won't have to be emulated when mounting Linux to Linux, but for most NAS and for Windows mounts posix lock emulation will still used for SMB2 in a similar fashion as we do for cifs). SMB2.1 dialect is supported. Although additional fixes to enable smb2 (the original smb2.02) dialect and to add various optional features of the smb3 dialect are expected to be added in the future as testing progresses, currently mounting with the "vers=2.1" is supported (in order to mount using SMB2.1 to servers like Samba 4, and Windows 7, Windows 2008R2)." * 'for-linus' of git://git.samba.org/sfrench/cifs-2.6: (82 commits) [CIFS] Fix indentation of fs/cifs/Kconfig entries [CIFS] Fix SMB2 negotiation support to select only one dialect (based on vers=) cifs: obtain file access during backup intent lookup (resend) CIFS: Fix possible freed pointer dereference in CIFS_SessSetup CIFS: Fix possible freed pointer dereference in SMB2_sess_setup CIFS: Make ops->close return void cifs: change DOS/NT/POSIX mapping of ERRnoresource cifs: remove support for deprecated "forcedirectio" and "strictcache" mount options cifs: remove support for CIFS_IOC_CHECKUMOUNT ioctl CIFS: Fix possible memory leaks in SMB2 code CIFS: Fix endian conversion of IndexNumber Trivial endian fixes MARK SMB2 support EXPERIMENTAL Update cifs version number cifs: add FL_CLOSE to fl_flags mask in cifs_read_flock cifs: Mangle string used for unc in /proc/mounts cifs: cleanups for cifs_mkdir_qinfo CIFS: Fix fast lease break after open problem CIFS: Add SMB2.1 lease break support CIFS: Fix cache coherency for read oplock case ...
Diffstat (limited to 'fs/cifs/smb2inode.c')
-rw-r--r--fs/cifs/smb2inode.c98
1 files changed, 96 insertions, 2 deletions
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 2aa5cb08c526..706482452df4 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -47,6 +47,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
int rc, tmprc = 0;
u64 persistent_fid, volatile_fid;
__le16 *utf16_path;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
if (!utf16_path)
@@ -54,7 +55,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
desired_access, create_disposition, file_attributes,
- create_options);
+ create_options, &oplock, NULL);
if (rc) {
kfree(utf16_path);
return rc;
@@ -74,6 +75,22 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
* SMB2_open() call.
*/
break;
+ case SMB2_OP_RENAME:
+ tmprc = SMB2_rename(xid, tcon, persistent_fid, volatile_fid,
+ (__le16 *)data);
+ break;
+ case SMB2_OP_HARDLINK:
+ tmprc = SMB2_set_hardlink(xid, tcon, persistent_fid,
+ volatile_fid, (__le16 *)data);
+ break;
+ case SMB2_OP_SET_EOF:
+ tmprc = SMB2_set_eof(xid, tcon, persistent_fid, volatile_fid,
+ current->tgid, (__le64 *)data);
+ break;
+ case SMB2_OP_SET_INFO:
+ tmprc = SMB2_set_info(xid, tcon, persistent_fid, volatile_fid,
+ (FILE_BASIC_INFO *)data);
+ break;
default:
cERROR(1, "Invalid command");
break;
@@ -86,7 +103,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
return rc;
}
-static void
+void
move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
{
memcpy(dst, src, (size_t)(&src->CurrentByteOffset) - (size_t)src);
@@ -161,3 +178,80 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
0, CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
NULL, SMB2_OP_DELETE);
}
+
+int
+smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *cifs_sb)
+{
+ return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
+ 0, CREATE_DELETE_ON_CLOSE, NULL,
+ SMB2_OP_DELETE);
+}
+
+static int
+smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb, __u32 access, int command)
+{
+ __le16 *smb2_to_name = NULL;
+ int rc;
+
+ smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
+ if (smb2_to_name == NULL) {
+ rc = -ENOMEM;
+ goto smb2_rename_path;
+ }
+
+ rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access,
+ FILE_OPEN, 0, 0, smb2_to_name, command);
+smb2_rename_path:
+ kfree(smb2_to_name);
+ return rc;
+}
+
+int
+smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb)
+{
+ return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
+ DELETE, SMB2_OP_RENAME);
+}
+
+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)
+{
+ return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
+ FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK);
+}
+
+int
+smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *full_path, __u64 size,
+ struct cifs_sb_info *cifs_sb, bool set_alloc)
+{
+ __le64 eof = cpu_to_le64(size);
+ return smb2_open_op_close(xid, tcon, cifs_sb, full_path,
+ FILE_WRITE_DATA, FILE_OPEN, 0, 0, &eof,
+ SMB2_OP_SET_EOF);
+}
+
+int
+smb2_set_file_info(struct inode *inode, const char *full_path,
+ FILE_BASIC_INFO *buf, const unsigned int xid)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink;
+ int rc;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path,
+ FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, 0, buf,
+ SMB2_OP_SET_INFO);
+ cifs_put_tlink(tlink);
+ return rc;
+}