Commit 2868fd35 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 ddac3ee3 cf3035f7
...@@ -1687,6 +1687,83 @@ struct data_blob { ...@@ -1687,6 +1687,83 @@ struct data_blob {
void (*free) (struct data_blob * data_blob); void (*free) (struct data_blob * data_blob);
}; };
#ifdef CIFS_POSIX
/*
For better POSIX semantics from Linux client, (even better
than the existing CIFS Unix Extensions) we need updated PDUs for:
1) PosixCreateX - to set and return the mode, inode#, device info and
perhaps add a CreateDevice - to create Pipes and other special .inodes
Also note POSIX open flags
2) Close - to return the last write time to do cache across close more safely
3) PosixQFSInfo - to return statfs info
4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
5) Mkdir - set mode
And under consideration:
6) FindClose2 (return nanosecond timestamp ??)
7) Use nanosecond timestamps throughout all time fields if
corresponding attribute flag is set
8) sendfile - handle based copy
9) Direct i/o
10) "POSIX ACL" support
11) Misc fcntls?
what about fixing 64 bit alignment
There are also various legacy SMB/CIFS requests used as is
From existing Lanman and NTLM dialects:
--------------------------------------
NEGOTIATE
SESSION_SETUP_ANDX (BB which?)
TREE_CONNECT_ANDX (BB which wct?)
TREE_DISCONNECT (BB add volume timestamp on response)
LOGOFF_ANDX
DELETE (note delete open file behavior)
DELETE_DIRECTORY
READ_AND_X
WRITE_AND_X
LOCKING_AND_X (note posix lock semantics)
RENAME (note rename across dirs and open file rename posix behaviors)
NT_RENAME (for hardlinks) Is this good enough for all features?
FIND_CLOSE2
TRANSACTION2 (18 cases)
SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
(BB verify that never need to set allocation size)
SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
COPY (note support for copy across directories) - FUTURE, OPTIONAL
setting/getting OS/2 EAs - FUTURE (BB can this handle
setting Linux xattrs perfectly) - OPTIONAL
dnotify - FUTURE, OPTIONAL
quota - FUTURE, OPTIONAL
Note that various requests implemented for NT interop such as
NT_TRANSACT (IOCTL) QueryReparseInfo
are unneeded to servers compliant with the CIFS POSIX extensions
From CIFS Unix Extensions:
-------------------------
T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
Actually need QUERY_FILE_UNIX_INFO since has inode num
BB what about a) blksize/blkbits/blocks
b) i_version
c) i_rdev
d) notify mask?
e) generation
f) size_seqcount
T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
*/
#endif
#pragma pack() /* resume default structure packing */ #pragma pack() /* resume default structure packing */
#endif /* _CIFSPDU_H */ #endif /* _CIFSPDU_H */
...@@ -37,13 +37,24 @@ ...@@ -37,13 +37,24 @@
#include "cifs_unicode.h" #include "cifs_unicode.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#ifdef CIFS_POSIX
static struct { static struct {
int index; int index;
char *name; char *name;
} protocols[] = { } protocols[] = {
{CIFS_PROT, "\2NT LM 0.12"}, {CIFS_PROT, "\2NT LM 0.12"},
{CIFS_PROT, "\2POSIX 2"},
{BAD_PROT, "\2"} {BAD_PROT, "\2"}
}; };
#else
static struct {
int index;
char *name;
} protocols[] = {
{CIFS_PROT, "\2NT LM 0.12"},
{BAD_PROT, "\2"}
};
#endif
/* Mark as invalid, all open files on tree connections since they /* Mark as invalid, all open files on tree connections since they
...@@ -987,60 +998,59 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, ...@@ -987,60 +998,59 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
int int
CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
const __u16 target_tid, const char *toName, const int flags, const __u16 target_tid, const char *toName, const int flags,
const struct nls_table *nls_codepage) const struct nls_table *nls_codepage)
{ {
int rc = 0; int rc = 0;
COPY_REQ *pSMB = NULL; COPY_REQ *pSMB = NULL;
COPY_RSP *pSMBr = NULL; COPY_RSP *pSMBr = NULL;
int bytes_returned; int bytes_returned;
int name_len, name_len2; int name_len, name_len2;
cFYI(1, ("In CIFSSMBCopy")); cFYI(1, ("In CIFSSMBCopy"));
copyRetry: copyRetry:
rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB, rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
(void **) &pSMBr); (void **) &pSMBr);
if (rc) if (rc)
return rc; return rc;
pSMB->BufferFormat = 0x04; pSMB->BufferFormat = 0x04;
pSMB->Tid2 = target_tid; pSMB->Tid2 = target_tid;
if(flags & COPY_TREE) if(flags & COPY_TREE)
pSMB->Flags |= COPY_TREE; pSMB->Flags |= COPY_TREE;
pSMB->Flags = cpu_to_le16(pSMB->Flags); pSMB->Flags = cpu_to_le16(pSMB->Flags);
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530 fromName,
/* find define for this maxpathcomponent */ 530 /* find define for this maxpathcomponent */,
, nls_codepage); nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
pSMB->OldFileName[name_len] = 0x04; /* pad */ pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */ /* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00; pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 = name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
cifs_strtoUCS((wchar_t *) & pSMB-> OldFileName[name_len + 2], toName, 530,
OldFileName[name_len + 2], toName, 530, nls_codepage);
nls_codepage); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */
name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */
} else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(fromName, 530);
name_len = strnlen(fromName, 530); name_len++; /* trailing null */
name_len++; /* trailing null */ strncpy(pSMB->OldFileName, fromName, name_len);
strncpy(pSMB->OldFileName, fromName, name_len); name_len2 = strnlen(toName, 530);
name_len2 = strnlen(toName, 530); name_len2++; /* trailing null */
name_len2++; /* trailing null */ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); name_len2++; /* trailing null */
name_len2++; /* trailing null */ name_len2++; /* signature byte */
name_len2++; /* signature byte */ }
}
pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2; pSMB->hdr.smb_buf_length += pSMB->ByteCount;
pSMB->hdr.smb_buf_length += pSMB->ByteCount; pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
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);
......
...@@ -53,10 +53,12 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -53,10 +53,12 @@ build_path_from_dentry(struct dentry *direntry)
namelen += (1 + temp->d_name.len); namelen += (1 + temp->d_name.len);
temp = temp->d_parent; temp = temp->d_parent;
} }
namelen += 1; /* allow for trailing null */
full_path = kmalloc(namelen, GFP_KERNEL); full_path = kmalloc(namelen+1, GFP_KERNEL);
namelen--; if(full_path == NULL)
return full_path;
full_path[namelen] = 0; /* trailing null */ full_path[namelen] = 0; /* trailing null */
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
namelen -= 1 + temp->d_name.len; namelen -= 1 + temp->d_name.len;
if (namelen < 0) { if (namelen < 0) {
...@@ -142,10 +144,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -142,10 +144,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
if(nd) { if(nd) {
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;
else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
...@@ -173,6 +177,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -173,6 +177,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
if(buf == NULL) {
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR, desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls); &fileHandle, &oplock, buf, cifs_sb->local_nls);
...@@ -273,8 +283,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev ...@@ -273,8 +283,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL)
if (pTcon->ses->capabilities & CAP_UNIX) { rc = -ENOMEM;
if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, current->euid, current->egid, full_path, mode, current->euid, current->egid,
device_number, cifs_sb->local_nls); device_number, cifs_sb->local_nls);
...@@ -298,7 +310,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev ...@@ -298,7 +310,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
struct dentry * struct dentry *
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
{ {
int rc, xid; int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode *newInode = NULL; struct inode *newInode = NULL;
...@@ -321,6 +334,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -321,6 +334,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return ERR_PTR(-ENOMEM);
}
if (direntry->d_inode != NULL) { if (direntry->d_inode != NULL) {
cFYI(1, (" non-NULL inode in lookup")); cFYI(1, (" non-NULL inode in lookup"));
} else { } else {
...@@ -347,10 +365,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -347,10 +365,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
rc = 0; rc = 0;
d_add(direntry, NULL); d_add(direntry, NULL);
} else { } else {
cERROR(1, cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup", /* BB special case check for Access Denied - watch security
rc, rc)); exposure of returning dir info implicitly via different rc
/* BB special case check for Access Denied - watch security exposure of returning dir info implicitly via different rc if file exists or not but no access BB */ if file exists or not but no access BB */
} }
if (full_path) if (full_path)
......
...@@ -40,8 +40,13 @@ int cifs_directory_notify(unsigned long arg, struct file * file) ...@@ -40,8 +40,13 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
cifs_sb = CIFS_SB(file->f_dentry->d_sb); cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
cFYI(1,("cifs dir notify on file %s",full_path)); if(full_path == NULL) {
/* CIFSSMBNotify */ rc = -ENOMEM;
} else {
cFYI(1,("cifs dir notify on file %s",full_path));
/* CIFSSMBNotify(xid, pTcon, full_path, cifs_sb->local_nls);*/
}
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
......
...@@ -81,6 +81,10 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -81,6 +81,10 @@ cifs_open(struct inode *inode, struct file *file)
} }
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, (" inode = 0x%p file flags are 0x%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)
...@@ -150,8 +154,6 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -150,8 +154,6 @@ cifs_open(struct inode *inode, struct file *file)
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 {
if(file->private_data)
kfree(file->private_data);
file->private_data = file->private_data =
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
if (file->private_data) { if (file->private_data) {
...@@ -286,6 +288,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file) ...@@ -286,6 +288,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
if(full_path == NULL) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, (" inode = 0x%p file flags are 0x%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)
...@@ -634,26 +641,22 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to) ...@@ -634,26 +641,22 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
int bytes_written = 0; int bytes_written = 0;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode *inode = page->mapping->host; struct inode *inode;
struct cifsInodeInfo *cifsInode; struct cifsInodeInfo *cifsInode;
struct cifsFileInfo *open_file = NULL; struct cifsFileInfo *open_file = NULL;
struct list_head *tmp; struct list_head *tmp;
struct list_head *tmp1; struct list_head *tmp1;
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
/* figure out which file struct to use
if (file->private_data == NULL) {
return -EBADF;
}
*/
if (!mapping) { if (!mapping) {
return -EFAULT; return -EFAULT;
} else if(!mapping->host) { } else if(!mapping->host) {
return -EFAULT; return -EFAULT;
} }
inode = page->mapping->host;
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
offset += (loff_t)from; offset += (loff_t)from;
write_data = kmap(page); write_data = kmap(page);
write_data += from; write_data += from;
......
...@@ -346,7 +346,10 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -346,7 +346,10 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
if (!rc) { if (!rc) {
...@@ -428,6 +431,10 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -428,6 +431,10 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
/* BB add setting the equivalent of mode via CreateX w/ACLs */ /* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
if (rc) { if (rc) {
...@@ -481,6 +488,10 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -481,6 +488,10 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
...@@ -527,6 +538,10 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry, ...@@ -527,6 +538,10 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
fromName = build_path_from_dentry(source_direntry); fromName = build_path_from_dentry(source_direntry);
toName = build_path_from_dentry(target_direntry); toName = build_path_from_dentry(target_direntry);
if((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_rename_exit;
}
rc = CIFSSMBRename(xid, pTcon, fromName, toName, rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls); cifs_sb_source->local_nls);
...@@ -549,6 +564,8 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry, ...@@ -549,6 +564,8 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
} }
} }
cifs_rename_exit:
if (fromName) if (fromName)
kfree(fromName); kfree(fromName);
if (toName) if (toName)
...@@ -587,6 +604,10 @@ cifs_revalidate(struct dentry *direntry) ...@@ -587,6 +604,10 @@ cifs_revalidate(struct dentry *direntry)
cifs_sb = CIFS_SB(direntry->d_sb); cifs_sb = CIFS_SB(direntry->d_sb);
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, cFYI(1,
("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld", ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
full_path, direntry->d_inode, full_path, direntry->d_inode,
...@@ -731,6 +752,10 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -731,6 +752,10 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cifsInode = CIFS_I(direntry->d_inode); cifsInode = CIFS_I(direntry->d_inode);
/* BB check if we need to refresh inode from server now ? BB */ /* BB check if we need to refresh inode from server now ? BB */
......
...@@ -48,6 +48,11 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -48,6 +48,11 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
fromName = build_path_from_dentry(old_file); fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry); toName = build_path_from_dentry(direntry);
if((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_hl_exit;
}
if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls); cifs_sb_target->local_nls);
...@@ -70,6 +75,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -70,6 +75,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifsInode = CIFS_I(old_file->d_inode); cifsInode = CIFS_I(old_file->d_inode);
cifsInode->time = 0; /* will force revalidate to go get info when needed */ cifsInode->time = 0; /* will force revalidate to go get info when needed */
cifs_hl_exit:
if (fromName) if (fromName)
kfree(fromName); kfree(fromName);
if (toName) if (toName)
...@@ -91,6 +97,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -91,6 +97,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid(); xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
...@@ -150,6 +160,11 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -150,6 +160,11 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, ("Full path: %s ", full_path)); cFYI(1, ("Full path: %s ", full_path));
cFYI(1, ("symname is %s", symname)); cFYI(1, ("symname is %s", symname));
...@@ -205,6 +220,11 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen) ...@@ -205,6 +220,11 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, cFYI(1,
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
full_path, inode, pBuffer, buflen)); full_path, inode, pBuffer, buflen));
......
...@@ -187,22 +187,26 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -187,22 +187,26 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return -EIO; return -EIO;
} }
/* make sure that we sign in the same order that we send on this socket
and avoid races inside tcp sendmsg code that could cause corruption
of smb data */
down(&ses->server->tcpSem);
if (ses->server->tcpStatus == CifsExiting) { if (ses->server->tcpStatus == CifsExiting) {
return -ENOENT; rc = -ENOENT;
goto out_unlock;
} else if (ses->server->tcpStatus == CifsNeedReconnect) { } else if (ses->server->tcpStatus == CifsNeedReconnect) {
cFYI(1,("tcp session dead - return to caller to retry")); cFYI(1,("tcp session dead - return to caller to retry"));
return -EAGAIN; rc = -EAGAIN;
goto out_unlock;
} else if (ses->status != CifsGood) { } else if (ses->status != CifsGood) {
/* check if SMB session is bad because we are setting it up */ /* check if SMB session is bad because we are setting it up */
if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) { (in_buf->Command != SMB_COM_NEGOTIATE)) {
return -EAGAIN; rc = -EAGAIN;
goto out_unlock;
} /* else ok - we are setting up session */ } /* else ok - we are setting up session */
} }
/* make sure that we sign in the same order that we send on this socket
and avoid races inside tcp sendmsg code that could cause corruption
of smb data */
down(&ses->server->tcpSem);
midQ = AllocMidQEntry(in_buf, ses); midQ = AllocMidQEntry(in_buf, ses);
if (midQ == NULL) { if (midQ == NULL) {
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
...@@ -288,7 +292,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -288,7 +292,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return rc; return rc;
} }
if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1, cERROR(1,
("Frame too large received. Length: %d Xid: %d", ("Frame too large received. Length: %d Xid: %d",
...@@ -342,4 +345,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -342,4 +345,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
- BB add background daemon to clean up Mid entries from - BB add background daemon to clean up Mid entries from
killed processes & test killing process with active mid */ killed processes & test killing process with active mid */
return rc; return rc;
out_unlock:
up(&ses->server->tcpSem);
return rc;
} }
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