1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/smfs/journal.c
5 * Lustre filesystem abstraction routines
7 * Copyright (C) 2004 Cluster File Systems, Inc.
9 * This file is part of Lustre, http://www.lustre.org.
11 * Lustre is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
15 * Lustre is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Lustre; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define DEBUG_SUBSYSTEM S_SM
26 #include <linux/kmod.h>
27 #include <linux/init.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <asm/segment.h>
32 #include <asm/uaccess.h>
33 #include <linux/obd_class.h>
34 #include <linux/obd_support.h>
35 #include <linux/lustre_lib.h>
36 #include <linux/lustre_idl.h>
37 #include <linux/lustre_fsfilt.h>
38 #include <linux/lustre_smfs.h>
39 #include <linux/lvfs.h>
40 #include "smfs_internal.h"
42 #define KML_BUF_REC_INIT(buffer, pbuf, len) \
44 pbuf = buffer + sizeof(int); \
48 #define KML_BUF_REC_END(buffer, length, pbuf) \
51 memcpy(buffer, &len, sizeof(len)); \
52 length += sizeof(int); \
53 pbuf = buffer + length; \
56 void *smfs_trans_start(struct inode *inode, int op, void *desc_private)
58 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
60 CDEBUG(D_INFO, "trans start %p\n", fsfilt->fs_start);
62 SMFS_TRANS_OP(inode, op);
64 /* There are some problem here. fs_start in fsfilt is used by lustre
65 * the journal blocks of write rec are not counted in FIXME later */
67 return fsfilt->fs_start(inode, op, desc_private, 0);
71 void smfs_trans_commit(struct inode *inode, void *handle, int force_sync)
73 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
78 CDEBUG(D_INFO, "trans commit %p\n", fsfilt->fs_commit);
80 if (fsfilt->fs_commit)
81 fsfilt->fs_commit(inode->i_sb, inode, handle, force_sync);
84 /*smfs_path is gotten from intermezzo*/
85 static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
88 char * end = buffer + buflen;
90 char * buf_end = buffer + buflen;
100 struct dentry * parent;
105 parent = dentry->d_parent;
106 if (dentry == parent)
108 namelen = dentry->d_name.len;
109 buflen -= namelen + 1;
113 memcpy(end, dentry->d_name.name, namelen);
119 while (end != buf_end)
125 static int smfs_log_path(struct super_block *sb,
126 struct dentry *dentry,
130 struct dentry *root=sb->s_root;
131 char *p_name = buffer + sizeof(int);
135 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
136 namelen = cpu_to_le32(strlen(p_name));
137 memcpy(buffer, &namelen, sizeof(int));
139 namelen += sizeof(int);
143 static inline int log_it(char *buffer, void *data, int length)
145 memcpy(buffer, &length, sizeof(int));
146 memcpy(buffer + sizeof(int), data, length);
147 return (sizeof(int) + length);
150 static int smfs_pack_rec (char *buffer, struct dentry *dentry,
151 struct inode *dir, void *data1,
154 smfs_pack_rec_func pack_func;
157 pack_func = smfs_get_rec_pack_type(dir->i_sb);
161 rc = pack_func(buffer, dentry, dir, data1, data2, op);
165 int smfs_post_rec_create(struct inode *dir, struct dentry *dentry,
166 void *data1, void *data2)
168 struct smfs_super_info *sinfo;
169 char *buffer = NULL, *pbuf;
170 int rc = 0, length = 0, buf_len = 0;
172 sinfo = S2SMI(dentry->d_inode->i_sb);
176 OBD_ALLOC(buffer, PAGE_SIZE);
178 GOTO(exit, rc = -ENOMEM);
181 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
182 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
186 KML_BUF_REC_END(buffer, length, pbuf);
188 rc = smfs_pack_rec(pbuf, dentry, dir,
189 data1, data2, REINT_CREATE);
194 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
197 OBD_FREE(buffer, PAGE_SIZE);
202 static int smfs_post_rec_link(struct inode *dir,
203 struct dentry *dentry,
207 struct smfs_super_info *sinfo;
208 struct dentry *old_dentry = (struct dentry *)data1;
209 char *buffer = NULL, *pbuf = NULL;
210 int rc = 0, length = 0, buf_len = 0;
212 sinfo = S2SMI(dir->i_sb);
215 OBD_ALLOC(buffer, PAGE_SIZE);
217 GOTO(exit, rc = -ENOMEM);
220 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
221 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
226 KML_BUF_REC_END(buffer, length, pbuf);
228 rc = smfs_pack_rec(pbuf, dentry, dir, dentry->d_parent,
229 old_dentry->d_parent, REINT_LINK);
234 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
237 OBD_FREE(buffer, PAGE_SIZE);
242 static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
243 void *data1, void *data2)
245 struct smfs_super_info *sinfo;
246 int mode = *((int*)data1);
247 char *buffer = NULL, *pbuf = NULL;
248 int length = 0, rc = 0, buf_len = 0;
250 sinfo = S2SMI(dentry->d_inode->i_sb);
254 OBD_ALLOC(buffer, PAGE_SIZE);
256 GOTO(exit, rc = -ENOMEM);
259 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
260 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
265 KML_BUF_REC_END(buffer, length, pbuf);
266 rc = smfs_pack_rec(pbuf, dentry, dir,
267 &mode, NULL, REINT_UNLINK);
273 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
276 OBD_FREE(buffer, PAGE_SIZE);
281 static int smfs_post_rec_rename(struct inode *dir,
282 struct dentry *dentry,
286 struct smfs_super_info *sinfo;
287 struct inode *new_dir = (struct inode *)data1;
288 struct dentry *new_dentry = (struct dentry *)data2;
289 char *buffer = NULL, *pbuf = NULL;
290 int rc = 0, length = 0, buf_len = 0;
292 sinfo = S2SMI(dir->i_sb);
296 OBD_ALLOC(buffer, PAGE_SIZE);
298 GOTO(exit, rc = -ENOMEM);
301 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
302 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
309 /*record new_dentry path*/
310 rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len);
315 KML_BUF_REC_END(buffer, length, pbuf);
317 rc = smfs_pack_rec(pbuf, dentry, dir,
318 new_dir, new_dentry, REINT_RENAME);
323 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
326 OBD_FREE(buffer, PAGE_SIZE);
330 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
332 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
335 if (SMFS_INODE_OVER_WRITE(inode))
338 rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode),
339 SIZE2BLKS(num, inode));
343 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
345 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
348 rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode),
349 SIZE2BLKS(num, inode));
354 static int smfs_remove_all_extents_ea(struct inode *inode)
356 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
359 rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);
362 static int smfs_init_extents_ea(struct inode *inode)
364 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
367 rc = fsfilt->fs_init_extents_ea(inode);
371 static int smfs_set_dirty_flags(struct inode *inode, int flags)
373 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
377 if (SMFS_INODE_OVER_WRITE(inode))
379 /*FIXME later, the blocks needed in journal here will be recalculated*/
380 handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL);
381 if (IS_ERR(handle)) {
382 CERROR("smfs_set_dirty_flag:no space for transaction\n");
385 if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) ||
386 ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {
387 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
388 &flags, sizeof(int));
392 if (flags == SMFS_OVER_WRITE)
393 SMFS_SET_INODE_OVER_WRITE(inode);
395 SMFS_SET_INODE_DIRTY_WRITE(inode);
397 smfs_trans_commit(inode, handle, 0);
401 int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
402 void *data1, void *data2)
404 struct smfs_super_info *sinfo;
405 struct iattr *attr = (struct iattr *)data1;
406 char *buffer = NULL, *pbuf;
407 int rc = 0, length = 0, buf_len = 0;
409 sinfo = S2SMI(inode->i_sb);
413 OBD_ALLOC(buffer, PAGE_SIZE);
415 GOTO(exit, rc = -ENOMEM);
418 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
419 rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len);
424 KML_BUF_REC_END(buffer, length, pbuf);
426 rc = smfs_pack_rec(pbuf, dentry, inode,
427 data1, data2, REINT_SETATTR);
433 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
435 if (attr && attr->ia_valid & ATTR_SIZE) {
436 smfs_remove_extents_ea(inode, attr->ia_size,
438 if (attr->ia_size == 0)
439 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
441 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
446 OBD_FREE(buffer, PAGE_SIZE);
450 static int all_blocks_present_ea(struct inode *inode)
456 int smfs_post_rec_write(struct inode *dir, struct dentry *dentry,
457 void *data1, void *data2)
459 struct smfs_super_info *sinfo;
460 char *buffer = NULL, *pbuf;
461 int rc = 0, length = 0, buf_len = 0;
463 if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) &&
464 !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
465 sinfo = S2SMI(dentry->d_inode->i_sb);
469 OBD_ALLOC(buffer, PAGE_SIZE);
471 GOTO(exit, rc = -ENOMEM);
474 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
475 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
480 memcpy(buffer, &rc, sizeof(int));
481 length = rc + sizeof(int);
483 rc = smfs_pack_rec(pbuf, dentry, dir,
484 data1, data2, REINT_WRITE);
490 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
493 rc = smfs_init_extents_ea(dentry->d_inode);
497 if (dentry->d_inode->i_size == 0) {
498 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
501 loff_t off = *((loff_t*)data1);
502 size_t count = *((size_t*)data2);
504 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);
507 if (all_blocks_present_ea(dentry->d_inode)){
508 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
509 smfs_remove_all_extents_ea(dentry->d_inode);
511 smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);
516 OBD_FREE(buffer, PAGE_SIZE);
520 typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
521 void *data1, void *data2);
523 static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
524 [HOOK_CREATE] smfs_post_rec_create,
526 [HOOK_LINK] smfs_post_rec_link,
527 [HOOK_UNLINK] smfs_post_rec_unlink,
528 [HOOK_SYMLINK] smfs_post_rec_create,
529 [HOOK_MKDIR] smfs_post_rec_create,
530 [HOOK_RMDIR] smfs_post_rec_unlink,
531 [HOOK_MKNOD] smfs_post_rec_create,
532 [HOOK_RENAME] smfs_post_rec_rename,
533 [HOOK_SETATTR] smfs_post_rec_setattr,
534 [HOOK_WRITE] smfs_post_rec_write,
537 int smfs_post_kml_rec(struct inode *dir, struct dentry *dst_dentry,
538 void *data1, void *data2, int op)
540 if (smfs_kml_post[op]) {
541 return smfs_kml_post[op](dir, dst_dentry, data1, data2);