1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 1998 Peter J. Braam <braam@clusterfs.com>
5 * Copyright (C) 2000 Red Hat, Inc.
6 * Copyright (C) 2000 Los Alamos National Laboratory
7 * Copyright (C) 2000 TurboLinux, Inc.
8 * Copyright (C) 2001 Mountain View Data, Inc.
10 * This file is part of InterMezzo, http://www.inter-mezzo.org.
12 * InterMezzo is free software; you can redistribute it and/or
13 * modify it under the terms of version 2 of the GNU General Public
14 * License as published by the Free Software Foundation.
16 * InterMezzo is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with InterMezzo; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <linux/types.h>
27 #include <linux/param.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
31 #include <linux/slab.h>
32 #include <linux/vmalloc.h>
33 #include <linux/stat.h>
34 #include <linux/errno.h>
35 #include <asm/segment.h>
36 #include <asm/uaccess.h>
37 #include <linux/string.h>
38 #ifdef CONFIG_OBDFS_FS
39 #include /usr/src/obd/include/linux/obdfs.h
42 #include "intermezzo_fs.h"
43 #include "intermezzo_psdev.h"
45 #ifdef CONFIG_OBDFS_FS
48 static unsigned long presto_obdfs_freespace(struct presto_file_set *fset,
49 struct super_block *sb)
54 /* start the filesystem journal operations */
55 static void *presto_obdfs_trans_start(struct presto_file_set *fset,
65 int trunc_blks, one_path_blks, extra_path_blks,
66 extra_name_blks, lml_blks;
67 __u32 avail_kmlblocks;
69 if ( presto_no_journal(fset) ||
70 strcmp(fset->fset_cache->cache_type, "ext3"))
72 CDEBUG(D_JOURNAL, "got cache_type \"%s\"\n",
73 fset->fset_cache->cache_type);
77 avail_kmlblocks = inode->i_sb->u.ext3_sb.s_es->s_free_blocks_count;
79 if ( avail_kmlblocks < 3 ) {
80 return ERR_PTR(-ENOSPC);
83 if ( (op != PRESTO_OP_UNLINK && op != PRESTO_OP_RMDIR)
84 && avail_kmlblocks < 6 ) {
85 return ERR_PTR(-ENOSPC);
88 /* Need journal space for:
89 at least three writes to KML (two one block writes, one a path)
90 possibly a second name (unlink, rmdir)
91 possibly a second path (symlink, rename)
92 a one block write to the last rcvd file
95 trunc_blks = EXT3_DATA_TRANS_BLOCKS + 1;
96 one_path_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 3;
97 lml_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 2;
98 extra_path_blks = EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode);
99 extra_name_blks = EXT3_DATA_TRANS_BLOCKS + MAX_NAME_BLOCKS(inode);
101 /* additional blocks appear for "two pathname" operations
102 and operations involving the LML records
105 case PRESTO_OP_TRUNC:
106 jblocks = one_path_blks + extra_name_blks + trunc_blks
107 + EXT3_DELETE_TRANS_BLOCKS;
109 case PRESTO_OP_RELEASE:
111 jblocks = one_path_blks + lml_blks + 2*trunc_blks;
113 jblocks = one_path_blks;
115 case PRESTO_OP_SETATTR:
116 jblocks = one_path_blks + trunc_blks + 1 ;
118 case PRESTO_OP_CREATE:
119 jblocks = one_path_blks + trunc_blks
120 + EXT3_DATA_TRANS_BLOCKS + 3;
123 jblocks = one_path_blks + trunc_blks
124 + EXT3_DATA_TRANS_BLOCKS;
126 case PRESTO_OP_UNLINK:
127 jblocks = one_path_blks + extra_name_blks + trunc_blks
128 + EXT3_DELETE_TRANS_BLOCKS;
130 case PRESTO_OP_SYMLINK:
131 jblocks = one_path_blks + extra_path_blks + trunc_blks
132 + EXT3_DATA_TRANS_BLOCKS + 5;
134 case PRESTO_OP_MKDIR:
135 jblocks = one_path_blks + trunc_blks
136 + EXT3_DATA_TRANS_BLOCKS + 4;
138 case PRESTO_OP_RMDIR:
139 jblocks = one_path_blks + extra_name_blks + trunc_blks
140 + EXT3_DELETE_TRANS_BLOCKS;
142 case PRESTO_OP_MKNOD:
143 jblocks = one_path_blks + trunc_blks +
144 EXT3_DATA_TRANS_BLOCKS + 3;
146 case PRESTO_OP_RENAME:
147 jblocks = one_path_blks + extra_path_blks + trunc_blks +
148 2 * EXT3_DATA_TRANS_BLOCKS + 2;
150 case PRESTO_OP_WRITE:
151 jblocks = one_path_blks;
152 /* add this when we can wrap our transaction with
153 that of ext3_file_write (ordered writes)
154 + EXT3_DATA_TRANS_BLOCKS;
158 CDEBUG(D_JOURNAL, "invalid operation %d for journal\n", op);
162 CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks);
163 return journal_start(EXT3_JOURNAL(inode), jblocks);
167 void presto_obdfs_trans_commit(struct presto_file_set *fset, void *handle)
170 if ( presto_no_journal(fset) || !handle)
173 journal_stop(handle);
177 void presto_obdfs_journal_file_data(struct inode *inode)
179 #ifdef EXT3_JOURNAL_DATA_FL
180 inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;
182 #warning You must have a facility to enable journaled writes for recovery!
186 struct journal_ops presto_obdfs_journal_ops = {
187 .tr_avail = presto_obdfs_freespace,
188 .tr_start = presto_obdfs_trans_start,
189 .tr_commit = presto_obdfs_trans_commit,
190 .tr_journal_data = presto_obdfs_journal_file_data