Commit 267880af authored by Steve French's avatar Steve French Committed by Steve French

Fix for file size handling for locally cached files.

parent e333e800
Version 0.86
------------
Fix oops on empty file readahead. Fix for file size handling for locally cached files.
Version 0.85 Version 0.85
------------ ------------
Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
......
...@@ -201,10 +201,11 @@ cifs_alloc_inode(struct super_block *sb) ...@@ -201,10 +201,11 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->cifsAttrs = 0x20; /* default */ cifs_inode->cifsAttrs = 0x20; /* default */
atomic_set(&cifs_inode->inUse, 0); atomic_set(&cifs_inode->inUse, 0);
cifs_inode->time = 0; cifs_inode->time = 0;
if(oplockEnabled) { /* Until the file is open and we have gotten oplock
cifs_inode->clientCanCacheRead = 1; info back from the server, can not assume caching of
cifs_inode->clientCanCacheAll = 1; file data or metadata */
} cifs_inode->clientCanCacheRead = FALSE;
cifs_inode->clientCanCacheAll = FALSE;
INIT_LIST_HEAD(&cifs_inode->openFileList); INIT_LIST_HEAD(&cifs_inode->openFileList);
return &cifs_inode->vfs_inode; return &cifs_inode->vfs_inode;
} }
......
...@@ -633,6 +633,12 @@ typedef struct smb_com_open_req { /* also handles create */ ...@@ -633,6 +633,12 @@ typedef struct smb_com_open_req { /* also handles create */
char fileName[1]; char fileName[1];
} OPEN_REQ; } OPEN_REQ;
/* open response: oplock levels */
#define OPLOCK_NONE 0
#define OPLOCK_EXCLUSIVE 1
#define OPLOCK_BATCH 2
#define OPLOCK_READ 3 /* level 2 oplock */
typedef struct smb_com_open_rsp { typedef struct smb_com_open_rsp {
struct smb_hdr hdr; /* wct = 34 BB */ struct smb_hdr hdr; /* wct = 34 BB */
__u8 AndXCommand; __u8 AndXCommand;
......
...@@ -144,7 +144,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -144,7 +144,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(nd) { if(nd) {
cFYI(1,("In create nd flags = 0x%x for %s",nd->flags,full_path)); cFYI(1,("In create for inode %p dentry->inode %p nd flags = 0x%x for %s",inode, direntry->d_inode, nd->flags,full_path));
if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ; desiredAccess = GENERIC_READ;
...@@ -165,6 +165,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -165,6 +165,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (rc) { if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc)); cFYI(1, ("cifs_create returned 0x%x ", rc));
} else { } else {
/* BB for case of overwriting existing file can we use the inode that was
passed in rather than creating new one?? */
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb); inode->i_sb);
...@@ -195,8 +197,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -195,8 +197,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist,&pTcon->openFileList);
pCifsInode = CIFS_I(newinode); pCifsInode = CIFS_I(newinode);
if(pCifsInode) if(pCifsInode) {
list_add(&pCifsFile->flist,&pCifsInode->openFileList); list_add(&pCifsFile->flist,&pCifsInode->openFileList);
if(oplock == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",newinode));
} else if(oplock == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
}
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode, CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
......
...@@ -50,6 +50,7 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -50,6 +50,7 @@ cifs_open(struct inode *inode, struct file *file)
int desiredAccess = 0x20197; int desiredAccess = 0x20197;
int disposition = FILE_OPEN; int disposition = FILE_OPEN;
__u16 netfid; __u16 netfid;
FILE_ALL_INFO * buf = NULL;
xid = GetXid(); xid = GetXid();
...@@ -117,11 +118,12 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -117,11 +118,12 @@ cifs_open(struct inode *inode, struct file *file)
/* BB pass O_SYNC flag through on file attributes .. BB */ /* BB pass O_SYNC flag through on file attributes .. BB */
/* BB add code to refresh inode by passing in file_info buf on open /* Also refresh inode by passing in file_info buf returned by SMBOpen
and calling get_inode_info with returned buf (at least and calling get_inode_info with returned buf (at least
helps non-Unix server case */ helps non-Unix server case */
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls); CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
if (rc) { if (rc) {
cFYI(1, ("cifs_open returned 0x%x ", rc)); cFYI(1, ("cifs_open returned 0x%x ", rc));
cFYI(1, ("oplock: %d ", oplock)); cFYI(1, ("oplock: %d ", oplock));
...@@ -140,8 +142,22 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -140,8 +142,22 @@ cifs_open(struct inode *inode, struct file *file)
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist,&pTcon->openFileList);
pCifsInode = CIFS_I(file->f_dentry->d_inode); pCifsInode = CIFS_I(file->f_dentry->d_inode);
if(pCifsInode->openFileList.next) if(pCifsInode) {
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
full_path, inode->i_sb);
else
rc = cifs_get_inode_info(&file->f_dentry->d_inode,
full_path, buf, inode->i_sb);
list_add(&pCifsFile->flist,&pCifsInode->openFileList); list_add(&pCifsFile->flist,&pCifsInode->openFileList);
if(oplock == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
} else if(oplock == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
}
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
write_unlock(&file->f_owner.lock); write_unlock(&file->f_owner.lock);
if(file->f_flags & O_CREAT) { if(file->f_flags & O_CREAT) {
...@@ -162,6 +178,8 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -162,6 +178,8 @@ cifs_open(struct inode *inode, struct file *file)
} }
} }
if (buf)
kfree(buf);
if (full_path) if (full_path)
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
...@@ -245,6 +263,13 @@ cifs_close(struct inode *inode, struct file *file) ...@@ -245,6 +263,13 @@ cifs_close(struct inode *inode, struct file *file)
} else } else
rc = -EBADF; rc = -EBADF;
if(list_empty(&(CIFS_I(inode)->openFileList))) {
cFYI(1,("closing last open instance for inode %p",inode));
/* if the file is not open we do not know if we can cache
info on this inode, much less write behind and read ahead */
CIFS_I(inode)->clientCanCacheRead = FALSE;
CIFS_I(inode)->clientCanCacheAll = FALSE;
}
if((rc ==0) && CIFS_I(inode)->write_behind_rc) if((rc ==0) && CIFS_I(inode)->write_behind_rc)
rc = CIFS_I(inode)->write_behind_rc; rc = CIFS_I(inode)->write_behind_rc;
FreeXid(xid); FreeXid(xid);
...@@ -837,7 +862,13 @@ cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -837,7 +862,13 @@ cifs_readpages(struct file *file, struct address_space *mapping,
break; break;
} }
} else { } else {
cFYI(1,("No bytes read")); cFYI(1,("No bytes read cleaning remaining pages off readahead list"));
/* BB turn off caching and do new lookup on file size at server? */
while (!list_empty(page_list) && (i < num_pages)) {
page = list_entry(page_list->prev, struct page, list);
list_del(&page->list);
}
break; break;
} }
if(smb_read_data) { if(smb_read_data) {
......
...@@ -43,6 +43,9 @@ cifs_get_inode_info_unix(struct inode **pinode, ...@@ -43,6 +43,9 @@ cifs_get_inode_info_unix(struct inode **pinode,
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
char *tmp_path; char *tmp_path;
/* BB add caching check so we do not go to server to overwrite inode info to cached file
where the local file sizes are correct and the server info is stale BB */
xid = GetXid(); xid = GetXid();
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
...@@ -169,7 +172,15 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, ...@@ -169,7 +172,15 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
xid = GetXid(); xid = GetXid();
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
cFYI(1, (" Getting info on %s ", search_path)); cFYI(1,("Getting info on %s ", search_path));
if((pfindData == NULL) && (*pinode != NULL)) {
if(CIFS_I(*pinode)->clientCanCacheRead) {
cFYI(1,("No need to revalidate inode sizes on cached file "));
FreeXid(xid);
return rc;
}
}
/* if file info not passed in then get it from server */ /* if file info not passed in then get it from server */
if(pfindData == NULL) { if(pfindData == NULL) {
......
...@@ -27,26 +27,31 @@ ...@@ -27,26 +27,31 @@
#define NtLmChallenge 2 #define NtLmChallenge 2
#define NtLmAuthenticate 3 #define NtLmAuthenticate 3
#define UnknownMessage 8 #define UnknownMessage 8
/* Negotiate Flags */ /* Negotiate Flags */
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode #define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM #define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm #define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability #define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality #define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040 #define NTLMSSP_NEGOTIATE_DGRAM 0x0040
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal #define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication #define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000 #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine #define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000 #define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
#define NTLMSSP_REQUEST_INIT_RESP 0x100000
#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
#define NTLMSSP_NEGOTIATE_128 0x20000000 #define NTLMSSP_NEGOTIATE_128 0x20000000
#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
/* server only negotiate flags */ #define NTLMSSP_NEGOTIATE_56 0x80000000
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 /* NEGOTIATE_DOMAIN 0x1000 ? */
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000 /* NEGOTIATE_WORKSTATION 0x2000 ? */
/* Although typedefs are not commonly used for structure definitions */ /* Although typedefs are not commonly used for structure definitions */
/* in the Linux kernel, in this particular case they are useful */ /* in the Linux kernel, in this particular case they are useful */
...@@ -62,7 +67,7 @@ typedef struct _SECURITY_BUFFER { ...@@ -62,7 +67,7 @@ typedef struct _SECURITY_BUFFER {
typedef struct _NEGOTIATE_MESSAGE { typedef struct _NEGOTIATE_MESSAGE {
__u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
__u32 MessageType; __u32 MessageType; /* 1 */
__u32 NegotiateFlags; __u32 NegotiateFlags;
SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
...@@ -72,7 +77,7 @@ typedef struct _NEGOTIATE_MESSAGE { ...@@ -72,7 +77,7 @@ typedef struct _NEGOTIATE_MESSAGE {
typedef struct _CHALLENGE_MESSAGE { typedef struct _CHALLENGE_MESSAGE {
__u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
__u32 MessageType; __u32 MessageType; /* 2 */
SECURITY_BUFFER TargetName; SECURITY_BUFFER TargetName;
__u32 NegotiateFlags; __u32 NegotiateFlags;
__u8 Challenge[CIFS_CRYPTO_KEY_SIZE]; __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
...@@ -82,7 +87,7 @@ typedef struct _CHALLENGE_MESSAGE { ...@@ -82,7 +87,7 @@ typedef struct _CHALLENGE_MESSAGE {
typedef struct _AUTHENTICATE_MESSAGE { typedef struct _AUTHENTICATE_MESSAGE {
__u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
__u32 MessageType; __u32 MessageType; /* 3 */
SECURITY_BUFFER LmChallengeResponse; SECURITY_BUFFER LmChallengeResponse;
SECURITY_BUFFER NtChallengeResponse; SECURITY_BUFFER NtChallengeResponse;
SECURITY_BUFFER DomainName; SECURITY_BUFFER DomainName;
......
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