Friday, March 04, 2011

Best Practice to Make Linux/Android Filesystem Robust

Introduction

There is a common concern in Linux-based design: the buffering of filesystem writes is very good for performance, but may cause the buffered data to be lost and so filesystem corruption when the system go down unexpectedly.
This documents presents some solutions you can take to make your Linux-based system perform more robustly.

1. Use a Read-Only Partition for Root Filesystem

The simplest solution to avoiding power failures during writes is to avoid all writes - files that don't to be modified should be kept on a partition that is mounted read-only. In most cases (not include NAND flash device) it means that there will be no modifications to the entire partition, and as a result there is no risk of corruption. If local data writing is required, an extra read-write partition can be established for that purpose only. With this setup, Even in worst-case, we can still ensure system will boot correctly.
In Android platform, there're several options to use read-only partitions:
  • Root filesystem as ramdisk and Android system partition as read-only partition.
  • Root filesystem and Android system files are in a same read-only partition.
  • Root filesystem and Android system files are in separate read-only partition.
Which option to use depends on the image size of the root filesystem. Ramdisk can only hold small rootfs, and a too large partition is not convenient to do upgrading.

2. Use the Right Filesystem for Read-write partitions

Linux offers many many filesystems, such as jffs2, yaffs2 and ubifs for flash devices, ext2, ext3, ext4 and btrfs for disk-like devices.
If the Linux-based system (i.e. Android platform) is booting from a SD/MMC card or managed NAND, the ext3 or ext4 is a good choice.
The ext3 or third extended filesystem (wiki:  http://en.wikipedia.org/wiki/Ext3) is a journaled file system that is commonly used by Linux kernel. Its main advantage over ext2 is journaling which improves reliability and eliminates the need to check the file system after an unclean shutdown. The ext4 is its successor which has many extensions and performance improvements but also brings more data loss probabilities to be paid more attention.
Starting from Android-2.3 (Gingerbread), many Android devices are going to be moving from YAFFS to the ext4 filesystem according to the post on Google official Android developer blog. ( http://android-developers.blogspot.com/2010/12/saving-data-safely.html)
With the ext3/4 filesystem, system crashes or power loss are far less likely to make system become corrupted because of the journaling design.
  • One of the ext3 features to be noted is that by default, ext3 will commit changes to its journal every 5 seconds. So, in general, 5 seconds worth of writes might be lost as the result of a system crash or power loss. The value can be tuned.
  • One feature to be noted in ext4 is the delayed allocation which means that the filesystem tries to delay the allocation of physical disk blocks for written data as long as possible. This policy brings some important performance benefits. Many files are short-lived; delayed allocation can keep the system from writing fleeting temporary files to disk at all. And, for longer-lived files, delayed allocation allows the kernel to accumulate more data and to allocate the blocks for data contiguously, speeding up both the write and any subsequent reads of that data. However, this also brings more data loss probabilities.
There are some sysctl variables to shorten the system’s writeback time and so as to reduce the data loss possibility:
/proc/sys/vm/dirty_expire_centiseconds
/proc/sys/vm/dirty_writeback_centiseconds
  • The first variable controls how long written data can sit in the page cache before it’s considered “expired” and queued to be written to disk; it defaults to 30 seconds.
  • The second variable controls how ofter the pdflush process wakes up to actually flush expired data to disk; it defaults to 5 seconds.
  • Lowering these values will cause the system to flush data to disk more aggressively, with a cost in the form of reduced performance.

3. Use Right Solution When Developing Applications

The final solution to this problem is to fix the applications which are expecting the filesystem to provide more guarantees than it really is.
  • Application developer should keep in mind that data doesn’t actually consistently reach the storage media when write() or even close() is called.
  • Applications which want to be sure that their critical data have been committed to the media can use the fsync() system call; that can be slow, so be careful not to call it carelessly.
  • In Android application, if you just use SharedPreferences? or SQLite, you don't need to worry about the data loss, because Android has already used fsync() to do the right thing about buffering.

Monday, May 17, 2010

Ubuntu - Install Redmine + MySQL in Ubuntu 10.04

Introduciton

Redmine
is an open source, web-based project management and bug-tracking tool. It includes calendar and gantt charts to aid visual representation of projects and their deadlines. It supports multiple projects. Redmine is free and open source software which provides integrated project management features, issue tracking, and support for multiple version control options.

The design of Redmine is significantly influenced by Trac, a software package with some similar features.

Redmine is written using the Ruby on Rails framework. It is cross-platform and cross-database.

Installation Steps
The following are my steps to install it on the new Ubuntu 10.04 system:
1) install mysql server & phpmyadmin tool
$ sudo apt-get install mysql-server phpmyadmin
You can just set all initial passwords to 'admin'. When finished, you can use http://localhost/phpmyadmin to manage your databases.
2) change mysql database directory (optional, I just want to store it in the /srv directory)
$ mysqladmin -u root -p shutdown
$ sudo mv /var/lib/mysql /srv/
$ sudo vi /etc/mysql/my.cnf (change datadir value from "/var/lib/mysql" to "/srv/mysql")
$ sudo vi /etc/apparmor.d/usr.sbin.mysqld (replace all "/var/lib/mysql" to "/srv/mysql")
$ sudo /etc/init.d/mysql restart (FIXME: doesn't work, I just reboot the system instead)
3) install redmine & redmine-mysql
$ sudo apt-get install redmine redmine-mysql
4) install rails...
$ sudo apt-get install mongrel ruby1.8-dev
5) change redmine files default directory (optional, I prefer to store them in the /srv directory)
$ sudo mv /var/lib/redmine /srv/
$ sudo vi /usr/share/redmine/config/environment.rb (replace all "/var/lib" to "/srv")
6) test redmine
$ cd /usr/share/redmine
$ sudo mkdir /usr/share/redmine/log
$ sudo ruby /usr/share/redmine/scripts/server -e production
(now in PC web-browser, you can use http://localhost:3000 to do the test)
7) configure apache to run redmine
$ sudo apt-get install libapache2-mod-passenger (seems it has been already installed)
$ sudo ln -s /usr/share/redmine/public /var/www/redmine
$ sudo a2enmod passanger (seems already been enabled too)
$ sudo vi /etc/apache2/site-available/default
+ RailsEnv production
+ RailsBaseURI /redmine
$ sudo chown www-data /usr/share/redmine/config/environment.rb
$ sudo /etc/init.d/apache2 reload
That's all. In your PC, you can use: http://localhost/redmine to access Redmine now.

