www.pudn.com > cryptfs030905.rar > super.c


/*
 * Copyright (c) 1997-2003 Erez Zadok
 * Copyright (c) 2001-2003 Stony Brook University
 *
 * For specific licensing information, see the COPYING file distributed with
 * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING.
 *
 * This Copyright notice must be kept intact and distributed with all
 * fistgen sources INCLUDING sources generated by fistgen.
 */
/*
 *  $Id: super.c,v 1.22 2003/07/29 18:17:21 ezk Exp $
 */

#ifdef HAVE_CONFIG_H
# include 
#endif /* HAVE_CONFIG_H */
#ifdef FISTGEN
# include "fist_cryptfs.h"
#endif /* FISTGEN */
#include "fist.h"
#include "cryptfs.h"


STATIC void
cryptfs_read_inode(inode_t *inode)
{

    print_entry_location();

    itopd(inode) = kmalloc(sizeof(struct cryptfs_inode_info), GFP_KERNEL);
    if (!itopd(inode)) {
	printk("<0>%s:%s:%d: No kernel memory!\n", __FILE__, __FUNCTION__, __LINE__);
	ASSERT(NULL);
    }
    itohi(inode) = NULL;

    inode->i_version = ++event;	/* increment inode version */
    inode->i_op = &cryptfs_main_iops;
    inode->i_fop = &cryptfs_main_fops;
#if 0
    /*
     * XXX: To export a file system via NFS, it has to have the
     * FS_REQUIRES_DEV flag, so turn it on.  But should we inherit it from
     * the lower file system, or can we allow our file system to be exported
     * even if the lower one cannot be natively exported.
     */
    inode->i_sb->s_type->fs_flags |= FS_REQUIRES_DEV;
    /*
     * OK, the above was a hack, which is now turned off because it may
     * cause a panic/oops on some systems.  The correct way to export a
     * "nodev" filesystem is via using nfs-utils > 1.0 and the "fsid=" export
     * parameter, which requires 2.4.20 or later.
     */
#endif
    inode->i_mapping->a_ops = &cryptfs_aops;

    print_exit_location();
}


#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
/*
 * No need to call write_inode() on the lower inode, as it
 * will have been marked 'dirty' anyway. But we might need
 * to write some of our own stuff to disk.
 */
STATIC void
cryptfs_write_inode(inode_t *inode, int sync)
{
    print_entry_location();
    print_exit_location();
}
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */


STATIC void
cryptfs_put_inode(inode_t *inode)
{
    print_entry_location();
    fist_dprint(8, "%s i_count = %d, i_nlink = %d\n", __FUNCTION__,
		atomic_read(&inode->i_count), inode->i_nlink);
    /*
     * This is really funky stuff:
     * Basically, if i_count == 1, iput will then decrement it and this inode will be destroyed.
     * It is currently holding a reference to the hidden inode.
     * Therefore, it needs to release that reference by calling iput on the hidden inode.
     * iput() _will_ do it for us (by calling our clear_inode), but _only_ if i_nlink == 0.
     * The problem is, NFS keeps i_nlink == 1 for silly_rename'd files.
     * So we must for our i_nlink to 0 here to trick iput() into calling our clear_inode.
     */
    if (atomic_read(&inode->i_count) == 1)
	inode->i_nlink = 0;
    print_exit_location();
}


#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
/*
 * we now define delete_inode, because there are two VFS paths that may
 * destroy an inode: one of them calls clear inode before doing everything
 * else that's needed, and the other is fine.  This way we truncate the inode
 * size (and its pages) and then clear our own inode, which will do an iput
 * on our and the lower inode.
 */
STATIC void
cryptfs_delete_inode(inode_t *inode)
{
    print_entry_location();

    fist_checkinode(inode, "cryptfs_delete_inode IN");
    inode->i_size = 0;		/* every f/s seems to do that */
    clear_inode(inode);

    print_exit_location();
}
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */


/* final actions when unmounting a file system */
STATIC void
cryptfs_put_super(super_block_t *sb)
{
    print_entry_location();

    if (stopd(sb)) {
	kfree(stopd(sb));
	stopd(sb) = NULL;
    }
    fist_dprint(6, "cryptfs: released super\n");

    print_exit_location();
}


#ifdef NOT_NEEDED
/*
 * This is called in do_umount before put_super.
 * The superblock lock is not held yet.
 * We probably do not need to define this or call write_super
 * on the hidden_sb, because sync_supers() will get to hidden_sb
 * sooner or later.  But it is also called from file_fsync()...
 */
STATIC void
cryptfs_write_super(super_block_t *sb)
{
    return;
}
#endif /* NOT_NEEDED */




/*
 * XXX: not implemented.  This is not allowed yet.
 * Should we call this on the hidden_sb?  Probably not.
 */
STATIC int
cryptfs_remount_fs(super_block_t *sb, int *flags, char *data)
{
    return -ENOSYS;
}


/*
 * Called by iput() when the inode reference count reached zero
 * and the inode is not hashed anywhere.  Used to clear anything
 * that needs to be, before the inode is completely destroyed and put
 * on the inode free list.
 */
STATIC void
cryptfs_clear_inode(inode_t *inode)
{

    print_entry_location();

    fist_checkinode(inode, "cryptfs_clear_inode IN");
    /*
     * Decrement a reference to a hidden_inode, which was incremented
     * by our read_inode when it was created initially.
     */
    iput(itohi(inode));
    // XXX: why this assertion fails?
    // because it doesn't like us
    // ASSERT((inode->i_state & I_DIRTY) == 0);
    kfree(itopd(inode));
    itopd(inode) = NULL;

    print_exit_location();
}


/*
 * Called in do_umount() if the MNT_FORCE flag was used and this
 * function is defined.  See comment in linux/fs/super.c:do_umount().
 * Used only in nfs, to kill any pending RPC tasks, so that subsequent
 * code can actually succeed and won't leave tasks that need handling.
 *
 * PS. I wonder if this is somehow useful to undo damage that was
 * left in the kernel after a user level file server (such as amd)
 * dies.
 */
STATIC void
cryptfs_umount_begin(super_block_t *sb)
{
    super_block_t *hidden_sb;

    print_entry_location();


    print_exit_location();
}


struct super_operations cryptfs_sops =
{
    read_inode:		cryptfs_read_inode,
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
    write_inode:	cryptfs_write_inode,
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
    put_inode:		cryptfs_put_inode,
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
    delete_inode:	cryptfs_delete_inode,
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
    put_super:		cryptfs_put_super,
    statfs:		cryptfs_statfs,
    remount_fs:		cryptfs_remount_fs,
    clear_inode:	cryptfs_clear_inode,
    umount_begin:	cryptfs_umount_begin,
};

/*
 * Local variables:
 * c-basic-offset: 4
 * End:
 */