aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2009-04-08 21:14:32 -0400
committerSteve French <sfrench@us.ibm.com>2009-04-16 21:26:49 -0400
commita6ce4932fbdbcd8f8e8c6df76812014351c32892 (patch)
tree4ffe9ea3379cb3227924491c93960108cf762b96 /fs/cifs/dir.c
parentd9fb5c091b419e0495c50c1cce9e4cf9f7105072 (diff)
[CIFS] Add support for posix open during lookup
This patch by utilizing lookup intents, and thus removing a network roundtrip in the open path, improves performance dramatically on open (30% or more) to Samba and other servers which support the cifs posix extensions Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c131
1 files changed, 85 insertions, 46 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e457e1434349..d9006b04324e 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -129,12 +129,64 @@ cifs_bp_rename_retry:
129 return full_path; 129 return full_path;
130} 130}
131 131
132static void
133cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
134 struct cifsTconInfo *tcon, bool write_only)
135{
136 int oplock = 0;
137 struct cifsFileInfo *pCifsFile;
138 struct cifsInodeInfo *pCifsInode;
139
140 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
141
142 if (pCifsFile == NULL)
143 return;
144
145 if (oplockEnabled)
146 oplock = REQ_OPLOCK;
147
148 pCifsFile->netfid = fileHandle;
149 pCifsFile->pid = current->tgid;
150 pCifsFile->pInode = newinode;
151 pCifsFile->invalidHandle = false;
152 pCifsFile->closePend = false;
153 mutex_init(&pCifsFile->fh_mutex);
154 mutex_init(&pCifsFile->lock_mutex);
155 INIT_LIST_HEAD(&pCifsFile->llist);
156 atomic_set(&pCifsFile->wrtPending, 0);
157
158 /* set the following in open now
159 pCifsFile->pfile = file; */
160 write_lock(&GlobalSMBSeslock);
161 list_add(&pCifsFile->tlist, &tcon->openFileList);
162 pCifsInode = CIFS_I(newinode);
163 if (pCifsInode) {
164 /* if readable file instance put first in list*/
165 if (write_only) {
166 list_add_tail(&pCifsFile->flist,
167 &pCifsInode->openFileList);
168 } else {
169 list_add(&pCifsFile->flist,
170 &pCifsInode->openFileList);
171 }
172 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
173 pCifsInode->clientCanCacheAll = true;
174 pCifsInode->clientCanCacheRead = true;
175 cFYI(1, ("Exclusive Oplock inode %p",
176 newinode));
177 } else if ((oplock & 0xF) == OPLOCK_READ)
178 pCifsInode->clientCanCacheRead = true;
179 }
180 write_unlock(&GlobalSMBSeslock);
181}
182
132int cifs_posix_open(char *full_path, struct inode **pinode, 183int cifs_posix_open(char *full_path, struct inode **pinode,
133 struct super_block *sb, int mode, int oflags, 184 struct super_block *sb, int mode, int oflags,
134 int *poplock, __u16 *pnetfid, int xid) 185 int *poplock, __u16 *pnetfid, int xid)
135{ 186{
136 int rc; 187 int rc;
137 __u32 oplock; 188 __u32 oplock;
189 bool write_only = false;
138 FILE_UNIX_BASIC_INFO *presp_data; 190 FILE_UNIX_BASIC_INFO *presp_data;
139 __u32 posix_flags = 0; 191 __u32 posix_flags = 0;
140 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 192 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -172,6 +224,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
172 if (oflags & O_DIRECT) 224 if (oflags & O_DIRECT)
173 posix_flags |= SMB_O_DIRECT; 225 posix_flags |= SMB_O_DIRECT;
174 226
227 if (!(oflags & FMODE_READ))
228 write_only = true;
175 229
176 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, 230 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
177 pnetfid, presp_data, &oplock, full_path, 231 pnetfid, presp_data, &oplock, full_path,
@@ -200,6 +254,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
200 254
201 posix_fill_in_inode(*pinode, presp_data, 1); 255 posix_fill_in_inode(*pinode, presp_data, 1);
202 256
257 cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
258
203posix_open_ret: 259posix_open_ret:
204 kfree(presp_data); 260 kfree(presp_data);
205 return rc; 261 return rc;
@@ -241,7 +297,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
241 char *full_path = NULL; 297 char *full_path = NULL;
242 FILE_ALL_INFO *buf = NULL; 298 FILE_ALL_INFO *buf = NULL;
243 struct inode *newinode = NULL; 299 struct inode *newinode = NULL;
244 struct cifsInodeInfo *pCifsInode;
245 int disposition = FILE_OVERWRITE_IF; 300 int disposition = FILE_OVERWRITE_IF;
246 bool write_only = false; 301 bool write_only = false;
247 302
@@ -412,44 +467,8 @@ cifs_create_set_dentry:
412 /* mknod case - do not leave file open */ 467 /* mknod case - do not leave file open */
413 CIFSSMBClose(xid, tcon, fileHandle); 468 CIFSSMBClose(xid, tcon, fileHandle);
414 } else if (newinode) { 469 } else if (newinode) {
415 struct cifsFileInfo *pCifsFile = 470 cifs_fill_fileinfo(newinode, fileHandle,
416 kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 471 cifs_sb->tcon, write_only);
417
418 if (pCifsFile == NULL)
419 goto cifs_create_out;
420 pCifsFile->netfid = fileHandle;
421 pCifsFile->pid = current->tgid;
422 pCifsFile->pInode = newinode;
423 pCifsFile->invalidHandle = false;
424 pCifsFile->closePend = false;
425 init_MUTEX(&pCifsFile->fh_sem);
426 mutex_init(&pCifsFile->lock_mutex);
427 INIT_LIST_HEAD(&pCifsFile->llist);
428 atomic_set(&pCifsFile->wrtPending, 0);
429
430 /* set the following in open now
431 pCifsFile->pfile = file; */
432 write_lock(&GlobalSMBSeslock);
433 list_add(&pCifsFile->tlist, &tcon->openFileList);
434 pCifsInode = CIFS_I(newinode);
435 if (pCifsInode) {
436 /* if readable file instance put first in list*/
437 if (write_only) {
438 list_add_tail(&pCifsFile->flist,
439 &pCifsInode->openFileList);
440 } else {
441 list_add(&pCifsFile->flist,
442 &pCifsInode->openFileList);
443 }
444 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
445 pCifsInode->clientCanCacheAll = true;
446 pCifsInode->clientCanCacheRead = true;
447 cFYI(1, ("Exclusive Oplock inode %p",
448 newinode));
449 } else if ((oplock & 0xF) == OPLOCK_READ)
450 pCifsInode->clientCanCacheRead = true;
451 }
452 write_unlock(&GlobalSMBSeslock);
453 } 472 }
454cifs_create_out: 473cifs_create_out:
455 kfree(buf); 474 kfree(buf);
@@ -582,17 +601,21 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
582 return rc; 601 return rc;
583} 602}
584 603
585
586struct dentry * 604struct dentry *
587cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, 605cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
588 struct nameidata *nd) 606 struct nameidata *nd)
589{ 607{
590 int xid; 608 int xid;
591 int rc = 0; /* to get around spurious gcc warning, set to zero here */ 609 int rc = 0; /* to get around spurious gcc warning, set to zero here */
610 int oplock = 0;
611 int mode;
612 __u16 fileHandle = 0;
613 bool posix_open = false;
592 struct cifs_sb_info *cifs_sb; 614 struct cifs_sb_info *cifs_sb;
593 struct cifsTconInfo *pTcon; 615 struct cifsTconInfo *pTcon;
594 struct inode *newInode = NULL; 616 struct inode *newInode = NULL;
595 char *full_path = NULL; 617 char *full_path = NULL;
618 struct file *filp;
596 619
597 xid = GetXid(); 620 xid = GetXid();
598 621
@@ -634,12 +657,27 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
634 } 657 }
635 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode)); 658 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
636 659
637 if (pTcon->unix_ext) 660 if (pTcon->unix_ext) {
638 rc = cifs_get_inode_info_unix(&newInode, full_path, 661 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
639 parent_dir_inode->i_sb, xid); 662 (nd->flags & LOOKUP_OPEN)) {
640 else 663 if (!((nd->intent.open.flags & O_CREAT) &&
664 (nd->intent.open.flags & O_EXCL))) {
665 mode = nd->intent.open.create_mode &
666 ~current->fs->umask;
667 rc = cifs_posix_open(full_path, &newInode,
668 parent_dir_inode->i_sb, mode,
669 nd->intent.open.flags, &oplock,
670 &fileHandle, xid);
671 if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
672 posix_open = true;
673 }
674 }
675 if (!posix_open)
676 rc = cifs_get_inode_info_unix(&newInode, full_path,
677 parent_dir_inode->i_sb, xid);
678 } else
641 rc = cifs_get_inode_info(&newInode, full_path, NULL, 679 rc = cifs_get_inode_info(&newInode, full_path, NULL,
642 parent_dir_inode->i_sb, xid, NULL); 680 parent_dir_inode->i_sb, xid, NULL);
643 681
644 if ((rc == 0) && (newInode != NULL)) { 682 if ((rc == 0) && (newInode != NULL)) {
645 if (pTcon->nocase) 683 if (pTcon->nocase)
@@ -647,7 +685,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
647 else 685 else
648 direntry->d_op = &cifs_dentry_ops; 686 direntry->d_op = &cifs_dentry_ops;
649 d_add(direntry, newInode); 687 d_add(direntry, newInode);
650 688 if (posix_open)
689 filp = lookup_instantiate_filp(nd, direntry, NULL);
651 /* since paths are not looked up by component - the parent 690 /* since paths are not looked up by component - the parent
652 directories are presumed to be good here */ 691 directories are presumed to be good here */
653 renew_parental_timestamps(direntry); 692 renew_parental_timestamps(direntry);