aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2009-03-03 13:00:34 -0500
committerSteve French <sfrench@us.ibm.com>2009-03-11 21:36:21 -0400
commit276a74a4835ad86d6da42f3a084b060afc5656e8 (patch)
treea2ef2452e2b0a24710b2298688e3beed4e353b5c /fs/cifs
parentfcc7c09d94be7b75c9ea2beb22d0fae191c6b4b9 (diff)
[CIFS] Use posix open on file open when server supports it
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/file.c124
1 files changed, 111 insertions, 13 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e4ecb1cb0b13..7bef4cce572a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -125,6 +125,80 @@ static inline int cifs_get_disposition(unsigned int flags)
125} 125}
126 126
127/* all arguments to this function must be checked for validity in caller */ 127/* all arguments to this function must be checked for validity in caller */
128static inline int cifs_posix_open_inode_helper(struct inode *inode,
129 struct file *file, struct cifsInodeInfo *pCifsInode,
130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
131{
132 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
133/* struct timespec temp; */ /* BB REMOVEME BB */
134
135 file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
136 if (file->private_data == NULL)
137 return -ENOMEM;
138 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
139 write_lock(&GlobalSMBSeslock);
140 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
141
142 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
143 if (pCifsInode == NULL) {
144 write_unlock(&GlobalSMBSeslock);
145 return -EINVAL;
146 }
147
148 /* want handles we can use to read with first
149 in the list so we do not have to walk the
150 list to search for one in write_begin */
151 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
152 list_add_tail(&pCifsFile->flist,
153 &pCifsInode->openFileList);
154 } else {
155 list_add(&pCifsFile->flist,
156 &pCifsInode->openFileList);
157 }
158
159 if (pCifsInode->clientCanCacheRead) {
160 /* we have the inode open somewhere else
161 no need to discard cache data */
162 goto psx_client_can_cache;
163 }
164
165 /* BB FIXME need to fix this check to move it earlier into posix_open
166 BB fIX following section BB FIXME */
167
168 /* if not oplocked, invalidate inode pages if mtime or file
169 size changed */
170/* temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
171 if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
172 (file->f_path.dentry->d_inode->i_size ==
173 (loff_t)le64_to_cpu(buf->EndOfFile))) {
174 cFYI(1, ("inode unchanged on server"));
175 } else {
176 if (file->f_path.dentry->d_inode->i_mapping) {
177 rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
178 if (rc != 0)
179 CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
180 }
181 cFYI(1, ("invalidating remote inode since open detected it "
182 "changed"));
183 invalidate_remote_inode(file->f_path.dentry->d_inode);
184 } */
185
186psx_client_can_cache:
187 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
188 pCifsInode->clientCanCacheAll = true;
189 pCifsInode->clientCanCacheRead = true;
190 cFYI(1, ("Exclusive Oplock granted on inode %p",
191 file->f_path.dentry->d_inode));
192 } else if ((oplock & 0xF) == OPLOCK_READ)
193 pCifsInode->clientCanCacheRead = true;
194
195 /* will have to change the unlock if we reenable the
196 filemap_fdatawrite (which does not seem necessary */
197 write_unlock(&GlobalSMBSeslock);
198 return 0;
199}
200
201/* all arguments to this function must be checked for validity in caller */
128static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, 202static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
129 struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, 203 struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
130 struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, 204 struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
@@ -195,7 +269,7 @@ int cifs_open(struct inode *inode, struct file *file)
195 int rc = -EACCES; 269 int rc = -EACCES;
196 int xid, oplock; 270 int xid, oplock;
197 struct cifs_sb_info *cifs_sb; 271 struct cifs_sb_info *cifs_sb;
198 struct cifsTconInfo *pTcon; 272 struct cifsTconInfo *tcon;
199 struct cifsFileInfo *pCifsFile; 273 struct cifsFileInfo *pCifsFile;
200 struct cifsInodeInfo *pCifsInode; 274 struct cifsInodeInfo *pCifsInode;
201 struct list_head *tmp; 275 struct list_head *tmp;
@@ -208,7 +282,7 @@ int cifs_open(struct inode *inode, struct file *file)
208 xid = GetXid(); 282 xid = GetXid();
209 283
210 cifs_sb = CIFS_SB(inode->i_sb); 284 cifs_sb = CIFS_SB(inode->i_sb);
211 pTcon = cifs_sb->tcon; 285 tcon = cifs_sb->tcon;
212 286
213 if (file->f_flags & O_CREAT) { 287 if (file->f_flags & O_CREAT) {
214 /* search inode for this file and fill in file->private_data */ 288 /* search inode for this file and fill in file->private_data */
@@ -248,6 +322,35 @@ int cifs_open(struct inode *inode, struct file *file)
248 322
249 cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", 323 cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
250 inode, file->f_flags, full_path)); 324 inode, file->f_flags, full_path));
325
326 if (oplockEnabled)
327 oplock = REQ_OPLOCK;
328 else
329 oplock = 0;
330
331 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
332 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
333 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
334 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
335 /* can not refresh inode info since size could be stale */
336 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
337 cifs_sb->mnt_file_mode /* ignored */,
338 oflags, &oplock, &netfid, xid);
339 if (rc == 0) {
340 cFYI(1, ("posix open succeeded"));
341 /* no need for special case handling of setting mode
342 on read only files needed here */
343
344 cifs_posix_open_inode_helper(inode, file, pCifsInode,
345 pCifsFile, oplock, netfid);
346 goto out;
347 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
348 (rc != -EOPNOTSUPP)) /* path not found or net err */
349 goto out;
350 /* fallthrough to retry open the old way on operation
351 not supported or DFS errors */
352 }
353
251 desiredAccess = cifs_convert_flags(file->f_flags); 354 desiredAccess = cifs_convert_flags(file->f_flags);
252 355
253/********************************************************************* 356/*********************************************************************
@@ -276,11 +379,6 @@ int cifs_open(struct inode *inode, struct file *file)
276 379
277 disposition = cifs_get_disposition(file->f_flags); 380 disposition = cifs_get_disposition(file->f_flags);
278 381
279 if (oplockEnabled)
280 oplock = REQ_OPLOCK;
281 else
282 oplock = 0;
283
284 /* BB pass O_SYNC flag through on file attributes .. BB */ 382 /* BB pass O_SYNC flag through on file attributes .. BB */
285 383
286 /* Also refresh inode by passing in file_info buf returned by SMBOpen 384 /* Also refresh inode by passing in file_info buf returned by SMBOpen
@@ -297,7 +395,7 @@ int cifs_open(struct inode *inode, struct file *file)
297 } 395 }
298 396
299 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 397 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
300 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 398 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
301 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, 399 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
302 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 400 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
303 & CIFS_MOUNT_MAP_SPECIAL_CHR); 401 & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -306,7 +404,7 @@ int cifs_open(struct inode *inode, struct file *file)
306 404
307 if (rc == -EIO) { 405 if (rc == -EIO) {
308 /* Old server, try legacy style OpenX */ 406 /* Old server, try legacy style OpenX */
309 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 407 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
310 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, 408 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
311 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 409 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
312 & CIFS_MOUNT_MAP_SPECIAL_CHR); 410 & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -323,12 +421,12 @@ int cifs_open(struct inode *inode, struct file *file)
323 } 421 }
324 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 422 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
325 write_lock(&GlobalSMBSeslock); 423 write_lock(&GlobalSMBSeslock);
326 list_add(&pCifsFile->tlist, &pTcon->openFileList); 424 list_add(&pCifsFile->tlist, &tcon->openFileList);
327 425
328 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 426 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
329 if (pCifsInode) { 427 if (pCifsInode) {
330 rc = cifs_open_inode_helper(inode, file, pCifsInode, 428 rc = cifs_open_inode_helper(inode, file, pCifsInode,
331 pCifsFile, pTcon, 429 pCifsFile, tcon,
332 &oplock, buf, full_path, xid); 430 &oplock, buf, full_path, xid);
333 } else { 431 } else {
334 write_unlock(&GlobalSMBSeslock); 432 write_unlock(&GlobalSMBSeslock);
@@ -337,7 +435,7 @@ int cifs_open(struct inode *inode, struct file *file)
337 if (oplock & CIFS_CREATE_ACTION) { 435 if (oplock & CIFS_CREATE_ACTION) {
338 /* time to set mode which we can not set earlier due to 436 /* time to set mode which we can not set earlier due to
339 problems creating new read-only files */ 437 problems creating new read-only files */
340 if (pTcon->unix_ext) { 438 if (tcon->unix_ext) {
341 struct cifs_unix_set_info_args args = { 439 struct cifs_unix_set_info_args args = {
342 .mode = inode->i_mode, 440 .mode = inode->i_mode,
343 .uid = NO_CHANGE_64, 441 .uid = NO_CHANGE_64,
@@ -347,7 +445,7 @@ int cifs_open(struct inode *inode, struct file *file)
347 .mtime = NO_CHANGE_64, 445 .mtime = NO_CHANGE_64,
348 .device = 0, 446 .device = 0,
349 }; 447 };
350 CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, 448 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
351 cifs_sb->local_nls, 449 cifs_sb->local_nls,
352 cifs_sb->mnt_cifs_flags & 450 cifs_sb->mnt_cifs_flags &
353 CIFS_MOUNT_MAP_SPECIAL_CHR); 451 CIFS_MOUNT_MAP_SPECIAL_CHR);