Commit 32995340 authored by Steve French's avatar Steve French

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

into hostme.bitkeeper.com:/repos/c/cifs/linux-2.5cifs
parents 3a2b9514 5221ad8c
Version 0.84
------------
Finish support for Linux 2.5 open/create changes, which removes the
redundant NTCreate/QPathInfo/close that was sent during file create.
Enable oplock by default. Enable packet signing by default (needed to
access many recent Windows servers)
Version 0.83 Version 0.83
------------ ------------
Fix oops when mounting to long server names caused by inverted parms to kmalloc. Fix oops when mounting to long server names caused by inverted parms to kmalloc.
......
...@@ -150,7 +150,10 @@ Configuration pseudo-files: ...@@ -150,7 +150,10 @@ Configuration pseudo-files:
point and if the uids user/password mapping point and if the uids user/password mapping
information is available. (default is 0) information is available. (default is 0)
PacketSigningEnabled If set to one, cifs packet signing is enabled PacketSigningEnabled If set to one, cifs packet signing is enabled
(default 0) and will be used if the server requires
it. If set to two, cifs packet signing is
required even if the server considers packet
signing optional. (default 1)
cifsFYI If set to one, additional debug information is cifsFYI If set to one, additional debug information is
logged to the system error log. (default 0) logged to the system error log. (default 0)
ExtendedSecurity If set to one, SPNEGO session establishment ExtendedSecurity If set to one, SPNEGO session establishment
...@@ -166,6 +169,7 @@ Configuration pseudo-files: ...@@ -166,6 +169,7 @@ Configuration pseudo-files:
for one second improving performance of lookups for one second improving performance of lookups
(default 1) (default 1)
OplockEnabled If set to one, safe distributed caching enabled. OplockEnabled If set to one, safe distributed caching enabled.
(default 1)
These experimental features and tracing can be enabled by changing flags in /proc/fs/cifs These experimental features and tracing can be enabled by changing flags in /proc/fs/cifs
(after the cifs module has been installed or built into the kernel, e.g. insmod cifs). (after the cifs module has been installed or built into the kernel, e.g. insmod cifs).
......
...@@ -47,12 +47,12 @@ extern struct file_system_type cifs_fs_type; ...@@ -47,12 +47,12 @@ 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 = 0; unsigned int oplockEnabled = 1;
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;
unsigned int ntlmv2_support = 0; unsigned int ntlmv2_support = 0;
unsigned int sign_CIFS_PDUs = 0; unsigned int sign_CIFS_PDUs = 1;
unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE; unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
struct task_struct * oplockThread = NULL; struct task_struct * oplockThread = NULL;
...@@ -439,7 +439,6 @@ static int cifs_oplock_thread(void * dummyarg) ...@@ -439,7 +439,6 @@ static int cifs_oplock_thread(void * dummyarg)
struct list_head * tmp; struct list_head * tmp;
struct list_head * tmp1; struct list_head * tmp1;
struct oplock_q_entry * oplock_item; struct oplock_q_entry * oplock_item;
struct file * pfile;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
int rc; int rc;
...@@ -457,23 +456,19 @@ static int cifs_oplock_thread(void * dummyarg) ...@@ -457,23 +456,19 @@ static int cifs_oplock_thread(void * dummyarg)
qhead); qhead);
if(oplock_item) { if(oplock_item) {
pTcon = oplock_item->tcon; pTcon = oplock_item->tcon;
pfile = oplock_item->file_to_flush;
cFYI(1,("process item on queue"));/* BB remove */
DeleteOplockQEntry(oplock_item); DeleteOplockQEntry(oplock_item);
write_unlock(&GlobalMid_Lock); write_unlock(&GlobalMid_Lock);
rc = filemap_fdatawrite(pfile->f_dentry->d_inode->i_mapping); rc = filemap_fdatawrite(oplock_item->pinode->i_mapping);
if(rc) if(rc)
CIFS_I(pfile->f_dentry->d_inode)->write_behind_rc CIFS_I(oplock_item->pinode)->write_behind_rc
= rc; = rc;
cFYI(1,("Oplock flush file %p rc %d",pfile,rc)); cFYI(1,("Oplock flush inode %p rc %d",oplock_item->pinode,rc));
if(pfile->private_data) { rc = CIFSSMBLock(0, pTcon,
rc = CIFSSMBLock(0, pTcon, oplock_item->netfid,
((struct cifsFileInfo *) pfile->private_data)->netfid, 0 /* len */ , 0 /* offset */, 0,
0 /* len */ , 0 /* offset */, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE,
0, LOCKING_ANDX_OPLOCK_RELEASE, 0 /* wait flag */);
0 /* wait flag */); cFYI(1,("Oplock release rc = %d ",rc));
cFYI(1,("Oplock release rc = %d ",rc));
}
write_lock(&GlobalMid_Lock); write_lock(&GlobalMid_Lock);
} else } else
break; break;
......
...@@ -208,6 +208,7 @@ struct cifsFileInfo { ...@@ -208,6 +208,7 @@ struct cifsFileInfo {
/* BB add lock scope info here if needed */ ; /* BB add lock scope info here if needed */ ;
/* lock scope id (0 if none) */ /* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */ struct file * pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */
int endOfSearch:1; /* we have reached end of search */ int endOfSearch:1; /* we have reached end of search */
int closePend:1; /* file is marked to close */ int closePend:1; /* file is marked to close */
int emptyDir:1; int emptyDir:1;
...@@ -263,8 +264,9 @@ struct mid_q_entry { ...@@ -263,8 +264,9 @@ struct mid_q_entry {
struct oplock_q_entry { struct oplock_q_entry {
struct list_head qhead; struct list_head qhead;
struct file * file_to_flush; struct inode * pinode;
struct cifsTconInfo * tcon; struct cifsTconInfo * tcon;
__u16 netfid;
}; };
#define MID_FREE 0 #define MID_FREE 0
......
...@@ -57,7 +57,7 @@ extern void header_assemble(struct smb_hdr *, char /* command */ , ...@@ -57,7 +57,7 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int const struct cifsTconInfo *, int
/* length of fixed section (word count) in two byte units */ /* length of fixed section (word count) in two byte units */
); );
struct oplock_q_entry * AllocOplockQEntry(struct file *,struct cifsTconInfo *); struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
void DeleteOplockQEntry(struct oplock_q_entry *); void DeleteOplockQEntry(struct oplock_q_entry *);
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
extern u64 cifs_UnixTimeToNT(struct timespec); extern u64 cifs_UnixTimeToNT(struct timespec);
...@@ -68,7 +68,8 @@ extern void RevUcode_to_Ucode_with_Len(char *revUnicode, char *UnicodeName, ...@@ -68,7 +68,8 @@ extern void RevUcode_to_Ucode_with_Len(char *revUnicode, char *UnicodeName,
extern void Ucode_to_RevUcode_with_Len(char *Unicode, char *revUnicodeName, extern void Ucode_to_RevUcode_with_Len(char *Unicode, char *revUnicodeName,
int Len); int Len);
extern int cifs_get_inode_info(struct inode **pinode, extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path, const unsigned char *search_path,
FILE_ALL_INFO * pfile_info,
struct super_block *sb); struct super_block *sb);
extern int cifs_get_inode_info_unix(struct inode **pinode, extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path, const unsigned char *search_path,
...@@ -195,7 +196,7 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid, ...@@ -195,7 +196,7 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid,
extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int disposition, const char *fileName, const int disposition,
const int access_flags, const int omode, const int access_flags, const int omode,
__u16 * netfid, int *pOplock, __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
const struct nls_table *nls_codepage); const struct nls_table *nls_codepage);
extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const int smb_file_id); const int smb_file_id);
......
...@@ -179,7 +179,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -179,7 +179,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
cERROR(1, cERROR(1,
("Server requires /proc/fs/cifs/PacketSigningEnabled")); ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
} else if(sign_CIFS_PDUs == 1) {
if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
} }
} }
if (pSMB) if (pSMB)
buf_release(pSMB); buf_release(pSMB);
...@@ -419,7 +423,8 @@ int ...@@ -419,7 +423,8 @@ int
CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int openDisposition, const char *fileName, const int openDisposition,
const int access_flags, const int create_options, __u16 * netfid, const int access_flags, const int create_options, __u16 * netfid,
int *pOplock, const struct nls_table *nls_codepage) int *pOplock, FILE_ALL_INFO * pfile_info,
const struct nls_table *nls_codepage)
{ {
int rc = -EACCES; int rc = -EACCES;
OPEN_REQ *pSMB = NULL; OPEN_REQ *pSMB = NULL;
...@@ -484,8 +489,14 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -484,8 +489,14 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
*pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
*netfid = pSMBr->Fid; /* cifs fid stays in le */ *netfid = pSMBr->Fid; /* cifs fid stays in le */
/* Do we care about the CreateAction in any cases? */ /* Do we care about the CreateAction in any cases? */
if(pfile_info) {
/* BB add code to update inode file sizes from create response */ memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
36 /* CreationTime to Attributes */);
/* the file_info buf is endian converted by caller */
pfile_info->AllocationSize = pSMBr->AllocationSize;
pfile_info->EndOfFile = pSMBr->EndOfFile;
pfile_info->NumberOfLinks = cpu_to_le32(1);
}
} }
if (pSMB) if (pSMB)
buf_release(pSMB); buf_release(pSMB);
...@@ -1231,11 +1242,12 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -1231,11 +1242,12 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
/* BB also check enough total bytes returned */ /* BB also check enough total bytes returned */
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
rc = -EIO; /* bad smb */ rc = -EIO; /* bad smb */
else { else if (pFindData){
memcpy((char *) pFindData, memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol + (char *) &pSMBr->hdr.Protocol +
pSMBr->DataOffset, sizeof (FILE_ALL_INFO)); pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
} } else
rc = -ENOMEM;
} }
if (pSMB) if (pSMB)
buf_release(pSMB); buf_release(pSMB);
......
...@@ -131,7 +131,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -131,7 +131,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
FILE_ALL_INFO * buf = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
struct cifsFileInfo * pCifsFile = NULL;
struct cifsInodeInfo * pCifsInode;
xid = GetXid(); xid = GetXid();
...@@ -140,10 +143,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -140,10 +143,9 @@ 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 nd flags = 0x%x for %s",nd->flags,full_path));
cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ; desiredAccess = GENERIC_READ;
else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
...@@ -152,12 +154,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -152,12 +154,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
desiredAccess = GENERIC_ALL; desiredAccess = GENERIC_ALL;
} }
/* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
if (!oplockEnabled)
oplock = REQ_OPLOCK;
/* BB add processing for setting the equivalent of mode - e.g. via CreateX with ACLs */ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
desiredAccess, CREATE_NOT_DIR, desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, cifs_sb->local_nls); &fileHandle, &oplock, buf, cifs_sb->local_nls);
if (rc) { if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc)); cFYI(1, ("cifs_create returned 0x%x ", rc));
} else { } else {
...@@ -166,28 +170,55 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -166,28 +170,55 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
inode->i_sb); inode->i_sb);
else else
rc = cifs_get_inode_info(&newinode, full_path, rc = cifs_get_inode_info(&newinode, full_path,
inode->i_sb); buf, inode->i_sb);
if (rc != 0) { if (rc != 0) {
cFYI(1,("Create worked but get_inode_info failed with rc = %d", cFYI(1,("Create worked but get_inode_info failed with rc = %d",
rc)); rc));
/* close handle */
} else { } else {
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode); d_instantiate(direntry, newinode);
} }
/* BB check oplock state before deciding to call following */
/* if(*oplock)
save off handle in inode and dontdoclose */
CIFSSMBClose(xid, pTcon, fileHandle);
/* BB In the future chain close with the NTCreateX to narrow window */
if(newinode) if(newinode) {
newinode->i_mode = mode; newinode->i_mode = mode;
} pCifsFile = (struct cifsFileInfo *)
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile) {
memset((char *)pCifsFile, 0,
sizeof (struct cifsFileInfo));
pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->pid;
pCifsFile->pInode = newinode;
/* pCifsFile->pfile = file; */ /* put in at open time */
write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList);
pCifsInode = CIFS_I(newinode);
if(pCifsInode->openFileList.next)
list_add(&pCifsFile->flist,&pCifsInode->openFileList);
write_unlock(&GlobalSMBSeslock);
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
else { /* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* in the meantime could set r/o dos attribute when perms are eg:
mode & 0222 == 0 */
}
}
}
}
if (buf)
kfree(buf);
if (full_path) if (full_path)
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
...@@ -261,17 +292,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -261,17 +292,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
cFYI(1, cFYI(1,
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode)); (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
if(nd) { /* BB remove begin */
cFYI(1,("In lookup nd flags = 0x%x",nd->flags));
cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
}
/* BB remove end BB */
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,
parent_dir_inode->i_sb); parent_dir_inode->i_sb);
else else
rc = cifs_get_inode_info(&newInode, full_path, rc = cifs_get_inode_info(&newInode, full_path, NULL,
parent_dir_inode->i_sb); parent_dir_inode->i_sb);
if ((rc == 0) && (newInode != NULL)) { if ((rc == 0) && (newInode != NULL)) {
...@@ -328,12 +353,6 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) ...@@ -328,12 +353,6 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */ /* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
if(nd) { /* BB remove begin */
cFYI(1,("In d_revalidate nd flags = 0x%x",nd->flags));
cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
}
/* BB remove end BB */
if (direntry->d_inode) { if (direntry->d_inode) {
if (cifs_revalidate(direntry)) { if (cifs_revalidate(direntry)) {
/* unlock_kernel(); */ /* unlock_kernel(); */
......
...@@ -45,6 +45,7 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -45,6 +45,7 @@ cifs_open(struct inode *inode, struct file *file)
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsFileInfo *pCifsFile; struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode; struct cifsInodeInfo *pCifsInode;
struct list_head * tmp;
char *full_path = NULL; char *full_path = NULL;
int desiredAccess = 0x20197; int desiredAccess = 0x20197;
int disposition = FILE_OPEN; int disposition = FILE_OPEN;
...@@ -55,6 +56,29 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -55,6 +56,29 @@ cifs_open(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
if (file->f_flags & O_CREAT) {
/* search inode for this file and fill in file->private_data = */
pCifsInode = CIFS_I(file->f_dentry->d_inode);
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
/* set mode ?? */
pCifsFile->pfile = file; /* needed for writepage */
file->private_data = pCifsFile;
break;
}
}
read_unlock(&GlobalSMBSeslock);
if(file->private_data != NULL) {
rc = 0;
FreeXid(xid);
return rc;
} else {
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 %x for %s", inode, file->f_flags,full_path));
...@@ -86,20 +110,21 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -86,20 +110,21 @@ cifs_open(struct inode *inode, struct file *file)
if (file->f_flags & O_CREAT) if (file->f_flags & O_CREAT)
disposition = FILE_OVERWRITE; disposition = FILE_OVERWRITE;
/* BB first check if file has batch oplock (or oplock ?) */
/* BB finish adding in oplock support BB */
if (oplockEnabled) if (oplockEnabled)
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
else else
oplock = FALSE; oplock = FALSE;
/* 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
and calling get_inode_info with returned buf (at least
helps non-Unix server case */
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
CREATE_NOT_DIR, &netfid, &oplock, cifs_sb->local_nls); CREATE_NOT_DIR, &netfid, &oplock, NULL, 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));
} else { } else {
file->private_data = file->private_data =
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
...@@ -110,6 +135,7 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -110,6 +135,7 @@ cifs_open(struct inode *inode, struct file *file)
pCifsFile->netfid = netfid; pCifsFile->netfid = netfid;
pCifsFile->pid = current->pid; pCifsFile->pid = current->pid;
pCifsFile->pfile = file; /* needed for writepage */ pCifsFile->pfile = file; /* needed for writepage */
pCifsFile->pInode = inode;
write_lock(&file->f_owner.lock); write_lock(&file->f_owner.lock);
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist,&pTcon->openFileList);
...@@ -1248,7 +1274,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1248,7 +1274,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
pfindDataUnix->FileName, pfindDataUnix->FileName,
cifsFile->resume_name_length); cifsFile->resume_name_length);
} }
for (i = 2; i < findParms.SearchCount + 2; i++) { for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
if (UnixSearch == FALSE) { if (UnixSearch == FALSE) {
pfindData->FileNameLength = pfindData->FileNameLength =
le32_to_cpu(pfindData->FileNameLength); le32_to_cpu(pfindData->FileNameLength);
......
...@@ -155,24 +155,30 @@ cifs_get_inode_info_unix(struct inode **pinode, ...@@ -155,24 +155,30 @@ cifs_get_inode_info_unix(struct inode **pinode,
} }
int int
cifs_get_inode_info(struct inode **pinode, cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
const unsigned char *search_path, struct super_block *sb) FILE_ALL_INFO * pfindData, struct super_block *sb)
{ {
int xid; int xid;
int rc = 0; int rc = 0;
FILE_ALL_INFO findData;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode *inode; struct inode *inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
char *tmp_path; char *tmp_path;
char *buf = NULL;
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));
/* we could have done a find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, pTcon, search_path, &findData, /* if file info not passed in then get it from server */
if(pfindData == NULL) {
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
pfindData = (FILE_ALL_INFO *)buf;
/* could do find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
cifs_sb->local_nls); cifs_sb->local_nls);
}
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
if (rc) { if (rc) {
if (rc == -EREMOTE) { if (rc == -EREMOTE) {
...@@ -183,8 +189,10 @@ cifs_get_inode_info(struct inode **pinode, ...@@ -183,8 +189,10 @@ cifs_get_inode_info(struct inode **pinode,
strnlen(search_path, MAX_PATHCONF) + 1, strnlen(search_path, MAX_PATHCONF) + 1,
GFP_KERNEL); GFP_KERNEL);
if (tmp_path == NULL) { if (tmp_path == NULL) {
FreeXid(xid); if(buf)
return -ENOMEM; kfree(buf);
FreeXid(xid);
return -ENOMEM;
} }
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
...@@ -195,8 +203,10 @@ cifs_get_inode_info(struct inode **pinode, ...@@ -195,8 +203,10 @@ cifs_get_inode_info(struct inode **pinode,
kfree(tmp_path); kfree(tmp_path);
/* BB fix up inode etc. */ /* BB fix up inode etc. */
} else if (rc) { } else if (rc) {
FreeXid(xid); if(buf)
return rc; kfree(buf);
FreeXid(xid);
return rc;
} }
} else { } else {
struct cifsInodeInfo *cifsInfo; struct cifsInodeInfo *cifsInfo;
...@@ -208,8 +218,8 @@ cifs_get_inode_info(struct inode **pinode, ...@@ -208,8 +218,8 @@ cifs_get_inode_info(struct inode **pinode,
inode = *pinode; inode = *pinode;
cifsInfo = CIFS_I(inode); cifsInfo = CIFS_I(inode);
findData.Attributes = le32_to_cpu(findData.Attributes); pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
cifsInfo->cifsAttrs = findData.Attributes; cifsInfo->cifsAttrs = pfindData->Attributes;
cFYI(1, (" Old time %ld ", cifsInfo->time)); cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies; cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time)); cFYI(1, (" New time %ld ", cifsInfo->time));
...@@ -219,21 +229,21 @@ cifs_get_inode_info(struct inode **pinode, ...@@ -219,21 +229,21 @@ cifs_get_inode_info(struct inode **pinode,
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00; (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
/* Linux can not store file creation time unfortunately so we ignore it */ /* Linux can not store file creation time unfortunately so we ignore it */
inode->i_atime = inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime)); cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
inode->i_mtime = inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastWriteTime)); cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
inode->i_ctime = inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(findData.ChangeTime)); cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
cFYI(0, cFYI(0,
(" Attributes came in as 0x%x ", findData.Attributes)); (" Attributes came in as 0x%x ", pfindData->Attributes));
/* set default mode. will override for dirs below */ /* set default mode. will override for dirs below */
inode->i_mode = cifs_sb->mnt_file_mode; inode->i_mode = cifs_sb->mnt_file_mode;
if (findData.Attributes & ATTR_REPARSE) { if (pfindData->Attributes & ATTR_REPARSE) {
/* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */ /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
inode->i_mode |= S_IFLNK; inode->i_mode |= S_IFLNK;
} else if (findData.Attributes & ATTR_DIRECTORY) { } else if (pfindData->Attributes & ATTR_DIRECTORY) {
/* override default perms since we do not do byte range locking on dirs */ /* override default perms since we do not do byte range locking on dirs */
inode->i_mode = cifs_sb->mnt_dir_mode; inode->i_mode = cifs_sb->mnt_dir_mode;
inode->i_mode |= S_IFDIR; inode->i_mode |= S_IFDIR;
...@@ -244,14 +254,14 @@ cifs_get_inode_info(struct inode **pinode, ...@@ -244,14 +254,14 @@ cifs_get_inode_info(struct inode **pinode,
inode->i_mode &= ~(S_IWUGO); inode->i_mode &= ~(S_IWUGO);
/* BB add code here - validate if device or weird share or device type? */ /* BB add code here - validate if device or weird share or device type? */
} }
inode->i_size = le64_to_cpu(findData.EndOfFile); inode->i_size = le64_to_cpu(pfindData->EndOfFile);
findData.AllocationSize = le64_to_cpu(findData.AllocationSize); pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
inode->i_blocks = inode->i_blocks =
do_div(findData.AllocationSize, inode->i_blksize); do_div(pfindData->AllocationSize, inode->i_blksize);
cFYI(1, cFYI(1,
(" Size %ld and blocks %ld ", (" Size %ld and blocks %ld ",
(unsigned long) inode->i_size, inode->i_blocks)); (unsigned long) inode->i_size, inode->i_blocks));
inode->i_nlink = le32_to_cpu(findData.NumberOfLinks); inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
/* BB fill in uid and gid here? with help from winbind? /* BB fill in uid and gid here? with help from winbind?
or retrieve from NTFS stream extended attribute */ or retrieve from NTFS stream extended attribute */
...@@ -275,6 +285,8 @@ cifs_get_inode_info(struct inode **pinode, ...@@ -275,6 +285,8 @@ cifs_get_inode_info(struct inode **pinode,
kdev_t_to_nr(inode->i_rdev)); kdev_t_to_nr(inode->i_rdev));
} }
} }
if(buf)
kfree(buf);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
...@@ -290,7 +302,7 @@ cifs_read_inode(struct inode *inode) ...@@ -290,7 +302,7 @@ cifs_read_inode(struct inode *inode)
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
cifs_get_inode_info_unix(&inode, "", inode->i_sb); cifs_get_inode_info_unix(&inode, "", inode->i_sb);
else else
cifs_get_inode_info(&inode, "", inode->i_sb); cifs_get_inode_info(&inode, "", NULL, inode->i_sb);
} }
int int
...@@ -323,7 +335,7 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -323,7 +335,7 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, cifs_sb->local_nls); &netfid, &oplock, NULL, cifs_sb->local_nls);
if(rc==0) { if(rc==0) {
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
/* BB In the future chain close with the NTCreateX to narrow window */ /* BB In the future chain close with the NTCreateX to narrow window */
...@@ -387,7 +399,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -387,7 +399,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb); inode->i_sb);
else else
rc = cifs_get_inode_info(&newinode, full_path, rc = cifs_get_inode_info(&newinode, full_path,NULL,
inode->i_sb); inode->i_sb);
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
...@@ -531,7 +543,7 @@ cifs_revalidate(struct dentry *direntry) ...@@ -531,7 +543,7 @@ cifs_revalidate(struct dentry *direntry)
cifs_get_inode_info_unix(&direntry->d_inode, full_path, cifs_get_inode_info_unix(&direntry->d_inode, full_path,
direntry->d_sb); direntry->d_sb);
else else
cifs_get_inode_info(&direntry->d_inode, full_path, cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
direntry->d_sb); direntry->d_sb);
/* BB if not oplocked, invalidate inode pages if mtime has changed */ /* BB if not oplocked, invalidate inode pages if mtime has changed */
......
...@@ -160,7 +160,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -160,7 +160,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb); inode->i_sb);
else else
rc = cifs_get_inode_info(&newinode, full_path, rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb); inode->i_sb);
if (rc != 0) { if (rc != 0) {
...@@ -221,7 +221,7 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen) ...@@ -221,7 +221,7 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cifs_sb->local_nls); cifs_sb->local_nls);
else { else {
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
OPEN_REPARSE_POINT,&fid, &oplock, cifs_sb->local_nls); OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
if(!rc) { if(!rc) {
rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
tmpbuffer, tmpbuffer,
......
...@@ -390,12 +390,12 @@ is_valid_oplock_break(struct smb_hdr *buf) ...@@ -390,12 +390,12 @@ is_valid_oplock_break(struct smb_hdr *buf)
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
cFYI(1,("Matching file id, processing oplock break")); cFYI(1,("Matching file id, processing oplock break"));
pCifsInode = pCifsInode =
CIFS_I(netfile->pfile->f_dentry->d_inode); CIFS_I(netfile->pInode);
pCifsInode->clientCanCacheAll = FALSE; pCifsInode->clientCanCacheAll = FALSE;
if(pSMB->OplockLevel == 0) if(pSMB->OplockLevel == 0)
pCifsInode->clientCanCacheRead = FALSE; pCifsInode->clientCanCacheRead = FALSE;
pCifsInode->oplockPending = TRUE; pCifsInode->oplockPending = TRUE;
AllocOplockQEntry(netfile->pfile, tcon); AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
cFYI(1,("about to wake up oplock thd")); cFYI(1,("about to wake up oplock thd"));
wake_up_process(oplockThread); wake_up_process(oplockThread);
return TRUE; return TRUE;
......
...@@ -101,10 +101,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) ...@@ -101,10 +101,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
} }
struct oplock_q_entry * struct oplock_q_entry *
AllocOplockQEntry(struct file * file, struct cifsTconInfo * tcon) AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
{ {
struct oplock_q_entry *temp; struct oplock_q_entry *temp;
if ((file == NULL) || (tcon == NULL)) { if ((pinode== NULL) || (tcon == NULL)) {
cERROR(1, ("Null parms passed to AllocOplockQEntry")); cERROR(1, ("Null parms passed to AllocOplockQEntry"));
return NULL; return NULL;
} }
...@@ -113,8 +113,9 @@ AllocOplockQEntry(struct file * file, struct cifsTconInfo * tcon) ...@@ -113,8 +113,9 @@ AllocOplockQEntry(struct file * file, struct cifsTconInfo * tcon)
if (temp == NULL) if (temp == NULL)
return temp; return temp;
else { else {
temp->file_to_flush = file; temp->pinode = pinode;
temp->tcon = tcon; temp->tcon = tcon;
temp->netfid = fid;
write_lock(&GlobalMid_Lock); write_lock(&GlobalMid_Lock);
list_add_tail(&temp->qhead, &GlobalOplock_Q); list_add_tail(&temp->qhead, &GlobalOplock_Q);
write_unlock(&GlobalMid_Lock); write_unlock(&GlobalMid_Lock);
......
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