Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Browse files Browse the repository at this point in the history
Pull CIFS updates from Steve French:
 "Includes a couple of fixes, plus changes to make multiplex identifiers
  easier to read and correlate with network traces, and a set of
  enhancements for SMB3 dialect.  Also adds support for per-file
  compression for both cifs and smb2/smb3 ("chattr +c filename).

  Should have at least one other merge request ready by next week with
  some new SMB3 security features and copy offload support"

* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6:
  Query network adapter info at mount time for debugging
  Fix unused variable warning when CIFS POSIX disabled
  Allow setting per-file compression via CIFS protocol
  Query File System Alignment
  Query device characteristics at mount time from server on SMB2/3 not just on cifs mounts
  cifs: Send a logoff request before removing a smb session
  cifs: Make big endian multiplex ID sequences monotonic on the wire
  cifs: Remove redundant multiplex identifier check from check_smb_hdr()
  Query file system attributes from server on SMB2, not just cifs, mounts
  Allow setting per-file compression via SMB2/3
  Fix corrupt SMB2 ioctl requests
  • Loading branch information
Linus Torvalds committed Nov 7, 2013
2 parents c224b76 + c481e9f commit 8efdf2b
Show file tree
Hide file tree
Showing 14 changed files with 464 additions and 57 deletions.
29 changes: 28 additions & 1 deletion fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ struct smb_version_operations {
/* set attributes */
int (*set_file_info)(struct inode *, const char *, FILE_BASIC_INFO *,
const unsigned int);
int (*set_compression)(const unsigned int, struct cifs_tcon *,
struct cifsFileInfo *);
/* check if we can send an echo or nor */
bool (*can_echo)(struct TCP_Server_Info *);
/* send echo request */
Expand Down Expand Up @@ -620,11 +622,34 @@ set_credits(struct TCP_Server_Info *server, const int val)
}

static inline __u64
get_next_mid(struct TCP_Server_Info *server)
get_next_mid64(struct TCP_Server_Info *server)
{
return server->ops->get_next_mid(server);
}

static inline __le16
get_next_mid(struct TCP_Server_Info *server)
{
__u16 mid = get_next_mid64(server);
/*
* The value in the SMB header should be little endian for easy
* on-the-wire decoding.
*/
return cpu_to_le16(mid);
}

static inline __u16
get_mid(const struct smb_hdr *smb)
{
return le16_to_cpu(smb->Mid);
}

static inline bool
compare_mid(__u16 mid, const struct smb_hdr *smb)
{
return mid == le16_to_cpu(smb->Mid);
}

/*
* When the server supports very large reads and writes via POSIX extensions,
* we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
Expand Down Expand Up @@ -828,6 +853,8 @@ struct cifs_tcon {
__u32 maximal_access;
__u32 vol_serial_number;
__le64 vol_create_time;
__u32 ss_flags; /* sector size flags */
__u32 perf_sector_size; /* best sector size for perf */
#endif /* CONFIG_CIFS_SMB2 */
#ifdef CONFIG_CIFS_FSCACHE
u64 resource_id; /* server resource id */
Expand Down
34 changes: 33 additions & 1 deletion fs/cifs/cifspdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ struct smb_hdr {
__u16 Tid;
__le16 Pid;
__u16 Uid;
__u16 Mid;
__le16 Mid;
__u8 WordCount;
} __attribute__((packed));

Expand Down Expand Up @@ -1352,6 +1352,35 @@ typedef struct smb_com_transaction_ioctl_req {
__u8 Data[1];
} __attribute__((packed)) TRANSACT_IOCTL_REQ;

typedef struct smb_com_transaction_compr_ioctl_req {
struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount;
__u16 Reserved;
__le32 TotalParameterCount;
__le32 TotalDataCount;
__le32 MaxParameterCount;
__le32 MaxDataCount;
__le32 ParameterCount;
__le32 ParameterOffset;
__le32 DataCount;
__le32 DataOffset;
__u8 SetupCount; /* four setup words follow subcommand */
/* SNIA spec incorrectly included spurious pad here */
__le16 SubCommand; /* 2 = IOCTL/FSCTL */
__le32 FunctionCode;
__u16 Fid;
__u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
__le16 ByteCount;
__u8 Pad[3];
__le16 compression_state; /* See below for valid flags */
} __attribute__((packed)) TRANSACT_COMPR_IOCTL_REQ;

/* compression state flags */
#define COMPRESSION_FORMAT_NONE 0x0000
#define COMPRESSION_FORMAT_DEFAULT 0x0001
#define COMPRESSION_FORMAT_LZNT1 0x0002

typedef struct smb_com_transaction_ioctl_rsp {
struct smb_hdr hdr; /* wct = 19 */
__u8 Reserved[3];
Expand Down Expand Up @@ -2215,6 +2244,9 @@ typedef struct {
__le32 DeviceCharacteristics;
} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */

/* minimum includes first three fields, and empty FS Name */
#define MIN_FS_ATTR_INFO_SIZE 12

typedef struct {
__le32 Attributes;
__le32 MaxPathNameComponentLength;
Expand Down
2 changes: 2 additions & 0 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
__u16 fid, char **symlinkinfo,
const struct nls_table *nls_codepage);
extern int CIFSSMB_set_compression(const unsigned int xid,
struct cifs_tcon *tcon, __u16 fid);
extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
const char *fileName, const int disposition,
const int access_flags, const int omode,
Expand Down
54 changes: 54 additions & 0 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3199,6 +3199,60 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
return rc;
}

int
CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
__u16 fid)
{
int rc = 0;
int bytes_returned;
struct smb_com_transaction_compr_ioctl_req *pSMB;
struct smb_com_transaction_ioctl_rsp *pSMBr;

cifs_dbg(FYI, "Set compression for %u\n", fid);
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;

pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);