Labels: , , ,

Tuesday, April 22, 2008

Ubuntu - Install privoxy to visit blocked web

Privoxy is worked with Tor. And it can forward http requests to socks requests used by Tor.

1) To install privoxy:
sudo apt-get install privoxy
2) To config privoxy
sudo vi /etc/privoxy/config
listen-address :8118
forward-socks4a / localhost:9050 .
3) To restart privoxy
sudo /etc/init.d/privoxy restart
4) To configure Firefox
Edit->Preferences->Advanced->Network->Settings->Manual proxy Configuration:
http prosy: localhost Port: 8118

Monday, January 21, 2008

Ubuntu - Install Tor to use the blocked MSN

The following step shows how to setup Tor to use the blocked MSN:
1) Install Tor
sudo apt-get install tor
sudo /etc/init.d/tor start
2) Config MSN for localhost
If your MSN and Tor are running at the same computer, the configuration is, Pidgin for example: Accounts --> Add/Edit --> (account) --> Modify Account --> Advanced --> Proxy Type --> Socks 5 --> Host: localhost, Port: 9050
3) Config for LAN
Open the config file:
sudo vi /etc/tor/torrc
Find the following line:
SocksListenAddress 127.0.0.1 # accept connections only from localhost
Add a new line:
SocksListenAddress XXX.XXX.XXX.XXX:PORT # accept connections from local network
XXX.XXX.XXX.XXX is the IP address of the pc running Tor, Port is any number not used.
For example:
172.21.18.247:9100
And then restart Tor:
sudo /etc/init.d/tor restart
Pidgin settings: ... --> Host: 172.21.18.247, Port: 9100
That's all.

Wednesday, December 19, 2007

Ubuntu - Play RM format movies

When I tried to play the rmvb format movies the first, the totem player said that the "Realvideo 4.0 decode can not be found", so there was only audio but no video. After I searched the internet about that, I found this site: medibuntu.org which has what I need.
The following shows the step to make my Ubuntu 7.10 pc play the rm movie:
1) Install the mplayer (Add/Remove --> Sound & Video --> check the MPlayer Movie Player)
2) Install w32codecs & libdvdcss2
a) sudo wget http://www.medibuntu.org/sources.list.d/gutsy.list -O /etc/apt/sources.list.d/medibuntu.list
b) wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add - && sudo apt-get update
c) sudo apt-get install w32codecs libdvdcss2
3) Now you can remove the default totem movie player if you like:
Open the Synaptic Package Manager, uncheck the totem-gstreamer (totem, totem-mozilla) and press Apply button
That's all!

Thursday, November 08, 2007

Indent - Beautify your C source code

Introduction

