Whamcloud - gitweb
Remove no-longer-needed inode operations (they previously had extN EA VFS
[fs/lustre-release.git] / lustre / mds / mds_extN.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  linux/mds/mds_extN.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/extN_fs.h>
21 #include <linux/extN_jbd.h>
22 #include <linux/extN_xattr.h>
23 #include <linux/lustre_mds.h>
24 #include <linux/module.h>
25
26 static struct mds_fs_operations mds_extN_fs_ops;
27 static kmem_cache_t *jcb_cache;
28 static int jcb_cache_count;
29
30 struct mds_cb_data {
31         struct journal_callback cb_jcb;
32         struct mds_obd *cb_mds;
33         __u64 cb_last_rcvd;
34 };
35
36 struct mds_objid {
37         __u16 mo_magic;
38         __u8  mo_unused;
39         __u8  mo_ost;
40         __u64 mo_id;
41 };
42
43 #define EXTN_XATTR_INDEX_LUSTRE         5
44 #define XATTR_LUSTRE_MDS_OBJID          "system.lustre_mds_objid"
45
46 #define XATTR_MDS_MO_MAGIC              0x4711
47
48 /*
49  * We don't currently need any additional blocks for rmdir and
50  * unlink transactions because we are storing the OST oa_id inside
51  * the inode (which we will be changing anyways as part of this
52  * transaction).
53  */
54 static void *mds_extN_start(struct inode *inode, int op)
55 {
56         /* For updates to the last recieved file */
57         int nblocks = EXTN_DATA_TRANS_BLOCKS;
58
59         switch(op) {
60         case MDS_FSOP_RMDIR:
61         case MDS_FSOP_UNLINK:
62                 nblocks += EXTN_DELETE_TRANS_BLOCKS;
63                 break;
64         case MDS_FSOP_RENAME:
65                 /* We may be modifying two directories */
66                 nblocks += EXTN_DATA_TRANS_BLOCKS;
67         case MDS_FSOP_SYMLINK:
68                 /* Possible new block + block bitmap + GDT for long symlink */
69                 nblocks += 3;
70         case MDS_FSOP_CREATE:
71         case MDS_FSOP_MKDIR:
72         case MDS_FSOP_MKNOD:
73                 /* New inode + block bitmap + GDT for new file */
74                 nblocks += 3;
75         case MDS_FSOP_LINK:
76                 /* Change parent directory */
77                 nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS;
78                 break;
79         case MDS_FSOP_SETATTR:
80                 /* Setattr on inode */
81                 nblocks += 1;
82                 break;
83         default: CERROR("unknown transaction start op %d\n", op);
84                  LBUG();
85         }
86
87         return journal_start(EXTN_JOURNAL(inode), nblocks);
88 }
89
90 static int mds_extN_commit(struct inode *inode, void *handle)
91 {
92         return journal_stop((handle_t *)handle);
93 }
94
95 static int mds_extN_setattr(struct dentry *dentry, void *handle,
96                             struct iattr *iattr)
97 {
98         struct inode *inode = dentry->d_inode;
99
100         if (inode->i_op->setattr)
101                 return inode->i_op->setattr(dentry, iattr);
102         else
103                 return inode_setattr(inode, iattr);
104 }
105
106 static int mds_extN_set_objid(struct inode *inode, void *handle, obd_id id)
107 {
108         struct mds_objid data;
109         int rc;
110
111         data.mo_magic = cpu_to_le16(XATTR_MDS_MO_MAGIC);
112         data.mo_unused = 0;
113         data.mo_ost = 0;  /* FIXME: store OST index here */
114         data.mo_id = cpu_to_le64(id);
115
116         lock_kernel();
117         down(&inode->i_sem);
118         if (id == 0) {
119                 rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
120                                     XATTR_LUSTRE_MDS_OBJID, NULL, 0, 0);
121         } else {
122                 rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
123                                     XATTR_LUSTRE_MDS_OBJID, &data,
124                                     sizeof(struct mds_objid), XATTR_CREATE);
125         }
126         up(&inode->i_sem);
127         unlock_kernel();
128
129         if (rc)
130                 CERROR("error adding objectid %Ld to inode %ld\n",
131                        (unsigned long long)id, inode->i_ino);
132         return rc;
133 }
134
135 static int mds_extN_get_objid(struct inode *inode, obd_id *id)
136 {
137         struct mds_objid data;
138         int rc;
139
140         lock_kernel();
141         down(&inode->i_sem);
142         rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_LUSTRE,
143                             XATTR_LUSTRE_MDS_OBJID, &data,
144                             sizeof(struct mds_objid));
145         up(&inode->i_sem);
146         unlock_kernel();
147
148         if (rc < 0) {
149                 CERROR("error getting EA %s from MDS inode %ld: rc = %d\n",
150                        XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc);
151                 *id = 0;
152         } else if (data.mo_magic != cpu_to_le16(XATTR_MDS_MO_MAGIC)) {
153                 CERROR("MDS object id %Ld has bad magic %x\n",
154                        (unsigned long long)le64_to_cpu(data.mo_id),
155                        le16_to_cpu(data.mo_magic));
156                 rc = -EINVAL;
157         } else {
158                 *id = le64_to_cpu(data.mo_id);
159                 /* FIXME: will actually use data.mo_ost at some point */
160                 if (data.mo_ost)
161                         CERROR("MDS objid %Ld with ost index %d!\n",
162                                *id, data.mo_ost);
163         }
164
165         return rc;
166 }
167
168 static ssize_t mds_extN_readpage(struct file *file, char *buf, size_t count,
169                                  loff_t *offset)
170 {
171         struct inode *inode = file->f_dentry->d_inode;
172         int rc = 0;
173
174         if (S_ISREG(inode->i_mode))
175                 rc = file->f_op->read(file, buf, count, offset);
176         else {
177                 struct buffer_head *bh;
178
179                 /* FIXME: this assumes the blocksize == count, but the calling
180                  *        function will detect this as an error for now */
181                 bh = extN_bread(NULL, inode,
182                                 *offset >> inode->i_sb->s_blocksize_bits,
183                                 0, &rc);
184
185                 if (bh) {
186                         memcpy(buf, bh->b_data, inode->i_blksize);
187                         brelse(bh);
188                         rc = inode->i_blksize;
189                 }
190         }
191
192         return rc;
193 }
194
195 static void mds_extN_delete_inode(struct inode *inode)
196 {
197         if (S_ISREG(inode->i_mode)) {
198                 void *handle = mds_extN_start(inode, MDS_FSOP_UNLINK);
199
200                 if (IS_ERR(handle)) {
201                         CERROR("unable to start transaction");
202                         EXIT;
203                         return;
204                 }
205                 if (mds_extN_set_objid(inode, handle, 0))
206                         CERROR("error clearing objid on %ld\n", inode->i_ino);
207
208                 if (mds_extN_fs_ops.cl_delete_inode)
209                         mds_extN_fs_ops.cl_delete_inode(inode);
210
211                 if (mds_extN_commit(inode, handle))
212                         CERROR("error closing handle on %ld\n", inode->i_ino);
213         } else
214                 mds_extN_fs_ops.cl_delete_inode(inode);
215 }
216
217 static void mds_extN_callback_status(struct journal_callback *jcb, int error)
218 {
219         struct mds_cb_data *mcb = (struct mds_cb_data *)jcb;
220
221         CDEBUG(D_EXT2, "got callback for last_rcvd %Ld: rc = %d\n",
222                mcb->cb_last_rcvd, error);
223         if (!error && mcb->cb_last_rcvd > mcb->cb_mds->mds_last_committed)
224                 mcb->cb_mds->mds_last_committed = mcb->cb_last_rcvd;
225
226         kmem_cache_free(jcb_cache, jcb);
227         --jcb_cache_count;
228 }
229
230 #ifdef HAVE_JOURNAL_CALLBACK
231 static void mds_extN_callback_func(void *cb_data)
232 {
233         mds_extN_callback_status(cb_data, 0);
234 }
235 #endif
236
237 static int mds_extN_set_last_rcvd(struct mds_obd *mds, void *handle)
238 {
239         struct mds_cb_data *mcb;
240
241         mcb = kmem_cache_alloc(jcb_cache, GFP_NOFS);
242         if (!mcb)
243                 RETURN(-ENOMEM);
244
245         ++jcb_cache_count;
246         mcb->cb_mds = mds;
247         mcb->cb_last_rcvd = mds->mds_last_rcvd;
248
249 #ifdef HAVE_JOURNAL_CALLBACK_STATUS
250         CDEBUG(D_EXT2, "set callback for last_rcvd: %Ld\n",
251                (unsigned long long)mcb->cb_last_rcvd);
252         journal_callback_set(handle, mds_extN_callback_status,
253                              (struct journal_callback *)mcb);
254 #elif defined(HAVE_JOURNAL_CALLBACK)
255         /* XXX original patch version - remove soon */
256 #warning "using old journal callback kernel patch, please update"
257         CDEBUG(D_EXT2, "set callback for last_rcvd: %Ld\n",
258                (unsigned long long)mcb->cb_last_rcvd);
259         journal_callback_set(handle, mds_extN_callback_func, mcb);
260 #else
261 #warning "no journal callback kernel patch, faking it..."
262         {
263         static long next = 0;
264
265         if (time_after(jiffies, next)) {
266                 CERROR("no journal callback kernel patch, faking it...\n");
267                 next = jiffies + 300 * HZ;
268         }
269         }
270         mds_extN_callback_status((struct journal_callback *)mcb, 0);
271 #endif
272
273         return 0;
274 }
275
276 static int mds_extN_journal_data(struct file *filp)
277 {
278         struct inode *inode = filp->f_dentry->d_inode;
279
280         EXTN_I(inode)->i_flags |= EXTN_JOURNAL_DATA_FL;
281
282         return 0;
283 }
284
285 static struct mds_fs_operations mds_extN_fs_ops = {
286         fs_start:               mds_extN_start,
287         fs_commit:              mds_extN_commit,
288         fs_setattr:             mds_extN_setattr,
289         fs_set_objid:           mds_extN_set_objid,
290         fs_get_objid:           mds_extN_get_objid,
291         fs_readpage:            mds_extN_readpage,
292         fs_delete_inode:        mds_extN_delete_inode,
293         cl_delete_inode:        clear_inode,
294         fs_journal_data:        mds_extN_journal_data,
295         fs_set_last_rcvd:       mds_extN_set_last_rcvd,
296 };
297
298 static int __init mds_extN_init(void)
299 {
300         int rc;
301
302         //rc = extN_xattr_register();
303         jcb_cache = kmem_cache_create("mds_extN_jcb",
304                                       sizeof(struct mds_cb_data), 0,
305                                       SLAB_POISON, NULL, NULL);
306         if (!jcb_cache) {
307                 CERROR("error allocating MDS journal callback cache\n");
308                 GOTO(out, rc = -ENOMEM);
309         }
310         rc = mds_register_fs_type(&mds_extN_fs_ops, "extN");
311
312         if (rc)
313                 kmem_cache_destroy(jcb_cache);
314 out:
315         return rc;
316 }
317
318 static void __exit mds_extN_exit(void)
319 {
320         int rc;
321
322         mds_unregister_fs_type("extN");
323         rc = kmem_cache_destroy(jcb_cache);
324
325         if (rc || jcb_cache_count) {
326                 CERROR("can't free MDS callback cache: count %d, rc = %d\n",
327                        jcb_cache_count, rc);
328         }
329
330         //rc = extN_xattr_unregister();
331 }
332
333 MODULE_AUTHOR("Cluster File Systems, Inc. <adilger@clusterfs.com>");
334 MODULE_DESCRIPTION("Lustre MDS extN Filesystem Helper v0.1");
335 MODULE_LICENSE("GPL");
336
337 module_init(mds_extN_init);
338 module_exit(mds_extN_exit);