Whamcloud - gitweb
Set a flag in the inode if we have stored the objid there, so we know when
[fs/lustre-release.git] / lustre / mds / mds_ext3.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  linux/mds/mds_ext3.c
5  *
6  *  Lustre Metadata Server (mds) journal abstraction routines
7  *
8  *  Copyright (C) 2002  Cluster File Systems, Inc.
9  *  author: Andreas Dilger <adilger@clusterfs.com>
10  *
11  *  This code is issued under the GNU General Public License.
12  *  See the file COPYING in this distribution
13  *
14  */
15
16 #define DEBUG_SUBSYSTEM S_MDS
17
18 #include <linux/fs.h>
19 #include <linux/jbd.h>
20 #include <linux/ext3_fs.h>
21 #include <linux/ext3_jbd.h>
22 #include <linux/lustre_mds.h>
23
24 /*
25  * We don't currently need any additional blocks for rmdir and
26  * unlink transactions because we are storing the OST oa_id inside
27  * the inode (which we will be changing anyways as part of this
28  * transaction).  When we store the oa_id in an EA (which may be
29  * in an external block) we need to increase nblocks by 1.
30  */
31 static void *mds_ext3_start(struct inode *inode, int op)
32 {
33         int nblocks = 0;
34
35         switch(op) {
36         case MDS_FSOP_RMDIR:
37         case MDS_FSOP_UNLINK:   nblocks = EXT3_DELETE_TRANS_BLOCKS; break;
38         }
39
40         return journal_start(EXT3_JOURNAL(inode), nblocks);
41 }
42
43 static int mds_ext3_commit(struct inode *inode, void *handle)
44 {
45         return journal_stop((handle_t *)handle);
46 }
47
48 static int mds_ext3_setattr(struct inode *inode, void *handle,
49                             struct iattr *iattr)
50 {
51         /* a _really_ horrible hack to avoid removing the data stored
52            in the block pointers; this data is the object id
53            this will go into an extended attribute at some point.
54         */
55         if ( iattr->ia_valid & ATTR_SIZE ) {
56                 /* ATTR_SIZE would invoke truncate: clear it */
57                 iattr->ia_valid &= ~ATTR_SIZE;
58                 inode->i_size = iattr->ia_size;
59
60                 /* an _even_more_ horrible hack to make this hack work with
61                  * ext3.  This is because ext3 keeps a separate inode size
62                  * until the inode is committed to ensure consistency.  This
63                  * will also go away with the move to EAs.
64                  */
65                 EXT3_I(inode)->i_disksize = inode->i_size;
66
67                 /* make sure _something_ gets set - so new inode
68                    goes to disk (probably won't work over XFS */
69                 if (!iattr->ia_valid & ATTR_MODE) {
70                         iattr->ia_valid |= ATTR_MODE;
71                         iattr->ia_mode = inode->i_mode;
72                 }
73         }
74
75         return 0;
76 }
77
78 /*
79  * FIXME: nasty hack - store the object id in the first two
80  *        direct block spots.  This should be done with EAs...
81  */
82 #define EXT3_OBJID_FL   0x40000000
83 static int mds_ext3_set_objid(struct inode *inode, void *handle, obd_id id)
84 {
85         memcpy(&EXT3_I(inode)->i_data, &id, sizeof(id));
86         EXT3_I(inode)->i_flags |= EXT3_OBJID_FL;
87         return 0;
88 }
89
90 static void mds_ext3_get_objid(struct inode *inode, obd_id *id)
91 {
92         memcpy(id, &EXT3_I(inode)->i_data, sizeof(*id));
93 }
94
95 static ssize_t mds_ext3_readpage(struct file *file, char *buf, size_t count,
96                                  loff_t *offset)
97 {
98         struct inode *inode = file->f_dentry->d_inode;
99         int rc = 0;
100
101         if (S_ISREG(inode->i_mode))
102                 rc = file->f_op->read(file, buf, count, offset);
103         else {
104                 struct buffer_head *bh;
105
106                 /* FIXME: this assumes the blocksize == count, but the calling
107                  *        function will detect this as an error for now */
108                 bh = ext3_bread(NULL, inode,
109                                 *offset >> inode->i_sb->s_blocksize_bits,
110                                 0, &rc);
111
112                 if (bh) {
113                         memcpy(buf, bh->b_data, inode->i_blksize);
114                         brelse(bh);
115                         rc = inode->i_blksize;
116                 }
117         }
118
119         return rc;
120 }
121
122 struct mds_fs_operations mds_ext3_fs_ops;
123
124 void mds_ext3_delete_inode(struct inode * inode)
125 {
126         void *handle;
127
128         if (EXT3_I(inode)->i_flags & EXT3_OBJID_FL) {
129                 handle = mds_ext3_start(inode, MDS_FSOP_UNLINK);
130
131                 if (IS_ERR(handle)) {
132                         CERROR("unable to start transaction");
133                         EXIT;
134                         return;
135                 }
136                 if (mds_ext3_set_objid(inode, handle, 0))
137                         CERROR("error clearing objid on %ld\n", inode->i_ino);
138
139                 if (mds_ext3_fs_ops.cl_delete_inode)
140                         mds_ext3_fs_ops.cl_delete_inode(inode);
141
142                 if (mds_ext3_commit(inode, handle))
143                         CERROR("error closing handle on %ld\n", inode->i_ino);
144         } else
145                 mds_ext3_fs_ops.cl_delete_inode(inode);
146 }
147
148 struct mds_fs_operations mds_ext3_fs_ops = {
149         fs_start:       mds_ext3_start,
150         fs_commit:      mds_ext3_commit,
151         fs_setattr:     mds_ext3_setattr,
152         fs_set_objid:   mds_ext3_set_objid,
153         fs_get_objid:   mds_ext3_get_objid,
154         fs_readpage:    mds_ext3_readpage,
155         fs_delete_inode:mds_ext3_delete_inode,
156         cl_delete_inode:clear_inode,
157 };