inode.c 6.13 KB
Newer Older
Robert Read's avatar
Robert Read committed
1 2 3 4 5 6 7 8 9
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 * vim:expandtab:shiftwidth=8:tabstop=8:
 *
 *  Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
 *    Michael Callahan <callahan@maths.ox.ac.uk>
 *  Copyright (C) 1999 Carnegie Mellon University
 *    Rewritten for Linux 2.1.  Peter Braam <braam@cs.cmu.edu>
 *
 *   This file is part of InterMezzo, http://www.inter-mezzo.org.
Linus Torvalds's avatar
Linus Torvalds committed
10
 *
Robert Read's avatar
Robert Read committed
11 12 13
 *   InterMezzo is free software; you can redistribute it and/or
 *   modify it under the terms of version 2 of the GNU General Public
 *   License as published by the Free Software Foundation.
Linus Torvalds's avatar
Linus Torvalds committed
14
 *
Robert Read's avatar
Robert Read committed
15 16 17 18 19 20 21 22 23 24
 *   InterMezzo 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 InterMezzo; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Super block/filesystem wide operations
Linus Torvalds's avatar
Linus Torvalds committed
25 26 27 28 29 30 31 32 33
 */

#define __NO_VERSION__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
Robert Read's avatar
Robert Read committed
34
#include <linux/smp_lock.h>
Linus Torvalds's avatar
Linus Torvalds committed
35 36 37 38 39 40 41 42
#include <linux/unistd.h>

#include <asm/system.h>
#include <asm/uaccess.h>

#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/errno.h>
Robert Read's avatar
Robert Read committed
43
#include <linux/smp_lock.h>
Linus Torvalds's avatar
Linus Torvalds committed
44 45 46 47
#include <linux/string.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
Robert Read's avatar
Robert Read committed
48
#include <asm/segment.h>
Linus Torvalds's avatar
Linus Torvalds committed
49 50 51 52 53 54 55 56

#include <linux/intermezzo_fs.h>
#include <linux/intermezzo_psdev.h>

extern void presto_free_cache(struct presto_cache *);

void presto_set_ops(struct inode *inode, struct  filter_fs *filter)
{
Robert Read's avatar
Robert Read committed
57 58 59 60 61
        ENTRY; 

        if (!inode || is_bad_inode(inode))
                return;

Linus Torvalds's avatar
Linus Torvalds committed
62 63 64
        if (S_ISREG(inode->i_mode)) {
                if ( !filter_c2cfiops(filter) ) {
                       filter_setup_file_ops(filter, 
Robert Read's avatar
Robert Read committed
65 66
                                             inode, &presto_file_iops,
                                             &presto_file_fops);
Linus Torvalds's avatar
Linus Torvalds committed
67
                }
Robert Read's avatar
Robert Read committed
68 69
                inode->i_op = filter_c2ufiops(filter);
                inode->i_fop = filter_c2uffops(filter);
Linus Torvalds's avatar
Linus Torvalds committed
70 71 72
                CDEBUG(D_INODE, "set file methods for %ld to %p\n",
                       inode->i_ino, inode->i_op);
        } else if (S_ISDIR(inode->i_mode)) {
Robert Read's avatar
Robert Read committed
73 74 75 76
                inode->i_op = filter_c2udiops(filter);
                inode->i_fop = filter_c2udfops(filter);
                CDEBUG(D_INODE, "set dir methods for %ld to %p ioctl %p\n",
                       inode->i_ino, inode->i_op, inode->i_fop->ioctl);
Linus Torvalds's avatar
Linus Torvalds committed
77 78 79 80 81
        } else if (S_ISLNK(inode->i_mode)) {
                if ( !filter_c2csiops(filter)) {
                        filter_setup_symlink_ops(filter, 
                                                 inode,
                                                 &presto_sym_iops, 
Robert Read's avatar
Robert Read committed
82
                                                 &presto_sym_fops);
Linus Torvalds's avatar
Linus Torvalds committed
83
                }
Robert Read's avatar
Robert Read committed
84 85
                inode->i_op = filter_c2usiops(filter);
                inode->i_fop = filter_c2usfops(filter);
Linus Torvalds's avatar
Linus Torvalds committed
86 87 88
                CDEBUG(D_INODE, "set link methods for %ld to %p\n",
                       inode->i_ino, inode->i_op);
        }
Robert Read's avatar
Robert Read committed
89
        EXIT;
Linus Torvalds's avatar
Linus Torvalds committed
90 91 92 93 94 95 96 97
}