GNU Indent is a GNU tool used to make code easier to read. It can also convert from one style of writing C to another.

Default Parameters file

indent will use the ~/.indent.pro file as the default parameter file. My content of the .indent.pro is:
-bad -bap -bbb -bbo -nbc -br -bli0 -bls -c33 -cd33 -ncdb -ncdw -ce -cli0 -cp33 -cs -d0 -nbfda -di2 -nfc1 -nfca -hnl -ip5 -l75 -lp -npcs -nprs -npsl -saf -sai -saw -nsc -nsob -nss -i4 -ts4 -ut
Reference:
http://linux.die.net/man/1/indent

Monday, November 05, 2007

ARM GCC inline assembly

Introduction

Just now I want to print the ARM CP15 registers' value in a C function, I know I need the inline assembly technology. After read some codes in linux kernel and searched the internet, I have got some simple idea.

Examples
Read ARM ID code:
u32 val;
__asm__ __volatile__ ("mrc p15, 0, %0, c0, c0, 0" : "=r" (val));
printk("ARM ID code: 0x%x\n", val);
Write TTB:
u32 val
/*... */
__asm__ __volatile__ ("mcr p15, 0, %0, c2, c0, 0" : : "r" (val));
For more information, see:
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

ARM coprocessor CP15 Summary

Introduction
* CP15 is a coprocessor of ARM chip, it used to configure and control the ARM core modules - The caches, Tightly-Coupled Memories (TCMs), Memory Management Unit (MMU), and most other system options.

Instructions
* You can only access CP15 registers with MRC and MCR instructions in a privileged mode.
mcr{cond} p15, <Opcode_1>, <Rd>, <CRn>, <CRm>, <Opcode_2>
mrc{cond} p15, <Opcode_1>, <Rd>, <CRn>, <CRm>, <Opcode_2>
- The Opcode_1 and Opcode_2 field Should Be Zero except when the values specified are used to select the desired operations.
- The CRm field should be c0 except when the the register specified are used to select the desired behavior.

Registers
* c0~c15
- c0: used to read ID code/Cache type/TCM status
> read ID code:
mrc p15, 0, <Rd>, c0, c0, 0
> read Cache type:
mrc p15, 0, <Rd>, c0, c0, 1
> read TCM status:
mrc p15, 0, <Rd>, c0, c0, 2
- c1: used to enable/disable caches and MMU
> read control register:
mrc p15, 0, <Rd>, c1, c0, 0
> write control register:
mcr p15, 0, <Rd>, c1, c0, 0
- c2: r/w Translation Table Base (TTB)
mrc p15, 0, <Rd>, c2, c0, 0; read TTBR
mcr p15, 0, <Rd>, c2, c0, 0; write TTBR
- c3: Domain access control
mrc p15, 0, <Rd>, c3, c0, 0; read domain access permissions
mcr p15, 0, <Rd>, c3, c0, 0; write domain access permissions
- c4: Reserved in ARM926EJ-S
- c5: Data fault status/Instruction fault status
- c6: Fault address
- c7: Cache operations
mrc p15, 0, <Rd>, c7, c7, 0; Invalidate ICache and DCache
mcr p15, 0, <Rd>, c7, c5, 0; Invalidate ICache
mcr p15, 0, <Rd>, c7, c5, 1; Invalidate ICache single entry (MVA)
mcr p15, 0, <Rd>, c7, c5, 2; Invalidate ICache single entry (Set/Way)
mcr p15, 0, <Rd>, c7, c13, 1; Prefetch ICache line (MVA)
mcr p15, 0, <Rd>, c7, c6, 0; Invalidate DCache
mcr p15, 0, <Rd>, c7, c6, 1; Invalidate DCache single entry (MVA)
mcr p15, 0, <Rd>, c7, c6, 2; Invalidate DCache single entry (Set/Way)
mcr p15, 0, <Rd>, c7, c10, 1; Clean DCache single entry (MVA)
mcr p15, 0, <Rd>, c7, c10, 2; Clean DCache single entry (Set/Way)
mrc p15, 0, <Rd>, c7, c10, 3; Test and clean DCache
mcr p15, 0, <Rd>, c7, c14, 1; Clean and invalidate DCache entry (MVA)
mcr p15, 0, <Rd>, c7, c14, 2; Clean and invaliate DCache entry (Set/Way)
mrc p15, 0, <Rd>, c7, c14, 3; Test, clean, and invalidate DCache
mcr p15, 0, <Rd>, c7, c10, 4; Drain write buffer
mcr p15, 0, <Rd>, c7, c0, 4; Wait for interrupt
> Clean the entire DCache:
tc_loop:
mrc p15, 0, r15, c7, c10, 3; test and clean, pc is not changed by this instrunction
bne tc_loop
> Clean and invalidate the entire DCache:
tci_loop:
mrc p15, 0, r15, c7, c14, 3; test clean and invalidate
bne tci_loop
- c8: (W) TLB operations
- c9: Cache lockdown/TCM region
mrc p15, 0, <Rd>, c9, c0, 0; read DCache lockdown register
mcr p15, 0, <Rd>, c9, c0, 0; write DCache lockdown register
mrc p15, 0, <Rd>, c9, c0, 1; read ICache lockdown register
mcr p15, 0, <Rd>, c9, c0, 1; write ICache lockdown register
- c10: TLB lockdown
- c11/c12: Reserved in ARM926EJ-S
- c13: FCSE PID/Context ID
- c14: Reserved in ARM926EJ-S
- c15: Test configuration

