Why don't we have a reference to this inode already? We can't have an oplock break unless the file is open, if the file is open then we have a reference to the inode ...<br><br><div class="gmail_quote">On Tue, Aug 18, 2009 at 1:07 PM, Jeff Layton <span dir="ltr"><<a href="mailto:jlayton@redhat.com">jlayton@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">When an oplock break comes in, cifs needs to do things like write out<br>
dirty data for it. It doesn't hold a reference to that inode in this<br>
case however. Get an active reference to the inode when an oplock break<br>
comes in. If we don't get a reference, we still need to create an oplock<br>
queue entry so that the oplock release call gets done, but we'll want to<br>
skip writeback in that case.<br>
<br>
Signed-off-by: Jeff Layton <<a href="mailto:jlayton@redhat.com">jlayton@redhat.com</a>><br>
---<br>
fs/cifs/cifsfs.c | 26 ++++++++++----------------<br>
fs/cifs/misc.c | 4 +++-<br>
2 files changed, 13 insertions(+), 17 deletions(-)<br>
<br>
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c<br>
index 2fcc722..647c5bc 100644<br>
--- a/fs/cifs/cifsfs.c<br>
+++ b/fs/cifs/cifsfs.c<br>
@@ -993,13 +993,8 @@ static int cifs_oplock_thread(void *dummyarg)<br>
cFYI(1, ("found oplock item to write out"));<br>
tcon = oplock->tcon;<br>
inode = oplock->pinode;<br>
- /* can not grab inode sem here since it would<br>
- deadlock when oplock received on delete<br>
- since vfs_unlink holds the i_mutex across<br>
- the call */<br>
- /* mutex_lock(&inode->i_mutex);*/<br>
- cifsi = CIFS_I(inode);<br>
- if (S_ISREG(inode->i_mode)) {<br>
+ if (inode && S_ISREG(inode->i_mode)) {<br>
+ cifsi = CIFS_I(inode);<br>
#ifdef CONFIG_CIFS_EXPERIMENTAL<br>
if (cifsi->clientCanCacheAll == 0)<br>
break_lease(inode, FMODE_READ);<br>
@@ -1010,17 +1005,16 @@ static int cifs_oplock_thread(void *dummyarg)<br>
if (cifsi->clientCanCacheRead == 0) {<br>
waitrc = filemap_fdatawait(<br>
inode->i_mapping);<br>
+ if (rc == 0)<br>
+ rc = waitrc;<br>
invalidate_remote_inode(inode);<br>
}<br>
- if (rc == 0)<br>
- rc = waitrc;<br>
- } else<br>
- rc = 0;<br>
- /* mutex_unlock(&inode->i_mutex);*/<br>
- if (rc)<br>
- cifsi->write_behind_rc = rc;<br>
- cFYI(1, ("Oplock flush inode %p rc %d",<br>
- inode, rc));<br>
+ if (rc)<br>
+ cifsi->write_behind_rc = rc;<br>
+ cFYI(1, ("Oplock flush inode %p rc %d",<br>
+ inode, rc));<br>
+ }<br>
+ iput(inode);<br>
<br>
/*<br>
* releasing stale oplock after recent reconnect<br>
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c<br>
index 7221af9..3bf3a52 100644<br>
--- a/fs/cifs/misc.c<br>
+++ b/fs/cifs/misc.c<br>
@@ -502,6 +502,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,<br>
struct cifsInodeInfo *pCifsInode;<br>
struct cifsFileInfo *netfile;<br>
struct oplock_q_entry *oplock;<br>
+ struct inode *inode;<br>
<br>
cFYI(1, ("Checking for oplock break or dnotify response"));<br>
if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&<br>
@@ -600,6 +601,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,<br>
pCifsInode->clientCanCacheAll = false;<br>
if (pSMB->OplockLevel == 0)<br>
pCifsInode->clientCanCacheRead = false;<br>
+ inode = igrab(netfile->pInode);<br>
<br>
if (!oplock) {<br>
cERROR(1, ("Unable to allocate "<br>
@@ -608,7 +610,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv,<br>
}<br>
<br>
oplock->tcon = tcon;<br>
- oplock->pinode = netfile->pInode;<br>
+ oplock->pinode = inode;<br>
oplock->netfid = netfile->netfid;<br>
spin_lock(&cifs_oplock_lock);<br>
list_add_tail(&oplock->qhead,<br>
<font color="#888888">--<br>
1.6.0.6<br>
<br>
</font></blockquote></div><br><br clear="all"><br>-- <br>Thanks,<br><br>Steve<br>