aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2009-09-21 06:47:50 -0400
committerSteve French <sfrench@us.ibm.com>2009-09-24 14:33:18 -0400
commit3bc303c254335dbd7c7012cc1760b12f1d5514d3 (patch)
tree7da17fbfd697216d9ed0ccd64ea9c03aaf3d52c1 /fs/cifs/dir.c
parent48541bd3dd4739b4d574b44ea47660c88d833677 (diff)
cifs: convert oplock breaks to use slow_work facility (try #4)
This is the fourth respin of the patch to convert oplock breaks to use the slow_work facility. A customer of ours was testing a backport of one of the earlier patchsets, and hit a "Busy inodes after umount..." problem. An oplock break job had raced with a umount, and the superblock got torn down and its memory reused. When the oplock break job tried to dereference the inode->i_sb, the kernel oopsed. This patchset has the oplock break job hold an inode and vfsmount reference until the oplock break completes. With this, there should be no need to take a tcon reference (the vfsmount implicitly holds one already). Currently, when an oplock break comes in there's a chance that the oplock break job won't occur if the allocation of the oplock_q_entry fails. There are also some rather nasty races in the allocation and handling these structs. Rather than allocating oplock queue entries when an oplock break comes in, add a few extra fields to the cifsFileInfo struct. Get rid of the dedicated cifs_oplock_thread as well and queue the oplock break job to the slow_work thread pool. This approach also has the advantage that the oplock break jobs can potentially run in parallel rather than be serialized like they are today. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 36435502b5e8..9a5df7a84698 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -24,6 +24,7 @@
24#include <linux/stat.h> 24#include <linux/stat.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/namei.h> 26#include <linux/namei.h>
27#include <linux/mount.h>
27#include "cifsfs.h" 28#include "cifsfs.h"
28#include "cifspdu.h" 29#include "cifspdu.h"
29#include "cifsglob.h" 30#include "cifsglob.h"
@@ -131,11 +132,12 @@ cifs_bp_rename_retry:
131 132
132static void 133static void
133cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle, 134cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
134 struct cifsTconInfo *tcon, bool write_only) 135 struct vfsmount *mnt, bool write_only)
135{ 136{
136 int oplock = 0; 137 int oplock = 0;
137 struct cifsFileInfo *pCifsFile; 138 struct cifsFileInfo *pCifsFile;
138 struct cifsInodeInfo *pCifsInode; 139 struct cifsInodeInfo *pCifsInode;
140 struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
139 141
140 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 142 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
141 143
@@ -148,17 +150,19 @@ cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
148 pCifsFile->netfid = fileHandle; 150 pCifsFile->netfid = fileHandle;
149 pCifsFile->pid = current->tgid; 151 pCifsFile->pid = current->tgid;
150 pCifsFile->pInode = igrab(newinode); 152 pCifsFile->pInode = igrab(newinode);
153 pCifsFile->mnt = mnt;
151 pCifsFile->invalidHandle = false; 154 pCifsFile->invalidHandle = false;
152 pCifsFile->closePend = false; 155 pCifsFile->closePend = false;
153 mutex_init(&pCifsFile->fh_mutex); 156 mutex_init(&pCifsFile->fh_mutex);
154 mutex_init(&pCifsFile->lock_mutex); 157 mutex_init(&pCifsFile->lock_mutex);
155 INIT_LIST_HEAD(&pCifsFile->llist); 158 INIT_LIST_HEAD(&pCifsFile->llist);
156 atomic_set(&pCifsFile->count, 1); 159 atomic_set(&pCifsFile->count, 1);
160 slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
157 161
158 /* set the following in open now 162 /* set the following in open now
159 pCifsFile->pfile = file; */ 163 pCifsFile->pfile = file; */
160 write_lock(&GlobalSMBSeslock); 164 write_lock(&GlobalSMBSeslock);
161 list_add(&pCifsFile->tlist, &tcon->openFileList); 165 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
162 pCifsInode = CIFS_I(newinode); 166 pCifsInode = CIFS_I(newinode);
163 if (pCifsInode) { 167 if (pCifsInode) {
164 /* if readable file instance put first in list*/ 168 /* if readable file instance put first in list*/
@@ -179,14 +183,14 @@ cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
179} 183}
180 184
181int cifs_posix_open(char *full_path, struct inode **pinode, 185int cifs_posix_open(char *full_path, struct inode **pinode,
182 struct super_block *sb, int mode, int oflags, 186 struct vfsmount *mnt, int mode, int oflags,
183 __u32 *poplock, __u16 *pnetfid, int xid) 187 __u32 *poplock, __u16 *pnetfid, int xid)
184{ 188{
185 int rc; 189 int rc;
186 bool write_only = false; 190 bool write_only = false;
187 FILE_UNIX_BASIC_INFO *presp_data; 191 FILE_UNIX_BASIC_INFO *presp_data;
188 __u32 posix_flags = 0; 192 __u32 posix_flags = 0;
189 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 193 struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
190 struct cifs_fattr fattr; 194 struct cifs_fattr fattr;
191 195
192 cFYI(1, ("posix open %s", full_path)); 196 cFYI(1, ("posix open %s", full_path));
@@ -243,7 +247,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
243 247
244 /* get new inode and set it up */ 248 /* get new inode and set it up */
245 if (*pinode == NULL) { 249 if (*pinode == NULL) {
246 *pinode = cifs_iget(sb, &fattr); 250 *pinode = cifs_iget(mnt->mnt_sb, &fattr);
247 if (!*pinode) { 251 if (!*pinode) {
248 rc = -ENOMEM; 252 rc = -ENOMEM;
249 goto posix_open_ret; 253 goto posix_open_ret;
@@ -252,7 +256,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
252 cifs_fattr_to_inode(*pinode, &fattr); 256 cifs_fattr_to_inode(*pinode, &fattr);
253 } 257 }
254 258
255 cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); 259 cifs_fill_fileinfo(*pinode, *pnetfid, mnt, write_only);
256 260
257posix_open_ret: 261posix_open_ret:
258 kfree(presp_data); 262 kfree(presp_data);
@@ -322,7 +326,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
322 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && 326 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
323 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 327 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
324 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 328 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
325 rc = cifs_posix_open(full_path, &newinode, inode->i_sb, 329 rc = cifs_posix_open(full_path, &newinode, nd->path.mnt,
326 mode, oflags, &oplock, &fileHandle, xid); 330 mode, oflags, &oplock, &fileHandle, xid);
327 /* EIO could indicate that (posix open) operation is not 331 /* EIO could indicate that (posix open) operation is not
328 supported, despite what server claimed in capability 332 supported, despite what server claimed in capability
@@ -469,8 +473,8 @@ cifs_create_set_dentry:
469 /* mknod case - do not leave file open */ 473 /* mknod case - do not leave file open */
470 CIFSSMBClose(xid, tcon, fileHandle); 474 CIFSSMBClose(xid, tcon, fileHandle);
471 } else if (!(posix_create) && (newinode)) { 475 } else if (!(posix_create) && (newinode)) {
472 cifs_fill_fileinfo(newinode, fileHandle, 476 cifs_fill_fileinfo(newinode, fileHandle, nd->path.mnt,
473 cifs_sb->tcon, write_only); 477 write_only);
474 } 478 }
475cifs_create_out: 479cifs_create_out:
476 kfree(buf); 480 kfree(buf);
@@ -682,8 +686,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
682 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && 686 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
683 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && 687 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
684 (nd->intent.open.flags & O_CREAT)) { 688 (nd->intent.open.flags & O_CREAT)) {
685 rc = cifs_posix_open(full_path, &newInode, 689 rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
686 parent_dir_inode->i_sb,
687 nd->intent.open.create_mode, 690 nd->intent.open.create_mode,
688 nd->intent.open.flags, &oplock, 691 nd->intent.open.flags, &oplock,
689 &fileHandle, xid); 692 &fileHandle, xid);