bk://cifs.bkbits.net/linux-2.5cifs cifs.adm@hostme.bitkeeper.com|ChangeSet|20040526013611|10092 cifs.adm # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/05/25 21:18:56-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/25 21:18:53-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/25 17:37:38-05:00 stevef@stevef95.austin.ibm.com # Merge bk://cifs.bkbits.net/linux-2.5cifs # into stevef95.austin.ibm.com:/home/stevef/linux-2.5cifs # # fs/cifs/cifssmb.c # 2004/05/25 17:37:26-05:00 stevef@stevef95.austin.ibm.com +0 -0 # Auto merged # # ChangeSet # 2004/05/25 17:36:24-05:00 stevef@stevef95.austin.ibm.com # do not log errors on write failures unless debug is on # # fs/cifs/cifssmb.c # 2004/05/25 17:36:16-05:00 stevef@stevef95.austin.ibm.com +2 -2 # do not log errors on write failures unless debug is on # # ChangeSet # 2004/05/25 00:13:22-05:00 stevef@smfhome.smfdom # Retry build_path_from_dentry if parent path changes in flight # # fs/cifs/dir.c # 2004/05/25 00:13:15-05:00 stevef@smfhome.smfdom +18 -1 # Retry build_path_from_dentry if parent path changes in flight # # ChangeSet # 2004/05/24 23:58:35-05:00 stevef@smfhome.smfdom # check for close pending and invalid file struct on writing out page # # fs/cifs/file.c # 2004/05/24 23:58:29-05:00 stevef@smfhome.smfdom +14 -1 # check for close pending and invalid file struct on writing out page # # fs/cifs/CHANGES # 2004/05/24 23:58:29-05:00 stevef@smfhome.smfdom +2 -1 # update cifs change log # # ChangeSet # 2004/05/24 18:04:01-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/24 18:03:57-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/24 19:51:38-05:00 stevef@smfhome1.smfsambadom # Fix incorrect file size on handle based setattr (for big endian hardware) # # fs/cifs/cifssmb.c # 2004/05/24 19:51:31-05:00 stevef@smfhome1.smfsambadom +1 -1 # Fix incorrect file size on handle based setattr (for big endian hardware) # # fs/cifs/cifsfs.h # 2004/05/24 19:51:31-05:00 stevef@smfhome1.smfsambadom +1 -1 # Update cifs version to 1.16 # # fs/cifs/CHANGES # 2004/05/24 19:51:30-05:00 stevef@smfhome1.smfsambadom +5 -0 # Update cifs version to 1.16 # # ChangeSet # 2004/05/22 23:28:34-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/22 23:28:31-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/22 23:20:38-05:00 stevef@smfhome1.smfsambadom # fix oops in heavy stress test caused by lack of check for bad dentry being passed in on reconnect # # fs/cifs/file.c # 2004/05/22 23:20:31-05:00 stevef@smfhome1.smfsambadom +6 -1 # fix oops in heavy stress test caused by lack of check for bad dentry being passed in on reconnect # # fs/cifs/dir.c # 2004/05/22 23:20:31-05:00 stevef@smfhome1.smfsambadom +6 -1 # fix oops in heavy stress test caused by lack of check for bad dentry being passed in on reconnect # # ChangeSet # 2004/05/22 05:47:17-05:00 stevef@steveft21.ltcsamba # Check for kmalloc failure on building full path # # fs/cifs/link.c # 2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +20 -0 # Check for kmalloc failure on building full path # # fs/cifs/inode.c # 2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +26 -1 # Check for kmalloc failure on building full path # # fs/cifs/file.c # 2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +9 -0 # Check for kmalloc failure on building full path # # fs/cifs/fcntl.c # 2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +7 -2 # Check for kmalloc failure on building full path # # fs/cifs/dir.c # 2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +27 -7 # Check for kmalloc failure on building full path # # fs/cifs/file.c # 2004/05/21 20:32:52-05:00 stevef@steveft21.ltcsamba +5 -11 # reorder check for bad pointer # # fs/cifs/dir.c # 2004/05/21 20:32:52-05:00 stevef@steveft21.ltcsamba +4 -6 # cleanup ugly code # # fs/cifs/transport.c # 2004/05/21 05:45:32-05:00 stevef@steveft21.ltcsamba +15 -8 # check session status in the right order, after getting ses semaphore # # ChangeSet # 2004/05/20 03:26:15-05:00 stevef@steveft21.ltcsamba # POSIX protocol extensions part 1 # # fs/cifs/cifssmb.c # 2004/05/20 03:25:20-05:00 stevef@steveft21.ltcsamba +54 -44 # POSIX protocol extensions part 1 # # fs/cifs/cifspdu.h # 2004/05/20 03:25:19-05:00 stevef@steveft21.ltcsamba +77 -0 # POSIX protocol extensions part 1 # # ChangeSet # 2004/05/18 14:31:25-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/05/18 14:31:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/11 16:37:09-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/11 16:37:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/04 13:51:19-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/04 13:51:17-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/02 21:56:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/02 21:56:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/cifs/cifsfs.c # 2004/05/02 21:56:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/01 15:05:17-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/01 15:05:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/29 15:41:50-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/04/29 15:41:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/26 18:11:55-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/26 18:11:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/23 12:36:52-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/23 12:36:49-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/19 19:23:58-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/19 19:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/16 20:19:53-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/16 20:19:51-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/16 20:18:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/16 20:18:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/CHANGES 2004-05-25 21:19:51 -07:00 @@ -1,3 +1,9 @@ +Version 1.16 +------------ +Fix incorrect file size in file handle based setattr on big endian hardware. +Fix oops in build_path_from_dentry when out of memory. Add checks for invalid +and closing file structs in writepage/partialpagewrite + Version 1.15 ------------ Change to mempools for alloc smb request buffers and multiplex structs diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h --- a/fs/cifs/cifsfs.h 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/cifsfs.h 2004-05-25 21:19:51 -07:00 @@ -93,5 +93,5 @@ size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -#define CIFS_VERSION "1.15" +#define CIFS_VERSION "1.16" #endif /* _CIFSFS_H */ diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h --- a/fs/cifs/cifspdu.h 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/cifspdu.h 2004-05-25 21:19:51 -07:00 @@ -1687,6 +1687,83 @@ 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 */ #endif /* _CIFSPDU_H */ diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c --- a/fs/cifs/cifssmb.c 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/cifssmb.c 2004-05-25 21:19:51 -07:00 @@ -37,13 +37,24 @@ #include "cifs_unicode.h" #include "cifs_debug.h" +#ifdef CIFS_POSIX static struct { int index; char *name; } protocols[] = { {CIFS_PROT, "\2NT LM 0.12"}, + {CIFS_PROT, "\2POSIX 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 @@ -728,7 +739,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, long_op); if (rc) { - cERROR(1, ("Send error in write = %d", rc)); + cFYI(1, ("Send error in write = %d", rc)); *nbytes = 0; } else *nbytes = le16_to_cpu(pSMBr->Count); @@ -792,7 +803,7 @@ (struct smb_hdr *) pSMBr, &bytes_returned, timeout); if (rc) { - cERROR(1, ("Send error in Lock = %d", rc)); + cFYI(1, ("Send error in Lock = %d", rc)); } if (pSMB) cifs_buf_release(pSMB); @@ -987,60 +998,59 @@ int CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, - const __u16 target_tid, const char *toName, const int flags, - const struct nls_table *nls_codepage) + const __u16 target_tid, const char *toName, const int flags, + const struct nls_table *nls_codepage) { - int rc = 0; - COPY_REQ *pSMB = NULL; - COPY_RSP *pSMBr = NULL; - int bytes_returned; - int name_len, name_len2; + int rc = 0; + COPY_REQ *pSMB = NULL; + COPY_RSP *pSMBr = NULL; + int bytes_returned; + int name_len, name_len2; - cFYI(1, ("In CIFSSMBCopy")); + cFYI(1, ("In CIFSSMBCopy")); copyRetry: - rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; + rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; - pSMB->BufferFormat = 0x04; + pSMB->BufferFormat = 0x04; pSMB->Tid2 = target_tid; if(flags & COPY_TREE) pSMB->Flags |= COPY_TREE; pSMB->Flags = cpu_to_le16(pSMB->Flags); - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530 - /* find define for this maxpathcomponent */ - , nls_codepage); - name_len++; /* trailing null */ - name_len *= 2; - pSMB->OldFileName[name_len] = 0x04; /* pad */ - /* protocol requires ASCII signature byte on Unicode string */ - pSMB->OldFileName[name_len + 1] = 0x00; - name_len2 = - cifs_strtoUCS((wchar_t *) & pSMB-> - OldFileName[name_len + 2], toName, 530, - nls_codepage); - name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; - name_len2 *= 2; /* convert to bytes */ - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, 530); - name_len++; /* trailing null */ - strncpy(pSMB->OldFileName, fromName, name_len); - name_len2 = strnlen(toName, 530); - name_len2++; /* trailing null */ - pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ - strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); - name_len2++; /* trailing null */ - name_len2++; /* signature byte */ - } - - pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2; - pSMB->hdr.smb_buf_length += pSMB->ByteCount; - pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, + fromName, + 530 /* find define for this maxpathcomponent */, + nls_codepage); + name_len++; /* trailing null */ + name_len *= 2; + pSMB->OldFileName[name_len] = 0x04; /* pad */ + /* protocol requires ASCII signature byte on Unicode string */ + pSMB->OldFileName[name_len + 1] = 0x00; + name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> + OldFileName[name_len + 2], toName, 530, + nls_codepage); + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; + name_len2 *= 2; /* convert to bytes */ + } else { /* BB improve the check for buffer overruns BB */ + name_len = strnlen(fromName, 530); + name_len++; /* trailing null */ + strncpy(pSMB->OldFileName, fromName, name_len); + name_len2 = strnlen(toName, 530); + name_len2++; /* trailing null */ + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ + strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); + name_len2++; /* trailing null */ + name_len2++; /* signature byte */ + } + + pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2; + pSMB->hdr.smb_buf_length += pSMB->ByteCount; + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); @@ -2581,7 +2591,7 @@ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) + pSMB->DataOffset); pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */ - parm_data->FileSize = size; + parm_data->FileSize = cpu_to_le64(size); pSMB->Fid = fid; if(SetAllocation) { if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c --- a/fs/cifs/dir.c 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/dir.c 2004-05-25 21:19:51 -07:00 @@ -38,7 +38,7 @@ do { direntry->d_time = jiffies; direntry = direntry->d_parent; - } while (!IS_ROOT(direntry)); /* BB for DFS case should stop at the root of share which could be lower than root of this mount due to implicit dfs connections */ + } while (!IS_ROOT(direntry)); } /* Note: caller must free return buffer */ @@ -49,14 +49,26 @@ int namelen = 0; char *full_path; + if(direntry == NULL) + return NULL; /* not much we can do if dentry is freed and + we need to reopen the file after it was closed implicitly + when the server crashed */ + +cifs_bp_rename_retry: for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); temp = temp->d_parent; + if(temp == NULL) { + cERROR(1,("corrupt dentry")); + return NULL; + } } - namelen += 1; /* allow for trailing null */ - full_path = kmalloc(namelen, GFP_KERNEL); - namelen--; + + full_path = kmalloc(namelen+1, GFP_KERNEL); + if(full_path == NULL) + return full_path; full_path[namelen] = 0; /* trailing null */ + for (temp = direntry; !IS_ROOT(temp);) { namelen -= 1 + temp->d_name.len; if (namelen < 0) { @@ -68,11 +80,23 @@ cFYI(0, (" name: %s ", full_path + namelen)); } temp = temp->d_parent; + if(temp == NULL) { + cERROR(1,("corrupt dentry")); + kfree(full_path); + return NULL; + } } - if (namelen != 0) + if (namelen != 0) { cERROR(1, ("We did not end path lookup where we expected namelen is %d", namelen)); + /* presumably this is only possible if we were racing with a rename + of one of the parent directories (we can not lock the dentries + above us to prevent this, but retrying should be harmless) */ + kfree(full_path); + namelen = 0; + goto cifs_bp_rename_retry; + } return full_path; } @@ -142,10 +166,12 @@ pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); + if(full_path == NULL) { + FreeXid(xid); + return -ENOMEM; + } - 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) { if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) desiredAccess = GENERIC_READ; else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) @@ -173,6 +199,12 @@ oplock = REQ_OPLOCK; 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, desiredAccess, CREATE_NOT_DIR, &fileHandle, &oplock, buf, cifs_sb->local_nls); @@ -273,8 +305,10 @@ pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); - - if (pTcon->ses->capabilities & CAP_UNIX) { + if(full_path == NULL) + rc = -ENOMEM; + + if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, current->euid, current->egid, device_number, cifs_sb->local_nls); @@ -298,7 +332,8 @@ struct dentry * 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 cifsTconInfo *pTcon; struct inode *newInode = NULL; @@ -321,6 +356,11 @@ pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); + if(full_path == NULL) { + FreeXid(xid); + return ERR_PTR(-ENOMEM); + } + if (direntry->d_inode != NULL) { cFYI(1, (" non-NULL inode in lookup")); } else { @@ -347,10 +387,10 @@ rc = 0; d_add(direntry, NULL); } else { - cERROR(1, - ("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup", - rc, 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 */ + cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",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 (full_path) diff -Nru a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c --- a/fs/cifs/fcntl.c 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/fcntl.c 2004-05-25 21:19:51 -07:00 @@ -40,8 +40,13 @@ cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(file->f_dentry); - cFYI(1,("cifs dir notify on file %s",full_path)); - /* CIFSSMBNotify */ + if(full_path == NULL) { + rc = -ENOMEM; + } else { + cFYI(1,("cifs dir notify on file %s",full_path)); + /* CIFSSMBNotify(xid, pTcon, full_path, cifs_sb->local_nls);*/ + } + FreeXid(xid); return rc; } diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c --- a/fs/cifs/file.c 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/file.c 2004-05-25 21:19:51 -07:00 @@ -81,6 +81,10 @@ } 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)); if ((file->f_flags & O_ACCMODE) == O_RDONLY) @@ -150,8 +154,6 @@ cFYI(1, ("cifs_open returned 0x%x ", rc)); cFYI(1, ("oplock: %d ", oplock)); } else { - if(file->private_data) - kfree(file->private_data); file->private_data = kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); if (file->private_data) { @@ -281,11 +283,21 @@ return 0; } - + if(file->f_dentry == NULL) { + up(&pCifsFile->fh_sem); + cFYI(1,("failed file reopen, no valid name if dentry freed")); + FreeXid(xid); + return -EBADF; + } cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; 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)); if ((file->f_flags & O_ACCMODE) == O_RDONLY) @@ -546,6 +558,9 @@ int xid, long_op; struct cifsFileInfo * open_file; + if(file->f_dentry == NULL) + return -EBADF; + xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -634,26 +649,22 @@ int bytes_written = 0; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; - struct inode *inode = page->mapping->host; + struct inode *inode; struct cifsInodeInfo *cifsInode; struct cifsFileInfo *open_file = NULL; struct list_head *tmp; 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) { return -EFAULT; } else if(!mapping->host) { return -EFAULT; } + inode = page->mapping->host; + cifs_sb = CIFS_SB(inode->i_sb); + pTcon = cifs_sb->tcon; + offset += (loff_t)from; write_data = kmap(page); write_data += from; @@ -678,6 +689,8 @@ read_lock(&GlobalSMBSeslock); list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { open_file = list_entry(tmp,struct cifsFileInfo, flist); + if(open_file->closePend) + continue; /* We check if file is open for writing first */ if((open_file->pfile) && ((open_file->pfile->f_flags & O_RDWR) || @@ -691,7 +704,15 @@ if ((bytes_written > 0) && (offset)) { rc = 0; } else if(bytes_written < 0) { - rc = bytes_written; + if(rc == -EBADF) { + /* have seen a case in which + kernel seemed to have closed/freed a file + even with writes active so we might as well + see if there are other file structs to try + for the same inode before giving up */ + continue; + } else + rc = bytes_written; } break; /* now that we found a valid file handle and tried to write to it we are done, no diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c --- a/fs/cifs/inode.c 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/inode.c 2004-05-25 21:19:51 -07:00 @@ -346,7 +346,10 @@ pTcon = cifs_sb->tcon; 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); if (!rc) { @@ -428,6 +431,10 @@ pTcon = cifs_sb->tcon; 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 */ rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); if (rc) { @@ -481,6 +488,10 @@ pTcon = cifs_sb->tcon; 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); @@ -527,6 +538,10 @@ fromName = build_path_from_dentry(source_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, cifs_sb_source->local_nls); @@ -549,6 +564,8 @@ CIFSSMBClose(xid, pTcon, netfid); } } + +cifs_rename_exit: if (fromName) kfree(fromName); if (toName) @@ -587,6 +604,10 @@ cifs_sb = CIFS_SB(direntry->d_sb); full_path = build_path_from_dentry(direntry); + if(full_path == NULL) { + FreeXid(xid); + return -ENOMEM; + } cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld", full_path, direntry->d_inode, @@ -731,6 +752,10 @@ pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); + if(full_path == NULL) { + FreeXid(xid); + return -ENOMEM; + } cifsInode = CIFS_I(direntry->d_inode); /* BB check if we need to refresh inode from server now ? BB */ diff -Nru a/fs/cifs/link.c b/fs/cifs/link.c --- a/fs/cifs/link.c 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/link.c 2004-05-25 21:19:51 -07:00 @@ -48,6 +48,11 @@ fromName = build_path_from_dentry(old_file); 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) rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, cifs_sb_target->local_nls); @@ -70,6 +75,7 @@ cifsInode = CIFS_I(old_file->d_inode); cifsInode->time = 0; /* will force revalidate to go get info when needed */ +cifs_hl_exit: if (fromName) kfree(fromName); if (toName) @@ -91,6 +97,10 @@ xid = GetXid(); 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)); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; @@ -150,6 +160,11 @@ pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); + if(full_path == NULL) { + FreeXid(xid); + return -ENOMEM; + } + cFYI(1, ("Full path: %s ", full_path)); cFYI(1, ("symname is %s", symname)); @@ -205,6 +220,11 @@ cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); + if(full_path == NULL) { + FreeXid(xid); + return -ENOMEM; + } + cFYI(1, ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", full_path, inode, pBuffer, buflen)); diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c --- a/fs/cifs/transport.c 2004-05-25 21:19:51 -07:00 +++ b/fs/cifs/transport.c 2004-05-25 21:19:51 -07:00 @@ -187,22 +187,26 @@ 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) { - return -ENOENT; + rc = -ENOENT; + goto out_unlock; } else if (ses->server->tcpStatus == CifsNeedReconnect) { cFYI(1,("tcp session dead - return to caller to retry")); - return -EAGAIN; + rc = -EAGAIN; + goto out_unlock; } else if (ses->status != CifsGood) { /* check if SMB session is bad because we are setting it up */ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && (in_buf->Command != SMB_COM_NEGOTIATE)) { - return -EAGAIN; + rc = -EAGAIN; + goto out_unlock; } /* 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); if (midQ == NULL) { up(&ses->server->tcpSem); @@ -288,7 +292,6 @@ return rc; } - if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { cERROR(1, ("Frame too large received. Length: %d Xid: %d", @@ -341,5 +344,9 @@ DeleteMidQEntry(midQ); /* BB what if process is killed? - BB add background daemon to clean up Mid entries from killed processes & test killing process with active mid */ + return rc; + +out_unlock: + up(&ses->server->tcpSem); return rc; }