pSMB->TotalParameterCount = 0;
pSMB->TotalDataCount = __constant_cpu_to_le32(2);
pSMB->MaxParameterCount = 0;
pSMB->MaxDataCount = 0;
pSMB->MaxSetupCount = 4;
pSMB->Reserved = 0;
pSMB->ParameterOffset = 0;
pSMB->DataCount = __constant_cpu_to_le32(2);
pSMB->DataOffset =
cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
compression_state) - 4); /* 84 */
pSMB->SetupCount = 4;
pSMB->SubCommand = __constant_cpu_to_le16(NT_TRANSACT_IOCTL);
pSMB->ParameterCount = 0;
pSMB->FunctionCode = __constant_cpu_to_le32(FSCTL_SET_COMPRESSION);
pSMB->IsFsctl = 1; /* FSCTL */
pSMB->IsRootFlag = 0;
pSMB->Fid = fid; /* file handle always le */
/* 3 byte pad, followed by 2 byte compress state */
pSMB->ByteCount = __constant_cpu_to_le16(5);
inc_rfc1001_len(pSMB, 5);

rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);

cifs_buf_release(pSMB);

/*
* Note: On -EAGAIN error only caller can retry on handle based calls
* since file handle passed in no longer valid.
*/
return rc;
}


#ifdef CONFIG_CIFS_POSIX

/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
Expand Down
25 changes: 20 additions & 5 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -2242,6 +2242,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)

spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
if (ses->status == CifsExiting)
continue;
if (!match_session(ses, vol))
continue;
++ses->ses_count;
Expand All @@ -2255,24 +2257,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
static void
cifs_put_smb_ses(struct cifs_ses *ses)
{
unsigned int xid;
unsigned int rc, xid;
struct TCP_Server_Info *server = ses->server;

cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);

spin_lock(&cifs_tcp_ses_lock);
if (ses->status == CifsExiting) {
spin_unlock(&cifs_tcp_ses_lock);
return;
}
if (--ses->ses_count > 0) {
spin_unlock(&cifs_tcp_ses_lock);
return;
}

list_del_init(&ses->smb_ses_list);
if (ses->status == CifsGood)
ses->status = CifsExiting;
spin_unlock(&cifs_tcp_ses_lock);

