tag:blogger.com,1999:blog-31031560965219388962024-02-19T14:21:51.579-08:00Devil's denThis blog mostly contains my random scribbling of linux notes. I try to make it little structured so that its useful if anyone else also happens to read it.Unknownnoreply@blogger.comBlogger16125tag:blogger.com,1999:blog-3103156096521938896.post-39257374476305966372015-08-15T00:35:00.000-07:002016-11-01T08:33:07.951-07:00Installing vmware-view client on Ubuntu 14.10 on 64 bit systems.<div dir="ltr" style="text-align: left;" trbidi="on">
Here are the instructions (along with the error messages) to install vmware-view client on ubuntu 64 bit systems.<br />
<br />
<b><u>Short version:</u></b> If you don't have time to read below. Copy following script, and run it from folder where you had downloaded the client.<br />
<blockquote class="tr_bq">
#!/bin/bash<br />sudo dpkg --add-architecture i386<br />sudo apt-get install libxml2:i386<br />sudo apt-get install libssl1.0.0:i386<br />sudo apt-get install libXtst6:i386<br />sudo apt-get install libudev1:i386<br />sudo apt-get install libpcsclite1:i386<br />sudo apt-get install libtheora0:i386<br />sudo apt-get install libv4l-0:i386<br />sudo apt-get install libpulse0:i386<br />sudo ln -sf /lib/i386-linux-gnu/libudev.so.1 /lib/i386-linux-gnu/libudev.so.0<br />sudo ln -sf /lib/i386-linux-gnu/libssl.so.1.0.0 /lib/i386-linux-gnu/libssl.so.1.0.1<br />sudo ln -sf /lib/i386-linux-gnu/libcrypto.so.1.0.0 /lib/i386-linux-gnu/libcrypto.so.1<br />sudo apt-get install libncurses5-dev:i386<br />sudo apt-get install libcanberra-gtk-module:i386<br />sudo apt-get install libxss-dev:i386<br />sudo apt-get install libxml2-dev:i386<br />sudo apt-get install lib32stdc++6<br />chmod a+x VMware-Horizon-Client-3.4.0-2769709.x86.bundle<br />sudo ./VMware-Horizon-Client-3.4.0-2769709.x86.bundle<br />vmware-view &</blockquote>
<br />
<br />
<b><u><br /></u></b>
<b><u>Longer version:</u></b><br />
<br />
<span style="color: red;">/tmp> uname -a</span><br />
Linux devils-den 3.16.0-44-generic #59-Ubuntu SMP Tue Jul 7 02:07:39 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux<br />
<span style="color: red;">/tmp> sudo ./VMware-Horizon-Client-3.4.0-2769709.x86.bundle</span><br />
VMWare Horizon Client is an x86 application but you are trying to install it to an x64 Linux.<br />
To run this installation, you may need to install 32-bit runtime libraries. Do you want to proceed? (yes/no)yes<br />
Extracting VMware Installer...done.<br />
/tmp/vmis.jIqCaw/install/vmware-installer/vmware-installer: line 57: /tmp/vmis.jIqCaw/install/vmware-installer/vmis-launcher: No such file or directory<br />
<br />
<span style="color: red;">/tmp> sudo dpkg --add-architecture i386</span><br />
<span style="color: red;">/tmp> sudo apt-get install libxml2:i386<br />/tmp> sudo apt-get install libssl1.0.0:i386<br />/tmp> sudo apt-get install libXtst6:i386<br />/tmp> sudo apt-get install libudev1:i386<br />/tmp> sudo apt-get install libpcsclite1:i386<br />/tmp> sudo apt-get install libtheora0:i386<br />/tmp> sudo apt-get install libv4l-0:i386<br />/tmp> sudo apt-get install libpulse0:i386<br />/tmp> sudo ln -sf /lib/i386-linux-gnu/libudev.so.1 /lib/i386-linux-gnu/libudev.so.0<br />/tmp> sudo ln -sf /lib/i386-linux-gnu/libssl.so.1.0.0 /lib/i386-linux-gnu/libssl.so.1.0.1<br />/tmp> sudo ln -sf /lib/i386-linux-gnu/libcrypto.so.1.0.0 /lib/i386-linux-gnu/libcrypto.so.1</span><br />
<br />
<span style="color: red;">/tmp> sudo ./VMware-Horizon-Client-3.4.0-2769709.x86.bundle</span><br />
VMWare Horizon Client is an x86 application but you are trying to install it to an x64 Linux.<br />
To run this installation, you may need to install 32-bit runtime libraries. Do you want to proceed? (yes/no)yes<br />
Extracting VMware Installer...done.<br />
User interface initialization failed. Exiting. Check the log for details.<br />
<span style="color: red;"><br />/tmp> sudo apt-get install libncurses5-dev:i386<br />/tmp> sudo apt-get install libcanberra-gtk-module:i386<br /><br />/tmp> sudo ./VMware-Horizon-Client-3.4.0-2769709.x86.bundle<br />/tmp> vmware-view &</span><br />
[1] 11398<br />
/tmp> /usr/lib/vmware/view/bin/vmware-view: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory<br />
<span style="color: red;">/tmp> sudo apt-get install libxss-dev:i386<br /><br />/tmp> vmware-view & </span> <br />
[1] 14472<br />
/tmp> /usr/lib/vmware/view/bin/vmware-view: error while loading shared libraries: libxml2.so.2: cannot open shared object file: No such file or directory<br />
<span style="color: red;">/tmp> sudo apt-get install libxml2-dev:i386<br /><br />/tmp> vmware-view &</span> <br />
[1] 16845<br />
/tmp> /usr/lib/vmware/view/bin/vmware-view: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory<br />
<span style="color: red;">/tmp> sudo apt-get install lib32stdc++6<br /><br /><br />/tmp> vmware-view & </span><br />
<br />
<br />
<span style="color: blue;">After this, vmware-view client works for me. Njoy ! </span></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-3103156096521938896.post-50008007397064874772013-02-24T16:55:00.001-08:002013-02-24T20:45:16.465-08:00<div dir="ltr" style="text-align: left;" trbidi="on">
<div align="center">
<div style="text-align: left;">
Here is a simple web remote you can use with your roku player. Chances are that it won't work directly from the blog. Unfortunately blogspot doesn't have a place to add a download link, so right click on the page, select "view source" and save it as a html file on your local disk. And then open the html, also make sure the input IP address provided is correct for your roku device.<u> </u></div>
<br />
<u>Roku Web Remote</u><br />
<br />
<b>Roku IP :</b>
<input id="ip" name="ipaddress" type="text" value="192.168.1.71" width="10" />
</div>
<br />
<table align="center" border="10">
<colgroup><col align="center"></col>
</colgroup><tbody>
<tr>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Back" style="text-decoration: none;"><=</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Back").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Back");
});
});
</script>
</td>
<td></td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Home" style="text-decoration: none;">Home</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Home").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Home");
});
});
</script>
</td>
</tr>
<tr>
<td></td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Up" style="text-decoration: none;">^</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Up").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Up");
});
});
</script>
</td>
<td></td>
</tr>
<tr>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Left" style="text-decoration: none;"><</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Left").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Left");
});
});
</script>
</td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Select" style="text-decoration: none;">Select</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Select").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Select");
});
});
</script>
</td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Right" style="text-decoration: none;">></a>
<script type="text/javascript">
$(document).ready(function(){
$("#Right").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Right");
});
});
</script>
</td>
</tr>
<tr>
<td></td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Down" style="text-decoration: none;">v</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Down").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Down");
});
});
</script>
</td>
<td></td>
</tr>
<tr>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Repeat" style="text-decoration: none;">Repeat</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Repeat").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Repeat");
});
});
</script>
</td>
<td></td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Info" style="text-decoration: none;">Info</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Info").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Info");
});
});
</script>
</td>
</tr>
<tr>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Revind" style="text-decoration: none;"><<</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Revind").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Rev");
});
});
</script>
</td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Play" style="text-decoration: none;">>||</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Play").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Play");
});
});
</script>
</td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Fwd" style="text-decoration: none;">>></a>
<script type="text/javascript">
$(document).ready(function(){
$("#Fwd").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Fwd");
});
});
</script>
</td>
</tr>
<tr>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Backspace" style="text-decoration: none;">Backspace</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Backspace").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Backspace");
});
});
</script>
</td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Instantreplay" style="text-decoration: none;">InstantReplay</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Instantreplay").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/InstantReplay");
});
});
</script>
</td>
<td align="center"><a href="http://www.blogger.com/blogger.g?blogID=3103156096521938896" id="Search" style="text-decoration: none;">Search</a>
<script type="text/javascript">
$(document).ready(function(){
$("#Search").click(function(){
$.post("http://"+document.getElementById("ip").value+":8060/keypress/Search");
});
});
</script>
</td>
</tr>
</tbody></table>
<br />
<div align="center">
<input id="searchtext" type="text" value="Enter Search text" />
<button id="searchtext1" onclick="SendText()">Submit</button>
<script type="text/javascript">
function SendText()
{
var searchtext = (document.getElementById("searchtext").value);
for (var i=0 ; i < searchtext.length ; i++) {
if (searchtext.charAt(i) == ' ') {
$.ajax({
url: "http://"+document.getElementById("ip").value+":8060/keypress/Lit_%20",
async: false,
type: 'post'
});
} else {
$.ajax({
url: "http://"+document.getElementById("ip").value+":8060/keypress/Lit_"+searchtext.charAt(i),
async: false,
type: 'post'
});
}
}
}
</script>
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-47262035154730597252013-02-10T11:27:00.002-08:002013-06-08T11:00:41.415-07:00<div dir="ltr" style="text-align: left;" trbidi="on">
<b>Communicating with roku box without remote</b><br />
<br />
It is bound to happen ! Some day you will lose your roku remote and start looking for alternatives. I was trying to re-configure my roku box, and happily did a factory reset by pressing the reset button at the back of the box and then realized...oops, I don't have a remote. Now the hunt for remote started which was nowhere to be seen. The next obvious choice to control roku is an iphone or android, but I don't possess any of apple products (because I love my freedom) and my android was with my wife in a foreign country. All I had was a 3 yr old IBM thinkpad with ubuntu 12.10. Thankfully there are two more choices available. Apparently there are couple of ports open by default on roku box (8060 and 8080-8085) through which you can communicate.<br />
All the settings were gone due to factory reset, so had to connect my Roku-XD with an ethernet cable and by logging into the router got the ip address of the device.<br />
Telnet to ipaddr:8080 succeeded first time and by mistake I quit the console, and after that even after repeated attempts I kept getting connection refused. Searching through net I came across a python script which had a GUI to control, but I couldn't get it to work because telnet to port 8080 wasn't succeeding even though I was able to ping the ip address.<br />
Next was to try the HTTP port, tried few commands and they seemed to go through..bingo ! That was all I needed. Next 10 mins. were spent writing a shell script and I had a reasonable command line remote for controlling the roku box. You can start the below shell script using the command "roku <ipaddr>" on your command line. Without the ipaddr parameter it connects to 192.168.1.66 by default.<br />
<br />
I couldn't figure out how to configure wireless using command line, because it just gets stuck once you select the SSID and the http request doesn't return for you to enter the next command.<br />
<br />
Below is the shell script, if this post or the shell script below helped you, I would like to know so please drop me a line. And because blogspot won't allow me to upload the script, its in plain text below. Just copy paste it to your local file, change execute permissions (chmod a+x <filename>) and run.<br />
<br />
<pre># Simple script to communicate with your roku box.
#Written by Manish Katiyar <mkatiyar gmail.com="">
# Date : 2/9/2013
#Enter your roku IP address here
ipaddr=192.168.1.66
[ ! -z "$1" ] && ipaddr=$1
echo "++++++++++++++++++++++++++++++++++++++++++++++"
echo "Sending commands to roku box ($ipaddr)"
echo "++++++++++++++++++++++++++++++++++++++++++++++"
runcmd() {
wget -O /dev/null --post-data "" "http://$ipaddr:8060/keypress/$cmd" 2> /dev/null
}
help() {
echo "Command Usage : $0 [ipaddr]<ipaddr>"
echo "Subcommands :"
printf "\tHome - [Hh]\n"
printf "\tRev - [Rr]ev\n"
printf "\tFwd - [Ff]\n"
printf "\tPlay - [Pp]\n"
printf "\tSelect - [Ss]\n"
printf "\tLeft - [Ll]\n"
printf "\tRight [Rr]\n"
printf "\tDown - [Dd]\n"
printf "\tUp - [Uu]\n"
printf "\tBack - [Bb]\n"
printf "\tInstantReplay - Ir\n"
printf "\tInfo - [Ii]nf\n"
printf "\tBackspace - bs\n"
printf "\tSearch - srch\n"
printf "\tEnter - [Ee]\n"
printf "\tInput - [Ii]\n"
printf "\tQuit - [Qq]\n"
printf "\t? help\n"
}
getinput() {
echo "Enter your phrase below"</ipaddr></mkatiyar></pre>
<pre><mkatiyar gmail.com=""><ipaddr> read word</ipaddr></mkatiyar></pre>
<pre><mkatiyar gmail.com=""><ipaddr> wordlen=`echo $word|wc -c`
wordlen=`expr $wordlen - 1`
for i in `seq 1 $wordlen`
do
char=`echo $word|cut -c $i`
cmd=Lit_$char</ipaddr></mkatiyar></pre>
<pre><mkatiyar gmail.com=""><ipaddr> sleep 0.3
runcmd
done
}
while [ 1 ]
do
printf "Enter roku command (?) > "
read a
case $a in
[Hh]) cmd=Home && runcmd ;;
[Rr]ev) cmd=Rev && runcmd ;;
[Ff]) cmd=Fwd && runcmd ;;
[Pp]) cmd=Play && runcmd ;;
[Ss]) cmd=Select && runcmd ;;
[Ll]) cmd=Left && runcmd ;;
[Rr]) cmd=Right && runcmd ;;
[Uu]) cmd=Up && runcmd ;;
[Dd]) cmd=Down && runcmd ;;
[Bb]) cmd=Back && runcmd ;;
[Ii]r]) cmd=InstantReplay && runcmd ;;
[Ii]nf) cmd=Info && runcmd ;;
bs) cmd=Backspace && runcmd ;;
srch) cmd=Search && runcmd ;;
[Ee]) cmd=Enter && runcmd ;;
[Ii]) getinput;;
[Qq]) exit -1;;
?) help;;
esac
done
</ipaddr></mkatiyar></pre>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-75987643920749761402012-07-30T22:02:00.003-07:002013-02-03T19:05:54.146-08:00Caricatures<div dir="ltr" style="text-align: left;" trbidi="on">
Have been trying to sketch on the WACOM bamboo tablet. Seems nice so far. Let's see how it goes.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo70H5y4akdDnP8uoWz3zwYiXEIeSjjWeHp7a28QEpanzj0LmL8bJMCc4xNr86N7Y_WolHckGQbQW5vckEluP-jmi-V8VWOR-L-MTa_fLTbTtA236yu3lZa4ZMfbzvG1VGqfVSli-2V0s/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo70H5y4akdDnP8uoWz3zwYiXEIeSjjWeHp7a28QEpanzj0LmL8bJMCc4xNr86N7Y_WolHckGQbQW5vckEluP-jmi-V8VWOR-L-MTa_fLTbTtA236yu3lZa4ZMfbzvG1VGqfVSli-2V0s/s320/3.png" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN4y3LaaOicC4LgxrmiHhWK0eCTwOCADSkXN9prrx6HH_BVFOte5sDx8nTbpDl-6kXSq123qx7osr-f1aqh2Db07z6AlUxGmfjfqxcLNuaHhMoX-sHzKgsGY-tYRA-2_nsJgThtwYtLVM/s1600/mahendra.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="260" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN4y3LaaOicC4LgxrmiHhWK0eCTwOCADSkXN9prrx6HH_BVFOte5sDx8nTbpDl-6kXSq123qx7osr-f1aqh2Db07z6AlUxGmfjfqxcLNuaHhMoX-sHzKgsGY-tYRA-2_nsJgThtwYtLVM/s320/mahendra.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7vBfjn9RfpNxkINVZQPgG4zeflIienji9yf_GGqQHeiyxiSDh65ThtfnfFVtpEG5AkscQ0gVEGSgBDAfBCZtiMnIB8WPKMyxofTzh1asSgkxIX2JCl3p_fbGUFmTNjKOKJKJwAGPEPbI/s1600/man.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7vBfjn9RfpNxkINVZQPgG4zeflIienji9yf_GGqQHeiyxiSDh65ThtfnfFVtpEG5AkscQ0gVEGSgBDAfBCZtiMnIB8WPKMyxofTzh1asSgkxIX2JCl3p_fbGUFmTNjKOKJKJwAGPEPbI/s320/man.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5em7Q2MHKdtizR_jfEFZodEAFhWOBYm4iXGPCnJ0uOyfOACTLS9u2htufdVS3xPPLX6Y-YYRQbKUmbIPBXrp-3-Szdz5tD54ojhjMhTFKc0LaXuTKJBqAg6YanTC9_tWsLgntX0T73R0/s1600/blonde.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5em7Q2MHKdtizR_jfEFZodEAFhWOBYm4iXGPCnJ0uOyfOACTLS9u2htufdVS3xPPLX6Y-YYRQbKUmbIPBXrp-3-Szdz5tD54ojhjMhTFKc0LaXuTKJBqAg6YanTC9_tWsLgntX0T73R0/s320/blonde.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigEN0aOSk08zOEb3hxwTSeY2FlDZs5Z3OstM5onccXuI9W5NmPb5mTem16B-fmreZ6hlxHQ4ACc2jtGv0VKgBr9Dt7YlhvPzRAD4GQwX6jGMu1pRX-s28lqOe1pGhyPiV53f1frhjpNMQ/s1600/girl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVWieZpFC5GwsZQZ3dr2lobhFEQRcEyFMw9Xzlu7ugsaIX4s26uiugDJwA8ZGJrnVmTeUWwA-lRc-cGvqo39VJuus9NKBwU8f11l5gZc28Gzfq0l_odqyZo9ahRZ5la_2ADbYG8OSiyg/s1600/girl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVWieZpFC5GwsZQZ3dr2lobhFEQRcEyFMw9Xzlu7ugsaIX4s26uiugDJwA8ZGJrnVmTeUWwA-lRc-cGvqo39VJuus9NKBwU8f11l5gZc28Gzfq0l_odqyZo9ahRZ5la_2ADbYG8OSiyg/s320/girl.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiiyGOTukS0n5Xj_8uPImG2EHjjJhnsIuCFatC7IyFJbovXJvifKZFDSYYtAjISKb0r7q4wn9X5wVbQOzRUzAMoWQCRUEDeoITsUVi8VbHCUUyMAxsDAjJCCwO1PJxatDk_CFGe6eYrg4/s1600/boy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiiyGOTukS0n5Xj_8uPImG2EHjjJhnsIuCFatC7IyFJbovXJvifKZFDSYYtAjISKb0r7q4wn9X5wVbQOzRUzAMoWQCRUEDeoITsUVi8VbHCUUyMAxsDAjJCCwO1PJxatDk_CFGe6eYrg4/s320/boy.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQtC2Kzf66-gJ47d__Uz1aoQiBr-rIKrfso-0xT00I4hTdUnsRFPkWGqHLcc4pFQrKzIJPSlRmnheEpi9wEqLfr9BpnNYfF3IBGvFAfV3IjJVHH435koOmvC5HbjDSsI6n5Aea1TUqHr0/s1600/man1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQtC2Kzf66-gJ47d__Uz1aoQiBr-rIKrfso-0xT00I4hTdUnsRFPkWGqHLcc4pFQrKzIJPSlRmnheEpi9wEqLfr9BpnNYfF3IBGvFAfV3IjJVHH435koOmvC5HbjDSsI6n5Aea1TUqHr0/s320/man1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuEYZ_dWJW7yVJgDX0ACxXesd1yYRQKPrdUMFs63WD58NUNIaBLJ6wuT3Bo9Fd30AeEMw3Cjr5Tz5DvliYLahaQoCyUyolNaWTcKXES3IpGUvxTZhR6WQ8hM4oj83r-1wuq3e2mqogZPQ/s1600/child.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuEYZ_dWJW7yVJgDX0ACxXesd1yYRQKPrdUMFs63WD58NUNIaBLJ6wuT3Bo9Fd30AeEMw3Cjr5Tz5DvliYLahaQoCyUyolNaWTcKXES3IpGUvxTZhR6WQ8hM4oj83r-1wuq3e2mqogZPQ/s320/child.png" width="240" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAFjJUtLA1AE4G8chPAzcGENTJ0O3BLyNUw9bKbilc-ROiQWddKjY-AyhpzMBUu-bB25uMA_B2RvHfI_K1zt5tJD-duPgEVeQpscJB__VJC-a7Y2EN405uf6gHBYnHyIUgT_H6UkDakpo/s1600/despair.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAFjJUtLA1AE4G8chPAzcGENTJ0O3BLyNUw9bKbilc-ROiQWddKjY-AyhpzMBUu-bB25uMA_B2RvHfI_K1zt5tJD-duPgEVeQpscJB__VJC-a7Y2EN405uf6gHBYnHyIUgT_H6UkDakpo/s320/despair.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdQ2CUG_cRrMB5k5k3rr3CGdIN5rEA0vs7XOtISWkldZ1giFwfZF0_TNFqELf9VpxV1mzFqZjCod4aC8xan-Eo0-9ZYwhhrVolOBvSOEwreQawsfDozlRNHpH5ED7csL_nJwDs8f2JhBc/s1600/scooter1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdQ2CUG_cRrMB5k5k3rr3CGdIN5rEA0vs7XOtISWkldZ1giFwfZF0_TNFqELf9VpxV1mzFqZjCod4aC8xan-Eo0-9ZYwhhrVolOBvSOEwreQawsfDozlRNHpH5ED7csL_nJwDs8f2JhBc/s320/scooter1.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNm3jEnmOxBTAz2mVv2VpKbe6aP_SalcPodj09aZVPt9qEsZvJ7jBE1KtMFqXj4r_lC5KLor5fmZBjlOnxoW7KHztKGwpdSse2ROBNYJpsimwGlysS5fVyD8dfD2scwA5ezTMBzuSVhDM/s1600/objects.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNm3jEnmOxBTAz2mVv2VpKbe6aP_SalcPodj09aZVPt9qEsZvJ7jBE1KtMFqXj4r_lC5KLor5fmZBjlOnxoW7KHztKGwpdSse2ROBNYJpsimwGlysS5fVyD8dfD2scwA5ezTMBzuSVhDM/s320/objects.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGT1v41UI87Aj-VST54vwSlj-zVsf8mw4g8um0UKl0p_ATbMDG9BlOgxb8vzu-SLUjVrXWK6GHz3BTd6m2BWEJQFOCWKIWKXUrfVIqsEo72H2TzDLCX2asWLC-5vgdKO3lhhCTFGUNdl8/s1600/lady.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGT1v41UI87Aj-VST54vwSlj-zVsf8mw4g8um0UKl0p_ATbMDG9BlOgxb8vzu-SLUjVrXWK6GHz3BTd6m2BWEJQFOCWKIWKXUrfVIqsEo72H2TzDLCX2asWLC-5vgdKO3lhhCTFGUNdl8/s320/lady.jpg" width="270" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeWYhyphenhyphenQDY-axWqH_f3RnnhrAPRi18YcCdmLB4TDg7yFOSwYfSjL2yyi0qSAjV-8DwtLm19KYV33rl1xxpPyhsQSKfZ8PZH3KU5OWw-WI-mQUg0C58kd-IAm0iRh8tDv22YgX6LQALWlXE/s1600/nitu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeWYhyphenhyphenQDY-axWqH_f3RnnhrAPRi18YcCdmLB4TDg7yFOSwYfSjL2yyi0qSAjV-8DwtLm19KYV33rl1xxpPyhsQSKfZ8PZH3KU5OWw-WI-mQUg0C58kd-IAm0iRh8tDv22YgX6LQALWlXE/s320/nitu.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh18SQij1Gak7OFMkuHU4jYz9XOdiFNJWe2jImDNYcSFLAlVi3rdxU5HEA5fdWEjVQUzd54clJwW5p3ANZ5pJeCefH22C8NE6T9sW7QZDTO2P8xG8-GlNtPUHTmYMTuQYFn91aeyRI_JIE/s1600/nitu1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh18SQij1Gak7OFMkuHU4jYz9XOdiFNJWe2jImDNYcSFLAlVi3rdxU5HEA5fdWEjVQUzd54clJwW5p3ANZ5pJeCefH22C8NE6T9sW7QZDTO2P8xG8-GlNtPUHTmYMTuQYFn91aeyRI_JIE/s320/nitu1.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxVRyqAN5g7kmpMjkliElYWU8iCBldf-8p4DmhYJucozGxU_oCIKUrrcfsdNzwJtnRUF9dG-9Hr_GDFxeHaCoZldXh47t6V11r2qK1FztTBTBUeHcyro27mnXyZUkxkSQurJ3F3NycaNw/s1600/mars.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxVRyqAN5g7kmpMjkliElYWU8iCBldf-8p4DmhYJucozGxU_oCIKUrrcfsdNzwJtnRUF9dG-9Hr_GDFxeHaCoZldXh47t6V11r2qK1FztTBTBUeHcyro27mnXyZUkxkSQurJ3F3NycaNw/s320/mars.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxooXXhHPKzG9ss51TGxoS3YCtf-3YgdJNsljy_xxUSvXIcw89oFkQD39ypgv7ntU7UJ-uh6aFc_6MTLm_ZBP6GcwJcZQWHOSRaiL45drEODl1ftIumU58CWi4l8yff76y2ptE7_DlY4Y/s1600/vsriram2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxooXXhHPKzG9ss51TGxoS3YCtf-3YgdJNsljy_xxUSvXIcw89oFkQD39ypgv7ntU7UJ-uh6aFc_6MTLm_ZBP6GcwJcZQWHOSRaiL45drEODl1ftIumU58CWi4l8yff76y2ptE7_DlY4Y/s320/vsriram2.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1lh9xAyds7Ca-Dwi0gsUwtGgk6jpwaFAgNIVUgSsomAyNpJZKhAhW3GCoK_SbwyI4BKQ4ia47MR_8jytC2gS7oBZOrVdRA444J_XYjOc4sEtiTwn3fMEM9aWmLvYTmWyQakLnFPpzRN0/s1600/vsriram3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1lh9xAyds7Ca-Dwi0gsUwtGgk6jpwaFAgNIVUgSsomAyNpJZKhAhW3GCoK_SbwyI4BKQ4ia47MR_8jytC2gS7oBZOrVdRA444J_XYjOc4sEtiTwn3fMEM9aWmLvYTmWyQakLnFPpzRN0/s320/vsriram3.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKbLwFIgLxadvnl0cbK2bhQ2T56phuQf2TE1A33rNv9ZoO6d0-p_FcbNN11poYHabSgbV04o0x22P9MwNHNJOfjw_IIilnsP0YKWocWWiqiAJbTL_buMjvk9ETci5ssE0kkL1z-v_jZkM/s1600/Screenshot+from+2012-10-13+17:20:25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKbLwFIgLxadvnl0cbK2bhQ2T56phuQf2TE1A33rNv9ZoO6d0-p_FcbNN11poYHabSgbV04o0x22P9MwNHNJOfjw_IIilnsP0YKWocWWiqiAJbTL_buMjvk9ETci5ssE0kkL1z-v_jZkM/s320/Screenshot+from+2012-10-13+17:20:25.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTEDtFmobPkfIRf_Oxde0LH0saynXaxL_k_sc-Ft0M1CtZGOLnEaHRF-xj-3tZ-M8w-wzcPHCdTw1CMcGH8Wtr3gDc8X3x1ZOUW1cDj07F3_aFNbME2dOc0y4aRJbEL5jwrdxk439izhs/s1600/random.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="269" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTEDtFmobPkfIRf_Oxde0LH0saynXaxL_k_sc-Ft0M1CtZGOLnEaHRF-xj-3tZ-M8w-wzcPHCdTw1CMcGH8Wtr3gDc8X3x1ZOUW1cDj07F3_aFNbME2dOc0y4aRJbEL5jwrdxk439izhs/s320/random.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNiDEfVaI3bmuZgX8jtFMGy2SlxFjQayOT-Y20n1nXU35xaewOARZA4kfv7dWwZ_SJ-UvR4cBWCHWodb5chp5NbPsxkKChNtfdTBT2eK2WZlft6jGn26Fr_FXNapg9Gh-Jz6X6LumBRbo/s1600/sage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNiDEfVaI3bmuZgX8jtFMGy2SlxFjQayOT-Y20n1nXU35xaewOARZA4kfv7dWwZ_SJ-UvR4cBWCHWodb5chp5NbPsxkKChNtfdTBT2eK2WZlft6jGn26Fr_FXNapg9Gh-Jz6X6LumBRbo/s320/sage.png" width="320" /></a></div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-23757490722474882522012-04-01T23:21:00.000-07:002012-04-04T20:59:55.040-07:00Applying filter to results in cscope<div dir="ltr" style="text-align: left;" trbidi="on">
I had always wanted cscope to be a little more intelligent and let me specify the range of search results, which may be very handy when you are browsing a large project and want to look into a particular file instead of whole project. Of course one way is to put the results in a file and use your shell scripting skills (but do you really want to do that ??).<br />
<br />
Googling didn't give any useful results, so I decided to spend my Sunday to do some useful work, and added support in cscope to apply filters to search. Here is what it can do currently.<br />
<br />
a) Apply filename filter to your "Find C symbols"<br />
b) You can tell cscope to not include the patterns from a particular file.<br />
c) It supports logical OR (I didn't try other regex)<br />
<br />
Snapshots below.<br />
<br />
=> Search of i_nlink in linux codebase 500 instances like below<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW-7frOCVrpjcMdq34OXREfiQwigNul95eOm5zZUvj59WtACb-0cRQyaz9Wml5iW2RekNAIkY-N6-eS7rfQdVB20tPnFq2GQxrrI358EKBoUt17vtLKZ18BOrEON_nJwB3GL7LuSqNUUk/s1600/basecase.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW-7frOCVrpjcMdq34OXREfiQwigNul95eOm5zZUvj59WtACb-0cRQyaz9Wml5iW2RekNAIkY-N6-eS7rfQdVB20tPnFq2GQxrrI358EKBoUt17vtLKZ18BOrEON_nJwB3GL7LuSqNUUk/s320/basecase.png" width="320" /></a> <br />
<br />
=> But I'm really interested in the places where its accessed in vfs_code. (Notice the message "(Filtered with : vfs)" at top.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp5b_bmukE7GKgqf8cYADD-Rf2vxdaPnQPd7iVwu3VYJgfMgI9soCdvGaRix4jHK2BJVE9f0lVI_HKYpuTFDNVZO8WHg5Y7HvVFBme7nmdq3VlmxO7KEJ37H3NhZ6j_Kh6ZMXEAB-CMVk/s1600/vfs_start.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp5b_bmukE7GKgqf8cYADD-Rf2vxdaPnQPd7iVwu3VYJgfMgI9soCdvGaRix4jHK2BJVE9f0lVI_HKYpuTFDNVZO8WHg5Y7HvVFBme7nmdq3VlmxO7KEJ37H3NhZ6j_Kh6ZMXEAB-CMVk/s320/vfs_start.png" width="320" /></a> <br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJCI00udP5A-bqE6bvLbW9O2PQqvBpOj6jzuMCIYwxxoQrNXKulS0xU6fBfi9OlfhKUmJil_f1wwIgGJ5XTpU8Gb8GUxmYNtxCgEA9jyuil-m6uUF1jsDBzT8fWcnI1NEVdRpBUd8cgDo/s1600/vfs_results.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJCI00udP5A-bqE6bvLbW9O2PQqvBpOj6jzuMCIYwxxoQrNXKulS0xU6fBfi9OlfhKUmJil_f1wwIgGJ5XTpU8Gb8GUxmYNtxCgEA9jyuil-m6uUF1jsDBzT8fWcnI1NEVdRpBUd8cgDo/s320/vfs_results.png" width="320" /></a><br />
=> Soon I realize, I was only interested in looking at header files (look at filter string at the top of screen)<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzCVzdpk9lSo6LC3fq8jATmwuPpNMQS8CHAr_lsIUyEXvoMRyOxyQW2nqKLSrjbbKCVPPY9O6qy0dY3EQ7gUBvCSMVoYdVw194nUc6LQwr8VMFNF1eSMMoD-3jbsGHUeKMsUVuwI5UW5I/s1600/header_files.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzCVzdpk9lSo6LC3fq8jATmwuPpNMQS8CHAr_lsIUyEXvoMRyOxyQW2nqKLSrjbbKCVPPY9O6qy0dY3EQ7gUBvCSMVoYdVw194nUc6LQwr8VMFNF1eSMMoD-3jbsGHUeKMsUVuwI5UW5I/s320/header_files.png" width="320" /></a><br />
<br />
=> Or not so, actually in only 'C' files.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9IyVmjQI6iKRgmGeBlS0A0px5IdrCLQOQdWgLMafyEQjiRhfYYe9tNr2SFIQz_x19iv99ZZzQo21JTYO-RCtDZP5dQLONirCF3A67B9DvLJ1YAy1TVlqttA8JrZxKCZjWnPi3StxKBSI/s1600/no_header_files.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9IyVmjQI6iKRgmGeBlS0A0px5IdrCLQOQdWgLMafyEQjiRhfYYe9tNr2SFIQz_x19iv99ZZzQo21JTYO-RCtDZP5dQLONirCF3A67B9DvLJ1YAy1TVlqttA8JrZxKCZjWnPi3StxKBSI/s320/no_header_files.png" width="320" /></a><br />
<br />
=> I want all references from directory and lock files.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-B1Oa28WErfAgLoKrN6kKNpr3bskTusqvbXsOLnC60tU3AJh1XlXELpR1rT7W6Wq3IvwtOayG5wF__MtT4rm7uOEwyS6l85k7hSwpUea5IHRMc0SM161RDy00BJNFZdBbkgbIJY1HyYs/s1600/dir_lock.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="199" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-B1Oa28WErfAgLoKrN6kKNpr3bskTusqvbXsOLnC60tU3AJh1XlXELpR1rT7W6Wq3IvwtOayG5wF__MtT4rm7uOEwyS6l85k7hSwpUea5IHRMc0SM161RDy00BJNFZdBbkgbIJY1HyYs/s320/dir_lock.png" width="320" /></a> <br />
<br />
Download the source code from <a href="https://sites.google.com/site/9271manish1729/files/cscope_with_filter.tar.gz?attredirects=0&d=1">here</a> and compile it as below.<br />
<br />
a) ./configure<br />
b) make<br />
c) src/cscope -R<br />
<br />
Njoy !! <br />
<br /></div>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-3103156096521938896.post-34726365667252901422011-07-02T02:38:00.000-07:002011-07-02T02:38:27.520-07:00Committing a journal transaction in jbd<div dir="ltr" style="text-align: left;" trbidi="on"><br />
Journal's transaction commit consists of <i><b>8 phases</b></i>, with the journal's state transitions mentioned as below in each of the phase.<br />
<br />
The main function which does the journal commit is <i style="color: red;"><b>journal_commit_transaction().</b></i> When we decide to commit the transaction, journal is in running state. <b><i>(T_RUNNING)</i></b><br />
<br />
Lock the transaction for new updates. ===> <b><i>T_LOCKED</i></b><br />
<b><i></i></b>---> Wait for any existing handles in the transaction to complete the updates.<br />
---> Discard buffers from reserved list. (<b><i>t_reserved_list</i></b>).<br />
<br />
If any buffer is part of next transaction, it is transferred to appropriate list of next transanction, otherwise dropped from journal's list.<br />
---> Drop write-back buffers from checkpoint list.(t_checkpoint_list). Unless the buffers belong to the running or commiting transaction, the corresponding transaction will also be freed up.<br />
<br />
<b style="color: red;">Phase 1 start</b><br />
<br />
---> Change transaction state to <b>T_FLUSH</b><br />
---> Switch the revoke tables.<br />
---> At this point there is no running transaction, it is changed to a commiting<br />
transaction.<br />
<br />
<b style="color: red;">Phase 2 start</b><br />
<br />
/* Flushing starts now */<br />
---> Data buffers are flushed first. (<i><b>t_sync_datalist</b></i>)<br />
---> Write out revoke records from the revoke hash list and flush to the descriptor blocks in journal.<br />
---> Change transaction state to <b>T_COMMIT</b><br />
<br />
<b style="color: red;">Phase 3 start</b><br />
<br />
---> Flush metadata buffers (present on <b>t_buffers</b> list). See <b><i>journal_write_metadata_buffer()</i></b><br />
<br />
<b style="color: red;">Phase 4 start</b><br />
<br />
---> Wait for all the IO submitted buffers above. Wait for metadata buffers which are present on <b>t_iobuf_list</b>. The dummy buffer heads created for metadata buffers are released. The original metadata buffer which was put on shadow list is released, but put into <b>t_forget</b> list.<br />
<br />
<b style="color: red;">Phase 5 start</b><br />
<br />
---> Wait for the submitted revoke record and descriptor buffers to complete and written out. This is done by waiting for buffers on <b>t_log_list.</b><br />
<br />
<b><span style="color: red;">Phase 6 start</span></b><br />
<br />
---> Change transaction state to <i><b>T_COMMIT_RECORD</b></i><br />
---> IO for data is complete now. Write the commit record in journal.<br />
<b style="color: red;"> </b><br />
<b style="color: red;">Phase 7 start</b><br />
<br />
---> Walk the journal's <i><b>t_forget</b></i> list to get rid of buffers till there are no more buffers on it. As each buffer is examined, we check if it was on the checkpoint io list of previous transaction. If it is, its removed and if required (in case its dirty) its transferred to the checkpoint list of the committing transaction. See <i><b>__journal_insert_checkpoint()</b></i><br />
<br />
<b style="color: red;">Phase 8 start</b><br />
<br />
--> We are done committing the transaction now.<br />
---> Change transaction state to <b><i>T_FINISHED</i></b><br />
---> Set <b>committing transaction = NULL.</b><br />
---> Calculate average commit time for future use.<br />
---> Setup the checkpointing transaction.</div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-3103156096521938896.post-63595822576159804382011-07-02T01:58:00.000-07:002011-07-02T01:58:41.882-07:00Journalling layer in ext3 (jbd)<div dir="ltr" style="text-align: left;" trbidi="on"><u><b>Terminology</b></u><br />
<b>Journal handle</b> - A handle pointer each of which represents a single atomic filesystem operation. It tracks all the modifications done as part of one atomic operation.<br />
<b>Transaction </b>- A single atomic sequence of events which guarantees filesytem consistency. It can consist of a single handle or multiple handles for batching efficiency.<br />
<b>Transaction commit</b> - Flushing the in-memory contents of journal to appropriate blocks in journal along with writing a commit record on disk in journal.<br />
<b>Transaction checkpoint </b>- Flushing the contents from journal to their actual location on disk. This is done periodically to make journal space reusable.<br />
<br />
Typically journalling a filesystem operation consists of following three steps :-<br />
<br />
a) Starting a handle -<b><i> journal_start()</i></b>. We need to specify how many fs blocks this op can potentially modify. This is required to ensure that there would be enough space in the journal to completely write contents of this operation.<br />
The number of blocks required is the total number of blocks, including the data which is going to change, metadata blocks, quota blocks if any etc. As an example see <i>EXT3_DATA_TRANS_BLOCKS</i>. These are called buffer credits for the handle.<br />
<br />
b) After getting a handle, next step is to associate the modified blocks with the journal handle, so that journal knows that it has to write these blocks in journal. This is done via following APIs <b><i>journal_get_write_access(handle, bh)</i></b> which tells the journal that this buffer is going to be modified. A buffer which is of interest to journalling layer has <i><b>BH_JBD</b></i> set on it and has a non-zero <b><i>b_count</i></b>. At this point a <i><b>"journal_head"</b></i> is attached to the buffer. A journal_head can only be part of 1 transaction.<br />
<br />
<pre>journal_get_write_access(handle, bh) {
journal_add_journal_head(bh);
do_get_write_access(handle, jh, 0);
journal_put_journal_head(bh);
}
journal_add_journal_head(bh) {
jh = journal_alloc_journal_head();
set_buffer_jbd(bh);
bh->b_private = jh;
jh->b_bh = bh;
jh->b_jcount++;
}
</pre><br />
PS: A buffer is already part of a transaction if its journal_head's <i><b>b_transaction</b></i> or <b><i>b_next_transaction</i></b> is set. Most of the times, only b_transaction is set. b_next_transaction will be set incase the buffer is getting committed from previous transaction and we are changing it for the current transaction. The b_next_transaction tells journal that this buffer is going in next transaction. In this case a copy on write is performed and the frozen copy is stored in jh->b_frozen_data.<br />
<b>NB : </b>Buffer's b_transaction will only be set if its part of running or committing transaction and not if it resides on some other list like checkpoint list etc.<br />
<br />
c) Stop the handle -<i> </i><b><i>journal_stop()</i> </b>: As the name suggests, journal stop marks the completion of an op wrt to journal. It returns any left over unused buffer credits to the transaction, drops appropriate references and frees the handle pointer.<br />
If the filesystem requested this op in sync mode, we also need to start committing the transaction to the journal on completion of handle. However in the current code there are some optimizations built around it to figure it out whether it is beneficial to start writing to disk immediately, or based on the op rate wait for sometime and let other op do it.<br />
<br />
See the following code as example.<br />
<br />
<pre>int journal_stop(handle_t *handle)
{
...............
if (trans_time < commit_time) {
ktime_t expires = ktime_add_ns(ktime_get(),
commit_time);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_hrtimeout(&expires, HRTIMER_MODE_ABS);
}
...............
}
</pre>Each journal_start/stop pair ie...each handle consists of one atomic filesystem operation. Some fs operations may be atomic in itself but still may not be sufficient enough to have the filesystem in a consistent state. An example of such an op is write which requires a quota update. Nested journal handles will be required to have such atomic op.<br />
<br />
Typical sequence would be<br />
a) Start journal handle for write<br />
b) Start journal handle for quota update<br />
c) Stop journal handle for quota update<br />
d) Stop journal handle for write.<br />
<br />
Its only after step (d) that the op can be committed to disk.<br />
<br />
<b>NB :</b> A buffer is a <b>"journalled"</b> buffer, only if it has a journal head attached to it.<br />
<br />
<br />
A journal transaction consists of various lists where buffers of interest can reside. Buffers end up on one of the list depending on what flag/state it has. Below is the buffer state to list mapping. See the function <b>__journal_file_buffer()</b> to see how buffers are moved across lists.<br />
<br />
<b>List type => buffer state flag</b><br />
transaction->t_sync_datalist => BJ_SyncData<br />
transaction->t_buffers => BJ_Metadata<br />
transaction->t_forget => BJ_Forget<br />
transaction->t_iobuf_list => BJ_IO<br />
transaction->t_shadow_list => BJ_Shadow<br />
transaction->t_log_list => BJ_LogCtl<br />
transaction->t_reserved_list => BJ_Reserved<br />
transaction->t_locked_list => BJ_Locked<br />
<br />
<br />
</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-84296986267270920952011-07-02T01:41:00.000-07:002011-07-02T01:42:40.753-07:00checkpointing transactions in journal (jbd)<div dir="ltr" style="text-align: left;" trbidi="on">Journal checkpointing : <b>jbd/checkpoint.c</b><br />
----------------------<br />
The main functions involved in doing journal checkpointing are :-<br />
<i><b>a) log_do_checkpoint<br />
b) __process_buffer<br />
c) __flush_batch<br />
d) __wait_cp_io</b></i><br />
<br />
<b><i>log_do_checkpoint</i></b> picks up the first transaction on the checkpoint list and then iterates over all the buffers present in the transaction by calling <b><i>__process_buffer </i></b>on each of them. As it traverses, it keeps accumulating them in a local array for batching of disk writes. As part of processing it also moves the buffer from checkpoint_list to checkpoint_io_list to indicate that io is pending on these buffers.<br />
Once the array is full or we have no more buffers to process <b><i>__flush_batch</i></b> is called to send those buffers to disk for writing.<br />
<br />
After the buffers are submitted to disk,<b><i> __wait_cp_io() </i></b>is called to wait on each of the buffers for write to complete. After they get cleaned they are removed from the checkpoint_io_list. After all the buffers are freed, transaction itself is freed.<br />
<br />
* Helper functions to clear all the clean buffers from the checkpoint list.<br />
<i><b>__journal_clean_checkpoint_list</b></i> : Traverses the transactions in checkpoint transactions list (<b><i>j_checkpoint_transactions</i></b>) and frees memory by walking each list (<i><b>j_checkpoint_list</b></i>) at a time.</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-43019788547238073702011-07-01T20:18:00.000-07:002011-07-01T20:18:48.829-07:00Journal (jbd) revoke mechanism<div dir="ltr" style="text-align: left;" trbidi="on">Journal revoke :-<b> jbd/revoke.c</b><br />
------------------<br />
<br />
Revoke is a method of preventing journal from corrupting filesystem by not replaying ops and overwriting the contents of a deleted block on a newer block. For example consider the following sequence of steps when the filesystem is mounted in metadata only journalling mode.<br />
<br />
<i><b>a) A metadata block 'B' is journalled and contents are copied to journal.<br />
b) Later 'B' gets freed<br />
c) 'B' is now used to write contents of user data, this is not journalled.</b></i><br />
<br />
Now if we crash and replay, we need to avoid replaying the contents of block 'B' in journal over the user contents.<br />
<br />
<b><u>Revoke mechanism:-</u></b> During commits of a transaction all the blocks which are revoked are stored in journal. This record of revoked blocks is used during journal recovery and journal is scanned for the revoked blocks before any ops is replayed. If there are transactions for the block after the last revoke record of a block, these ops are safe to replay. Any transactions which appear before the revoke record aren't replayed. The basic idea is that you don't want to replay ops corresponding to a block which may have been freed. Also note that if there are multiple revoke records corresponding to a block in a journal, we only need to worry about the latest record ie...one with highest transaction id.<br />
<br />
From file <i>jbd/revoke.c</i>. <br />
<pre> * We can get interactions between revokes and new log data within a
* single transaction:
*
* Block is revoked and then journaled:
* The desired end result is the journaling of the new block, so we
* cancel the revoke before the transaction commits.
*
* Block is journaled and then revoked:
* The revoke must take precedence over the write of the block, so we
* need either to cancel the journal entry or to write the revoke
* later in the log than the log block. In this case, we choose the
* latter: journaling a block cancels any revoke record for that block
* in the current transaction, so any revoke for that block in the
* transaction must have happened after the block was journaled and so
* the revoke must take precedence.
*
* Block is revoked and then written as data:
* The data write is allowed to succeed, but the revoke is _not_
* cancelled. We still need to prevent old log records from
* overwriting the new data. We don't even need to clear the revoke
* bit here.
</pre><br />
There are two hash tables to store the revoked entries. These two tables are required one for the running transaction and one for the committing transaction (if any). As you can guess new entries are always logged into the revoke table pointed by current <b>journal->j_revoke</b> pointer which points to the one corresponding to running transaction. You can think of it as a double buffering mechanism. These tables are switched alternately during the commit from kjounald. Access to these hash table entries is protected by the<b> j_revoke_lock.</b><br />
<br />
<b><u>Important functions:-</u></b><br />
Initialize revoke hash : <i>journal_init_revoke()</i><br />
Inserts in hash : <i>insert_revoke_hash()</i><br />
Find in hash : <i>find_revoke_record()</i><br />
Transfer the in-memory revoke table to ondisk journal : <i>journal_write_revoke_records()</i><br />
<br />
<b>NB:</b> Note that you need to revoke a block before freeing it in bitmap and not the viceversa to prevent races.<br />
<br />
The buffer heads maintains two set of flags to indicate the revoke status of a buffer.<br />
a) <i><b>RevokeValid </b></i>: The revoke status of this buffer is known and can be trusted. If this is not set we can't say much about the buffer and need to search for it in hash.<br />
b) <i><b>Revoke{set/clear}</b></i> : These flags make sense when above is set. They tell whether the block is revoked or not.</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-25062954522261514342011-06-26T23:05:00.000-07:002011-07-02T01:31:03.110-07:00Journal recovery in jbd<div dir="ltr" style="text-align: left;" trbidi="on">Journal recovery :-<b> jbd/recovery.c</b><br />
------------------<br />
<br />
Journal recovery is quite simple. It basically consists of below steps.<br />
<br />
a) Readahead journal blocks in memory.<br />
<br />
b) Do first pass <b>(PASS_SCAN</b>) to see if we need a recovery. If yes what all transactions do we need to replay, if the journal is valid etc other sanity checks. After the first scan pass, an incore data structure about the journal (struct recovery_info) is populated which contains the required information about the recovery.<br />
<br />
c) Do second pass (<b>PASS_REVOKE</b>). This traverses all the revoke block types and builds the incore hash of block numbers which are revoked. This ensures that we don't replay ops corresponding to these blocks when we do the actual replay.<br />
<br />
d) Do the third/final pass (<b>PASS_REPLAY</b>) which actually does the job of replaying the journal and copies the data from journal to the real filesystem. Replaying a op simply consists of reading the corresponding block number from filesystem, copying the contents from journal to buffer and then marking the buffer dirty which would be written back to the actual location in filesystem.<br />
<br />
<b>NB:</b> Steps (b), (c) and (d) are done through a common function <i><b>do_one_pass().</b></i><br />
e) Once the replay is complete, throw away the in-memory revoke hash.<br />
<br />
f) Sync the blockdevice.<br />
<br />
g) Once the recovery is done, journal_reset() is called to setup the inmemory fields of journal, and journal is ready for business again.<br />
<br />
journal_recover()<br />
|<br />
--> do_one_pass(PASS_SCAN)<br />
|<br />
--> do_one_pass(PASS_REVOKE)<br />
|<br />
--> do_one_pass(PASS_REPLAY)<br />
|<br />
--> journal_clear_revoke()<br />
|<br />
--> sync_blockdev() and journal_reset()</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-69758348797439608082010-08-23T22:52:00.000-07:002010-08-23T22:52:12.492-07:00mcopy support in fsdb for ufsutilsI have been looking for something like mcopy support in ufsutils so that I could just copy any files from userspace to the UFS filesystem. This is primarily important because by default kernel is not configured/compiled to have readwrite support for UFS. Either you need to have your own custom compiled kernel or something else so that you can mount the UFS filesystem and then do a copy.<br />
<br />
Below is a patch (quick, ugly and dirty) which I wrote for myself which might be useful to you too. It is definitely not the best written but it does its job. Inorder to keep things simple even though I wanted to add a new command "addfile" (or something similar) to fsdb, I have removed other commands from this fsdb and just made it to work like mcopy because I needed it to be integrated with my shell scripts.<br />
<br />
Copy the file fsdb.c in the folder ufsutils-7.0/fsdb.ufs/ and then recompile fsdb. If you have a newer version you will want to copy the contents from the original file. Just grep for "MANISH" in the file. Recompile and njoy !!!<br />
<br />
Typical invocation would be something like<br />
<br />
$./fsdb myufs_file_system local_file_to_copy destination_path_in_FS<br />
eg..<br />
<br />
$./fsdb myfs testfile.c /boot/dummyfile.c<br />
<br />
Download <a href="https://docs.google.com/leaf?id=0B7IdXzyV1V5PYWNmYzNmOTgtMWYxMy00MzI4LTg5NGMtNTM3YjA5OWFkYmFk&hl=en&authkey=CM__krwP">fsdb.c</a> here<br />
<br />
Always verify your FS with fsck after running this :-). I'm not responsible if you lose your data.<br />
<br />
* I think it has a small bug while doing truncation of files which are less than size 48K.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-64789204441987312172009-05-15T03:11:00.000-07:002009-05-15T03:13:14.618-07:00Compatibility flags in ext filesystemsEver wondered how do ext filesystems are compatible with each other in a way that most of the times they can be mounted seamlessly even though they have ondisk different structures, or in other words how does ext ensures that the ondisk changes are compatible across different releases ?<br />This is possible due to three important fields present in ext superblock collectively known as compatibilty bitmaps. We will discuss each of them with anexample.<br /><br />Usually when a new feature is added in ext, a bit is assigned in superblock to indicate whether the filesystem has that feature or not. The decision of putting this bit in which compatibility bitmap is of utmost importance and depends on the nature of the enhancement done.<br /><br />Compatible features :(s_features_compat) (EXT3_FEATURE_COMPAT_HAS_JOURNAL - Journal support is valid)<br /><br />Readonly compatible features :(s_feature_ro_compat) (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER - Filesystem has sparse superblocks ie.. there are backups of superblock in block numbers multiple of 3,5 & 7). - These are the features which are only supported if the file system is mounted in read only mode.<br /><br />Incompatible features :(s_feature_incompat) EXT4_FEATURE_INCOMPAT_EXTENTS These are the features which older kernel won't be able to interpret and understand and in such cases they should refuse to mount if an incompat bit is set. One such example is the extent map changes, since it changes the way block pointers are stored on disk, older kernels who know only direct/indirect block formats will not be able to read this properly and thus can't serve data when requested.<br /><br />Inorder to specify a new feature, its compatibility has to be decided and then it is added to the compatibility flags appropriately. See the macro EXT3_FEATURE_RO_COMPAT_SUPP and others to get an idea.<br /><br />There have been talks and suggestions about adding these compatibility flags on per inode basis rather than the filesystem to achieve maximum backwards compatibility, so that only fewer files are non-compatible.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-21723204250459485612009-03-05T22:03:00.000-08:002009-03-15T22:59:20.737-07:00ext3 write call stack<a href="http://nngfs.pbwiki.com/f/ext3.png"><img src="http://nngfs.pbwiki.com/f/ext3.png" height=300 width=500/></a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-71243869885384785202008-09-18T23:13:00.001-07:002008-09-20T05:53:59.332-07:00Easy way to convert negative integers to hexadecimalIf you came here looking for some magic......sorry .... I had some issues representing negative integers in hex. Every time I had to convert them to binary, do a 2's complement and then reconvert to hex :-( so was looking for a way which I could use to quickly do my job. I got this trick from net and thought it is pretty easy. You just need to keep the following mapping in mind (or paper :-) though it is pretty simple).<br /><br />0 1 2 3 4 5 6 7<br />F E D C B A 9 8<br /><br />that's all. The above table is just numbers 1-15 in clockwise direction, or more technically the upper number is inverse of the below one.<br /><br />Now to convert any number say -7218, follow below steps :-<br /><br />a) Convert 7218 to hex = 0x1C32<br />b) Interchange each digit with its corresponding counter bit from mapping = 0xE3CD<br />c) Shift the last digit to left by 1 place...so D becomes E = 0xE3CE = -7218 = 0xFFFFE3CE (don't forget to fill it with 'F's on left. If you don't fill it with 'F' it becomes 65536-7218 = 58318)<br /><br />NOTE : If the last digit is 'F' and you shift left, you go to '0' and then shift the next digit to left. (Much like carry over).Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-42770750914084227122008-09-12T23:03:00.000-07:002008-09-15T01:25:00.800-07:00ext filesystem online resizing.Below notes are based on my understanding of code and most of the stuff is copied directly from the paper presented by <span style="font-style:italic;">Andreas Dilger</span> in OLS-2002 "<span style="font-weight:bold;"><span style="font-style:italic;">Online ext2 and ext3 Filesystem Resizing</span></span>". So if you find any errors below they are due to me, and you may want to read the <a href="http://edgyu.excess.org/ols/2002/Andreas%20E%20Dilger%20-%20Online%20Resizing%20with%20ext2%20and%20ext3.pdf">full paper</a> for proper detailed explaination.<br /><br />Primary operations involved in resizing :-<br />a) Increase the total number of blocks in primary and backup superblock.<br />b) Increase the count of free blocks in primary superblock and group descriptor for that group.<br />c) Increase the number of reserved filesystem blocks.<br />d) Remount with "<span style="font-weight:bold;">-o remount,resize=<newsize></span>" option.<br /><br />NOTE: You cannot shrink the filesystem. Shrinking is in general discouraged by filesystems and most of them don't support it, because this might lead to stale/invalid nfs file handles if the client has a file opened and you shrunk the filesystem.<br /><br /><span style="font-weight:bold;">Case 1: Adding blocks to the end of the last partially filled block group.</span><br /><br />In order to increase the free blocks count and update block bitmaps, a fake inode is created which spans the newly added blocks at the end of last block group. Since the blocks are already being used by this fake inode we don't have risk of getting it used by anyone else. Now to make these blocks available to filesystem all that needs to be done is to delete this inode by <span style="font-style:italic;">ext2_free_blocks()</span>. During freeing of this inode, appropriate counts and block bitmaps will be updated. This inode is only in memory and has enough fields as required by <span style="font-style:italic;">ext2_free_blocks()</span>.<br />Next is to update the superblock in backup superblocks. Since the backup superblocks are not accessed by kernel they can be directly modified by userspace. If the resize operations is done via mount then since backup superblocks are not updated, but they will be updated to proper values when e2fsck is run next time.<br /><br /><span style="font-weight:bold;">Case 2: Adding new block groups at the end of full block group.</span><br /><br />Main steps required to handle this case are :-<br />a) Create new block bitmaps and inode bitmaps for each added block group and updated them appropriately to reflect the available block and inodes within the group.<br />b) Add the new entry to group descriptor table. Increase the number of groups in the filesystem so that the inode/block allocation routines know that there are new groups available with free resources.<br /><br />Inorder to avoid doing all this stuff from kernel, increasing the resources is done from userspace before the kernel becomes aware of new groups. Since as long as the kernel is unaware of new groups, it cannot allocate anything from there and moreover since we are adding at the last, it is safe to do these operations from userspace.<br /><br /><span style="font-weight:bold;">Case 3 : Adding a new block group in new group descriptor block.</span><br /><br />This is a bit complex situation because backup superblocks and group descriptors are situated at the start of a block group (so as to be easily identifiable by e2fsck in case of corrruptions), followed by inode and block bitmap. Adding a new block group would mean overwriting these bitmaps and thus they need to be shifted to accomodate the new block. This relocation is not of a serious problem since gdt stores the location of bitmaps. So all we need to do is shift the blocks and then update the new information in the gdt. But this movement of blocks cannot be done while the filesystem is mounted, to avoid any mess within kernel. <br />Such cases need an unmount of the filesystem (commonly known as filesystem preparation) and they have the advantage that the changes made are compatible with older kernels. However there is another alternative without offlining the filesystem if the user is ready to break this compatibility.<br /><br />Andreas nicely explains this case in his paper, and I would suggest to read section 3.4 for those who are interested.<br /><br /><br />Above strategy is for ext2, however resizing in ext3 using the above poses certain problems like :-<br /><br />a) Writing directly to the device is unsafe since, there is a journalling layer whose job is to make sure that everything is consistent. Thus if you bypass it, it might lead to ondisk corruptions in the filesystem.<br />b) Unlike ext2, there may be copies of data in ext3 made by journalling and thus there may be differences in what was read and what actually is there if you try to do it from userspace. (See paper)<br />c) Since ext3 resizing is done through journal, in case if the resize has made to journal and then system crashed. In such cases during reboot journal will be replayed, however since superblock is read first the new size will not be updated. This case is detected by comparing filesystem size before and after journal replay and then update the appropriate datastructures.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3103156096521938896.post-75673748726375816832008-09-07T23:18:00.001-07:002008-09-13T11:18:22.370-07:00ioctls - An easy interface to talk to kernelThere are many *good* resources available on net if you want to know about ioctls. One of them is "man ioctl"<br />If you want to know about the list of ioctls, one quick way is "man ioctl_list". What follows below is a layman explaination and may not be liked by "strict" technical persons.<br /><br /><span style="font-weight:bold;">a) What are ioctls ?</span><br />ioctls are like swiss knife, one interface to do lot of things. A simple way for userspace to talk to kernel.<br />Among other available options (syscalls, procfs, sysfs, debugfs .. etc.), probably ioctls are the easiest one if you want to talk to kernel space as well as get that into mainline kernel. One of the reasons is because they are easy to implement and everyone follows its own convention (though it is discouraged) due to lack of no single standard.<br /><br />To implement an ioctl, all you need to do is tell kernel that I will be sending some *codenumber* from userspace and depending on the codenumber you have to do something (execute a function). Much like switch-case or RPC.<br /><br /><span style="font-weight:bold;">b) How to implement ioctls ?</span><br />Depending on the way you want to talk to kernel, you can have an in, out, none or both arguments and you need to tell kernel accordingly so that it can take the appropriate action. Remember that you have to send a *codenumber* to kernel, so you must embed this information in it along with the functionality that you desire.<br /><br />ioctls are declared using the standard macros defined in asm/ioctl.h. Macros are of type _IO(type,nr) and {_IOR,_IOW,_IOWR}(type,nr,size). Note that R and W are from user perspective (same as read & write). The last parameter 'size' is actually the datatype that needs to be transferred. <br /><br />An example of ioctl by which you need to change the version of a file in kernel is :-<br />#define EXMPL_IOC_CHANGE_VERSION _IOW('f',7,long)<br /><br />This gets expanded into a *codenumber* due to below defined macros :-<br />#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))<br />#define _IOC(dir,type,nr,size) \<br /> (((dir) << _IOC_DIRSHIFT) | \ /* DIRSHIFT == 30 */<br /> ((type) << _IOC_TYPESHIFT) | \ /* TYPESHIFT == 8 */<br /> ((nr) << _IOC_NRSHIFT) | \ /* NRSHIFT == 0 */<br /> ((size) << _IOC_SIZESHIFT)) /* SIZESHIFT == 16 */<br /># define _IOC_WRITE 1U<br /><br />Based on the arguments passed this will create a unique *codenumber* which your module needs to understand. _IOC_TYPECHECK is just a macro for compiler to check for invalid uses of size argument. The ioctl number 'nr' should be chosen such that it doesn't conflict with others (that is one reason why ppl hate ioctls). Some devices use their major number for this.<br /><br />Once I have defined my ioctl, I need to make kernel understand it. This is done by installing your ioctl handler in the kernel as below :-<br /><pre><br />struct file_operations my_file_operations = {<br /> .read = my_read_func,<br /> .write = my_write_func,<br /> ........<br /> .ioctl = my_ioctl_handler,<br /> ........<br /> ........<br />}<br /></pre><br />and then define my_ioctl_handler() which performs the actual action.<pre><br />long my_ioctl_handler(struct file *filp, unsigned int cmd, unsigned long arg) {<br /> struct inode *inode = filp->f_dentry->d_inode;<br /> unsigned int version;<br /> switch(cmd) {<br /> ...........<br /> case EXMPL_IOC_CHANGE_VERSION : <br /> if (get_user(version, (int __user *) arg)) {<br /> err = -EFAULT;<br /> goto err_out;<br /> }<br /> inode->i_version = version;<br /> return 0;<br /> ............<br />}<br /></pre><br /><br />And then in userspace, you need to invoke your ioctl as :-<br /><pre><br />main() {<br /> int fd;<br /> fd = open("myfile",O_RDWR);<br /> if(fd<0)<br /> exit(1);<br /> if(ioctl(fd,EXMPL_IOC_CHANGE_VERSION,123)))<br /> fprintf(stderr,"Some error in ioctl ...\n")<br /> ........<br />}<br /></pre><br /><br />As you can see from the example above, ioctls are very easy interface to notify kernel to do something and are largely used in device drivers. Read Documentation/ioctl-numbers.txt for more on them.Unknownnoreply@blogger.com0