void presto_read_inode(struct inode *inode)
{
        struct presto_cache *cache;

        cache = presto_get_cache(inode);
        if ( !cache ) {
Robert Read's avatar
Robert Read committed
98
                CERROR("PRESTO: BAD, BAD: cannot find cache\n");
Linus Torvalds's avatar
Linus Torvalds committed
99 100 101 102 103 104 105
                make_bad_inode(inode);
                return ;
        }

        filter_c2csops(cache->cache_filter)->read_inode(inode);

        CDEBUG(D_INODE, "presto_read_inode: ino %ld, gid %d\n", 
Robert Read's avatar
Robert Read committed
106
               inode->i_ino, inode->i_gid);
Linus Torvalds's avatar
Linus Torvalds committed
107

Robert Read's avatar
Robert Read committed
108
        presto_set_ops(inode, cache->cache_filter); 
Linus Torvalds's avatar
Linus Torvalds committed
109 110 111
        /* XXX handle special inodes here or not - probably not? */
}

Robert Read's avatar
Robert Read committed
112
static void presto_put_super(struct super_block *sb)
Linus Torvalds's avatar
Linus Torvalds committed
113 114
{
        struct presto_cache *cache;
Robert Read's avatar
Robert Read committed
115
        struct upc_channel *channel;
Linus Torvalds's avatar
Linus Torvalds committed
116 117
        struct super_operations *sops;
        struct list_head *lh;
Robert Read's avatar
Robert Read committed
118
        int err;
Linus Torvalds's avatar
Linus Torvalds committed
119

Robert Read's avatar
Robert Read committed
120 121
        ENTRY;
        cache = presto_cache_find(to_kdev_t(sb->s_dev));
Linus Torvalds's avatar
Linus Torvalds committed
122
        if (!cache) {
Robert Read's avatar
Robert Read committed
123
                EXIT;
Linus Torvalds's avatar
Linus Torvalds committed
124
                goto exit;
Robert Read's avatar
Robert Read committed
125 126
        }
        channel = &izo_channels[presto_c2m(cache)];
Linus Torvalds's avatar
Linus Torvalds committed
127
        sops = filter_c2csops(cache->cache_filter);
Robert Read's avatar
Robert Read committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
        err = izo_clear_all_fsetroots(cache); 
        if (err) { 
                CERROR("%s: err %d\n", __FUNCTION__, err);
        }
        PRESTO_FREE(cache->cache_vfsmount, sizeof(struct vfsmount));

        /* look at kill_super - fsync_super is not exported GRRR but 
           probably not needed */ 
        unlock_super(sb);
        shrink_dcache_parent(cache->cache_root); 
        dput(cache->cache_root); 
        //fsync_super(sb); 
        lock_super(sb);

        if (sops->write_super)
                sops->write_super(sb); 

Linus Torvalds's avatar
Linus Torvalds committed
145 146 147 148
        if (sops->put_super)
                sops->put_super(sb);

        /* free any remaining async upcalls when the filesystem is unmounted */
Robert Read's avatar
Robert Read committed
149 150 151
        spin_lock(&channel->uc_lock);
        lh = channel->uc_pending.next;
        while ( lh != &channel->uc_pending) {
Linus Torvalds's avatar
Linus Torvalds committed
152 153 154 155 156 157 158 159 160 161 162
                struct upc_req *req;
                req = list_entry(lh, struct upc_req, rq_chain);

                /* assignment must be here: we are about to free &lh */
                lh = lh->next;
                if ( ! (req->rq_flags & REQ_ASYNC) ) 
                        continue;
                list_del(&(req->rq_chain));
                PRESTO_FREE(req->rq_data, req->rq_bufsize);
                PRESTO_FREE(req, sizeof(struct upc_req));
        }
Robert Read's avatar
Robert Read committed
163 164
        list_del(&cache->cache_channel_list); 
        spin_unlock(&channel->uc_lock);
Linus Torvalds's avatar
Linus Torvalds committed
165 166 167 168 169 170 171 172 173 174

        presto_free_cache(cache);

exit:
        CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
               presto_kmemory, presto_vmemory);
        MOD_DEC_USE_COUNT;
        return ;
}

Robert Read's avatar
Robert Read committed
175 176 177 178 179
struct super_operations presto_super_ops = {
        .read_inode    = presto_read_inode,
        .put_super     = presto_put_super,
};

Linus Torvalds's avatar
Linus Torvalds committed
180 181 182

/* symlinks can be chowned */
struct inode_operations presto_sym_iops = {
Robert Read's avatar
Robert Read committed
183
        .setattr       = presto_setattr
Linus Torvalds's avatar
Linus Torvalds committed
184 185 186 187
};

/* NULL for now */
struct file_operations presto_sym_fops;