if (ses->status == CifsGood && server->ops->logoff) {
if (ses->status == CifsExiting && server->ops->logoff) {
xid = get_xid();
server->ops->logoff(xid, ses);
rc = server->ops->logoff(xid, ses);
if (rc)
cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
__func__, rc);
_free_xid(xid);
}

spin_lock(&cifs_tcp_ses_lock);
list_del_init(&ses->smb_ses_list);
spin_unlock(&cifs_tcp_ses_lock);

sesInfoFree(ses);
cifs_put_tcp_session(server);
}
Expand Down
57 changes: 38 additions & 19 deletions fs/cifs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* vfs operations that deal with io control
*
* Copyright (C) International Business Machines Corp., 2005,2007
* Copyright (C) International Business Machines Corp., 2005,2013
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -34,13 +34,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
int rc = -ENOTTY; /* strange error - but the precedent */
unsigned int xid;
struct cifs_sb_info *cifs_sb;
#ifdef CONFIG_CIFS_POSIX
struct cifsFileInfo *pSMBFile = filep->private_data;
struct cifs_tcon *tcon;
__u64 ExtAttrBits = 0;
__u64 ExtAttrMask = 0;
__u64 caps;
#endif /* CONFIG_CIFS_POSIX */

xid = get_xid();

Expand All @@ -49,43 +46,65 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
cifs_sb = CIFS_SB(inode->i_sb);

switch (command) {
#ifdef CONFIG_CIFS_POSIX
case FS_IOC_GETFLAGS:
if (pSMBFile == NULL)
break;
tcon = tlink_tcon(pSMBFile->tlink);
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
#ifdef CONFIG_CIFS_POSIX
if (CIFS_UNIX_EXTATTR_CAP & caps) {
__u64 ExtAttrMask = 0;
rc = CIFSGetExtAttr(xid, tcon,
pSMBFile->fid.netfid,
&ExtAttrBits, &ExtAttrMask);
if (rc == 0)
rc = put_user(ExtAttrBits &
FS_FL_USER_VISIBLE,
(int __user *)arg);
if (rc != EOPNOTSUPP)
break;
}
#endif /* CONFIG_CIFS_POSIX */
rc = 0;
if (CIFS_I(inode)->cifsAttrs & ATTR_COMPRESSED) {
/* add in the compressed bit */
ExtAttrBits = FS_COMPR_FL;
rc = put_user(ExtAttrBits & FS_FL_USER_VISIBLE,
(int __user *)arg);
}
break;

case FS_IOC_SETFLAGS:
if (pSMBFile == NULL)
break;
tcon = tlink_tcon(pSMBFile->tlink);
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
if (CIFS_UNIX_EXTATTR_CAP & caps) {
if (get_user(ExtAttrBits, (int __user *)arg)) {
rc = -EFAULT;
break;
}
/*
* rc = CIFSGetExtAttr(xid, tcon,
* pSMBFile->fid.netfid,
* extAttrBits,
* &ExtAttrMask);
*/

if (get_user(ExtAttrBits, (int __user *)arg)) {
rc = -EFAULT;
break;
}

/*
* if (CIFS_UNIX_EXTATTR_CAP & caps)
* rc = CIFSSetExtAttr(xid, tcon,
* pSMBFile->fid.netfid,
* extAttrBits,
* &ExtAttrMask);
* if (rc != EOPNOTSUPP)
* break;
*/

/* Currently only flag we can set is compressed flag */
if ((ExtAttrBits & FS_COMPR_FL) == 0)
break;

/* Try to set compress flag */
if (tcon->ses->server->ops->set_compression) {
rc = tcon->ses->server->ops->set_compression(
xid, tcon, pSMBFile);
cifs_dbg(FYI, "set compress flag rc %d\n", rc);
}
cifs_dbg(FYI, "set flags not implemented yet\n");
break;
#endif /* CONFIG_CIFS_POSIX */
default:
cifs_dbg(FYI, "unsupported ioctl\n");
break;
Expand Down
Loading

0 comments on commit 8efdf2b

Please sign in to comment.