[linux-cifs-client] [PATCH 4/5] cifs: take reference to inode for oplock breaks
Jeff Layton
jlayton at redhat.com
Tue Aug 18 12:07:01 MDT 2009
When an oplock break comes in, cifs needs to do things like write out
dirty data for it. It doesn't hold a reference to that inode in this
case however. Get an active reference to the inode when an oplock break
comes in. If we don't get a reference, we still need to create an oplock
queue entry so that the oplock release call gets done, but we'll want to
skip writeback in that case.
Signed-off-by: Jeff Layton <jlayton at redhat.com>
---
fs/cifs/cifsfs.c | 26 ++++++++++----------------
fs/cifs/misc.c | 4 +++-
2 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 2fcc722..647c5bc 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -993,13 +993,8 @@ static int cifs_oplock_thread(void *dummyarg)
cFYI(1, ("found oplock item to write out"));
tcon = oplock->tcon;
inode = oplock->pinode;
- /* can not grab inode sem here since it would
- deadlock when oplock received on delete
- since vfs_unlink holds the i_mutex across
- the call */
- /* mutex_lock(&inode->i_mutex);*/
- cifsi = CIFS_I(inode);
- if (S_ISREG(inode->i_mode)) {
+ if (inode && S_ISREG(inode->i_mode)) {
+ cifsi = CIFS_I(inode);
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (cifsi->clientCanCacheAll == 0)
break_lease(inode, FMODE_READ);
@@ -1010,17 +1005,16 @@ static int cifs_oplock_thread(void *dummyarg)
if (cifsi->clientCanCacheRead == 0) {
waitrc = filemap_fdatawait(
inode->i_mapping);
+ if (rc == 0)
+ rc = waitrc;
invalidate_remote_inode(inode);
}
- if (rc == 0)
- rc = waitrc;
- } else
- rc = 0;
- /* mutex_unlock(&inode->i_mutex);*/
- if (rc)
- cifsi->write_behind_rc = rc;
- cFYI(1, ("Oplock flush inode %p rc %d",
- inode, rc));
+ if (rc)
+ cifsi->write_behind_rc = rc;
+ cFYI(1, ("Oplock flush inode %p rc %d",
+ inode, rc));
+ }
+ iput(inode);
/*
* releasing stale oplock after recent reconnect
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 7221af9..3bf3a52 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -502,6 +502,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,
struct cifsInodeInfo *pCifsInode;
struct cifsFileInfo *netfile;
struct oplock_q_entry *oplock;
+ struct inode *inode;
cFYI(1, ("Checking for oplock break or dnotify response"));
if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
@@ -600,6 +601,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,
pCifsInode->clientCanCacheAll = false;
if (pSMB->OplockLevel == 0)
pCifsInode->clientCanCacheRead = false;
+ inode = igrab(netfile->pInode);
if (!oplock) {
cERROR(1, ("Unable to allocate "
@@ -608,7 +610,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,
}
oplock->tcon = tcon;
- oplock->pinode = netfile->pInode;
+ oplock->pinode = inode;
oplock->netfid = netfile->netfid;
spin_lock(&cifs_oplock_lock);
list_add_tail(&oplock->qhead,
--
1.6.0.6
More information about the linux-cifs-client
mailing list