aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastryyy@gmail.com>2010-11-25 07:12:39 -0500
committerSteve French <sfrench@us.ibm.com>2011-01-06 14:07:53 -0500
commiteeb910a6d46103594eb63e6eba1aeb02022368a4 (patch)
tree93cc726fbf34bc55979dab967775096e879a0826 /fs/cifs/file.c
parent4b886136df2b923b6fc6b2d83faa9554e84e05ab (diff)
CIFS: Simplify non-posix open stuff (try #2)
Delete cifs_open_inode_helper and move non-posix open related things to cifs_nt_open function. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c189
1 files changed, 73 insertions, 116 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5a28660ca2b5..f95ba451173f 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -104,53 +104,6 @@ static inline int cifs_get_disposition(unsigned int flags)
104 return FILE_OPEN; 104 return FILE_OPEN;
105} 105}
106 106
107static inline int cifs_open_inode_helper(struct inode *inode,
108 struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf,
109 char *full_path, int xid)
110{
111 struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
112 struct timespec temp;
113 int rc;
114
115 if (pCifsInode->clientCanCacheRead) {
116 /* we have the inode open somewhere else
117 no need to discard cache data */
118 goto client_can_cache;
119 }
120
121 /* BB need same check in cifs_create too? */
122 /* if not oplocked, invalidate inode pages if mtime or file
123 size changed */
124 temp = cifs_NTtimeToUnix(buf->LastWriteTime);
125 if (timespec_equal(&inode->i_mtime, &temp) &&
126 (inode->i_size ==
127 (loff_t)le64_to_cpu(buf->EndOfFile))) {
128 cFYI(1, "inode unchanged on server");
129 } else {
130 if (inode->i_mapping) {
131 /* BB no need to lock inode until after invalidate
132 since namei code should already have it locked? */
133 rc = filemap_write_and_wait(inode->i_mapping);
134 mapping_set_error(inode->i_mapping, rc);
135 }
136 cFYI(1, "invalidating remote inode since open detected it "
137 "changed");
138 invalidate_remote_inode(inode);
139 }
140
141client_can_cache:
142 if (pTcon->unix_ext)
143 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
144 xid);
145 else
146 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
147 xid, NULL);
148
149 cifs_set_oplock_level(pCifsInode, oplock);
150
151 return rc;
152}
153
154int cifs_posix_open(char *full_path, struct inode **pinode, 107int cifs_posix_open(char *full_path, struct inode **pinode,
155 struct super_block *sb, int mode, unsigned int f_flags, 108 struct super_block *sb, int mode, unsigned int f_flags,
156 __u32 *poplock, __u16 *pnetfid, int xid) 109 __u32 *poplock, __u16 *pnetfid, int xid)
@@ -213,6 +166,76 @@ posix_open_ret:
213 return rc; 166 return rc;
214} 167}
215 168
169static int
170cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
171 struct cifsTconInfo *tcon, unsigned int f_flags, __u32 *poplock,
172 __u16 *pnetfid, int xid)
173{
174 int rc;
175 int desiredAccess;
176 int disposition;
177 FILE_ALL_INFO *buf;
178
179 desiredAccess = cifs_convert_flags(f_flags);
180
181/*********************************************************************
182 * open flag mapping table:
183 *
184 * POSIX Flag CIFS Disposition
185 * ---------- ----------------
186 * O_CREAT FILE_OPEN_IF
187 * O_CREAT | O_EXCL FILE_CREATE
188 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
189 * O_TRUNC FILE_OVERWRITE
190 * none of the above FILE_OPEN
191 *
192 * Note that there is not a direct match between disposition
193 * FILE_SUPERSEDE (ie create whether or not file exists although
194 * O_CREAT | O_TRUNC is similar but truncates the existing
195 * file rather than creating a new file as FILE_SUPERSEDE does
196 * (which uses the attributes / metadata passed in on open call)
197 *?
198 *? O_SYNC is a reasonable match to CIFS writethrough flag
199 *? and the read write flags match reasonably. O_LARGEFILE
200 *? is irrelevant because largefile support is always used
201 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
202 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
203 *********************************************************************/
204
205 disposition = cifs_get_disposition(f_flags);
206
207 /* BB pass O_SYNC flag through on file attributes .. BB */
208
209 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
210 if (!buf)
211 return -ENOMEM;
212
213 if (tcon->ses->capabilities & CAP_NT_SMBS)
214 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
215 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
217 & CIFS_MOUNT_MAP_SPECIAL_CHR);
218 else
219 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
220 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
221 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
222 & CIFS_MOUNT_MAP_SPECIAL_CHR);
223
224 if (rc)
225 goto out;
226
227 if (tcon->unix_ext)
228 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
229 xid);
230 else
231 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
232 xid, pnetfid);
233
234out:
235 kfree(buf);
236 return rc;
237}
238
216struct cifsFileInfo * 239struct cifsFileInfo *
217cifs_new_fileinfo(__u16 fileHandle, struct file *file, 240cifs_new_fileinfo(__u16 fileHandle, struct file *file,
218 struct tcon_link *tlink, __u32 oplock) 241 struct tcon_link *tlink, __u32 oplock)
@@ -317,10 +340,7 @@ int cifs_open(struct inode *inode, struct file *file)
317 struct cifsFileInfo *pCifsFile = NULL; 340 struct cifsFileInfo *pCifsFile = NULL;
318 struct cifsInodeInfo *pCifsInode; 341 struct cifsInodeInfo *pCifsInode;
319 char *full_path = NULL; 342 char *full_path = NULL;
320 int desiredAccess;
321 int disposition;
322 __u16 netfid; 343 __u16 netfid;
323 FILE_ALL_INFO *buf = NULL;
324 344
325 xid = GetXid(); 345 xid = GetXid();
326 346
@@ -385,71 +405,9 @@ int cifs_open(struct inode *inode, struct file *file)
385 or DFS errors */ 405 or DFS errors */
386 } 406 }
387 407
388 desiredAccess = cifs_convert_flags(file->f_flags); 408 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, file->f_flags,
389 409 &oplock, &netfid, xid);
390/********************************************************************* 410 if (rc)
391 * open flag mapping table:
392 *
393 * POSIX Flag CIFS Disposition
394 * ---------- ----------------
395 * O_CREAT FILE_OPEN_IF
396 * O_CREAT | O_EXCL FILE_CREATE
397 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
398 * O_TRUNC FILE_OVERWRITE
399 * none of the above FILE_OPEN
400 *
401 * Note that there is not a direct match between disposition
402 * FILE_SUPERSEDE (ie create whether or not file exists although
403 * O_CREAT | O_TRUNC is similar but truncates the existing
404 * file rather than creating a new file as FILE_SUPERSEDE does
405 * (which uses the attributes / metadata passed in on open call)
406 *?
407 *? O_SYNC is a reasonable match to CIFS writethrough flag
408 *? and the read write flags match reasonably. O_LARGEFILE
409 *? is irrelevant because largefile support is always used
410 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
411 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
412 *********************************************************************/
413
414 disposition = cifs_get_disposition(file->f_flags);
415
416 /* BB pass O_SYNC flag through on file attributes .. BB */
417
418 /* Also refresh inode by passing in file_info buf returned by SMBOpen
419 and calling get_inode_info with returned buf (at least helps
420 non-Unix server case) */
421
422 /* BB we can not do this if this is the second open of a file
423 and the first handle has writebehind data, we might be
424 able to simply do a filemap_fdatawrite/filemap_fdatawait first */
425 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
426 if (!buf) {
427 rc = -ENOMEM;
428 goto out;
429 }
430
431 if (tcon->ses->capabilities & CAP_NT_SMBS)
432 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
433 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
434 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
435 & CIFS_MOUNT_MAP_SPECIAL_CHR);
436 else
437 rc = -EIO; /* no NT SMB support fall into legacy open below */
438
439 if (rc == -EIO) {
440 /* Old server, try legacy style OpenX */
441 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
442 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
443 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
444 & CIFS_MOUNT_MAP_SPECIAL_CHR);
445 }
446 if (rc) {
447 cFYI(1, "cifs_open returned 0x%x", rc);
448 goto out;
449 }
450
451 rc = cifs_open_inode_helper(inode, tcon, oplock, buf, full_path, xid);
452 if (rc != 0)
453 goto out; 411 goto out;
454 412
455 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock); 413 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
@@ -481,7 +439,6 @@ int cifs_open(struct inode *inode, struct file *file)
481 } 439 }
482 440
483out: 441out:
484 kfree(buf);
485 kfree(full_path); 442 kfree(full_path);
486 FreeXid(xid); 443 FreeXid(xid);
487 cifs_put_tlink(tlink); 444 cifs_put_tlink(tlink);