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) { |