summaryrefslogtreecommitdiff
path: root/fs/aufs/fhsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/aufs/fhsm.c')
-rw-r--r--fs/aufs/fhsm.c426
1 files changed, 0 insertions, 426 deletions
diff --git a/fs/aufs/fhsm.c b/fs/aufs/fhsm.c
deleted file mode 100644
index 7ca4d1759..000000000
--- a/fs/aufs/fhsm.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright (C) 2011-2015 Junjiro R. Okajima
- *
- * This program, aufs 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, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * File-based Hierarchy Storage Management
- */
-
-#include <linux/anon_inodes.h>
-#include <linux/poll.h>
-#include <linux/seq_file.h>
-#include <linux/statfs.h>
-#include "aufs.h"
-
-static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
-{
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
-
- SiMustAnyLock(sb);
-
- sbinfo = au_sbi(sb);
- fhsm = &sbinfo->si_fhsm;
- AuDebugOn(!fhsm);
- return fhsm->fhsm_bottom;
-}
-
-void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
-{
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
-
- SiMustWriteLock(sb);
-
- sbinfo = au_sbi(sb);
- fhsm = &sbinfo->si_fhsm;
- AuDebugOn(!fhsm);
- fhsm->fhsm_bottom = bindex;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
-{
- struct au_br_fhsm *bf;
-
- bf = br->br_fhsm;
- MtxMustLock(&bf->bf_lock);
-
- return !bf->bf_readable
- || time_after(jiffies,
- bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void au_fhsm_notify(struct super_block *sb, int val)
-{
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
-
- SiMustAnyLock(sb);
-
- sbinfo = au_sbi(sb);
- fhsm = &sbinfo->si_fhsm;
- if (au_fhsm_pid(fhsm)
- && atomic_read(&fhsm->fhsm_readable) != -1) {
- atomic_set(&fhsm->fhsm_readable, val);
- if (val)
- wake_up(&fhsm->fhsm_wqh);
- }
-}
-
-static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex,
- struct aufs_stfs *rstfs, int do_lock, int do_notify)
-{
- int err;
- struct au_branch *br;
- struct au_br_fhsm *bf;
-
- br = au_sbr(sb, bindex);
- AuDebugOn(au_br_rdonly(br));
- bf = br->br_fhsm;
- AuDebugOn(!bf);
-
- if (do_lock)
- mutex_lock(&bf->bf_lock);
- else
- MtxMustLock(&bf->bf_lock);
-
- /* sb->s_root for NFS is unreliable */
- err = au_br_stfs(br, &bf->bf_stfs);
- if (unlikely(err)) {
- AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err);
- goto out;
- }
-
- bf->bf_jiffy = jiffies;
- bf->bf_readable = 1;
- if (do_notify)
- au_fhsm_notify(sb, /*val*/1);
- if (rstfs)
- *rstfs = bf->bf_stfs;
-
-out:
- if (do_lock)
- mutex_unlock(&bf->bf_lock);
- au_fhsm_notify(sb, /*val*/1);
-
- return err;
-}
-
-void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
-{
- int err;
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
- struct au_branch *br;
- struct au_br_fhsm *bf;
-
- AuDbg("b%d, force %d\n", bindex, force);
- SiMustAnyLock(sb);
-
- sbinfo = au_sbi(sb);
- fhsm = &sbinfo->si_fhsm;
- if (!au_ftest_si(sbinfo, FHSM)
- || fhsm->fhsm_bottom == bindex)
- return;
-
- br = au_sbr(sb, bindex);
- bf = br->br_fhsm;
- AuDebugOn(!bf);
- mutex_lock(&bf->bf_lock);
- if (force
- || au_fhsm_pid(fhsm)
- || au_fhsm_test_jiffy(sbinfo, br))
- err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
- /*do_notify*/1);
- mutex_unlock(&bf->bf_lock);
-}
-
-void au_fhsm_wrote_all(struct super_block *sb, int force)
-{
- aufs_bindex_t bindex, bend;
- struct au_branch *br;
-
- /* exclude the bottom */
- bend = au_fhsm_bottom(sb);
- for (bindex = 0; bindex < bend; bindex++) {
- br = au_sbr(sb, bindex);
- if (au_br_fhsm(br->br_perm))
- au_fhsm_wrote(sb, bindex, force);
- }
-}
-
-/* ---------------------------------------------------------------------- */
-
-static unsigned int au_fhsm_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- unsigned int mask;
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
-
- mask = 0;
- sbinfo = file->private_data;
- fhsm = &sbinfo->si_fhsm;
- poll_wait(file, &fhsm->fhsm_wqh, wait);
- if (atomic_read(&fhsm->fhsm_readable))
- mask = POLLIN /* | POLLRDNORM */;
-
- AuTraceErr((int)mask);
- return mask;
-}
-
-static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr,
- struct aufs_stfs *stfs, __s16 brid)
-{
- int err;
-
- err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs));
- if (!err)
- err = __put_user(brid, &stbr->brid);
- if (unlikely(err))
- err = -EFAULT;
-
- return err;
-}
-
-static ssize_t au_fhsm_do_read(struct super_block *sb,
- struct aufs_stbr __user *stbr, size_t count)
-{
- ssize_t err;
- int nstbr;
- aufs_bindex_t bindex, bend;
- struct au_branch *br;
- struct au_br_fhsm *bf;
-
- /* except the bottom branch */
- err = 0;
- nstbr = 0;
- bend = au_fhsm_bottom(sb);
- for (bindex = 0; !err && bindex < bend; bindex++) {
- br = au_sbr(sb, bindex);
- if (!au_br_fhsm(br->br_perm))
- continue;
-
- bf = br->br_fhsm;
- mutex_lock(&bf->bf_lock);
- if (bf->bf_readable) {
- err = -EFAULT;
- if (count >= sizeof(*stbr))
- err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs,
- br->br_id);
- if (!err) {
- bf->bf_readable = 0;
- count -= sizeof(*stbr);
- nstbr++;
- }
- }
- mutex_unlock(&bf->bf_lock);
- }
- if (!err)
- err = sizeof(*stbr) * nstbr;
-
- return err;
-}
-
-static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
- loff_t *pos)
-{
- ssize_t err;
- int readable;
- aufs_bindex_t nfhsm, bindex, bend;
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
- struct au_branch *br;
- struct super_block *sb;
-
- err = 0;
- sbinfo = file->private_data;
- fhsm = &sbinfo->si_fhsm;
-need_data:
- spin_lock_irq(&fhsm->fhsm_wqh.lock);
- if (!atomic_read(&fhsm->fhsm_readable)) {
- if (vfsub_file_flags(file) & O_NONBLOCK)
- err = -EAGAIN;
- else
- err = wait_event_interruptible_locked_irq
- (fhsm->fhsm_wqh,
- atomic_read(&fhsm->fhsm_readable));
- }
- spin_unlock_irq(&fhsm->fhsm_wqh.lock);
- if (unlikely(err))
- goto out;
-
- /* sb may already be dead */
- au_rw_read_lock(&sbinfo->si_rwsem);
- readable = atomic_read(&fhsm->fhsm_readable);
- if (readable > 0) {
- sb = sbinfo->si_sb;
- AuDebugOn(!sb);
- /* exclude the bottom branch */
- nfhsm = 0;
- bend = au_fhsm_bottom(sb);
- for (bindex = 0; bindex < bend; bindex++) {
- br = au_sbr(sb, bindex);
- if (au_br_fhsm(br->br_perm))
- nfhsm++;
- }
- err = -EMSGSIZE;
- if (nfhsm * sizeof(struct aufs_stbr) <= count) {
- atomic_set(&fhsm->fhsm_readable, 0);
- err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
- count);
- }
- }
- au_rw_read_unlock(&sbinfo->si_rwsem);
- if (!readable)
- goto need_data;
-
-out:
- return err;
-}
-
-static int au_fhsm_release(struct inode *inode, struct file *file)
-{
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
-
- /* sb may already be dead */
- sbinfo = file->private_data;
- fhsm = &sbinfo->si_fhsm;
- spin_lock(&fhsm->fhsm_spin);
- fhsm->fhsm_pid = 0;
- spin_unlock(&fhsm->fhsm_spin);
- kobject_put(&sbinfo->si_kobj);
-
- return 0;
-}
-
-static const struct file_operations au_fhsm_fops = {
- .owner = THIS_MODULE,
- .llseek = noop_llseek,
- .read = au_fhsm_read,
- .poll = au_fhsm_poll,
- .release = au_fhsm_release
-};
-
-int au_fhsm_fd(struct super_block *sb, int oflags)
-{
- int err, fd;
- struct au_sbinfo *sbinfo;
- struct au_fhsm *fhsm;
-
- err = -EPERM;
- if (unlikely(!capable(CAP_SYS_ADMIN)))
- goto out;
-
- err = -EINVAL;
- if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK)))
- goto out;
-
- err = 0;
- sbinfo = au_sbi(sb);
- fhsm = &sbinfo->si_fhsm;
- spin_lock(&fhsm->fhsm_spin);
- if (!fhsm->fhsm_pid)
- fhsm->fhsm_pid = current->pid;
- else
- err = -EBUSY;
- spin_unlock(&fhsm->fhsm_spin);
- if (unlikely(err))
- goto out;
-
- oflags |= O_RDONLY;
- /* oflags |= FMODE_NONOTIFY; */
- fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags);
- err = fd;
- if (unlikely(fd < 0))
- goto out_pid;
-
- /* succeed reglardless 'fhsm' status */
- kobject_get(&sbinfo->si_kobj);
- si_noflush_read_lock(sb);
- if (au_ftest_si(sbinfo, FHSM))
- au_fhsm_wrote_all(sb, /*force*/0);
- si_read_unlock(sb);
- goto out; /* success */
-
-out_pid:
- spin_lock(&fhsm->fhsm_spin);
- fhsm->fhsm_pid = 0;
- spin_unlock(&fhsm->fhsm_spin);
-out:
- AuTraceErr(err);
- return err;
-}
-
-/* ---------------------------------------------------------------------- */
-
-int au_fhsm_br_alloc(struct au_branch *br)
-{
- int err;
-
- err = 0;
- br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS);
- if (br->br_fhsm)
- au_br_fhsm_init(br->br_fhsm);
- else
- err = -ENOMEM;
-
- return err;
-}
-
-/* ---------------------------------------------------------------------- */
-
-void au_fhsm_fin(struct super_block *sb)
-{
- au_fhsm_notify(sb, /*val*/-1);
-}
-
-void au_fhsm_init(struct au_sbinfo *sbinfo)
-{
- struct au_fhsm *fhsm;
-
- fhsm = &sbinfo->si_fhsm;
- spin_lock_init(&fhsm->fhsm_spin);
- init_waitqueue_head(&fhsm->fhsm_wqh);
- atomic_set(&fhsm->fhsm_readable, 0);
- fhsm->fhsm_expire
- = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
- fhsm->fhsm_bottom = -1;
-}
-
-void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
-{
- sbinfo->si_fhsm.fhsm_expire
- = msecs_to_jiffies(sec * MSEC_PER_SEC);
-}
-
-void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo)
-{
- unsigned int u;
-
- if (!au_ftest_si(sbinfo, FHSM))
- return;
-
- u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC;
- if (u != AUFS_FHSM_CACHE_DEF_SEC)
- seq_printf(seq, ",fhsm_sec=%u", u);
-}