Monday, October 22, 2007

Ubuntu - Install subversion over apache2 & trac

This article covers installation subversion over apache2 and trac so that it can be easily accessed from other systems on a public network. Multiple projects are supported in this installation.

1. install related packages
You can use the Synaptic Package Manager or the sudo apt-get install command to download and install packages. The following steps only show the sudo apt-get install method.
1) install subversion
sudo apt-get install subversion
2) install apache2
Install apache2 (+apache2-mpm-worker, apache2-utils, apache2.2-common, apache2-doc & libapache2-svn)
sudo apt-get install apache2 libapache2-svn
3) install trac
Install trac (+python-clearsilver, python-pysqlite2, python-subversion, libapache2-mod-python & libapache2-mod-python-doc)

sudo apt-get install trac libapache2-mod-python libapache2-mod-python-doc
2. create svn repository
There are several typical places to put a subversion repository; most common places are: /srv/svn, /usr/local/svn & /home/svn. The following comand uses the /srv/svn:
sudo mkdir -p /srv/svn
The /srv/svn is a root directory for multiple projects. To create a project use the command like this:
sudo svnadmin create /srv/svn/project1
The project1 is the project name, you can change to your project name. And then change the owner of the folder:
sudo chown -R www-data:www-data /srv/svn/project
Modify the configuration file:
sudo vi /etc/apache2/mods-available/dav_svn.conf
<Location /svn>
DAV svn
SVNParentPath /srv/svn
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/apache2/dav_svn.passwd
&LimitExcept ...> </LimitExcept>
</Location>
After the changes have been made, restart the apache2:
sudo /etc/init.d/apache2 restart
Create user account and set password (please change bhduan to your own user account):
sudo htpasswd -cm /etc/apache2/dav_svn.passwd bhduan
3. Create trac Environments Directory

sudo mkdir /srv/trac
This is the root directory for multiple projects. If you put your environment somewhere else, make sure to note that and use that location in the appropriate places in the next steps. To enable the trac site by the apache2 server:
cd /etc/apache2/sites-available
sudo cp default trac
sudo vi trac
<Location>
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /srv/trac
PythonOption TracUrlRoot /trac
</Location>
sudo a2dissite default
sudo a2ensite trac
sudo /etc/init.d/apache2 reload
To create and initialize the trac environment:
sudo trac-admin /srv/trac/project1 initenv
Please note that you must fill the correct svn path (/srv/svn), change the owner:
sudo chown -R www-data:www-data /srv/trac
Set authenfication:
sudo vi /etc/apache2/sites-available/trac
Add the following lines before </Location>
<Location /trac>
# ...
AuthType Basic
AuthName "Trac Projects"
AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
</Location>
4. Create new project example
The following example shows the steps to create a project named as linux:
1) Open a Terminal and change the current directory to /srv/svn
cd /srv/svn
2) Create a new project named as linux
sudo svnadmin create linux
3) Change the owner of the folder and its sub directories and files:
sudo chown -R www-data:www-data linux
4) Change current directory to trac
cd /srv/trac
5) Create and initialize the linux trac environment, set Project Name [My Project] > as Linux and set Path to repository [/path/to/repos]> to /srv/svn/linux, and use default value for other options:
sudo trac-admin /srv/trac/linux initenv
6) Also change its owner
sudo chown -R www-data:www-data linux
7) Change current directory to your project's working folder, the following just shows the empty project in a tmp foler:
mkdir ~/tmp
cd ~/tmp
mkdir branches tags trunk
8) Import the project to the svn
svn import -m "original version for testing" ./ http://localhost/svn/linux
Here I use the localhost as the svn server address, you can change it to your real svn server ip address.

Labels: