[CIFS] Fix oops in cifs_unlink. Caused in some cases when renaming over existing,

newly created, file.

Samba bugzilla: 2697

Signed-off-by: Steve French (sfrench@us.ibm.com)
This commit is contained in:
Steve French 2005-05-17 13:16:18 -05:00
parent 67594feb4b
commit b2aeb9d565
2 changed files with 17 additions and 10 deletions

View file

@ -392,7 +392,8 @@ 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,("Error 0x%x or on cifs_get_inode_info in lookup",rc)); cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
rc,full_path));
/* BB special case check for Access Denied - watch security /* BB special case check for Access Denied - watch security
exposure of returning dir info implicitly via different rc 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 */

View file

@ -422,7 +422,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) { if (!rc) {
direntry->d_inode->i_nlink--; if(direntry->d_inode)
direntry->d_inode->i_nlink--;
} else if (rc == -ENOENT) { } else if (rc == -ENOENT) {
d_drop(direntry); d_drop(direntry);
} else if (rc == -ETXTBSY) { } else if (rc == -ETXTBSY) {
@ -440,7 +441,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--; if(direntry->d_inode)
direntry->d_inode->i_nlink--;
} }
} else if (rc == -EACCES) { } else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */ /* try only if r/o attribute set in local lookup data? */
@ -494,7 +496,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) { if (!rc) {
direntry->d_inode->i_nlink--; if(direntry->d_inode)
direntry->d_inode->i_nlink--;
} else if (rc == -ETXTBSY) { } else if (rc == -ETXTBSY) {
int oplock = FALSE; int oplock = FALSE;
__u16 netfid; __u16 netfid;
@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--; if(direntry->d_inode)
direntry->d_inode->i_nlink--;
} }
/* BB if rc = -ETXTBUSY goto the rename logic BB */ /* BB if rc = -ETXTBUSY goto the rename logic BB */
} }
} }
} }
cifsInode = CIFS_I(direntry->d_inode); if(direntry->d_inode) {
cifsInode->time = 0; /* will force revalidate to get info when cifsInode = CIFS_I(direntry->d_inode);
needed */ cifsInode->time = 0; /* will force revalidate to get info
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = when needed */
current_fs_time(inode->i_sb); direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
}
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
cifsInode = CIFS_I(inode); cifsInode = CIFS_I(inode);
cifsInode->time = 0; /* force revalidate of dir as well */ cifsInode->time = 0; /* force revalidate of dir as well */