Commit 493c848b authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://cifs.bkbits.net/linux-2.5cifs

into home.osdl.org:/home/torvalds/v2.5/linux
parents 3aa4ac18 498af5e3
Version 0.89
------------
Fix oops on write to dead tcp session. Remove error log write for case when file open
O_CREAT but not O_EXCL
Version 0.88
------------
Fix non-POSIX behavior on rename of open file and delete of open file by taking
advantage of trans2 SetFileInfo rename facility if available on target server.
Retry on ENOSPC and EAGAIN socket errors.
Version 0.87 Version 0.87
------------ ------------
Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
......
...@@ -197,6 +197,8 @@ static read_proc_t ntlmv2_enabled_read; ...@@ -197,6 +197,8 @@ static read_proc_t ntlmv2_enabled_read;
static write_proc_t ntlmv2_enabled_write; static write_proc_t ntlmv2_enabled_write;
static read_proc_t packet_signing_enabled_read; static read_proc_t packet_signing_enabled_read;
static write_proc_t packet_signing_enabled_write; static write_proc_t packet_signing_enabled_write;
static read_proc_t quotaEnabled_read;
static write_proc_t quotaEnabled_write;
void void
cifs_proc_init(void) cifs_proc_init(void)
...@@ -233,6 +235,11 @@ cifs_proc_init(void) ...@@ -233,6 +235,11 @@ cifs_proc_init(void)
if (pde) if (pde)
pde->write_proc = oplockEnabled_write; pde->write_proc = oplockEnabled_write;
pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
quotaEnabled_read, 0);
if (pde)
pde->write_proc = quotaEnabled_write;
pde = pde =
create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs, create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
multiuser_mount_read, 0); multiuser_mount_read, 0);
...@@ -361,6 +368,47 @@ oplockEnabled_write(struct file *file, const char *buffer, ...@@ -361,6 +368,47 @@ oplockEnabled_write(struct file *file, const char *buffer,
return count; return count;
} }
static int
quotaEnabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", quotaEnabled);
/* could also check if quotas are enabled in kernel
as a whole first */
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int
quotaEnabled_write(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char c;
int rc;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
quotaEnabled = 0;
else if (c == '1' || c == 'y' || c == 'Y')
quotaEnabled = 1;
return count;
}
static int static int
lookupFlag_read(char *page, char **start, off_t off, lookupFlag_read(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
......
...@@ -94,9 +94,14 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, ...@@ -94,9 +94,14 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
if (cifs_pdu->Command == SMB_COM_NEGOTIATE) if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
return 0; return 0;
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
return 0;
}
/* BB what if signatures are supposed to be on for session but server does not /* BB what if signatures are supposed to be on for session but server does not
send one? BB */ send one? BB */
/* BB also do not verify oplock breaks for signature */
/* Do not need to verify session setups with signature "BSRSPYL " */ /* Do not need to verify session setups with signature "BSRSPYL " */
if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0) if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
......
...@@ -42,12 +42,17 @@ ...@@ -42,12 +42,17 @@
#include <linux/mm.h> #include <linux/mm.h>
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of all SMB PDUs */ #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of all SMB PDUs */
#ifdef CIFS_QUOTA
static struct quotactl_ops cifs_quotactl_ops;
#endif
extern struct file_system_type cifs_fs_type; extern struct file_system_type cifs_fs_type;
int cifsFYI = 0; int cifsFYI = 0;
int cifsERROR = 1; int cifsERROR = 1;
int traceSMB = 0; int traceSMB = 0;
unsigned int oplockEnabled = 1; unsigned int oplockEnabled = 1;
unsigned int quotaEnabled = 0;
unsigned int lookupCacheEnabled = 1; unsigned int lookupCacheEnabled = 1;
unsigned int multiuser_mount = 0; unsigned int multiuser_mount = 0;
unsigned int extended_security = 0; unsigned int extended_security = 0;
...@@ -92,7 +97,9 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -92,7 +97,9 @@ cifs_read_super(struct super_block *sb, void *data,
sb->s_op = &cifs_super_ops; sb->s_op = &cifs_super_ops;
/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) /* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
#ifdef CIFS_QUOTA
sb->s_qcop = &cifs_quotactl_ops;
#endif
sb->s_blocksize = CIFS_MAX_MSGSIZE; sb->s_blocksize = CIFS_MAX_MSGSIZE;
sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
inode = iget(sb, ROOT_I); inode = iget(sb, ROOT_I);
...@@ -247,6 +254,110 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) ...@@ -247,6 +254,110 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
return 0; return 0;
} }
#ifdef CIFS_QUOTA
int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
struct fs_disk_quota * pdquota)
{
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
if(cifs_sb)
pTcon = cifs_sb->tcon;
else
return -EIO;
xid = GetXid();
if(pTcon) {
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
} else {
return -EIO;
}
FreeXid(xid);
return rc;
}
int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
struct fs_disk_quota * pdquota)
{
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
if(cifs_sb)
pTcon = cifs_sb->tcon;
else
return -EIO;
xid = GetXid();
if(pTcon) {
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
} else {
rc = -EIO;
}
FreeXid(xid);
return rc;
}
int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
{
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
if(cifs_sb)
pTcon = cifs_sb->tcon;
else
return -EIO;
xid = GetXid();
if(pTcon) {
cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
} else {
rc = -EIO;
}
FreeXid(xid);
return rc;
}
int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
{
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
if(cifs_sb) {
pTcon = cifs_sb->tcon;
} else {
return -EIO;
}
xid = GetXid();
if(pTcon) {
cFYI(1,("pqstats %p",qstats));
} else {
rc = -EIO;
}
FreeXid(xid);
return rc;
}
static struct quotactl_ops cifs_quotactl_ops = {
.set_xquota = cifs_xquota_set,
.get_xquota = cifs_xquota_set,
.set_xstate = cifs_xstate_set,
.get_xstate = cifs_xstate_get,
};
#endif
struct super_operations cifs_super_ops = { struct super_operations cifs_super_ops = {
.read_inode = cifs_read_inode, .read_inode = cifs_read_inode,
.put_super = cifs_put_super, .put_super = cifs_put_super,
......
...@@ -347,6 +347,7 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions ...@@ -347,6 +347,7 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
have the uid/password or Kerberos credential have the uid/password or Kerberos credential
or equivalent for current user */ or equivalent for current user */
GLOBAL_EXTERN unsigned int oplockEnabled; GLOBAL_EXTERN unsigned int oplockEnabled;
GLOBAL_EXTERN unsigned int quotaEnabled;
GLOBAL_EXTERN unsigned int lookupCacheEnabled; GLOBAL_EXTERN unsigned int lookupCacheEnabled;
GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */ with more secure ntlmssp2 challenge/resp */
......
...@@ -68,6 +68,8 @@ ...@@ -68,6 +68,8 @@
#define NT_TRANSACT_NOTIFY_CHANGE 0x04 #define NT_TRANSACT_NOTIFY_CHANGE 0x04
#define NT_TRANSACT_RENAME 0x05 #define NT_TRANSACT_RENAME 0x05
#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06 #define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
#define NT_TRANSACT_GET_USER_QUOTA 0x07
#define NT_TRANSACT_SET_USER_QUOTA 0x08
#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */ #define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
...@@ -867,6 +869,52 @@ typedef struct smb_com_transaction_ioctl_rsp { ...@@ -867,6 +869,52 @@ typedef struct smb_com_transaction_ioctl_rsp {
__u8 Pad[3]; __u8 Pad[3];
} TRANSACT_IOCTL_RSP; } TRANSACT_IOCTL_RSP;
typedef struct smb_com_transaction_change_notify_req {
struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount;
__u16 Reserved;
__u32 TotalParameterCount;
__u32 TotalDataCount;
__u32 MaxParameterCount;
__u32 MaxDataCount;
__u32 ParameterCount;
__u32 ParameterOffset;
__u32 DataCount;
__u32 DataOffset;
__u8 SetupCount; /* four setup words follow subcommand */
/* SNIA spec incorrectly included spurious pad here */
__u16 SubCommand;/* 4 = Change Notify */
__u32 CompletionFilter; /* operation to monitor */
__u16 Fid;
__u8 WatchTree; /* 1 = Monitor subdirectories */
__u16 ByteCount;
__u8 Pad[3];
__u8 Data[1];
} TRANSACT_CHANGE_NOTIFY_REQ;
/* Completion Filter flags */
#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
#define FILE_NOTIFY_CHANGE_NAME 0x00000003
#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
#define FILE_NOTIFY_CHANGE_EA 0x00000080
#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
/* response contains array of the following structures */
struct file_notify_information {
__u32 NextEntryOffset;
__u32 Action;
__u32 FileNameLength;
__u8 FileName[1];
};
struct reparse_data { struct reparse_data {
__u32 ReparseTag; __u32 ReparseTag;
__u16 ReparseDataLength; __u16 ReparseDataLength;
...@@ -878,6 +926,21 @@ struct reparse_data { ...@@ -878,6 +926,21 @@ struct reparse_data {
char LinkNamesBuf[1]; char LinkNamesBuf[1];
}; };
struct cifs_quota_data {
__u32 rsrvd1; /* 0 */
__u32 sid_size;
__u64 rsrvd2; /* 0 */
__u64 space_used;
__u64 soft_limit;
__u64 hard_limit;
char sid[1]; /* variable size? */
};
/* quota sub commands */
#define QUOTA_LIST_CONTINUE 0
#define QUOTA_LIST_START 0x100
#define QUOTA_FOR_SID 0x101
typedef union smb_com_transaction2 { typedef union smb_com_transaction2 {
struct { struct {
struct smb_hdr hdr; /* wct = 14+ */ struct smb_hdr hdr; /* wct = 14+ */
...@@ -919,35 +982,36 @@ typedef union smb_com_transaction2 { ...@@ -919,35 +982,36 @@ typedef union smb_com_transaction2 {
} TRANSACTION2; } TRANSACTION2;
/* PathInfo/FileInfo infolevels */ /* PathInfo/FileInfo infolevels */
#define SMB_INFO_STANDARD 1 #define SMB_INFO_STANDARD 1
#define SMB_INFO_IS_NAME_VALID 6 #define SMB_INFO_IS_NAME_VALID 6
#define SMB_QUERY_FILE_BASIC_INFO 0x101 #define SMB_QUERY_FILE_BASIC_INFO 0x101
#define SMB_QUERY_FILE_STANDARD_INFO 0x102 #define SMB_QUERY_FILE_STANDARD_INFO 0x102
#define SMB_QUERY_FILE_NAME_INFO 0x104 #define SMB_QUERY_FILE_NAME_INFO 0x104
#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105 #define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106 #define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
#define SMB_QUERY_FILE_ALL_INFO 0x107 #define SMB_QUERY_FILE_ALL_INFO 0x107
#define SMB_QUERY_ALT_NAME_INFO 0x108 #define SMB_QUERY_ALT_NAME_INFO 0x108
#define SMB_QUERY_FILE_STREAM_INFO 0x109 #define SMB_QUERY_FILE_STREAM_INFO 0x109
#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B #define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
#define SMB_QUERY_FILE_UNIX_BASIC 0x200 #define SMB_QUERY_FILE_UNIX_BASIC 0x200
#define SMB_QUERY_FILE_UNIX_LINK 0x201 #define SMB_QUERY_FILE_UNIX_LINK 0x201
#define SMB_SET_FILE_BASIC_INFO 0x101 #define SMB_SET_FILE_BASIC_INFO 0x101
#define SMB_SET_FILE_DISPOSITION_INFO 0x102 #define SMB_SET_FILE_DISPOSITION_INFO 0x102
#define SMB_SET_FILE_ALLOCATION_INFO 0x103 #define SMB_SET_FILE_ALLOCATION_INFO 0x103
#define SMB_SET_FILE_END_OF_FILE_INFO 0x104 #define SMB_SET_FILE_END_OF_FILE_INFO 0x104
#define SMB_SET_FILE_UNIX_BASIC 0x200 #define SMB_SET_FILE_UNIX_BASIC 0x200
#define SMB_SET_FILE_UNIX_LINK 0x201 #define SMB_SET_FILE_UNIX_LINK 0x201
#define SMB_SET_FILE_UNIX_HLINK 0x203 #define SMB_SET_FILE_UNIX_HLINK 0x203
#define SMB_SET_FILE_BASIC_INFO2 0x3ec #define SMB_SET_FILE_BASIC_INFO2 0x3ec
#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc #define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
/* Find File infolevels */ /* Find File infolevels */
#define SMB_FIND_FILE_DIRECTORY_INFO 0x101 #define SMB_FIND_FILE_DIRECTORY_INFO 0x101
#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
#define SMB_FIND_FILE_NAMES_INFO 0x103 #define SMB_FIND_FILE_NAMES_INFO 0x103
#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 #define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
#define SMB_FIND_FILE_UNIX 0x202 #define SMB_FIND_FILE_UNIX 0x202
...@@ -1036,6 +1100,13 @@ typedef struct smb_com_transaction2_spi_rsp { ...@@ -1036,6 +1100,13 @@ typedef struct smb_com_transaction2_spi_rsp {
__u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
} TRANSACTION2_SPI_RSP; } TRANSACTION2_SPI_RSP;
struct set_file_rename {
__u32 overwrite; /* 1 = overwrite dest */
__u32 root_fid; /* zero */
__u32 target_name_len;
char target_name[0]; /* Must be unicode */
};
struct smb_com_transaction2_sfi_req { struct smb_com_transaction2_sfi_req {
struct smb_hdr hdr; /* wct = 15 */ struct smb_hdr hdr; /* wct = 15 */
__u16 TotalParameterCount; __u16 TotalParameterCount;
...@@ -1057,7 +1128,7 @@ struct smb_com_transaction2_sfi_req { ...@@ -1057,7 +1128,7 @@ struct smb_com_transaction2_sfi_req {
__u16 ByteCount; __u16 ByteCount;
__u8 Pad; __u8 Pad;
__u16 Pad1; __u16 Pad1;
__u16 Fid; __u16 Fid;
__u16 InformationLevel; __u16 InformationLevel;
__u16 Reserved4; __u16 Reserved4;
}; };
...@@ -1395,6 +1466,9 @@ typedef struct { ...@@ -1395,6 +1466,9 @@ typedef struct {
__u16 MinorVersionNumber; __u16 MinorVersionNumber;
__u64 Capability; __u64 Capability;
} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ } FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
/* Linux/Unix extensions capability flags */
#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
/* DeviceType Flags */ /* DeviceType Flags */
#define FILE_DEVICE_CD_ROM 0x00000002 #define FILE_DEVICE_CD_ROM 0x00000002
......
...@@ -170,6 +170,8 @@ extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, ...@@ -170,6 +170,8 @@ extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
const struct nls_table *nls_codepage); const struct nls_table *nls_codepage);
extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
int netfid, char * target_name, const struct nls_table *nls_codepage);
extern int CIFSCreateHardLink(const int xid, extern int CIFSCreateHardLink(const int xid,
struct cifsTconInfo *tcon, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
......
...@@ -526,6 +526,10 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, ...@@ -526,6 +526,10 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
if (rc) if (rc)
return rc; return rc;
/* tcon and ses pointer are checked in smb_init */
if (tcon->ses->server == NULL)
return -ECONNABORTED;
pSMB->AndXCommand = 0xFF; /* none */ pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = netfid; pSMB->Fid = netfid;
pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
...@@ -584,6 +588,9 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, ...@@ -584,6 +588,9 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
(void **) &pSMBr); (void **) &pSMBr);
if (rc) if (rc)
return rc; return rc;
/* tcon and ses pointer are checked in smb_init */
if (tcon->ses->server == NULL)
return -ECONNABORTED;
pSMB->AndXCommand = 0xFF; /* none */ pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = netfid; pSMB->Fid = netfid;
...@@ -639,8 +646,9 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -639,8 +646,9 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
if (rc) if (rc)
return rc; return rc;
if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
timeout = -1; /* no response expected */ timeout = -1; /* no response expected */
}
pSMB->NumberOfLocks = cpu_to_le32(numLock); pSMB->NumberOfLocks = cpu_to_le32(numLock);
pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock); pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
...@@ -754,7 +762,7 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, ...@@ -754,7 +762,7 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { if (rc) {
cFYI(1, ("Send error in RMDir = %d", rc)); cFYI(1, ("Send error in rename = %d", rc));
} }
if (pSMB) if (pSMB)
buf_release(pSMB); buf_release(pSMB);
...@@ -762,6 +770,81 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, ...@@ -762,6 +770,81 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
return rc; return rc;
} }
int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
int netfid, char * target_name, const struct nls_table * nls_codepage)
{
struct smb_com_transaction2_sfi_req *pSMB = NULL;
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
struct set_file_rename * rename_info;
char *data_offset;
char dummy_string[30];
int rc = 0;
int bytes_returned = 0;
int len_of_str;
cFYI(1, ("Rename to File by handle"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
pSMB->ParameterCount = 6;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
Fid) - 4;
pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
rename_info = (struct set_file_rename *) data_offset;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
/* construct random name ".cifs_tmp<inodenum><mid>" */
rename_info->overwrite = cpu_to_le32(1);
rename_info->root_fid = 0;
/* unicode only call */
if(target_name == NULL) {
sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
} else {
len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
}
cFYI(1,("len of str: %d", len_of_str)); /* BB removeme BB */
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
pSMB->ByteCount += pSMB->DataCount;
pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->Fid = netfid;
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += pSMB->ByteCount;
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1,("Send error in Rename (by file handle) = %d", rc));
}
if (pSMB)
buf_release(pSMB);
return rc;
}
int int
CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon, CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
...@@ -1979,7 +2062,7 @@ CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon, ...@@ -1979,7 +2062,7 @@ CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { if (rc) {
cERROR(1, ("Send error in QFSDeviceInfo = %d", rc)); cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
} else { /* decode response */ } else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)) if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
...@@ -2202,10 +2285,10 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, ...@@ -2202,10 +2285,10 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
pSMB->TotalDataCount = pSMB->DataCount; pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount; pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
parm_data = parm_data =
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
pSMB->DataOffset); pSMB->DataOffset);
pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
parm_data->FileSize = size; parm_data->FileSize = size;
pSMB->Fid = fid; pSMB->Fid = fid;
if(SetAllocation) { if(SetAllocation) {
......
...@@ -102,7 +102,7 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -102,7 +102,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
} }
list_for_each(tmp, &GlobalTreeConnectionList) { list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if(tcon->ses->server == server) { if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
tcon->tidStatus = CifsNeedReconnect; tcon->tidStatus = CifsNeedReconnect;
} }
} }
...@@ -233,9 +233,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -233,9 +233,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
(checkSMBhdr (checkSMBhdr
(smb_buffer, smb_buffer->Mid))) { (smb_buffer, smb_buffer->Mid))) {
cERROR(1, cERROR(1,
(KERN_ERR ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
"Invalid size or format for SMB found with length %d and pdu_lenght %d",
length, pdu_length)); length, pdu_length));
cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
/* BB fix by finding next smb signature - and reading off data until next smb ? BB */ /* BB fix by finding next smb signature - and reading off data until next smb ? BB */
/* BB add reconnect here */ /* BB add reconnect here */
...@@ -728,6 +728,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket) ...@@ -728,6 +728,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
*csocket = NULL; *csocket = NULL;
return rc; return rc;
} else { } else {
/* BB other socket options to set KEEPALIVE, timeouts? NODELAY? */
cFYI(1,("Socket created")); cFYI(1,("Socket created"));
} }
} }
...@@ -783,6 +784,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -783,6 +784,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
(struct sockaddr *) psin_server, (struct sockaddr *) psin_server,
sizeof (struct sockaddr_in6),0); sizeof (struct sockaddr_in6),0);
if (rc >= 0) { if (rc >= 0) {
/* BB other socket options to set KEEPALIVE, timeouts? NODELAY? */
return rc; return rc;
} }
} }
......
...@@ -51,7 +51,6 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -51,7 +51,6 @@ build_path_from_dentry(struct dentry *direntry)
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len); namelen += (1 + temp->d_name.len);
cFYI(1, (" len %d ", namelen));
temp = temp->d_parent; temp = temp->d_parent;
} }
namelen += 1; /* allow for trailing null */ namelen += 1; /* allow for trailing null */
......
...@@ -76,13 +76,14 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -76,13 +76,14 @@ cifs_open(struct inode *inode, struct file *file)
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} else { } else {
cERROR(1,("could not find file instance for new file %p ",file)); if(file->f_flags & O_EXCL)
cERROR(1,("could not find file instance for new file %p ",file));
} }
} }
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
cFYI(1, (" inode = 0x%p file flags are %x for %s", inode, file->f_flags,full_path)); cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
if ((file->f_flags & O_ACCMODE) == O_RDONLY) if ((file->f_flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ; desiredAccess = GENERIC_READ;
else if ((file->f_flags & O_ACCMODE) == O_WRONLY) else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
...@@ -1121,9 +1122,6 @@ construct_dentry(struct qstr *qstring, struct file *file, ...@@ -1121,9 +1122,6 @@ construct_dentry(struct qstr *qstring, struct file *file,
} }
tmp_dentry->d_time = jiffies; tmp_dentry->d_time = jiffies;
(*ptmp_inode)->i_blksize =
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
cFYI(1, ("i_blksize = %ld", (*ptmp_inode)->i_blksize));
*pnew_dentry = tmp_dentry; *pnew_dentry = tmp_dentry;
} }
......
...@@ -353,8 +353,9 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -353,8 +353,9 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL, cifs_sb->local_nls); &netfid, &oplock, NULL, cifs_sb->local_nls);
if(rc==0) { if(rc==0) {
CIFSSMBRenameOpenFile(xid,pTcon,netfid,
NULL, cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
/* BB In the future chain close with the NTCreateX to narrow window */
direntry->d_inode->i_nlink--; direntry->d_inode->i_nlink--;
} }
} else if (rc == -EACCES) { } else if (rc == -EACCES) {
...@@ -370,8 +371,22 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -370,8 +371,22 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
} }
if(rc==0) { if(rc==0) {
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
if (!rc) if (!rc) {
direntry->d_inode->i_nlink--; direntry->d_inode->i_nlink--;
} else if (rc == -ETXTBSY) {
int oplock = FALSE;
__u16 netfid;
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL, cifs_sb->local_nls);
if(rc==0) {
CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--;
}
/* BB if rc = -ETXTBUSY goto the rename logic BB */
}
} }
} }
cifsInode = CIFS_I(direntry->d_inode); cifsInode = CIFS_I(direntry->d_inode);
...@@ -511,6 +526,20 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry, ...@@ -511,6 +526,20 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
rc = CIFSSMBRename(xid, pTcon, fromName, toName, rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls); cifs_sb_source->local_nls);
} }
if((rc == -EIO)||(rc == -EEXIST)) {
int oplock = FALSE;
__u16 netfid;
rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR,
&netfid, &oplock, NULL, cifs_sb_source->local_nls);
if(rc==0) {
CIFSSMBRenameOpenFile(xid,pTcon,netfid,
toName, cifs_sb_source->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
}
}
if (fromName) if (fromName)
kfree(fromName); kfree(fromName);
if (toName) if (toName)
......
...@@ -169,7 +169,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -169,7 +169,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
temp_fs = get_fs(); /* we must turn off socket api parm checking */ temp_fs = get_fs(); /* we must turn off socket api parm checking */
set_fs(get_ds()); set_fs(get_ds());
rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4); rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
while((rc == -ENOSPC) || (rc == -EAGAIN)) {
schedule_timeout(HZ/2);
rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
}
set_fs(temp_fs); set_fs(temp_fs);
if (rc < 0) { if (rc < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment