<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<blockquote style="margin-left: 0.8ex; padding-left: 1ex; border-left: 3px solid rgb(200, 200, 200);">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- Flag name suggests it should always indicate that inode is locked,</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
but for !close_wait path it does not, this can be a problem if we reuse</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
this flag without checking that it is not always set.</div>
</blockquote>
<p class="elementToProof" style="margin-top: 0px; margin-bottom: 0px; font-family: Aptos; font-size: 11pt;">
<span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">I don't think the flag will ever be used in !close_wait path.&nbsp;</span></p>
<div class="elementToProof" style="margin-top: 0px; margin-bottom: 0px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<blockquote style="margin-left: 0.8ex; padding-left: 1ex; border-left: 3px solid rgb(200, 200, 200);">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- Let's maybe indicate the flag scope, we currently use it only on fuse_open,</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
maybe we should rename it to FUSE_S_OPEN_INODE_LOCKED?</div>
</blockquote>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
yeah, it's more appropriate&nbsp;</div>
<blockquote style="margin-left: 0.8ex; padding-left: 1ex; border-left: 3px solid rgb(200, 200, 200);">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- What if after rebase the lock condition will change e.g. not (is_wb_truncate</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
|| dax_truncate) but something else, maybe we should use a helper variable</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
&quot;locked&quot; in fuse_open which is set only when lock is taken?</div>
</blockquote>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
agreed, this could be a risk.&nbsp;</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<hr style="display: inline-block; width: 98%;">
<div id="divRplyFwdMsg">
<div style="direction: ltr; font-family: Calibri, sans-serif; font-size: 11pt; color: rgb(0, 0, 0);">
<b>From:</b>&nbsp;Pavel Tikhomirov &lt;ptikhomirov@virtuozzo.com&gt;<br>
<b>Sent:</b>&nbsp;29 June 2026 18:04<br>
<b>To:</b>&nbsp;Kui Liu &lt;kui.liu@virtuozzo.com&gt;; devel@openvz.org &lt;devel@openvz.org&gt;<br>
<b>Cc:</b>&nbsp;Andrey Zaitsev &lt;azaitsev@virtuozzo.com&gt;<br>
<b>Subject:</b>&nbsp;Re: [Devel] [PATCH VZ10 v3] fs/fuse: align fuse_create_open()'s open path with fuse_open()</div>
<div style="direction: ltr;">&nbsp;</div>
</div>
<div style="font-size: 11pt;">Reviewed-by: Pavel Tikhomirov &lt;ptikhomirov@virtuozzo.com&gt;<br>
<br>
Generally looks good, though, please, see comments inline.<br>
<br>
On 6/26/26 16:32, Liu Kui wrote:<br>
&gt; fuse_create_open()'s close_wait branch was not correct; in particular the<br>
&gt; fput() in its error path was wrong. fuse_open()'s close_wait branch should<br>
&gt; apply instead.<br>
&gt;<br>
&gt; The two sites differ in one important way, though: fuse_open() runs the<br>
&gt; block before FMODE_OPENED is set, where fuse_sync_release() is the correct<br>
&gt; cleanup on error, whereas fuse_create_open() runs it after FMODE_OPENED is<br>
&gt; set, where fuse_sync_release() must not be called. To unify them, refactor<br>
&gt; the sequence into fuse_open_close_wait() and call it from<br>
&gt; fuse_finish_open(), so the block runs before FMODE_OPENED on both paths.<br>
&gt; The error then propagates to the caller and the block itself no longer<br>
&gt; needs to call fuse_sync_release().<br>
&gt;<br>
&gt; Add a per-open FUSE_S_INODE_LOCKED flag telling fuse_open_close_wait() that<br>
&gt; the caller already holds the inode lock, so it is not re-acquired and<br>
&gt; deadlocks on the atomic O_TRUNC path.<br>
&gt;<br>
&gt; <a href="https://virtuozzo.atlassian.net/browse/VSTOR-136027" id="OWAd3c088a2-5827-6ff5-d503-ff7bf9ca59e6" class="OWAAutoLink" data-auth="NotApplicable">
https://virtuozzo.atlassian.net/browse/VSTOR-136027</a><br>
&gt; Signed-off-by: Liu Kui &lt;kui.liu@virtuozzo.com&gt;<br>
&gt; ---<br>
&gt; Changes in v3:<br>
&gt;&nbsp;&nbsp; - Call fuse_open_close_wait() from fuse_finish_open() instead of from<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; the fuse_open() and fuse_create_open() call sites, so the sequence<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; runs before FMODE_OPENED is set on both paths.<br>
&gt;&nbsp;&nbsp; - Drop the fuse_sync_release() call inside fuse_open_close_wait(); the<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; error now propagates to the caller, which releases the file before<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; FMODE_OPENED is set.<br>
&gt;&nbsp;&nbsp; - Make fuse_open_close_wait() static and drop its fuse_i.h prototype.<br>
&gt;&nbsp;&nbsp; - Acquire the inode lock in fuse_open_close_wait() only when the caller<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; does not already hold it, tracked by a per-open FUSE_S_INODE_LOCKED<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; flag, so the atomic O_TRUNC path (which already holds it) does not<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; self-deadlock.<br>
&gt;<br>
&gt; Changes in v2:<br>
&gt;&nbsp;&nbsp; - Factor the close_wait open branch into fuse_open_close_wait();<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; call it from both fuse_open() and fuse_create_open() instead of<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; duplicating the block in each.<br>
&gt;&nbsp;&nbsp; - Use fuse_sync_release() on the close_wait error path for both<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; callers. It is functionally equivalent to fuse_release_common()<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; used in fuse_open().<br>
&gt;<br>
&gt;&nbsp; fs/fuse/dir.c&nbsp;&nbsp;&nbsp; | 17 -----------<br>
&gt;&nbsp; fs/fuse/file.c&nbsp;&nbsp; | 73 ++++++++++++++++++++++++++++--------------------<br>
&gt;&nbsp; fs/fuse/fuse_i.h |&nbsp; 4 ++-<br>
&gt;&nbsp; 3 files changed, 46 insertions(+), 48 deletions(-)<br>
&gt;<br>
&gt; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c<br>
&gt; index 45ee4f1e4b68..9799c2b6eb4d 100644<br>
&gt; --- a/fs/fuse/dir.c<br>
&gt; +++ b/fs/fuse/dir.c<br>
&gt; @@ -722,23 +722,6 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invalidate_inode_pages2(inode-&gt;i_mapping);<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&nbsp;<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp; if (fm-&gt;fc-&gt;close_wait) {<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct fuse_inode *fi = get_fuse_inode(inode);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool need_open;<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode_lock(inode);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;fi-&gt;lock);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; need_open = (++fi-&gt;num_openers == 1);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;fi-&gt;lock);<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (need_open &amp;&amp; fm-&gt;fc-&gt;kio.op &amp;&amp; fm-&gt;fc-&gt;kio.op-&gt;file_open) {<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fm-&gt;fc-&gt;kio.op-&gt;file_open(file, inode);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (err)<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fput(file);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode_unlock(inode);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; -<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return err;<br>
&gt;&nbsp;<br>
&gt;&nbsp; out_free_ff:<br>
&gt; diff --git a/fs/fuse/file.c b/fs/fuse/file.c<br>
&gt; index 58202a96517e..8750cbdf0596 100644<br>
&gt; --- a/fs/fuse/file.c<br>
&gt; +++ b/fs/fuse/file.c<br>
&gt; @@ -286,6 +286,43 @@ static void fuse_link_rw_file(struct file *file)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;fi-&gt;lock);<br>
&gt;&nbsp; }<br>
&gt;&nbsp;<br>
&gt; +static int fuse_open_close_wait(struct inode *inode, struct file *file)<br>
&gt; +{<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct fuse_conn *fc = get_fuse_conn(inode);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct fuse_inode *fi = get_fuse_inode(inode);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct fuse_file *ff = file-&gt;private_data;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; /* the caller already holds the inode lock (e.g. truncate open) */<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; bool locked = test_and_clear_bit(FUSE_S_INODE_LOCKED, &amp;ff-&gt;ff_state);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; int err = 0;<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (!locked)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode_lock(inode);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;fi-&gt;lock);<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (++fi-&gt;num_openers == 1 || fi-&gt;i_size_unstable) {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;i_size_unstable = 1;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;inval_mask = ~0;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;fi-&gt;lock);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fuse_update_attributes(inode, file, ~0);<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!err &amp;&amp; fc-&gt;kio.op &amp;&amp; fc-&gt;kio.op-&gt;file_open)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fc-&gt;kio.op-&gt;file_open(file, inode);<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;fi-&gt;lock);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;i_size_unstable = 0;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (err)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;num_openers--;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; file-&gt;f_mode |= FMODE_NOWAIT;<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;fi-&gt;lock);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (!locked)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode_unlock(inode);<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; return err;<br>
&gt; +}<br>
&gt; +<br>
&gt;&nbsp; int fuse_finish_open(struct inode *inode, struct file *file)<br>
&gt;&nbsp; {<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct fuse_file *ff = file-&gt;private_data;<br>
&gt; @@ -319,6 +356,9 @@ int fuse_finish_open(struct inode *inode, struct file *file)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!test_bit(FUSE_S_FAIL_IMMEDIATELY, &amp;ff-&gt;ff_state))<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fuse_wait_on_inval_files(inode);<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!err)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fuse_open_close_wait(inode, file);<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt;&nbsp;<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return err;<br>
&gt; @@ -378,6 +418,9 @@ static int fuse_open(struct inode *inode, struct file *file)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fuse_do_open(fm, get_node_id(inode), file, false);<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!err) {<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ff = file-&gt;private_data;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* tell fuse_open_close_wait() we already hold the inode lock */<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((is_wb_truncate || dax_truncate) &amp;&amp; fc-&gt;close_wait)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_bit(FUSE_S_INODE_LOCKED, &amp;ff-&gt;ff_state);<br>
<br>
Technically correct. Some concerns:<br>
<br>
- Flag name suggests it should always indicate that inode is locked,<br>
but for !close_wait path it does not, this can be a problem if we reuse<br>
this flag without checking that it is not always set.<br>
<br>
- Let's maybe indicate the flag scope, we currently use it only on fuse_open,<br>
maybe we should&nbsp;rename it to FUSE_S_OPEN_INODE_LOCKED?<br>
<br>
- What if after rebase the lock condition will change e.g. not (is_wb_truncate<br>
|| dax_truncate) but something else, maybe we should use a helper variable<br>
&quot;locked&quot; in fuse_open which is set only when lock is taken?<br>
<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fuse_finish_open(inode, file);<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (err)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fuse_sync_release(fi, ff, file-&gt;f_flags);<br>
&gt; @@ -399,36 +442,6 @@ static int fuse_open(struct inode *inode, struct file *file)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (is_wb_truncate || dax_truncate)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode_unlock(inode);<br>
&gt;&nbsp;<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp; if (!err &amp;&amp; fc-&gt;close_wait) {<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode_lock(inode);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;fi-&gt;lock);<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (++fi-&gt;num_openers == 1 || fi-&gt;i_size_unstable) {<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;i_size_unstable = 1;<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;inval_mask = ~0;<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;fi-&gt;lock);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fuse_update_attributes(inode, file, ~0);<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!err &amp;&amp; fc-&gt;kio.op &amp;&amp; fc-&gt;kio.op-&gt;file_open)<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; err = fc-&gt;kio.op-&gt;file_open(file, inode);<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;fi-&gt;lock);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;i_size_unstable = 0;<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (err)<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi-&gt;num_openers--;<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file-&gt;f_mode |= FMODE_NOWAIT;<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;fi-&gt;lock);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode_unlock(inode);<br>
&gt; -<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (err) {<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fuse_release_common(file, false);<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return err;<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; -<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return err;<br>
&gt;&nbsp; }<br>
&gt;&nbsp;<br>
&gt; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h<br>
&gt; index a834a5b4dfe2..53dfcb495ca0 100644<br>
&gt; --- a/fs/fuse/fuse_i.h<br>
&gt; +++ b/fs/fuse/fuse_i.h<br>
&gt; @@ -327,7 +327,9 @@ struct fuse_file {<br>
&gt;&nbsp; enum {<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Any fops on given ff should fail immediately */<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FUSE_S_FAIL_IMMEDIATELY = 0,<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp; FUSE_S_CLOSING&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 1<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; FUSE_S_CLOSING&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 1,<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; /** The open path already holds the inode lock (close_wait) */<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; FUSE_S_INODE_LOCKED&nbsp;&nbsp;&nbsp;&nbsp; = 2,<br>
&gt;&nbsp; };<br>
&gt;&nbsp;<br>
&gt;&nbsp; /** One input argument of a request */<br>
<br>
--<br>
Best regards, Pavel Tikhomirov<br>
Senior Software Developer, Virtuozzo.<br>
<br>
</div>
</body>
</html>