diff options
Diffstat (limited to 'fs/cifs/file.c')
| -rw-r--r-- | fs/cifs/file.c | 100 |
1 files changed, 35 insertions, 65 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 75541af4b3db..409e4f523e61 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -162,44 +162,12 @@ psx_client_can_cache: | |||
| 162 | return 0; | 162 | return 0; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static struct cifsFileInfo * | ||
| 166 | cifs_fill_filedata(struct file *file) | ||
| 167 | { | ||
| 168 | struct list_head *tmp; | ||
| 169 | struct cifsFileInfo *pCifsFile = NULL; | ||
| 170 | struct cifsInodeInfo *pCifsInode = NULL; | ||
| 171 | |||
| 172 | /* search inode for this file and fill in file->private_data */ | ||
| 173 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | ||
| 174 | read_lock(&GlobalSMBSeslock); | ||
| 175 | list_for_each(tmp, &pCifsInode->openFileList) { | ||
| 176 | pCifsFile = list_entry(tmp, struct cifsFileInfo, flist); | ||
| 177 | if ((pCifsFile->pfile == NULL) && | ||
| 178 | (pCifsFile->pid == current->tgid)) { | ||
| 179 | /* mode set in cifs_create */ | ||
| 180 | |||
| 181 | /* needed for writepage */ | ||
| 182 | pCifsFile->pfile = file; | ||
| 183 | file->private_data = pCifsFile; | ||
| 184 | break; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | read_unlock(&GlobalSMBSeslock); | ||
| 188 | |||
| 189 | if (file->private_data != NULL) { | ||
| 190 | return pCifsFile; | ||
| 191 | } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL)) | ||
| 192 | cERROR(1, "could not find file instance for " | ||
| 193 | "new file %p", file); | ||
| 194 | return NULL; | ||
| 195 | } | ||
| 196 | |||
| 197 | /* all arguments to this function must be checked for validity in caller */ | 165 | /* all arguments to this function must be checked for validity in caller */ |
| 198 | static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | 166 | static inline int cifs_open_inode_helper(struct inode *inode, |
| 199 | struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, | ||
| 200 | struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, | 167 | struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, |
| 201 | char *full_path, int xid) | 168 | char *full_path, int xid) |
| 202 | { | 169 | { |
| 170 | struct cifsInodeInfo *pCifsInode = CIFS_I(inode); | ||
| 203 | struct timespec temp; | 171 | struct timespec temp; |
| 204 | int rc; | 172 | int rc; |
| 205 | 173 | ||
| @@ -213,36 +181,35 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | |||
| 213 | /* if not oplocked, invalidate inode pages if mtime or file | 181 | /* if not oplocked, invalidate inode pages if mtime or file |
| 214 | size changed */ | 182 | size changed */ |
| 215 | temp = cifs_NTtimeToUnix(buf->LastWriteTime); | 183 | temp = cifs_NTtimeToUnix(buf->LastWriteTime); |
| 216 | if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && | 184 | if (timespec_equal(&inode->i_mtime, &temp) && |
| 217 | (file->f_path.dentry->d_inode->i_size == | 185 | (inode->i_size == |
| 218 | (loff_t)le64_to_cpu(buf->EndOfFile))) { | 186 | (loff_t)le64_to_cpu(buf->EndOfFile))) { |
| 219 | cFYI(1, "inode unchanged on server"); | 187 | cFYI(1, "inode unchanged on server"); |
| 220 | } else { | 188 | } else { |
| 221 | if (file->f_path.dentry->d_inode->i_mapping) { | 189 | if (inode->i_mapping) { |
| 222 | /* BB no need to lock inode until after invalidate | 190 | /* BB no need to lock inode until after invalidate |
| 223 | since namei code should already have it locked? */ | 191 | since namei code should already have it locked? */ |
| 224 | rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); | 192 | rc = filemap_write_and_wait(inode->i_mapping); |
| 225 | if (rc != 0) | 193 | if (rc != 0) |
| 226 | CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; | 194 | pCifsInode->write_behind_rc = rc; |
| 227 | } | 195 | } |
| 228 | cFYI(1, "invalidating remote inode since open detected it " | 196 | cFYI(1, "invalidating remote inode since open detected it " |
| 229 | "changed"); | 197 | "changed"); |
| 230 | invalidate_remote_inode(file->f_path.dentry->d_inode); | 198 | invalidate_remote_inode(inode); |
| 231 | } | 199 | } |
| 232 | 200 | ||
| 233 | client_can_cache: | 201 | client_can_cache: |
| 234 | if (pTcon->unix_ext) | 202 | if (pTcon->unix_ext) |
| 235 | rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode, | 203 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, |
| 236 | full_path, inode->i_sb, xid); | 204 | xid); |
| 237 | else | 205 | else |
| 238 | rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, | 206 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, |
| 239 | full_path, buf, inode->i_sb, xid, NULL); | 207 | xid, NULL); |
| 240 | 208 | ||
| 241 | if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 209 | if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
| 242 | pCifsInode->clientCanCacheAll = true; | 210 | pCifsInode->clientCanCacheAll = true; |
| 243 | pCifsInode->clientCanCacheRead = true; | 211 | pCifsInode->clientCanCacheRead = true; |
| 244 | cFYI(1, "Exclusive Oplock granted on inode %p", | 212 | cFYI(1, "Exclusive Oplock granted on inode %p", inode); |
| 245 | file->f_path.dentry->d_inode); | ||
| 246 | } else if ((*oplock & 0xF) == OPLOCK_READ) | 213 | } else if ((*oplock & 0xF) == OPLOCK_READ) |
| 247 | pCifsInode->clientCanCacheRead = true; | 214 | pCifsInode->clientCanCacheRead = true; |
| 248 | 215 | ||
| @@ -256,7 +223,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 256 | __u32 oplock; | 223 | __u32 oplock; |
| 257 | struct cifs_sb_info *cifs_sb; | 224 | struct cifs_sb_info *cifs_sb; |
| 258 | struct cifsTconInfo *tcon; | 225 | struct cifsTconInfo *tcon; |
| 259 | struct cifsFileInfo *pCifsFile; | 226 | struct cifsFileInfo *pCifsFile = NULL; |
| 260 | struct cifsInodeInfo *pCifsInode; | 227 | struct cifsInodeInfo *pCifsInode; |
| 261 | char *full_path = NULL; | 228 | char *full_path = NULL; |
| 262 | int desiredAccess; | 229 | int desiredAccess; |
| @@ -270,12 +237,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 270 | tcon = cifs_sb->tcon; | 237 | tcon = cifs_sb->tcon; |
| 271 | 238 | ||
| 272 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | 239 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); |
| 273 | pCifsFile = cifs_fill_filedata(file); | ||
| 274 | if (pCifsFile) { | ||
| 275 | rc = 0; | ||
| 276 | FreeXid(xid); | ||
| 277 | return rc; | ||
| 278 | } | ||
| 279 | 240 | ||
| 280 | full_path = build_path_from_dentry(file->f_path.dentry); | 241 | full_path = build_path_from_dentry(file->f_path.dentry); |
| 281 | if (full_path == NULL) { | 242 | if (full_path == NULL) { |
| @@ -299,8 +260,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 299 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | 260 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); |
| 300 | oflags |= SMB_O_CREAT; | 261 | oflags |= SMB_O_CREAT; |
| 301 | /* can not refresh inode info since size could be stale */ | 262 | /* can not refresh inode info since size could be stale */ |
| 302 | rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, | 263 | rc = cifs_posix_open(full_path, &inode, inode->i_sb, |
| 303 | inode->i_sb, | ||
| 304 | cifs_sb->mnt_file_mode /* ignored */, | 264 | cifs_sb->mnt_file_mode /* ignored */, |
| 305 | oflags, &oplock, &netfid, xid); | 265 | oflags, &oplock, &netfid, xid); |
| 306 | if (rc == 0) { | 266 | if (rc == 0) { |
| @@ -308,9 +268,20 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 308 | /* no need for special case handling of setting mode | 268 | /* no need for special case handling of setting mode |
| 309 | on read only files needed here */ | 269 | on read only files needed here */ |
| 310 | 270 | ||
| 311 | pCifsFile = cifs_fill_filedata(file); | 271 | rc = cifs_posix_open_inode_helper(inode, file, |
| 312 | cifs_posix_open_inode_helper(inode, file, pCifsInode, | 272 | pCifsInode, oplock, netfid); |
| 313 | oplock, netfid); | 273 | if (rc != 0) { |
| 274 | CIFSSMBClose(xid, tcon, netfid); | ||
| 275 | goto out; | ||
| 276 | } | ||
| 277 | |||
| 278 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, | ||
| 279 | file->f_path.mnt, | ||
| 280 | oflags); | ||
| 281 | if (pCifsFile == NULL) { | ||
| 282 | CIFSSMBClose(xid, tcon, netfid); | ||
| 283 | rc = -ENOMEM; | ||
| 284 | } | ||
| 314 | goto out; | 285 | goto out; |
| 315 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 286 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
| 316 | if (tcon->ses->serverNOS) | 287 | if (tcon->ses->serverNOS) |
| @@ -391,17 +362,17 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 391 | goto out; | 362 | goto out; |
| 392 | } | 363 | } |
| 393 | 364 | ||
| 365 | rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid); | ||
| 366 | if (rc != 0) | ||
| 367 | goto out; | ||
| 368 | |||
| 394 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, | 369 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, |
| 395 | file->f_flags); | 370 | file->f_flags); |
| 396 | file->private_data = pCifsFile; | 371 | if (pCifsFile == NULL) { |
| 397 | if (file->private_data == NULL) { | ||
| 398 | rc = -ENOMEM; | 372 | rc = -ENOMEM; |
| 399 | goto out; | 373 | goto out; |
| 400 | } | 374 | } |
| 401 | 375 | ||
| 402 | rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon, | ||
| 403 | &oplock, buf, full_path, xid); | ||
| 404 | |||
| 405 | if (oplock & CIFS_CREATE_ACTION) { | 376 | if (oplock & CIFS_CREATE_ACTION) { |
| 406 | /* time to set mode which we can not set earlier due to | 377 | /* time to set mode which we can not set earlier due to |
| 407 | problems creating new read-only files */ | 378 | problems creating new read-only files */ |
| @@ -513,8 +484,7 @@ reopen_error_exit: | |||
| 513 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 484 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| 514 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | 485 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); |
| 515 | /* can not refresh inode info since size could be stale */ | 486 | /* can not refresh inode info since size could be stale */ |
| 516 | rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, | 487 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, |
| 517 | inode->i_sb, | ||
| 518 | cifs_sb->mnt_file_mode /* ignored */, | 488 | cifs_sb->mnt_file_mode /* ignored */, |
| 519 | oflags, &oplock, &netfid, xid); | 489 | oflags, &oplock, &netfid, xid); |
| 520 | if (rc == 0) { | 490 | if (rc == 0) { |
