/*
 * Copyright (c) 1998-2014 Erez Zadok
 * Copyright (c) 2009	   Shrikar Archak
 * Copyright (c) 2003-2014 Stony Brook University
 * Copyright (c) 2003-2014 The Research Foundation of SUNY
 * Copyright (C) 2013-2014 Motorola Mobility, LLC
 * Copyright (C) 2017      Google, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include "esdfs.h"

/*
 * The inode cache is used with alloc_inode for both our inode info and the
 * vfs inode.
 */
static struct kmem_cache *esdfs_inode_cachep;
static LIST_HEAD(esdfs_list);
static DEFINE_SPINLOCK(esdfs_list_lock);

void esdfs_msg(struct super_block *sb, const char *level, const char *fmt, ...)
{
	struct va_format vaf;
	va_list args;

	va_start(args, fmt);
	vaf.fmt = fmt;
	vaf.va = &args;
	printk("%sESDFS-fs (%s): %pV", level, sb->s_id, &vaf);
	va_end(args);
}

void esdfs_add_super(struct esdfs_sb_info *sbi, struct super_block *sb)
{
	sbi->s_sb = sb;

	spin_lock(&esdfs_list_lock);
	list_add_tail(&sbi->s_list, &esdfs_list);
	spin_unlock(&esdfs_list_lock);
}

static void esdfs_remove_super(struct esdfs_sb_info *sbi)
{
	spin_lock(&esdfs_list_lock);
	list_del(&sbi->s_list);
	spin_unlock(&esdfs_list_lock);
}

void esdfs_truncate_share(struct super_block *sb, struct inode *lower_inode,
				loff_t newsize)
{
	struct list_head *p;
	struct esdfs_sb_info *sbi;
	struct super_block *lower_sb = lower_inode->i_sb;
	struct inode *inode;

	spin_lock(&esdfs_list_lock);
	p = esdfs_list.next;
	while (p != &esdfs_list) {
		sbi = list_entry(p, struct esdfs_sb_info, s_list);
		if (sbi->s_sb == sb || sbi->lower_sb != lower_sb) {
			p = p->next;
			continue;
		}
		spin_unlock(&esdfs_list_lock);
		inode = ilookup(sbi->s_sb, lower_inode->i_ino);
		if (inode) {
			truncate_setsize(inode, newsize);
			iput(inode);
		}
		spin_lock(&esdfs_list_lock);
		p = p->next;
	}
	spin_unlock(&esdfs_list_lock);
}

/* final actions when unmounting a file system */
static void esdfs_put_super(struct super_block *sb)
{
	struct esdfs_sb_info *spd;
	struct super_block *s;

	spd = ESDFS_SB(sb);
	if (!spd)
		return;

	/* decrement lower super references */
	s = esdfs_lower_super(sb);
	esdfs_set_lower_super(sb, NULL);
	atomic_dec(&s->s_active);

	esdfs_remove_super(spd);

	kfree(spd);
	sb->s_fs_info = NULL;
}

static int esdfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
	int err;
	struct path lower_path;
	struct inode *inode = dentry->d_inode;

	if (test_opt(ESDFS_SB(inode->i_sb), ACCESS_DISABLE))
		return -ENOENT;

	esdfs_get_lower_path(dentry, &lower_path);
	err = vfs_statfs(&lower_path, buf);
	esdfs_put_lower_path(dentry, &lower_path);

	/* set return buf to our f/s to avoid confusing user-level utils */
	buf->f_type = ESDFS_SUPER_MAGIC;

	return err;
}

/*
 * @flags: numeric mount options
 * @options: mount options string
 */
static int esdfs_remount_fs(struct super_block *sb, int *flags, char *options)
{
	int err = 0;

	/*
	 * The VFS will take care of "ro" and "rw" flags among others.  We
	 * can safely accept a few flags (RDONLY, MANDLOCK), and honor
	 * SILENT, but anything else left over is an error.
	 */
	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT)) != 0) {
		esdfs_msg(sb, KERN_ERR, "remount flags 0x%x unsupported\n",
			*flags);
		err = -EINVAL;
	}

	return err;
}

/*
 * 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 esdfs_evict_inode(struct inode *inode)
{
	struct inode *lower_inode;

	truncate_inode_pages(&inode->i_data, 0);
	clear_inode(inode);
	/*
	 * Decrement a reference to a lower_inode, which was incremented
	 * by our read_inode when it was created initially.
	 */
	lower_inode = esdfs_lower_inode(inode);
	esdfs_set_lower_inode(inode, NULL);
	iput(lower_inode);
}

static struct inode *esdfs_alloc_inode(struct super_block *sb)
{
	struct esdfs_inode_info *i;

