
# Copyright (C) 2005-2021 Junjiro R. Okajima
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

Export Aufs via NFS
----------------------------------------------------------------------
Here is an approach.
- like xino/xib, add a new file 'xigen' which stores aufs inode
  generation.
- iget_locked(): initialize aufs inode generation for a new inode, and
  store it in xigen file.
- destroy_inode(): increment aufs inode generation and store it in xigen
  file. it is necessary even if it is not unlinked, because any data of
  inode may be changed by UDBA.
- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
  build file handle by
  + branch id (4 bytes)
  + superblock generation (4 bytes)
  + inode number (4 or 8 bytes)
  + parent dir inode number (4 or 8 bytes)
  + inode generation (4 bytes))
  + return value of exportfs_encode_fh() for the parent on a branch (4
    bytes)
  + file handle for a branch (by exportfs_encode_fh())
- fh_to_dentry():
  + find the index of a branch from its id in handle, and check it is
    still exist in aufs.
  + 1st level: get the inode number from handle and search it in cache.
  + 2nd level: if not found in cache, get the parent inode number from
    the handle and search it in cache. and then open the found parent
    dir, find the matching inode number by vfs_readdir() and get its
    name, and call lookup_one_len() for the target dentry.
  + 3rd level: if the parent dir is not cached, call
    exportfs_decode_fh() for a branch and get the parent on a branch,
    build a pathname of it, convert it a pathname in aufs, call
    path_lookup(). now aufs gets a parent dir dentry, then handle it as
    the 2nd level.
  + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
    for every branch, but not itself. to get this, (currently) aufs
    searches in current->nsproxy->mnt_ns list. it may not be a good
    idea, but I didn't get other approach.
  + test the generation of the gotten inode.
- every inode operation: they may get EBUSY due to UDBA. in this case,
  convert it into ESTALE for NFSD.
- readdir(): call lockdep_on/off() because filldir in NFSD calls
  lookup_one_len(), vfs_getattr(), encode_fh() and others.
