<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=koi8-r">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I did look into that matter, and here is my thoughts.</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
So far if inode ever reach i_count == 0, iput will call iput_final,</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
which will call&nbsp;<span style="color: rgb(0, 0, 0); font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;">drop function sb-&gt;op-&gt;drop_inode,&nbsp;</span><span style="color: rgb(0, 0, 0); font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;">set
 I_FREEING status</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="color: rgb(0, 0, 0); font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;">and then call evict.&nbsp; I don't really think any sane code</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="color: rgb(0, 0, 0); font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;">will ever increment i_count back.</span></div>
<div id="appendonsend"></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>От:</b> Pavel Tikhomirov &lt;ptikhomirov@virtuozzo.com&gt;<br>
<b>Отправлено:</b> 29 июля 2020 г. 13:46<br>
<b>Кому:</b> Andrey Zhadchenko &lt;andrey.zhadchenko@virtuozzo.com&gt;; devel@openvz.org &lt;devel@openvz.org&gt;<br>
<b>Тема:</b> Re: [PATCH RH7 v3] cgroup: add export_operations to cgroup super block</font>
<div>&nbsp;</div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt">
<div class="PlainText">Except for two small nits it looks good.<br>
<br>
Note: Because we use atomic_inc_not_zero(i_count) and the fact that iput <br>
can increment i_count back, we can _potentially_ see situation that <br>
open_by_handle_at first fails to open and next is able to open the same <br>
handle. But I don't think it's a big deal for us.<br>
<br>
On 7/28/20 2:59 PM, Andrey Zhadchenko wrote:<br>
&gt; criu uses fhandle from fdinfo to dump inotify objects. cgroup super block has<br>
&gt; no export operations, but .encode_fh and .fh_to_dentry are needed for<br>
&gt; inotify_fdinfo function and open_by_handle_at syscall in order to correctly<br>
&gt; open files located on cgroupfs by fhandle.<br>
&gt; Add hash table as a storage for inodes with exported fhandle.<br>
&gt; <br>
&gt; v3: use inode-&gt;i_gen to protect from i_ino reusage. increase fhandle size to<br>
&gt; 2 * u32.<br>
&gt; Add an option to take reference of inode in cgroup_find_inode, so no one can<br>
&gt; delete recently found inode.<br>
&gt; <br>
&gt; <a href="https://jira.sw.ru/browse/PSBM-105889">https://jira.sw.ru/browse/PSBM-105889</a><br>
&gt; Signed-off-by: Andrey Zhadchenko &lt;andrey.zhadchenko@virtuozzo.com&gt;<br>
&gt; ---<br>
&gt;&nbsp;&nbsp; kernel/cgroup.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-<br>
&gt;&nbsp;&nbsp; 1 file changed, 136 insertions(+), 1 deletion(-)<br>
&gt; <br>
&gt; diff --git a/kernel/cgroup.c b/kernel/cgroup.c<br>
&gt; index 9fdba79..267a5a4 100644<br>
&gt; --- a/kernel/cgroup.c<br>
&gt; +++ b/kernel/cgroup.c<br>
&gt; @@ -62,6 +62,8 @@<br>
&gt;&nbsp;&nbsp; #include &lt;linux/kthread.h&gt;<br>
&gt;&nbsp;&nbsp; #include &lt;linux/ve.h&gt;<br>
&gt;&nbsp;&nbsp; #include &lt;linux/stacktrace.h&gt;<br>
&gt; +#include &lt;linux/exportfs.h&gt;<br>
&gt; +#include &lt;linux/time.h&gt;<br>
&gt;&nbsp;&nbsp; <br>
&gt;&nbsp;&nbsp; #include &lt;linux/atomic.h&gt;<br>
&gt;&nbsp;&nbsp; <br>
&gt; @@ -765,6 +767,7 @@ static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb)<br>
&gt;&nbsp;&nbsp; <br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inode) {<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode-&gt;i_ino = get_next_ino();<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode-&gt;i_generation = get_seconds();<br>
<br>
We likely want to use prandom_u32() instead, see mainstream linux commit <br>
46c9a946d766 (&quot;shmem: use monotonic time for i_generation&quot;), they've <br>
change it for shmem to overcome overflow.<br>
<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode-&gt;i_mode = mode;<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode-&gt;i_uid = current_fsuid();<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inode-&gt;i_gid = current_fsgid();<br>
&gt; @@ -1390,9 +1393,140 @@ out:<br>
&gt;&nbsp;&nbsp; }<br>
&gt;&nbsp;&nbsp; #endif<br>
&gt;&nbsp;&nbsp; <br>
&gt; +/*<br>
&gt; + * hashtable for inodes that have exported fhandles.<br>
&gt; + * When we export fhandle, we add it's inode into<br>
&gt; + * hashtable so we can find it fast<br>
&gt; + */<br>
&gt; +<br>
&gt; +#define CGROUP_INODE_HASH_BITS 10<br>
&gt; +static DEFINE_HASHTABLE(cgroup_inode_table, CGROUP_INODE_HASH_BITS);<br>
&gt; +static DEFINE_SPINLOCK(cgroup_inode_table_lock);<br>
&gt; +<br>
&gt; +struct cg_inode_hitem {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct inode *inode;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct hlist_node hlist;<br>
&gt; +};<br>
&gt; +<br>
&gt; +static inline unsigned long cgroup_inode_get_hash(unsigned int i_ino)<br>
&gt; +{<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; return hash_32(i_ino, CGROUP_INODE_HASH_BITS);<br>
&gt; +}<br>
&gt; +<br>
&gt; +static struct cg_inode_hitem *cgroup_find_inode(unsigned long fhandle[2],<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char take_ref)<br>
&gt; +{<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct cg_inode_hitem *i;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct hlist_head *head = cgroup_inode_table<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + cgroup_inode_get_hash(fhandle[1]);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct cg_inode_hitem *found = NULL;<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;cgroup_inode_table_lock);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; hlist_for_each_entry(i, head, hlist) {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i-&gt;inode-&gt;i_generation == fhandle[0] &amp;&amp;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i-&gt;inode-&gt;i_ino == fhandle[1]) {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * If we need to increase refcount, we should be aware<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * of possible deadlock. Another thread may have<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * started deleting this inode: iput-&gt;iput_final-&gt;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * -&gt;cgroup_delete_inode-&gt;cgroup_find_inode. if we<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * just call igrab, it will try to take i_lock and<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * this will result in deadlock, because deleting<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * thread has already taken it and waits on<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * cgroup_inode_table_lock to find inode in hashtable.<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * If i_count is zero, someone is deleting it -&gt; skip.<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (take_ref)<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; if (!atomic_inc_not_zero(&amp;i-&gt;inode-&gt;i_count))<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>
<br>
Should be break instead of continue? There can't be another entry in <br>
hash with same i_ino and i_generation.<br>
<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; found = i;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;cgroup_inode_table_lock);<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; return found;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static struct dentry *cgroup_fh_to_dentry(struct super_block *sb,<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct fid *fid, int fh_len, int fh_type)<br>
&gt; +{<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct cg_inode_hitem *item;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct dentry *dentry = ERR_PTR(-ENOENT);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; unsigned long fhandle[2] = {fid-&gt;raw[0], fid-&gt;raw[1]};<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (fh_len &lt; 2)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; item = cgroup_find_inode(fhandle, 1);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (item) {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dentry = d_find_alias(item-&gt;inode);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iput(item-&gt;inode);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; return dentry;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static int cgroup_encode_fh(struct inode *inode, __u32 *fh, int *len,<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; struct inode *parent)<br>
&gt; +{<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct cg_inode_hitem *item;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct hlist_head *head = cgroup_inode_table<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + cgroup_inode_get_hash(inode-&gt;i_ino);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; unsigned long fhandle[2] = {inode-&gt;i_generation, inode-&gt;i_ino};<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (*len &lt; 2) {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *len = 2;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FILEID_INVALID;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (!cgroup_find_inode(fhandle, 0)) {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; item = kmalloc(sizeof(struct cg_inode_hitem),<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GFP_KERNEL);<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;&nbsp; * encode_fh is expected to return 255 (FILEID_INVALID)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * in case of failure. We can't return ENOMEM, so<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * return FILEID_INVALID at least<br>
&gt; +&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; if (!item)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FILEID_INVALID;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; item-&gt;inode = inode;<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;cgroup_inode_table_lock);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hlist_add_head(&amp;item-&gt;hlist, head);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;cgroup_inode_table_lock);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; fh[0] = fhandle[0];<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; fh[1] = fhandle[1];<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; *len = 2;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static const struct export_operations cgroup_export_ops = {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; .encode_fh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = cgroup_encode_fh,<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; .fh_to_dentry&nbsp;&nbsp; = cgroup_fh_to_dentry,<br>
&gt; +};<br>
&gt; +<br>
&gt; +static int cgroup_delete_inode(struct inode *inode)<br>
&gt; +{<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; struct cg_inode_hitem *item = NULL;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; unsigned long fhandle[2] = {inode-&gt;i_generation, inode-&gt;i_ino};<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; item = cgroup_find_inode(fhandle, 0);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (item) {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_lock(&amp;cgroup_inode_table_lock);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hlist_del(&amp;item-&gt;hlist);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spin_unlock(&amp;cgroup_inode_table_lock);<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kfree(item);<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&gt; +<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; return generic_delete_inode(inode);<br>
&gt; +}<br>
&gt; +<br>
&gt;&nbsp;&nbsp; static const struct super_operations cgroup_ops = {<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .statfs = simple_statfs,<br>
&gt; -&nbsp;&nbsp;&nbsp;&nbsp; .drop_inode = generic_delete_inode,<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; .drop_inode = cgroup_delete_inode,<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .show_options = cgroup_show_options,<br>
&gt;&nbsp;&nbsp; #ifdef CONFIG_VE<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .show_path = cgroup_show_path,<br>
&gt; @@ -1539,6 +1673,7 @@ static int cgroup_set_super(struct super_block *sb, void *data)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_blocksize_bits = PAGE_CACHE_SHIFT;<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_magic = CGROUP_SUPER_MAGIC;<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_op = &amp;cgroup_ops;<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; sb-&gt;s_export_op = &amp;cgroup_export_ops;<br>
&gt;&nbsp;&nbsp; <br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
&gt;&nbsp;&nbsp; }<br>
&gt; <br>
<br>
-- <br>
Best regards, Tikhomirov Pavel<br>
Software Developer, Virtuozzo.<br>
</div>
</span></font></div>
</body>
</html>