Commit f280895e authored by Steve French's avatar Steve French Committed by Steve French

cifs enablement for lookup intents (new 2.5 create/lookup flags) final part

parent f02e6170
......@@ -208,6 +208,7 @@ struct cifsFileInfo {
/* BB add lock scope info here if needed */ ;
/* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */
int endOfSearch:1; /* we have reached end of search */
int closePend:1; /* file is marked to close */
int emptyDir:1;
......@@ -263,8 +264,9 @@ struct mid_q_entry {
struct oplock_q_entry {
struct list_head qhead;
struct file * file_to_flush;
struct inode * pinode;
struct cifsTconInfo * tcon;
__u16 netfid;
};
#define MID_FREE 0
......
......@@ -57,7 +57,7 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int
/* 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 *);
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
extern u64 cifs_UnixTimeToNT(struct timespec);
......@@ -69,6 +69,7 @@ extern void Ucode_to_RevUcode_with_Len(char *Unicode, char *revUnicodeName,
int Len);
extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path,
FILE_ALL_INFO * pfile_info,
struct super_block *sb);
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
......@@ -195,7 +196,7 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid,
extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int disposition,
const int access_flags, const int omode,
__u16 * netfid, int *pOplock,
__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
const struct nls_table *nls_codepage);
extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const int smb_file_id);
......
......@@ -179,7 +179,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
cERROR(1,
("Server requires /proc/fs/cifs/PacketSigningEnabled"));
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)
buf_release(pSMB);
......@@ -419,7 +423,8 @@ int
CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int openDisposition,
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;
OPEN_REQ *pSMB = NULL;
......@@ -484,8 +489,14 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
*pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
*netfid = pSMBr->Fid; /* cifs fid stays in le */
/* Do we care about the CreateAction in any cases? */
/* BB add code to update inode file sizes from create response */
if(pfile_info) {
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)
buf_release(pSMB);
......@@ -1231,11 +1242,12 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
/* BB also check enough total bytes returned */
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
rc = -EIO; /* bad smb */
else {
else if (pFindData){
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
}
} else
rc = -ENOMEM;
}
if (pSMB)
buf_release(pSMB);
......
......@@ -131,7 +131,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
FILE_ALL_INFO * buf = NULL;
struct inode *newinode = NULL;
struct cifsFileInfo * pCifsFile = NULL;
struct cifsInodeInfo * pCifsInode;
xid = GetXid();
......@@ -140,10 +143,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
full_path = build_path_from_dentry(direntry);
if(nd) {
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)
desiredAccess = GENERIC_READ;
else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
......@@ -152,14 +154,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
desiredAccess = GENERIC_ALL;
}
/* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
if (!oplockEnabled)
oplock = REQ_OPLOCK;
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, cifs_sb->local_nls);
&fileHandle, &oplock, buf, cifs_sb->local_nls);
if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc));
} else {
......@@ -168,26 +170,53 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
inode->i_sb);
else
rc = cifs_get_inode_info(&newinode, full_path,
inode->i_sb);
buf, inode->i_sb);
if (rc != 0) {
cFYI(1,("Create worked but get_inode_info failed with rc = %d",
rc));
/* close handle */
} else {
direntry->d_op = &cifs_dentry_ops;
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;
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)
kfree(full_path);
FreeXid(xid);
......@@ -263,17 +292,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
cFYI(1,
(" 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)
rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb);
else
rc = cifs_get_inode_info(&newInode, full_path,
rc = cifs_get_inode_info(&newInode, full_path, NULL,
parent_dir_inode->i_sb);
if ((rc == 0) && (newInode != NULL)) {
......@@ -330,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 */
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 (cifs_revalidate(direntry)) {
/* unlock_kernel(); */
......
......@@ -45,6 +45,7 @@ cifs_open(struct inode *inode, struct file *file)
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
struct list_head * tmp;
char *full_path = NULL;
int desiredAccess = 0x20197;
int disposition = FILE_OPEN;
......@@ -55,6 +56,29 @@ cifs_open(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb);
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);
cFYI(1, (" inode = 0x%p file flags are %x for %s", inode, file->f_flags,full_path));
......@@ -92,8 +116,12 @@ cifs_open(struct inode *inode, struct file *file)
oplock = FALSE;
/* 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,
CREATE_NOT_DIR, &netfid, &oplock, cifs_sb->local_nls);
CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
if (rc) {
cFYI(1, ("cifs_open returned 0x%x ", rc));
cFYI(1, ("oplock: %d ", oplock));
......@@ -107,6 +135,7 @@ cifs_open(struct inode *inode, struct file *file)
pCifsFile->netfid = netfid;
pCifsFile->pid = current->pid;
pCifsFile->pfile = file; /* needed for writepage */
pCifsFile->pInode = inode;
write_lock(&file->f_owner.lock);
write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList);
......@@ -1245,7 +1274,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
pfindDataUnix->FileName,
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) {
pfindData->FileNameLength =
le32_to_cpu(pfindData->FileNameLength);
......
......@@ -155,24 +155,30 @@ cifs_get_inode_info_unix(struct inode **pinode,
}
int
cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path, struct super_block *sb)
cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
FILE_ALL_INFO * pfindData, struct super_block *sb)
{
int xid;
int rc = 0;
FILE_ALL_INFO findData;
struct cifsTconInfo *pTcon;
struct inode *inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
char *tmp_path;
char *buf = NULL;
xid = GetXid();
pTcon = cifs_sb->tcon;
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);
}
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
if (rc) {
if (rc == -EREMOTE) {
......@@ -183,6 +189,8 @@ cifs_get_inode_info(struct inode **pinode,
strnlen(search_path, MAX_PATHCONF) + 1,
GFP_KERNEL);
if (tmp_path == NULL) {
if(buf)
kfree(buf);
FreeXid(xid);
return -ENOMEM;
}
......@@ -195,6 +203,8 @@ cifs_get_inode_info(struct inode **pinode,
kfree(tmp_path);
/* BB fix up inode etc. */
} else if (rc) {
if(buf)
kfree(buf);
FreeXid(xid);
return rc;
}
......@@ -208,8 +218,8 @@ cifs_get_inode_info(struct inode **pinode,
inode = *pinode;
cifsInfo = CIFS_I(inode);
findData.Attributes = le32_to_cpu(findData.Attributes);
cifsInfo->cifsAttrs = findData.Attributes;
pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
cifsInfo->cifsAttrs = pfindData->Attributes;
cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
......@@ -219,21 +229,21 @@ cifs_get_inode_info(struct inode **pinode,
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
/* Linux can not store file creation time unfortunately so we ignore it */
inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastWriteTime));
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(findData.ChangeTime));
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
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 */
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? */
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 */
inode->i_mode = cifs_sb->mnt_dir_mode;
inode->i_mode |= S_IFDIR;
......@@ -244,14 +254,14 @@ cifs_get_inode_info(struct inode **pinode,
inode->i_mode &= ~(S_IWUGO);
/* BB add code here - validate if device or weird share or device type? */
}
inode->i_size = le64_to_cpu(findData.EndOfFile);
findData.AllocationSize = le64_to_cpu(findData.AllocationSize);
inode->i_size = le64_to_cpu(pfindData->EndOfFile);
pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
inode->i_blocks =
do_div(findData.AllocationSize, inode->i_blksize);
do_div(pfindData->AllocationSize, inode->i_blksize);
cFYI(1,
(" Size %ld and blocks %ld ",
(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?
or retrieve from NTFS stream extended attribute */
......@@ -275,6 +285,8 @@ cifs_get_inode_info(struct inode **pinode,
kdev_t_to_nr(inode->i_rdev));
}
}
if(buf)
kfree(buf);
FreeXid(xid);
return rc;
}
......@@ -290,7 +302,7 @@ cifs_read_inode(struct inode *inode)
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
cifs_get_inode_info_unix(&inode, "", inode->i_sb);
else
cifs_get_inode_info(&inode, "", inode->i_sb);
cifs_get_inode_info(&inode, "", NULL, inode->i_sb);
}
int
......@@ -323,7 +335,7 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, cifs_sb->local_nls);
&netfid, &oplock, NULL, cifs_sb->local_nls);
if(rc==0) {
CIFSSMBClose(xid, pTcon, netfid);
/* 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)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb);
else
rc = cifs_get_inode_info(&newinode, full_path,
rc = cifs_get_inode_info(&newinode, full_path,NULL,
inode->i_sb);
direntry->d_op = &cifs_dentry_ops;
......@@ -531,7 +543,7 @@ cifs_revalidate(struct dentry *direntry)
cifs_get_inode_info_unix(&direntry->d_inode, full_path,
direntry->d_sb);
else
cifs_get_inode_info(&direntry->d_inode, full_path,
cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
direntry->d_sb);
/* 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)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb);
else
rc = cifs_get_inode_info(&newinode, full_path,
rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb);
if (rc != 0) {
......@@ -221,7 +221,7 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cifs_sb->local_nls);
else {
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) {
rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
tmpbuffer,
......
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