<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);">
<div>criu uses fhandle from fdinfo to dump inotify objects. cgroup super block has<br>
</div>
<div>no export operations, but .encode_fh and .fh_to_dentry are needed for<br>
</div>
<div>inotify_fdinfo function and open_by_handle_at syscall in order to correctly<br>
</div>
<div>open files located on cgroupfs by fhandle.<br>
</div>
<div>Add hash table as a storage for inodes with exported fhandle.<br>
</div>
<div><br>
</div>
<div>https://jira.sw.ru/browse/PSBM-105889<br>
</div>
<div>Signed-off-by: Andrey Zhadchenko &lt;andrey.zhadchenko@virtuozzo.com&gt;<br>
</div>
<div>---<br>
</div>
<div>&nbsp;kernel/cgroup.c | 107 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;-<br>
</div>
<div>&nbsp;1 file changed, 106 insertions(&#43;), 1 deletion(-)<br>
</div>
<div><br>
</div>
<div>diff --git a/kernel/cgroup.c b/kernel/cgroup.c<br>
</div>
<div>index 9fdba79..a06c809 100644<br>
</div>
<div>--- a/kernel/cgroup.c<br>
</div>
<div>&#43;&#43;&#43; b/kernel/cgroup.c<br>
</div>
<div>@@ -62,6 &#43;62,7 @@<br>
</div>
<div>&nbsp;#include &lt;linux/kthread.h&gt;<br>
</div>
<div>&nbsp;#include &lt;linux/ve.h&gt;<br>
</div>
<div>&nbsp;#include &lt;linux/stacktrace.h&gt;<br>
</div>
<div>&#43;#include &lt;linux/exportfs.h&gt;<br>
</div>
<div>&nbsp;<br>
</div>
<div>&nbsp;#include &lt;linux/atomic.h&gt;<br>
</div>
<div>&nbsp;<br>
</div>
<div>@@ -1390,9 &#43;1391,112 @@ out:<br>
</div>
<div>&nbsp;}<br>
</div>
<div>&nbsp;#endif<br>
</div>
<div>&nbsp;<br>
</div>
<div>&#43;/*<br>
</div>
<div>&#43; * hashtable for inodes that have exported fhandles.<br>
</div>
<div>&#43; * When we export fhandle, we add it's inode into<br>
</div>
<div>&#43; * hashtable so we can find it fast<br>
</div>
<div>&#43; */<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;#define CGROUP_INODE_HASH_BITS 10<br>
</div>
<div>&#43;static DEFINE_HASHTABLE(cgroup_inode_table, CGROUP_INODE_HASH_BITS);<br>
</div>
<div>&#43;static DEFINE_SPINLOCK(cgroup_inode_table_lock);<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;struct cgroup_inode_hash_item {<br>
</div>
<div>&#43; struct inode* inode;<br>
</div>
<div>&#43; struct hlist_node hlist;<br>
</div>
<div>&#43;};<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;static inline unsigned long cgroup_inode_get_hash(unsigned int i_ino)<br>
</div>
<div>&#43;{<br>
</div>
<div>&#43; return hash_32(i_ino, CGROUP_INODE_HASH_BITS);<br>
</div>
<div>&#43;}<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;static struct cgroup_inode_hash_item* cgroup_inode_hash_find(unsigned int i_ino)<br>
</div>
<div>&#43;{<br>
</div>
<div>&#43; struct cgroup_inode_hash_item *i;<br>
</div>
<div>&#43; struct hlist_head *head = cgroup_inode_table &#43; cgroup_inode_get_hash(i_ino);<br>
</div>
<div>&#43; struct cgroup_inode_hash_item* found = 0;<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; spin_lock(&amp;cgroup_inode_table_lock);<br>
</div>
<div>&#43; hlist_for_each_entry(i, head, hlist) {<br>
</div>
<div>&#43; if(i-&gt;inode-&gt;i_ino == i_ino) {<br>
</div>
<div>&#43; found = i;<br>
</div>
<div>&#43; break;<br>
</div>
<div>&#43; }<br>
</div>
<div>&#43; }<br>
</div>
<div>&#43; spin_unlock(&amp;cgroup_inode_table_lock);<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; return found;<br>
</div>
<div>&#43;}<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;static struct dentry *cgroup_fh_to_dentry(struct super_block *sb,<br>
</div>
<div>&#43; struct fid *fid, int fh_len, int fh_type)<br>
</div>
<div>&#43;{<br>
</div>
<div>&#43; struct cgroup_inode_hash_item *item;<br>
</div>
<div>&#43; struct dentry *dentry = ERR_PTR(-ENOENT);<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; if (fh_len &lt; 1)<br>
</div>
<div>&#43; return NULL;<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; item = cgroup_inode_hash_find(fid-&gt;raw[0]);<br>
</div>
<div>&#43; if (item)<br>
</div>
<div>&#43; dentry = d_find_alias(item-&gt;inode);<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; return dentry;<br>
</div>
<div>&#43;}<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;static int cgroup_encode_fh(struct inode *inode, __u32 *fh, int *len,<br>
</div>
<div>&#43; struct inode *parent)<br>
</div>
<div>&#43;{<br>
</div>
<div>&#43; struct hlist_head *head = cgroup_inode_table &#43; cgroup_inode_get_hash(inode-&gt;i_ino);<br>
</div>
<div>&#43; struct cgroup_inode_hash_item *item;<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; if (*len &lt; 1) {<br>
</div>
<div>&#43; *len = 1;<br>
</div>
<div>&#43; return FILEID_INVALID;<br>
</div>
<div>&#43; }<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; if(cgroup_inode_hash_find(inode-&gt;i_ino) == 0) {<br>
</div>
<div>&#43; item = kmalloc(sizeof(struct cgroup_inode_hash_item), GFP_KERNEL);<br>
</div>
<div>&#43; /*<br>
</div>
<div>&#43; * encode_fh is expected to return 255 (FILEID_INVALID) in case of<br>
</div>
<div>&#43; * failure. We can't return ENOMEM, so return FILEID_INVALID at least<br>
</div>
<div>&#43; */<br>
</div>
<div>&#43; if(!item)<br>
</div>
<div>&#43; return FILEID_INVALID;<br>
</div>
<div>&#43; item-&gt;inode = inode;<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; spin_lock(&amp;cgroup_inode_table_lock);<br>
</div>
<div>&#43; hlist_add_head(&amp;item-&gt;hlist, head);<br>
</div>
<div>&#43; spin_unlock(&amp;cgroup_inode_table_lock);<br>
</div>
<div>&#43; }<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; fh[0] = inode-&gt;i_ino;<br>
</div>
<div>&#43; *len = 1;<br>
</div>
<div>&#43; return 1;<br>
</div>
<div>&#43;}<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;static const struct export_operations cgroup_export_ops = {<br>
</div>
<div>&#43; .encode_fh &nbsp; &nbsp; &nbsp;= cgroup_encode_fh,<br>
</div>
<div>&#43; .fh_to_dentry = cgroup_fh_to_dentry,<br>
</div>
<div>&#43;};<br>
</div>
<div>&#43;<br>
</div>
<div>&#43;static int cgroup_delete_inode(struct inode *inode){<br>
</div>
<div>&#43; struct cgroup_inode_hash_item *item = cgroup_inode_hash_find(inode-&gt;i_ino);<br>
</div>
<div>&#43; if(item) {<br>
</div>
<div>&#43; spin_lock(&amp;cgroup_inode_table_lock);<br>
</div>
<div>&#43; hlist_del(&amp;item-&gt;hlist);<br>
</div>
<div>&#43; spin_unlock(&amp;cgroup_inode_table_lock);<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; kfree(item);<br>
</div>
<div>&#43; }<br>
</div>
<div>&#43;<br>
</div>
<div>&#43; return generic_delete_inode(inode);<br>
</div>
<div>&#43;}<br>
</div>
<div>&#43;<br>
</div>
<div>&nbsp;static const struct super_operations cgroup_ops = {<br>
</div>
<div>&nbsp; .statfs = simple_statfs,<br>
</div>
<div>- .drop_inode = generic_delete_inode,<br>
</div>
<div>&#43; .drop_inode = cgroup_delete_inode,<br>
</div>
<div>&nbsp; .show_options = cgroup_show_options,<br>
</div>
<div>&nbsp;#ifdef CONFIG_VE<br>
</div>
<div>&nbsp; .show_path = cgroup_show_path,<br>
</div>
<div>@@ -1539,6 &#43;1643,7 @@ static int cgroup_set_super(struct super_block *sb, void *data)<br>
</div>
<div>&nbsp; sb-&gt;s_blocksize_bits = PAGE_CACHE_SHIFT;<br>
</div>
<div>&nbsp; sb-&gt;s_magic = CGROUP_SUPER_MAGIC;<br>
</div>
<div>&nbsp; sb-&gt;s_op = &amp;cgroup_ops;<br>
</div>
<div>&#43; sb-&gt;s_export_op = &amp;cgroup_export_ops;<br>
</div>
<div>&nbsp;<br>
</div>
<div>&nbsp; return 0;<br>
</div>
<div>&nbsp;}<br>
</div>
<div>-- <br>
</div>
<div>1.8.3.1<br>
</div>
<span></span><br>
</div>
</body>
</html>