	i = kmem_cache_alloc(esdfs_inode_cachep, GFP_KERNEL);
	if (!i)
		return NULL;

	/* memset everything up to the inode to 0 */
	memset(i, 0, offsetof(struct esdfs_inode_info, vfs_inode));

	inode_set_iversion(&i->vfs_inode, 1);
	return &i->vfs_inode;
}

static void i_callback(struct rcu_head *head)
{
	struct inode *inode = container_of(head, struct inode, i_rcu);

	kmem_cache_free(esdfs_inode_cachep, ESDFS_I(inode));
}

static void esdfs_destroy_inode(struct inode *inode)
{
	call_rcu(&inode->i_rcu, i_callback);
}

/* esdfs inode cache constructor */
static void init_once(void *obj)
{
	struct esdfs_inode_info *i = obj;

	inode_init_once(&i->vfs_inode);
}

int esdfs_init_inode_cache(void)
{
	int err = 0;

	esdfs_inode_cachep =
		kmem_cache_create("esdfs_inode_cache",
				  sizeof(struct esdfs_inode_info), 0,
				  SLAB_RECLAIM_ACCOUNT, init_once);
	if (!esdfs_inode_cachep)
		err = -ENOMEM;
	return err;
}

/* esdfs inode cache destructor */
void esdfs_destroy_inode_cache(void)
{
	if (esdfs_inode_cachep)
		kmem_cache_destroy(esdfs_inode_cachep);
}

/*
 * 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.
 */
static void esdfs_umount_begin(struct super_block *sb)
{
	struct super_block *lower_sb;

	lower_sb = esdfs_lower_super(sb);
	if (lower_sb && lower_sb->s_op && lower_sb->s_op->umount_begin)
		lower_sb->s_op->umount_begin(lower_sb);
}

static int esdfs_show_options(struct seq_file *seq, struct dentry *root)
{
	struct esdfs_sb_info *sbi = ESDFS_SB(root->d_sb);

	if (memcmp(&sbi->lower_perms,
		   &esdfs_perms_table[ESDFS_PERMS_LOWER_DEFAULT],
		   sizeof(struct esdfs_perms)))
		seq_printf(seq, ",lower=%u:%u:%ho:%ho",
				sbi->lower_perms.raw_uid,
				sbi->lower_perms.raw_gid,
				sbi->lower_perms.fmask,
				sbi->lower_perms.dmask);

	if (memcmp(&sbi->upper_perms,
		   &esdfs_perms_table[ESDFS_PERMS_UPPER_LEGACY],
		   sizeof(struct esdfs_perms)))
		seq_printf(seq, ",upper=%u:%u:%ho:%ho",
				sbi->upper_perms.raw_uid,
				sbi->upper_perms.raw_gid,
				sbi->upper_perms.fmask,
				sbi->upper_perms.dmask);

	if (test_opt(sbi, DERIVE_PUBLIC))
		seq_puts(seq, ",derive=public");
	else if (test_opt(sbi, DERIVE_MULTI))
		seq_puts(seq, ",derive=multi");
	else if (test_opt(sbi, DERIVE_UNIFIED))
		seq_puts(seq, ",derive=unified");
	else if (test_opt(sbi, DERIVE_LEGACY))
		seq_puts(seq, ",derive=legacy");
	else
		seq_puts(seq, ",derive=none");

	if (test_opt(sbi, DERIVE_CONFINE))
		seq_puts(seq, ",confine");
	else
		seq_puts(seq, ",noconfine");
	if (test_opt(sbi, GID_DERIVATION))
		seq_puts(seq, ",derive_gid");
	if (test_opt(sbi, DEFAULT_NORMAL))
		seq_puts(seq, ",default_normal");
	if (test_opt(sbi, SPECIAL_DOWNLOAD)) {
		seq_printf(seq, ",dl_loc=%s", sbi->dl_loc);
		seq_printf(seq, ",dl_uid=%d", sbi->lower_dl_perms.raw_uid);
		seq_printf(seq, ",dl_gid=%d", sbi->lower_dl_perms.raw_gid);
	}
	return 0;
}

const struct super_operations esdfs_sops = {
	.put_super	= esdfs_put_super,
	.statfs		= esdfs_statfs,
	.remount_fs	= esdfs_remount_fs,
	.evict_inode	= esdfs_evict_inode,
	.umount_begin	= esdfs_umount_begin,
	.show_options	= esdfs_show_options,
	.alloc_inode	= esdfs_alloc_inode,
	.destroy_inode	= esdfs_destroy_inode,
	.drop_inode	= generic_delete_inode,
};
