Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / fs / intermezzo / journal.c
blob655fe5f7a5024817b05bc8dd72a028e336366d51
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
5 * Copyright (C) 2001 Cluster File Systems, Inc.
6 * Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
8 * Support for journalling extended attributes
9 * Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
11 * This file is part of InterMezzo, http://www.inter-mezzo.org.
13 * InterMezzo is free software; you can redistribute it and/or
14 * modify it under the terms of version 2 of the GNU General Public
15 * License as published by the Free Software Foundation.
17 * InterMezzo is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with InterMezzo; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <linux/types.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/fs.h>
31 #include <linux/namei.h>
32 #include <linux/slab.h>
33 #include <linux/vmalloc.h>
34 #include <linux/time.h>
35 #include <linux/errno.h>
36 #include <linux/smp_lock.h>
37 #include <asm/segment.h>
38 #include <asm/uaccess.h>
39 #include <linux/string.h>
40 #include <linux/smp_lock.h>
41 #include <linux/intermezzo_fs.h>
42 #include <linux/intermezzo_psdev.h>
44 struct presto_reservation_data {
45 unsigned int ri_recno;
46 loff_t ri_offset;
47 loff_t ri_size;
48 struct list_head ri_list;
51 /*
52 * Locking Semantics
54 * write lock in struct presto_log_fd:
55 * - name: fd_lock
56 * - required for: accessing any field in a presto_log_fd
57 * - may not be held across I/O
58 * -
63 * reserve record space and/or atomically request state of the log
64 * rec will hold the location reserved record upon return
65 * this reservation will be placed in the queue
66 */
67 static void presto_reserve_record(struct presto_file_set *fset,
68 struct presto_log_fd *fd,
69 struct rec_info *rec,
70 struct presto_reservation_data *rd)
72 int chunked_record = 0;
73 ENTRY;
75 write_lock(&fd->fd_lock);
76 if ( rec->is_kml ) {
77 int chunk = 1 << fset->fset_chunkbits;
78 int chunk_mask = ~(chunk -1);
79 loff_t boundary;
81 boundary = (fd->fd_offset + chunk - 1) & chunk_mask;
82 if ( fd->fd_offset + rec->size >= boundary ) {
83 chunked_record = 1;
84 fd->fd_offset = boundary;
88 fd->fd_recno++;
90 /* this moves the fd_offset back after truncation */
91 if ( list_empty(&fd->fd_reservations) &&
92 !chunked_record) {
93 fd->fd_offset = fd->fd_file->f_dentry->d_inode->i_size;
96 rec->offset = fd->fd_offset;
97 if (rec->is_kml)
98 rec->offset += fset->fset_kml_logical_off;
100 rec->recno = fd->fd_recno;
102 /* add the reservation data to the end of the list */
103 rd->ri_offset = fd->fd_offset;
104 rd->ri_size = rec->size;
105 rd->ri_recno = rec->recno;
106 list_add(&rd->ri_list, fd->fd_reservations.prev);
108 fd->fd_offset += rec->size;
110 write_unlock(&fd->fd_lock);
112 EXIT;
115 static inline void presto_release_record(struct presto_log_fd *fd,
116 struct presto_reservation_data *rd)
118 write_lock(&fd->fd_lock);
119 list_del(&rd->ri_list);
120 write_unlock(&fd->fd_lock);
123 /* XXX should we ask for do_truncate to be exported? */
124 int izo_do_truncate(struct presto_file_set *fset, struct dentry *dentry,
125 loff_t length, loff_t size_check)
127 struct inode *inode = dentry->d_inode;
128 int error;
129 struct iattr newattrs;
131 ENTRY;
133 if (length < 0) {
134 EXIT;
135 return -EINVAL;
138 down(&inode->i_sem);
139 lock_kernel();
141 if (size_check != inode->i_size) {
142 unlock_kernel();
143 up(&inode->i_sem);
144 EXIT;
145 return -EALREADY;
148 newattrs.ia_size = length;
149 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
151 if (inode->i_op && inode->i_op->setattr)
152 error = inode->i_op->setattr(dentry, &newattrs);
153 else {
154 inode_setattr(dentry->d_inode, &newattrs);
155 error = 0;
158 unlock_kernel();
159 up(&inode->i_sem);
160 EXIT;
161 return error;
164 static void presto_kml_truncate(struct presto_file_set *fset)
166 int rc;
167 ENTRY;
169 write_lock(&fset->fset_kml.fd_lock);
170 if (fset->fset_kml.fd_truncating == 1 ) {
171 write_unlock(&fset->fset_kml.fd_lock);
172 EXIT;
173 return;
176 fset->fset_kml.fd_truncating = 1;
177 write_unlock(&fset->fset_kml.fd_lock);
179 CERROR("islento: %d, count: %d\n",
180 ISLENTO(presto_i2m(fset->fset_dentry->d_inode)),
181 fset->fset_permit_count);
183 rc = izo_upc_kml_truncate(fset->fset_cache->cache_psdev->uc_minor,
184 fset->fset_lento_off, fset->fset_lento_recno,
185 fset->fset_name);
187 /* Userspace is the only permitholder now, and will retain an exclusive
188 * hold on the permit until KML truncation completes. */
189 /* FIXME: double check this code path now that the precise semantics of
190 * fset->fset_permit_count have changed. */
192 if (rc != 0) {
193 write_lock(&fset->fset_kml.fd_lock);
194 fset->fset_kml.fd_truncating = 0;
195 write_unlock(&fset->fset_kml.fd_lock);
198 EXIT;
201 void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,
202 int op)
204 ENTRY;
205 if ( !fset->fset_cache->cache_filter->o_trops ) {
206 EXIT;
207 return NULL;
209 EXIT;
210 return fset->fset_cache->cache_filter->o_trops->tr_start
211 (fset, inode, op);
214 void presto_trans_commit(struct presto_file_set *fset, void *handle)
216 ENTRY;
217 if (!fset->fset_cache->cache_filter->o_trops ) {
218 EXIT;
219 return;
222 fset->fset_cache->cache_filter->o_trops->tr_commit(fset, handle);
224 /* Check to see if the KML needs truncated. */
225 if (fset->kml_truncate_size > 0 &&
226 !fset->fset_kml.fd_truncating &&
227 fset->fset_kml.fd_offset > fset->kml_truncate_size) {
228 CDEBUG(D_JOURNAL, "kml size: %lu; truncating\n",
229 (unsigned long)fset->fset_kml.fd_offset);
230 presto_kml_truncate(fset);
232 EXIT;
235 inline int presto_no_journal(struct presto_file_set *fset)
237 int minor = fset->fset_cache->cache_psdev->uc_minor;
238 return izo_channels[minor].uc_no_journal;
241 #define size_round(x) (((x)+3) & ~0x3)
243 #define BUFF_FREE(buf) PRESTO_FREE(buf, PAGE_SIZE)
244 #define BUFF_ALLOC(newbuf, oldbuf) \
245 PRESTO_ALLOC(newbuf, PAGE_SIZE); \
246 if ( !newbuf ) { \
247 if (oldbuf) \
248 BUFF_FREE(oldbuf); \
249 return -ENOMEM; \
253 * "buflen" should be PAGE_SIZE or more.
254 * Give relative path wrt to a fsetroot
256 char * presto_path(struct dentry *dentry, struct dentry *root,
257 char *buffer, int buflen)
259 char * end = buffer+buflen;
260 char * retval;
262 *--end = '\0';
263 buflen--;
264 if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
265 buflen -= 10;
266 end -= 10;
267 memcpy(end, " (deleted)", 10);
270 /* Get '/' right */
271 retval = end-1;
272 *retval = '/';
274 for (;;) {
275 struct dentry * parent;
276 int namelen;
278 if (dentry == root)
279 break;
280 parent = dentry->d_parent;
281 if (dentry == parent)
282 break;
283 namelen = dentry->d_name.len;
284 buflen -= namelen + 1;
285 if (buflen < 0)
286 break;
287 end -= namelen;
288 memcpy(end, dentry->d_name.name, namelen);
289 *--end = '/';
290 retval = end;
291 dentry = parent;
293 return retval;
296 static inline char *logit(char *buf, const void *value, int size)
298 char *ptr = (char *)value;
300 memcpy(buf, ptr, size);
301 buf += size;
302 return buf;
306 static inline char *
307 journal_log_prefix_with_groups_and_ids(char *buf, int opcode,
308 struct rec_info *rec,
309 __u32 ngroups, gid_t *groups,
310 __u32 fsuid, __u32 fsgid)
312 struct kml_prefix_hdr p;
313 u32 loggroups[NGROUPS_MAX];
315 int i;
317 p.len = cpu_to_le32(rec->size);
318 p.version = KML_MAJOR_VERSION | KML_MINOR_VERSION;
319 p.pid = cpu_to_le32(current->pid);
320 p.auid = cpu_to_le32(current->uid);
321 p.fsuid = cpu_to_le32(fsuid);
322 p.fsgid = cpu_to_le32(fsgid);
323 p.ngroups = cpu_to_le32(ngroups);
324 p.opcode = cpu_to_le32(opcode);
325 for (i=0 ; i < ngroups ; i++)
326 loggroups[i] = cpu_to_le32((__u32) groups[i]);
328 buf = logit(buf, &p, sizeof(struct kml_prefix_hdr));
329 buf = logit(buf, &loggroups, sizeof(__u32) * ngroups);
330 return buf;
333 static inline char *
334 journal_log_prefix(char *buf, int opcode, struct rec_info *rec)
336 __u32 groups[NGROUPS_MAX];
337 int i;
339 /* convert 16 bit gid's to 32 bit gid's */
340 for (i=0; i<current->ngroups; i++)
341 groups[i] = (__u32) current->groups[i];
343 return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
344 (__u32)current->ngroups,
345 groups,
346 (__u32)current->fsuid,
347 (__u32)current->fsgid);
350 static inline char *
351 journal_log_prefix_with_groups(char *buf, int opcode, struct rec_info *rec,
352 __u32 ngroups, gid_t *groups)
354 return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
355 ngroups, groups,
356 (__u32)current->fsuid,
357 (__u32)current->fsgid);
360 static inline char *log_dentry_version(char *buf, struct dentry *dentry)
362 struct presto_version version;
364 presto_getversion(&version, dentry->d_inode);
366 version.pv_mtime = HTON__u64(version.pv_mtime);
367 version.pv_ctime = HTON__u64(version.pv_ctime);
368 version.pv_size = HTON__u64(version.pv_size);
370 return logit(buf, &version, sizeof(version));
373 static inline char *log_version(char *buf, struct presto_version *pv)
375 struct presto_version version;
377 memcpy(&version, pv, sizeof(version));
379 version.pv_mtime = HTON__u64(version.pv_mtime);
380 version.pv_ctime = HTON__u64(version.pv_ctime);
381 version.pv_size = HTON__u64(version.pv_size);
383 return logit(buf, &version, sizeof(version));
386 static inline char *log_rollback(char *buf, struct izo_rollback_data *rb)
388 struct izo_rollback_data rollback;
390 memcpy(&rollback, rb, sizeof(rollback));
392 rollback.rb_mode = HTON__u32(rollback.rb_mode);
393 rollback.rb_rdev = HTON__u32(rollback.rb_rdev);
394 rollback.rb_uid = HTON__u64(rollback.rb_uid);
395 rollback.rb_gid = HTON__u64(rollback.rb_gid);
397 return logit(buf, &rollback, sizeof(rollback));
400 static inline char *journal_log_suffix(char *buf, char *log,
401 struct presto_file_set *fset,
402 struct dentry *dentry,
403 struct rec_info *rec)
405 struct kml_suffix s;
406 struct kml_prefix_hdr *p = (struct kml_prefix_hdr *)log;
408 #if 0
409 /* XXX needs to be done after reservation,
410 disable ths until version 1.2 */
411 if ( dentry ) {
412 s.prevrec = cpu_to_le32(rec->offset -
413 presto_d2d(dentry)->dd_kml_offset);
414 presto_d2d(dentry)->dd_kml_offset = rec->offset;
415 } else {
416 s.prevrec = -1;
418 #endif
419 s.prevrec = 0;
421 /* record number needs to be filled in after reservation
422 s.recno = cpu_to_le32(rec->recno); */
423 s.time = cpu_to_le32(get_seconds());
424 s.len = p->len;
425 return logit(buf, &s, sizeof(s));
428 int izo_log_close(struct presto_log_fd *logfd)
430 int rc = 0;
432 if (logfd->fd_file) {
433 rc = filp_close(logfd->fd_file, 0);
434 logfd->fd_file = NULL;
435 } else
436 CERROR("InterMezzo: %s: no filp\n", __FUNCTION__);
437 if (rc != 0)
438 CERROR("InterMezzo: close files: filp won't close: %d\n", rc);
440 return rc;
443 int presto_fwrite(struct file *file, const char *str, int len, loff_t *off)
445 int rc;
446 mm_segment_t old_fs;
447 ENTRY;
449 rc = -EINVAL;
450 if ( !off ) {
451 EXIT;
452 return rc;
455 if ( ! file ) {
456 EXIT;
457 return rc;
460 if ( ! file->f_op ) {
461 EXIT;
462 return rc;
465 if ( ! file->f_op->write ) {
466 EXIT;
467 return rc;
470 old_fs = get_fs();
471 set_fs(get_ds());
472 rc = file->f_op->write(file, str, len, off);
473 if (rc != len) {
474 CERROR("presto_fwrite: wrote %d bytes instead of "
475 "%d at %ld\n", rc, len, (long)*off);
476 rc = -EIO;
478 set_fs(old_fs);
479 EXIT;
480 return rc;
483 int presto_fread(struct file *file, char *str, int len, loff_t *off)
485 int rc;
486 mm_segment_t old_fs;
487 ENTRY;
489 if (len > 512)
490 CERROR("presto_fread: read at %Ld for %d bytes, ino %ld\n",
491 *off, len, file->f_dentry->d_inode->i_ino);
493 rc = -EINVAL;
494 if ( !off ) {
495 EXIT;
496 return rc;
499 if ( ! file ) {
500 EXIT;
501 return rc;
504 if ( ! file->f_op ) {
505 EXIT;
506 return rc;
509 if ( ! file->f_op->read ) {
510 EXIT;
511 return rc;
514 old_fs = get_fs();
515 set_fs(get_ds());
516 rc = file->f_op->read(file, str, len, off);
517 if (rc != len) {
518 CDEBUG(D_FILE, "presto_fread: read %d bytes instead of "
519 "%d at %Ld\n", rc, len, *off);
520 rc = -EIO;
522 set_fs(old_fs);
523 EXIT;
524 return rc;
527 loff_t presto_kml_offset(struct presto_file_set *fset)
529 unsigned int kml_recno;
530 struct presto_log_fd *fd = &fset->fset_kml;
531 loff_t offset;
532 ENTRY;
534 write_lock(&fd->fd_lock);
536 /* Determine the largest valid offset, i.e. up until the first
537 * reservation held on the file. */
538 if ( !list_empty(&fd->fd_reservations) ) {
539 struct presto_reservation_data *rd;
540 rd = list_entry(fd->fd_reservations.next,
541 struct presto_reservation_data,
542 ri_list);
543 offset = rd->ri_offset;
544 kml_recno = rd->ri_recno;
545 } else {
546 offset = fd->fd_file->f_dentry->d_inode->i_size;
547 kml_recno = fset->fset_kml.fd_recno;
549 write_unlock(&fd->fd_lock);
550 return offset;
553 static int presto_kml_dispatch(struct presto_file_set *fset)
555 int rc = 0;
556 unsigned int kml_recno;
557 struct presto_log_fd *fd = &fset->fset_kml;
558 loff_t offset;
559 ENTRY;
561 write_lock(&fd->fd_lock);
563 /* Determine the largest valid offset, i.e. up until the first
564 * reservation held on the file. */
565 if ( !list_empty(&fd->fd_reservations) ) {
566 struct presto_reservation_data *rd;
567 rd = list_entry(fd->fd_reservations.next,
568 struct presto_reservation_data,
569 ri_list);
570 offset = rd->ri_offset;
571 kml_recno = rd->ri_recno;
572 } else {
573 offset = fd->fd_file->f_dentry->d_inode->i_size;
574 kml_recno = fset->fset_kml.fd_recno;
577 if ( kml_recno < fset->fset_lento_recno ) {
578 CERROR("presto_kml_dispatch: smoke is coming\n");
579 write_unlock(&fd->fd_lock);
580 EXIT;
581 return 0;
582 } else if ( kml_recno == fset->fset_lento_recno ) {
583 write_unlock(&fd->fd_lock);
584 EXIT;
585 return 0;
586 /* XXX add a further "if" here to delay the KML upcall */
587 #if 0
588 } else if ( kml_recno < fset->fset_lento_recno + 100) {
589 write_unlock(&fd->fd_lock);
590 EXIT;
591 return 0;
592 #endif
594 CDEBUG(D_PIOCTL, "fset: %s\n", fset->fset_name);
596 rc = izo_upc_kml(fset->fset_cache->cache_psdev->uc_minor,
597 fset->fset_lento_off, fset->fset_lento_recno,
598 offset + fset->fset_kml_logical_off, kml_recno,
599 fset->fset_name);
601 if ( rc ) {
602 write_unlock(&fd->fd_lock);
603 EXIT;
604 return rc;
607 fset->fset_lento_off = offset;
608 fset->fset_lento_recno = kml_recno;
609 write_unlock(&fd->fd_lock);
610 EXIT;
611 return 0;
614 int izo_lookup_file(struct presto_file_set *fset, char *path,
615 struct nameidata *nd)
617 int error = 0;
619 CDEBUG(D_CACHE, "looking up: %s\n", path);
621 error = path_lookup(path, LOOKUP_PARENT, nd);
622 if (error) {
623 EXIT;
624 return error;
627 return 0;
630 /* FIXME: this function is a mess of locking and error handling. There's got to
631 * be a better way. */
632 static int do_truncate_rename(struct presto_file_set *fset, char *oldname,
633 char *newname)
635 struct dentry *old_dentry, *new_dentry;
636 struct nameidata oldnd, newnd;
637 char *oldpath, *newpath;
638 int error;
640 ENTRY;
642 oldpath = izo_make_path(fset, oldname);
643 if (oldpath == NULL) {
644 EXIT;
645 return -ENOENT;
648 newpath = izo_make_path(fset, newname);
649 if (newpath == NULL) {
650 error = -ENOENT;
651 EXIT;
652 goto exit;
655 if ((error = izo_lookup_file(fset, oldpath, &oldnd)) != 0) {
656 EXIT;
657 goto exit1;
660 if ((error = izo_lookup_file(fset, newpath, &newnd)) != 0) {
661 EXIT;
662 goto exit2;
665 lock_rename(newnd.dentry, oldnd.dentry);
666 old_dentry = lookup_hash(&oldnd.last, oldnd.dentry);
667 error = PTR_ERR(old_dentry);
668 if (IS_ERR(old_dentry)) {
669 EXIT;
670 goto exit3;
672 error = -ENOENT;
673 if (!old_dentry->d_inode) {
674 EXIT;
675 goto exit4;
677 new_dentry = lookup_hash(&newnd.last, newnd.dentry);
678 error = PTR_ERR(new_dentry);
679 if (IS_ERR(new_dentry)) {
680 EXIT;
681 goto exit4;
685 extern int presto_rename(struct inode *old_dir,struct dentry *old_dentry,
686 struct inode *new_dir,struct dentry *new_dentry);
687 error = presto_rename(old_dentry->d_parent->d_inode, old_dentry,
688 new_dentry->d_parent->d_inode, new_dentry);
691 dput(new_dentry);
692 EXIT;
693 exit4:
694 dput(old_dentry);
695 exit3:
696 unlock_rename(newnd.dentry, oldnd.dentry);
697 path_release(&newnd);
698 exit2:
699 path_release(&oldnd);
700 exit1:
701 PRESTO_FREE(newpath, strlen(newpath) + 1);
702 exit:
703 PRESTO_FREE(oldpath, strlen(oldpath) + 1);
704 return error;
707 /* This function is called with the fset->fset_kml.fd_lock held */
708 int presto_finish_kml_truncate(struct presto_file_set *fset,
709 unsigned long int offset)
711 struct lento_vfs_context info;
712 void *handle;
713 struct file *f;
714 struct dentry *dentry;
715 int error = 0, len;
716 struct nameidata nd;
717 char *kmlpath = NULL, *smlpath = NULL;
718 ENTRY;
720 if (offset == 0) {
721 /* Lento couldn't do what it needed to; abort the truncation. */
722 fset->fset_kml.fd_truncating = 0;
723 EXIT;
724 return 0;
727 /* someone is about to write to the end of the KML; try again later. */
728 if ( !list_empty(&fset->fset_kml.fd_reservations) ) {
729 EXIT;
730 return -EAGAIN;
733 f = presto_copy_kml_tail(fset, offset);
734 if (IS_ERR(f)) {
735 EXIT;
736 return PTR_ERR(f);
739 /* In a single transaction:
741 * - unlink 'kml'
742 * - rename 'kml_tmp' to 'kml'
743 * - unlink 'sml'
744 * - rename 'sml_tmp' to 'sml'
745 * - rewrite the first record of last_rcvd with the new kml
746 * offset.
748 handle = presto_trans_start(fset, fset->fset_dentry->d_inode,
749 KML_OPCODE_KML_TRUNC);
750 if (IS_ERR(handle)) {
751 presto_release_space(fset->fset_cache, PRESTO_REQLOW);
752 CERROR("ERROR: presto_finish_kml_truncate: no space for transaction\n");
753 EXIT;
754 return -ENOMEM;
757 memset(&info, 0, sizeof(info));
758 info.flags = LENTO_FL_IGNORE_TIME;
760 kmlpath = izo_make_path(fset, "kml");
761 if (kmlpath == NULL) {
762 error = -ENOMEM;
763 CERROR("make_path failed: ENOMEM\n");
764 EXIT;
765 goto exit_commit;
768 if ((error = izo_lookup_file(fset, kmlpath, &nd)) != 0) {
769 CERROR("izo_lookup_file(kml) failed: %d.\n", error);
770 EXIT;
771 goto exit_commit;
773 down(&nd.dentry->d_inode->i_sem);
774 dentry = lookup_hash(&nd.last, nd.dentry);
775 error = PTR_ERR(dentry);
776 if (IS_ERR(dentry)) {
777 up(&nd.dentry->d_inode->i_sem);
778 path_release(&nd);
779 CERROR("lookup_hash failed\n");
780 EXIT;
781 goto exit_commit;
783 error = presto_do_unlink(fset, dentry->d_parent, dentry, &info);
784 dput(dentry);
785 up(&nd.dentry->d_inode->i_sem);
786 path_release(&nd);
788 if (error != 0) {
789 CERROR("presto_do_unlink(kml) failed: %d.\n", error);
790 EXIT;
791 goto exit_commit;
794 smlpath = izo_make_path(fset, "sml");
795 if (smlpath == NULL) {
796 error = -ENOMEM;
797 CERROR("make_path() failed: ENOMEM\n");
798 EXIT;
799 goto exit_commit;
802 if ((error = izo_lookup_file(fset, smlpath, &nd)) != 0) {
803 CERROR("izo_lookup_file(sml) failed: %d.\n", error);
804 EXIT;
805 goto exit_commit;
807 down(&nd.dentry->d_inode->i_sem);
808 dentry = lookup_hash(&nd.last, nd.dentry);
809 error = PTR_ERR(dentry);
810 if (IS_ERR(dentry)) {
811 up(&nd.dentry->d_inode->i_sem);
812 path_release(&nd);
813 CERROR("lookup_hash failed\n");
814 EXIT;
815 goto exit_commit;
817 error = presto_do_unlink(fset, dentry->d_parent, dentry, &info);
818 dput(dentry);
819 up(&nd.dentry->d_inode->i_sem);
820 path_release(&nd);
822 if (error != 0) {
823 CERROR("presto_do_unlink(sml) failed: %d.\n", error);
824 EXIT;
825 goto exit_commit;
828 error = do_truncate_rename(fset, "kml_tmp", "kml");
829 if (error != 0)
830 CERROR("do_truncate_rename(kml_tmp, kml) failed: %d\n", error);
831 error = do_truncate_rename(fset, "sml_tmp", "sml");
832 if (error != 0)
833 CERROR("do_truncate_rename(sml_tmp, sml) failed: %d\n", error);
835 /* Write a new 'last_rcvd' record with the new KML offset */
836 fset->fset_kml_logical_off += offset;
837 CDEBUG(D_CACHE, "new kml_logical_offset: %Lu\n",
838 fset->fset_kml_logical_off);
839 if (presto_write_kml_logical_offset(fset) != 0) {
840 CERROR("presto_write_kml_logical_offset failed\n");
843 presto_trans_commit(fset, handle);
845 /* Everything was successful, so swap the KML file descriptors */
846 filp_close(fset->fset_kml.fd_file, NULL);
847 fset->fset_kml.fd_file = f;
848 fset->fset_kml.fd_offset -= offset;
849 fset->fset_kml.fd_truncating = 0;
851 EXIT;
852 return 0;
854 exit_commit:
855 presto_trans_commit(fset, handle);
856 len = strlen("/.intermezzo/") + strlen(fset->fset_name) +strlen("sml");
857 if (kmlpath != NULL)
858 PRESTO_FREE(kmlpath, len);
859 if (smlpath != NULL)
860 PRESTO_FREE(smlpath, len);
861 return error;
864 /* structure of an extended log record:
866 buf-prefix buf-body [string1 [string2 [string3]]] buf-suffix
868 note: moves offset forward
870 static inline int presto_write_record(struct file *f, loff_t *off,
871 const char *buf, size_t size,
872 const char *string1, int len1,
873 const char *string2, int len2,
874 const char *string3, int len3)
876 size_t prefix_size;
877 int rc;
879 prefix_size = size - sizeof(struct kml_suffix);
880 rc = presto_fwrite(f, buf, prefix_size, off);
881 if ( rc != prefix_size ) {
882 CERROR("Write error!\n");
883 EXIT;
884 return -EIO;
887 if ( string1 && len1 ) {
888 rc = presto_fwrite(f, string1, len1, off);
889 if ( rc != len1 ) {
890 CERROR("Write error!\n");
891 EXIT;
892 return -EIO;
896 if ( string2 && len2 ) {
897 rc = presto_fwrite(f, string2, len2, off);
898 if ( rc != len2 ) {
899 CERROR("Write error!\n");
900 EXIT;
901 return -EIO;
905 if ( string3 && len3 ) {
906 rc = presto_fwrite(f, string3, len3, off);
907 if ( rc != len3 ) {
908 CERROR("Write error!\n");
909 EXIT;
910 return -EIO;
914 rc = presto_fwrite(f, buf + prefix_size,
915 sizeof(struct kml_suffix), off);
916 if ( rc != sizeof(struct kml_suffix) ) {
917 CERROR("Write error!\n");
918 EXIT;
919 return -EIO;
921 return 0;
926 * rec->size must be valid prior to calling this function.
928 * had to export this for branch_reinter in kml_reint.c
930 int presto_log(struct presto_file_set *fset, struct rec_info *rec,
931 const char *buf, size_t size,
932 const char *string1, int len1,
933 const char *string2, int len2,
934 const char *string3, int len3)
936 int rc;
937 struct presto_reservation_data rd;
938 loff_t offset;
939 struct presto_log_fd *fd;
940 struct kml_suffix *s;
941 int prefix_size;
943 ENTRY;
945 /* buf is NULL when no_journal is in effect */
946 if (!buf) {
947 EXIT;
948 return -EINVAL;
951 if (rec->is_kml) {
952 fd = &fset->fset_kml;
953 } else {
954 fd = &fset->fset_lml;
957 presto_reserve_record(fset, fd, rec, &rd);
959 if (rec->is_kml) {
960 if (rec->offset < fset->fset_kml_logical_off) {
961 CERROR("record with pre-trunc offset. tell phil.\n");
962 BUG();
964 offset = rec->offset - fset->fset_kml_logical_off;
965 } else {
966 offset = rec->offset;
969 /* now we know the record number */
970 prefix_size = size - sizeof(struct kml_suffix);
971 s = (struct kml_suffix *) (buf + prefix_size);
972 s->recno = cpu_to_le32(rec->recno);
974 rc = presto_write_record(fd->fd_file, &offset, buf, size,
975 string1, len1, string2, len2, string3, len3);
976 if (rc) {
977 CERROR("presto: error writing record to %s\n",
978 rec->is_kml ? "KML" : "LML");
979 return rc;
981 presto_release_record(fd, &rd);
983 rc = presto_kml_dispatch(fset);
985 EXIT;
986 return rc;
989 /* read from the record at tail */
990 static int presto_last_record(struct presto_log_fd *fd, loff_t *size,
991 loff_t *tail_offset, __u32 *recno, loff_t tail)
993 struct kml_suffix suffix;
994 int rc;
995 loff_t zeroes;
997 *recno = 0;
998 *tail_offset = 0;
999 *size = 0;
1001 if (tail < sizeof(struct kml_prefix_hdr) + sizeof(suffix)) {
1002 EXIT;
1003 return 0;
1006 zeroes = tail - sizeof(int);
1007 while ( zeroes >= 0 ) {
1008 int data;
1009 rc = presto_fread(fd->fd_file, (char *)&data, sizeof(data),
1010 &zeroes);
1011 if ( rc != sizeof(data) ) {
1012 rc = -EIO;
1013 return rc;
1015 if (data)
1016 break;
1017 zeroes -= 2 * sizeof(data);
1020 /* zeroes at the begining of file. this is needed to prevent
1021 presto_fread errors -SHP
1023 if (zeroes <= 0) return 0;
1025 zeroes -= sizeof(suffix) + sizeof(int);
1026 rc = presto_fread(fd->fd_file, (char *)&suffix, sizeof(suffix), &zeroes);
1027 if ( rc != sizeof(suffix) ) {
1028 EXIT;
1029 return rc;
1031 if ( suffix.len > 500 ) {
1032 CERROR("InterMezzo: Warning long record tail at %ld, rec tail_offset at %ld (size %d)\n",
1033 (long) zeroes, (long)*tail_offset, suffix.len);
1036 *recno = suffix.recno;
1037 *size = suffix.len;
1038 *tail_offset = zeroes;
1039 return 0;
1042 static int izo_kml_last_recno(struct presto_log_fd *logfd)
1044 int rc;
1045 loff_t size;
1046 loff_t tail_offset;
1047 int recno;
1048 loff_t tail = logfd->fd_file->f_dentry->d_inode->i_size;
1050 rc = presto_last_record(logfd, &size, &tail_offset, &recno, tail);
1051 if (rc != 0) {
1052 EXIT;
1053 return rc;
1056 logfd->fd_offset = tail_offset;
1057 logfd->fd_recno = recno;
1058 CDEBUG(D_JOURNAL, "setting fset_kml->fd_recno to %d, offset %Ld\n",
1059 recno, tail_offset);
1060 EXIT;
1061 return 0;
1064 struct file *izo_log_open(struct presto_file_set *fset, char *name, int flags)
1066 struct presto_cache *cache = fset->fset_cache;
1067 struct file *f;
1068 int error;
1069 ENTRY;
1071 f = izo_fset_open(fset, name, flags, 0644);
1072 error = PTR_ERR(f);
1073 if (IS_ERR(f)) {
1074 EXIT;
1075 return f;
1078 error = -EINVAL;
1079 if ( cache != presto_get_cache(f->f_dentry->d_inode) ) {
1080 CERROR("InterMezzo: %s cache does not match fset cache!\n",name);
1081 fset->fset_kml.fd_file = NULL;
1082 filp_close(f, NULL);
1083 f = NULL;
1084 EXIT;
1085 return f;
1088 if (cache->cache_filter && cache->cache_filter->o_trops &&
1089 cache->cache_filter->o_trops->tr_journal_data) {
1090 cache->cache_filter->o_trops->tr_journal_data
1091 (f->f_dentry->d_inode);
1092 } else {
1093 CERROR("InterMezzo WARNING: no file data logging!\n");
1096 EXIT;
1098 return f;
1101 int izo_init_kml_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
1103 int error = 0;
1104 struct file *f;
1106 ENTRY;
1107 if (logfd->fd_file) {
1108 CDEBUG(D_INODE, "fset already has KML open\n");
1109 EXIT;
1110 return 0;
1113 logfd->fd_lock = RW_LOCK_UNLOCKED;
1114 INIT_LIST_HEAD(&logfd->fd_reservations);
1115 f = izo_log_open(fset, "kml", O_RDWR | O_CREAT);
1116 if (IS_ERR(f)) {
1117 error = PTR_ERR(f);
1118 return error;
1121 logfd->fd_file = f;
1122 error = izo_kml_last_recno(logfd);
1124 if (error) {
1125 logfd->fd_file = NULL;
1126 filp_close(f, NULL);
1127 CERROR("InterMezzo: IO error in KML of fset %s\n",
1128 fset->fset_name);
1129 EXIT;
1130 return error;
1132 fset->fset_lento_off = logfd->fd_offset;
1133 fset->fset_lento_recno = logfd->fd_recno;
1135 EXIT;
1136 return error;
1139 int izo_init_last_rcvd_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
1141 int error = 0;
1142 struct file *f;
1143 struct rec_info recinfo;
1145 ENTRY;
1146 if (logfd->fd_file != NULL) {
1147 CDEBUG(D_INODE, "fset already has last_rcvd open\n");
1148 EXIT;
1149 return 0;
1152 logfd->fd_lock = RW_LOCK_UNLOCKED;
1153 INIT_LIST_HEAD(&logfd->fd_reservations);
1154 f = izo_log_open(fset, "last_rcvd", O_RDWR | O_CREAT);
1155 if (IS_ERR(f)) {
1156 error = PTR_ERR(f);
1157 return error;
1160 logfd->fd_file = f;
1161 logfd->fd_offset = f->f_dentry->d_inode->i_size;
1163 error = izo_rep_cache_init(fset);
1165 if (presto_read_kml_logical_offset(&recinfo, fset) == 0) {
1166 fset->fset_kml_logical_off = recinfo.offset;
1167 } else {
1168 /* The 'last_rcvd' file doesn't contain a kml offset record,
1169 * probably because we just created 'last_rcvd'. Write one. */
1170 fset->fset_kml_logical_off = 0;
1171 presto_write_kml_logical_offset(fset);
1174 EXIT;
1175 return error;
1178 int izo_init_lml_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
1180 int error = 0;
1181 struct file *f;
1183 ENTRY;
1184 if (logfd->fd_file) {
1185 CDEBUG(D_INODE, "fset already has lml open\n");
1186 EXIT;
1187 return 0;
1190 logfd->fd_lock = RW_LOCK_UNLOCKED;
1191 INIT_LIST_HEAD(&logfd->fd_reservations);
1192 f = izo_log_open(fset, "lml", O_RDWR | O_CREAT);
1193 if (IS_ERR(f)) {
1194 error = PTR_ERR(f);
1195 return error;
1198 logfd->fd_file = f;
1199 logfd->fd_offset = f->f_dentry->d_inode->i_size;
1201 EXIT;
1202 return error;
1205 /* Get the KML-offset record from the last_rcvd file */
1206 int presto_read_kml_logical_offset(struct rec_info *recinfo,
1207 struct presto_file_set *fset)
1209 loff_t off;
1210 struct izo_rcvd_rec rec;
1211 char uuid[16] = {0};
1213 off = izo_rcvd_get(&rec, fset, uuid);
1214 if (off < 0)
1215 return -1;
1217 recinfo->offset = rec.lr_local_offset;
1218 return 0;
1221 int presto_write_kml_logical_offset(struct presto_file_set *fset)
1223 loff_t rc;
1224 struct izo_rcvd_rec rec;
1225 char uuid[16] = {0};
1227 rc = izo_rcvd_get(&rec, fset, uuid);
1228 if (rc < 0)
1229 memset(&rec, 0, sizeof(rec));
1231 rec.lr_local_offset =
1232 cpu_to_le64(fset->fset_kml_logical_off);
1234 return izo_rcvd_write(fset, &rec);
1237 struct file * presto_copy_kml_tail(struct presto_file_set *fset,
1238 unsigned long int start)
1240 struct file *f;
1241 int len;
1242 loff_t read_off, write_off, bytes;
1244 ENTRY;
1246 /* Copy the tail of 'kml' to 'kml_tmp' */
1247 f = izo_log_open(fset, "kml_tmp", O_RDWR);
1248 if (IS_ERR(f)) {
1249 EXIT;
1250 return f;
1253 write_off = 0;
1254 read_off = start;
1255 bytes = fset->fset_kml.fd_offset - start;
1256 while (bytes > 0) {
1257 char buf[4096];
1258 int toread;
1260 if (bytes > sizeof(buf))
1261 toread = sizeof(buf);
1262 else
1263 toread = bytes;
1265 len = presto_fread(fset->fset_kml.fd_file, buf, toread,
1266 &read_off);
1267 if (len <= 0)
1268 break;
1270 if (presto_fwrite(f, buf, len, &write_off) != len) {
1271 filp_close(f, NULL);
1272 EXIT;
1273 return ERR_PTR(-EIO);
1276 bytes -= len;
1279 EXIT;
1280 return f;
1284 /* LML records here */
1285 /* this writes an LML record to the LML file (rec->is_kml =0) */
1286 int presto_write_lml_close(struct rec_info *rec,
1287 struct presto_file_set *fset,
1288 struct file *file,
1289 __u64 remote_ino,
1290 __u64 remote_generation,
1291 struct presto_version *remote_version,
1292 struct presto_version *new_file_ver)
1294 int opcode = KML_OPCODE_CLOSE;
1295 char *buffer;
1296 struct dentry *dentry = file->f_dentry;
1297 __u64 ino;
1298 __u32 pathlen;
1299 char *path;
1300 __u32 generation;
1301 int size;
1302 char *logrecord;
1303 char record[292];
1304 struct dentry *root;
1305 int error;
1307 ENTRY;
1309 if ( presto_no_journal(fset) ) {
1310 EXIT;
1311 return 0;
1313 root = fset->fset_dentry;
1315 BUFF_ALLOC(buffer, NULL);
1316 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1317 CDEBUG(D_INODE, "Path: %s\n", path);
1318 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1319 ino = cpu_to_le64(dentry->d_inode->i_ino);
1320 generation = cpu_to_le32(dentry->d_inode->i_generation);
1321 size = sizeof(__u32) * current->ngroups +
1322 sizeof(struct kml_prefix_hdr) + sizeof(*new_file_ver) +
1323 sizeof(ino) + sizeof(generation) + sizeof(pathlen) +
1324 sizeof(remote_ino) + sizeof(remote_generation) +
1325 sizeof(remote_version) + sizeof(rec->offset) +
1326 sizeof(struct kml_suffix);
1328 if ( size > sizeof(record) )
1329 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1331 rec->is_kml = 0;
1332 rec->size = size + size_round(le32_to_cpu(pathlen));
1334 logrecord = journal_log_prefix(record, opcode, rec);
1335 logrecord = log_version(logrecord, new_file_ver);
1336 logrecord = logit(logrecord, &ino, sizeof(ino));
1337 logrecord = logit(logrecord, &generation, sizeof(generation));
1338 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1339 logrecord = logit(logrecord, &remote_ino, sizeof(remote_ino));
1340 logrecord = logit(logrecord, &remote_generation,
1341 sizeof(remote_generation));
1342 logrecord = log_version(logrecord, remote_version);
1343 logrecord = logit(logrecord, &rec->offset, sizeof(rec->offset));
1344 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1346 error = presto_log(fset, rec, record, size,
1347 path, size_round(le32_to_cpu(pathlen)),
1348 NULL, 0, NULL, 0);
1350 BUFF_FREE(buffer);
1352 EXIT;
1353 return error;
1357 * Check if the given record is at the end of the file. If it is, truncate
1358 * the lml to the record's offset, removing it. Repeat on prior record,
1359 * until we reach an active record or a reserved record (as defined by the
1360 * reservations list).
1362 static int presto_truncate_lml_tail(struct presto_file_set *fset)
1364 loff_t lml_tail;
1365 loff_t lml_last_rec;
1366 loff_t lml_last_recsize;
1367 loff_t local_offset;
1368 int recno;
1369 struct kml_prefix_hdr prefix;
1370 struct inode *inode = fset->fset_lml.fd_file->f_dentry->d_inode;
1371 void *handle;
1372 int rc;
1374 ENTRY;
1375 /* If someone else is already truncating the LML, return. */
1376 write_lock(&fset->fset_lml.fd_lock);
1377 if (fset->fset_lml.fd_truncating == 1 ) {
1378 write_unlock(&fset->fset_lml.fd_lock);
1379 EXIT;
1380 return 0;
1382 /* someone is about to write to the end of the LML */
1383 if ( !list_empty(&fset->fset_lml.fd_reservations) ) {
1384 write_unlock(&fset->fset_lml.fd_lock);
1385 EXIT;
1386 return 0;
1388 lml_tail = fset->fset_lml.fd_file->f_dentry->d_inode->i_size;
1389 /* Nothing to truncate?*/
1390 if (lml_tail == 0) {
1391 write_unlock(&fset->fset_lml.fd_lock);
1392 EXIT;
1393 return 0;
1395 fset->fset_lml.fd_truncating = 1;
1396 write_unlock(&fset->fset_lml.fd_lock);
1398 presto_last_record(&fset->fset_lml, &lml_last_recsize,
1399 &lml_last_rec, &recno, lml_tail);
1400 /* Do we have a record to check? If not we have zeroes at the
1401 beginning of the file. -SHP
1403 if (lml_last_recsize != 0) {
1404 local_offset = lml_last_rec - lml_last_recsize;
1405 rc = presto_fread(fset->fset_lml.fd_file, (char *)&prefix,
1406 sizeof(prefix), &local_offset);
1407 if (rc != sizeof(prefix)) {
1408 EXIT;
1409 goto tr_out;
1412 if ( prefix.opcode != KML_OPCODE_NOOP ) {
1413 EXIT;
1414 rc = 0;
1415 /* We may have zeroes at the end of the file, should
1416 we clear them out? -SHP
1418 goto tr_out;
1420 } else
1421 lml_last_rec=0;
1423 handle = presto_trans_start(fset, inode, KML_OPCODE_TRUNC);
1424 if ( IS_ERR(handle) ) {
1425 EXIT;
1426 rc = -ENOMEM;
1427 goto tr_out;
1430 rc = izo_do_truncate(fset, fset->fset_lml.fd_file->f_dentry,
1431 lml_last_rec - lml_last_recsize, lml_tail);
1432 presto_trans_commit(fset, handle);
1433 if ( rc == 0 ) {
1434 rc = 1;
1436 EXIT;
1438 tr_out:
1439 CDEBUG(D_JOURNAL, "rc = %d\n", rc);
1440 write_lock(&fset->fset_lml.fd_lock);
1441 fset->fset_lml.fd_truncating = 0;
1442 write_unlock(&fset->fset_lml.fd_lock);
1443 return rc;
1446 int presto_truncate_lml(struct presto_file_set *fset)
1448 int rc;
1449 ENTRY;
1451 while ( (rc = presto_truncate_lml_tail(fset)) > 0);
1452 if ( rc < 0 && rc != -EALREADY) {
1453 CERROR("truncate_lml error %d\n", rc);
1455 EXIT;
1456 return rc;
1459 int presto_clear_lml_close(struct presto_file_set *fset, loff_t lml_offset)
1461 int rc;
1462 struct kml_prefix_hdr record;
1463 loff_t offset = lml_offset;
1465 ENTRY;
1467 if ( presto_no_journal(fset) ) {
1468 EXIT;
1469 return 0;
1472 CDEBUG(D_JOURNAL, "reading prefix: off %ld, size %d\n",
1473 (long)lml_offset, sizeof(record));
1474 rc = presto_fread(fset->fset_lml.fd_file, (char *)&record,
1475 sizeof(record), &offset);
1477 if ( rc != sizeof(record) ) {
1478 CERROR("presto: clear_lml io error %d\n", rc);
1479 EXIT;
1480 return -EIO;
1483 /* overwrite the prefix */
1484 CDEBUG(D_JOURNAL, "overwriting prefix: off %ld\n", (long)lml_offset);
1485 record.opcode = KML_OPCODE_NOOP;
1486 offset = lml_offset;
1487 /* note: this does just a single transaction in the cache */
1488 rc = presto_fwrite(fset->fset_lml.fd_file, (char *)(&record),
1489 sizeof(record), &offset);
1490 if ( rc != sizeof(record) ) {
1491 EXIT;
1492 return -EIO;
1495 EXIT;
1496 return 0;
1501 /* now a journal function for every operation */
1503 int presto_journal_setattr(struct rec_info *rec, struct presto_file_set *fset,
1504 struct dentry *dentry, struct presto_version *old_ver,
1505 struct izo_rollback_data *rb, struct iattr *iattr)
1507 int opcode = KML_OPCODE_SETATTR;
1508 char *buffer, *path, *logrecord, record[316];
1509 struct dentry *root;
1510 __u32 uid, gid, mode, valid, flags, pathlen;
1511 __u64 fsize, mtime, ctime;
1512 int error, size;
1514 ENTRY;
1515 if ( presto_no_journal(fset) ) {
1516 EXIT;
1517 return 0;
1520 if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0)
1521 || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
1522 EXIT;
1523 return 0;
1526 root = fset->fset_dentry;
1528 BUFF_ALLOC(buffer, NULL);
1529 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1530 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1531 size = sizeof(__u32) * current->ngroups +
1532 sizeof(struct kml_prefix_hdr) + sizeof(*old_ver) +
1533 sizeof(valid) + sizeof(mode) + sizeof(uid) + sizeof(gid) +
1534 sizeof(fsize) + sizeof(mtime) + sizeof(ctime) + sizeof(flags) +
1535 sizeof(pathlen) + sizeof(*rb) + sizeof(struct kml_suffix);
1537 if ( size > sizeof(record) )
1538 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1540 /* Only journal one kind of mtime, and not atime at all. Also don't
1541 * journal bogus data in iattr, to make the journal more compressible.
1543 if (iattr->ia_valid & ATTR_MTIME_SET)
1544 iattr->ia_valid = iattr->ia_valid | ATTR_MTIME;
1545 valid = cpu_to_le32(iattr->ia_valid & ~(ATTR_ATIME | ATTR_MTIME_SET |
1546 ATTR_ATIME_SET));
1547 mode = iattr->ia_valid & ATTR_MODE ? cpu_to_le32(iattr->ia_mode): 0;
1548 uid = iattr->ia_valid & ATTR_UID ? cpu_to_le32(iattr->ia_uid): 0;
1549 gid = iattr->ia_valid & ATTR_GID ? cpu_to_le32(iattr->ia_gid): 0;
1550 fsize = iattr->ia_valid & ATTR_SIZE ? cpu_to_le64(iattr->ia_size): 0;
1551 mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime.tv_sec): 0;
1552 ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime.tv_sec): 0;
1553 flags = iattr->ia_valid & ATTR_ATTR_FLAG ?
1554 cpu_to_le32(iattr->ia_attr_flags): 0;
1556 rec->is_kml = 1;
1557 rec->size = size + size_round(le32_to_cpu(pathlen));
1559 logrecord = journal_log_prefix(record, opcode, rec);
1560 logrecord = log_version(logrecord, old_ver);
1561 logrecord = logit(logrecord, &valid, sizeof(valid));
1562 logrecord = logit(logrecord, &mode, sizeof(mode));
1563 logrecord = logit(logrecord, &uid, sizeof(uid));
1564 logrecord = logit(logrecord, &gid, sizeof(gid));
1565 logrecord = logit(logrecord, &fsize, sizeof(fsize));
1566 logrecord = logit(logrecord, &mtime, sizeof(mtime));
1567 logrecord = logit(logrecord, &ctime, sizeof(ctime));
1568 logrecord = logit(logrecord, &flags, sizeof(flags));
1569 logrecord = log_rollback(logrecord, rb);
1570 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1571 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1573 error = presto_log(fset, rec, record, size,
1574 path, size_round(le32_to_cpu(pathlen)),
1575 NULL, 0, NULL, 0);
1577 BUFF_FREE(buffer);
1578 EXIT;
1579 return error;
1582 int presto_get_fileid(int minor, struct presto_file_set *fset,
1583 struct dentry *dentry)
1585 int opcode = KML_OPCODE_GET_FILEID;
1586 struct rec_info rec;
1587 char *buffer, *path, *logrecord, record[4096]; /*include path*/
1588 struct dentry *root;
1589 __u32 uid, gid, pathlen;
1590 int error, size;
1591 struct kml_suffix *suffix;
1593 ENTRY;
1595 root = fset->fset_dentry;
1597 uid = cpu_to_le32(dentry->d_inode->i_uid);
1598 gid = cpu_to_le32(dentry->d_inode->i_gid);
1599 BUFF_ALLOC(buffer, NULL);
1600 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1601 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1602 size = sizeof(__u32) * current->ngroups +
1603 sizeof(struct kml_prefix_hdr) + sizeof(pathlen) +
1604 size_round(le32_to_cpu(pathlen)) +
1605 sizeof(struct kml_suffix);
1607 CDEBUG(D_FILE, "kml size: %d\n", size);
1608 if ( size > sizeof(record) )
1609 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1611 memset(&rec, 0, sizeof(rec));
1612 rec.is_kml = 1;
1613 rec.size = size;
1615 logrecord = journal_log_prefix(record, opcode, &rec);
1616 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1617 logrecord = logit(logrecord, path, size_round(le32_to_cpu(pathlen)));
1618 suffix = (struct kml_suffix *)logrecord;
1619 logrecord = journal_log_suffix(logrecord, record, fset, dentry, &rec);
1620 /* journal_log_suffix expects journal_log to set this */
1621 suffix->recno = 0;
1623 CDEBUG(D_FILE, "actual kml size: %d\n", logrecord - record);
1624 CDEBUG(D_FILE, "get fileid: uid %d, gid %d, path: %s\n", uid, gid,path);
1626 error = izo_upc_get_fileid(minor, size, record,
1627 size_round(le32_to_cpu(pathlen)), path,
1628 fset->fset_name);
1630 BUFF_FREE(buffer);
1631 EXIT;
1632 return error;
1635 int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset,
1636 struct dentry *dentry,
1637 struct presto_version *tgt_dir_ver,
1638 struct presto_version *new_file_ver, int mode)
1640 int opcode = KML_OPCODE_CREATE;
1641 char *buffer, *path, *logrecord, record[292];
1642 struct dentry *root;
1643 __u32 uid, gid, lmode, pathlen;
1644 int error, size;
1646 ENTRY;
1647 if ( presto_no_journal(fset) ) {
1648 EXIT;
1649 return 0;
1652 root = fset->fset_dentry;
1654 uid = cpu_to_le32(dentry->d_inode->i_uid);
1655 gid = cpu_to_le32(dentry->d_inode->i_gid);
1656 lmode = cpu_to_le32(mode);
1658 BUFF_ALLOC(buffer, NULL);
1659 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1660 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1661 size = sizeof(__u32) * current->ngroups +
1662 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1663 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
1664 sizeof(struct kml_suffix);
1666 if ( size > sizeof(record) )
1667 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1669 rec->is_kml = 1;
1670 rec->size = size + size_round(le32_to_cpu(pathlen));
1672 logrecord = journal_log_prefix(record, opcode, rec);
1673 logrecord = log_version(logrecord, tgt_dir_ver);
1674 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1675 logrecord = log_version(logrecord, new_file_ver);
1676 logrecord = logit(logrecord, &lmode, sizeof(lmode));
1677 logrecord = logit(logrecord, &uid, sizeof(uid));
1678 logrecord = logit(logrecord, &gid, sizeof(gid));
1679 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1680 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1682 error = presto_log(fset, rec, record, size,
1683 path, size_round(le32_to_cpu(pathlen)),
1684 NULL, 0, NULL, 0);
1686 BUFF_FREE(buffer);
1687 EXIT;
1688 return error;
1691 int presto_journal_symlink(struct rec_info *rec, struct presto_file_set *fset,
1692 struct dentry *dentry, const char *target,
1693 struct presto_version *tgt_dir_ver,
1694 struct presto_version *new_link_ver)
1696 int opcode = KML_OPCODE_SYMLINK;
1697 char *buffer, *path, *logrecord, record[292];
1698 struct dentry *root;
1699 __u32 uid, gid, pathlen;
1700 __u32 targetlen = cpu_to_le32(strlen(target));
1701 int error, size;
1703 ENTRY;
1704 if ( presto_no_journal(fset) ) {
1705 EXIT;
1706 return 0;
1709 root = fset->fset_dentry;
1711 uid = cpu_to_le32(dentry->d_inode->i_uid);
1712 gid = cpu_to_le32(dentry->d_inode->i_gid);
1714 BUFF_ALLOC(buffer, NULL);
1715 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1716 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1717 size = sizeof(__u32) * current->ngroups +
1718 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1719 sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
1720 sizeof(targetlen) + sizeof(struct kml_suffix);
1722 if ( size > sizeof(record) )
1723 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1725 rec->is_kml = 1;
1726 rec->size = size + size_round(le32_to_cpu(pathlen)) +
1727 size_round(le32_to_cpu(targetlen));
1729 logrecord = journal_log_prefix(record, opcode, rec);
1730 logrecord = log_version(logrecord, tgt_dir_ver);
1731 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1732 logrecord = log_version(logrecord, new_link_ver);
1733 logrecord = logit(logrecord, &uid, sizeof(uid));
1734 logrecord = logit(logrecord, &gid, sizeof(gid));
1735 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1736 logrecord = logit(logrecord, &targetlen, sizeof(targetlen));
1737 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1739 error = presto_log(fset, rec, record, size,
1740 path, size_round(le32_to_cpu(pathlen)),
1741 target, size_round(le32_to_cpu(targetlen)),
1742 NULL, 0);
1744 BUFF_FREE(buffer);
1745 EXIT;
1746 return error;
1749 int presto_journal_mkdir(struct rec_info *rec, struct presto_file_set *fset,
1750 struct dentry *dentry,
1751 struct presto_version *tgt_dir_ver,
1752 struct presto_version *new_dir_ver, int mode)
1754 int opcode = KML_OPCODE_MKDIR;
1755 char *buffer, *path, *logrecord, record[292];
1756 struct dentry *root;
1757 __u32 uid, gid, lmode, pathlen;
1758 int error, size;
1760 ENTRY;
1761 if ( presto_no_journal(fset) ) {
1762 EXIT;
1763 return 0;
1766 root = fset->fset_dentry;
1768 uid = cpu_to_le32(dentry->d_inode->i_uid);
1769 gid = cpu_to_le32(dentry->d_inode->i_gid);
1770 lmode = cpu_to_le32(mode);
1772 BUFF_ALLOC(buffer, NULL);
1773 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1774 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1775 size = sizeof(__u32) * current->ngroups +
1776 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1777 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
1778 sizeof(struct kml_suffix);
1780 if ( size > sizeof(record) )
1781 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1783 rec->is_kml = 1;
1784 rec->size = size + size_round(le32_to_cpu(pathlen));
1785 logrecord = journal_log_prefix(record, opcode, rec);
1787 logrecord = log_version(logrecord, tgt_dir_ver);
1788 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1789 logrecord = log_version(logrecord, new_dir_ver);
1790 logrecord = logit(logrecord, &lmode, sizeof(lmode));
1791 logrecord = logit(logrecord, &uid, sizeof(uid));
1792 logrecord = logit(logrecord, &gid, sizeof(gid));
1793 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1794 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1796 error = presto_log(fset, rec, record, size,
1797 path, size_round(le32_to_cpu(pathlen)),
1798 NULL, 0, NULL, 0);
1800 BUFF_FREE(buffer);
1801 EXIT;
1802 return error;
1807 presto_journal_rmdir(struct rec_info *rec, struct presto_file_set *fset,
1808 struct dentry *dir, struct presto_version *tgt_dir_ver,
1809 struct presto_version *old_dir_ver,
1810 struct izo_rollback_data *rb, int len, const char *name)
1812 int opcode = KML_OPCODE_RMDIR;
1813 char *buffer, *path, *logrecord, record[316];
1814 __u32 pathlen, llen;
1815 struct dentry *root;
1816 int error, size;
1818 ENTRY;
1819 if ( presto_no_journal(fset) ) {
1820 EXIT;
1821 return 0;
1824 root = fset->fset_dentry;
1826 llen = cpu_to_le32(len);
1827 BUFF_ALLOC(buffer, NULL);
1828 path = presto_path(dir, root, buffer, PAGE_SIZE);
1829 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1830 size = sizeof(__u32) * current->ngroups +
1831 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1832 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
1833 sizeof(struct kml_suffix);
1835 if ( size > sizeof(record) )
1836 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1838 CDEBUG(D_JOURNAL, "path: %s (%d), name: %s (%d), size %d\n",
1839 path, pathlen, name, len, size);
1841 rec->is_kml = 1;
1842 rec->size = size + size_round(le32_to_cpu(pathlen)) +
1843 size_round(len);
1845 logrecord = journal_log_prefix(record, opcode, rec);
1846 logrecord = log_version(logrecord, tgt_dir_ver);
1847 logrecord = log_dentry_version(logrecord, dir);
1848 logrecord = log_version(logrecord, old_dir_ver);
1849 logrecord = logit(logrecord, rb, sizeof(*rb));
1850 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1851 logrecord = logit(logrecord, &llen, sizeof(llen));
1852 logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
1853 error = presto_log(fset, rec, record, size,
1854 path, size_round(le32_to_cpu(pathlen)),
1855 name, size_round(len),
1856 NULL, 0);
1858 BUFF_FREE(buffer);
1859 EXIT;
1860 return error;
1865 presto_journal_mknod(struct rec_info *rec, struct presto_file_set *fset,
1866 struct dentry *dentry, struct presto_version *tgt_dir_ver,
1867 struct presto_version *new_node_ver, int mode,
1868 int dmajor, int dminor )
1870 int opcode = KML_OPCODE_MKNOD;
1871 char *buffer, *path, *logrecord, record[292];
1872 struct dentry *root;
1873 __u32 uid, gid, lmode, lmajor, lminor, pathlen;
1874 int error, size;
1876 ENTRY;
1877 if ( presto_no_journal(fset) ) {
1878 EXIT;
1879 return 0;
1882 root = fset->fset_dentry;
1884 uid = cpu_to_le32(dentry->d_inode->i_uid);
1885 gid = cpu_to_le32(dentry->d_inode->i_gid);
1886 lmode = cpu_to_le32(mode);
1887 lmajor = cpu_to_le32(dmajor);
1888 lminor = cpu_to_le32(dminor);
1890 BUFF_ALLOC(buffer, NULL);
1891 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1892 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1893 size = sizeof(__u32) * current->ngroups +
1894 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1895 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(lmajor) +
1896 sizeof(lminor) + sizeof(pathlen) +
1897 sizeof(struct kml_suffix);
1899 if ( size > sizeof(record) )
1900 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1902 rec->is_kml = 1;
1903 rec->size = size + size_round(le32_to_cpu(pathlen));
1905 logrecord = journal_log_prefix(record, opcode, rec);
1906 logrecord = log_version(logrecord, tgt_dir_ver);
1907 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1908 logrecord = log_version(logrecord, new_node_ver);
1909 logrecord = logit(logrecord, &lmode, sizeof(lmode));
1910 logrecord = logit(logrecord, &uid, sizeof(uid));
1911 logrecord = logit(logrecord, &gid, sizeof(gid));
1912 logrecord = logit(logrecord, &lmajor, sizeof(lmajor));
1913 logrecord = logit(logrecord, &lminor, sizeof(lminor));
1914 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1915 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1917 error = presto_log(fset, rec, record, size,
1918 path, size_round(le32_to_cpu(pathlen)),
1919 NULL, 0, NULL, 0);
1921 BUFF_FREE(buffer);
1922 EXIT;
1923 return error;
1927 presto_journal_link(struct rec_info *rec, struct presto_file_set *fset,
1928 struct dentry *src, struct dentry *tgt,
1929 struct presto_version *tgt_dir_ver,
1930 struct presto_version *new_link_ver)
1932 int opcode = KML_OPCODE_LINK;
1933 char *buffer, *srcbuffer, *path, *srcpath, *logrecord, record[292];
1934 __u32 pathlen, srcpathlen;
1935 struct dentry *root;
1936 int error, size;
1938 ENTRY;
1939 if ( presto_no_journal(fset) ) {
1940 EXIT;
1941 return 0;
1944 root = fset->fset_dentry;
1946 BUFF_ALLOC(srcbuffer, NULL);
1947 srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
1948 srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
1950 BUFF_ALLOC(buffer, srcbuffer);
1951 path = presto_path(tgt, root, buffer, PAGE_SIZE);
1952 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1953 size = sizeof(__u32) * current->ngroups +
1954 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1955 sizeof(srcpathlen) + sizeof(pathlen) +
1956 sizeof(struct kml_suffix);
1958 if ( size > sizeof(record) )
1959 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1961 rec->is_kml = 1;
1962 rec->size = size + size_round(le32_to_cpu(pathlen)) +
1963 size_round(le32_to_cpu(srcpathlen));
1965 logrecord = journal_log_prefix(record, opcode, rec);
1966 logrecord = log_version(logrecord, tgt_dir_ver);
1967 logrecord = log_dentry_version(logrecord, tgt->d_parent);
1968 logrecord = log_version(logrecord, new_link_ver);
1969 logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
1970 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1971 logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
1973 error = presto_log(fset, rec, record, size,
1974 srcpath, size_round(le32_to_cpu(srcpathlen)),
1975 path, size_round(le32_to_cpu(pathlen)),
1976 NULL, 0);
1978 BUFF_FREE(srcbuffer);
1979 BUFF_FREE(buffer);
1980 EXIT;
1981 return error;
1985 int presto_journal_rename(struct rec_info *rec, struct presto_file_set *fset,
1986 struct dentry *src, struct dentry *tgt,
1987 struct presto_version *src_dir_ver,
1988 struct presto_version *tgt_dir_ver)
1990 int opcode = KML_OPCODE_RENAME;
1991 char *buffer, *srcbuffer, *path, *srcpath, *logrecord, record[292];
1992 __u32 pathlen, srcpathlen;
1993 struct dentry *root;
1994 int error, size;
1996 ENTRY;
1997 if ( presto_no_journal(fset) ) {
1998 EXIT;
1999 return 0;
2002 root = fset->fset_dentry;
2004 BUFF_ALLOC(srcbuffer, NULL);
2005 srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
2006 srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
2008 BUFF_ALLOC(buffer, srcbuffer);
2009 path = presto_path(tgt, root, buffer, PAGE_SIZE);
2010 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
2011 size = sizeof(__u32) * current->ngroups +
2012 sizeof(struct kml_prefix_hdr) + 4 * sizeof(*src_dir_ver) +
2013 sizeof(srcpathlen) + sizeof(pathlen) +
2014 sizeof(struct kml_suffix);
2016 if ( size > sizeof(record) )
2017 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2019 rec->is_kml = 1;
2020 rec->size = size + size_round(le32_to_cpu(pathlen)) +
2021 size_round(le32_to_cpu(srcpathlen));
2023 logrecord = journal_log_prefix(record, opcode, rec);
2024 logrecord = log_version(logrecord, src_dir_ver);
2025 logrecord = log_dentry_version(logrecord, src->d_parent);
2026 logrecord = log_version(logrecord, tgt_dir_ver);
2027 logrecord = log_dentry_version(logrecord, tgt->d_parent);
2028 logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
2029 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2030 logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
2032 error = presto_log(fset, rec, record, size,
2033 srcpath, size_round(le32_to_cpu(srcpathlen)),
2034 path, size_round(le32_to_cpu(pathlen)),
2035 NULL, 0);
2037 BUFF_FREE(buffer);
2038 BUFF_FREE(srcbuffer);
2039 EXIT;
2040 return error;
2043 int presto_journal_unlink(struct rec_info *rec, struct presto_file_set *fset,
2044 struct dentry *dir, struct presto_version *tgt_dir_ver,
2045 struct presto_version *old_file_ver,
2046 struct izo_rollback_data *rb, struct dentry *dentry,
2047 char *old_target, int old_targetlen)
2049 int opcode = KML_OPCODE_UNLINK;
2050 char *buffer, *path, *logrecord, record[316];
2051 const char *name;
2052 __u32 pathlen, llen;
2053 struct dentry *root;
2054 int error, size, len;
2056 ENTRY;
2057 if ( presto_no_journal(fset) ) {
2058 EXIT;
2059 return 0;
2062 root = fset->fset_dentry;
2064 name = dentry->d_name.name;
2065 len = dentry->d_name.len;
2067 llen = cpu_to_le32(len);
2068 BUFF_ALLOC(buffer, NULL);
2069 path = presto_path(dir, root, buffer, PAGE_SIZE);
2070 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
2071 size = sizeof(__u32) * current->ngroups +
2072 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
2073 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
2074 sizeof(old_targetlen) + sizeof(struct kml_suffix);
2076 if ( size > sizeof(record) )
2077 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2079 rec->is_kml = 1;
2080 rec->size = size + size_round(le32_to_cpu(pathlen)) + size_round(len) +
2081 size_round(old_targetlen);
2083 logrecord = journal_log_prefix(record, opcode, rec);
2084 logrecord = log_version(logrecord, tgt_dir_ver);
2085 logrecord = log_dentry_version(logrecord, dir);
2086 logrecord = log_version(logrecord, old_file_ver);
2087 logrecord = log_rollback(logrecord, rb);
2088 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2089 logrecord = logit(logrecord, &llen, sizeof(llen));
2090 logrecord = logit(logrecord, &old_targetlen, sizeof(old_targetlen));
2091 logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
2093 error = presto_log(fset, rec, record, size,
2094 path, size_round(le32_to_cpu(pathlen)),
2095 name, size_round(len),
2096 old_target, size_round(old_targetlen));
2098 BUFF_FREE(buffer);
2099 EXIT;
2100 return error;
2104 presto_journal_close(struct rec_info *rec, struct presto_file_set *fset,
2105 struct file *file, struct dentry *dentry,
2106 struct presto_version *old_file_ver,
2107 struct presto_version *new_file_ver)
2109 int opcode = KML_OPCODE_CLOSE;
2110 struct presto_file_data *fd;
2111 char *buffer, *path, *logrecord, record[316];
2112 struct dentry *root;
2113 int error, size, i;
2114 __u32 pathlen, generation;
2115 __u64 ino;
2116 __u32 open_fsuid;
2117 __u32 open_fsgid;
2118 __u32 open_ngroups;
2119 __u32 open_groups[NGROUPS_MAX];
2120 __u32 open_mode;
2121 __u32 open_uid;
2122 __u32 open_gid;
2124 ENTRY;
2126 if ( presto_no_journal(fset) ) {
2127 EXIT;
2128 return 0;
2131 if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0)
2132 || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
2133 EXIT;
2134 return 0;
2137 root = fset->fset_dentry;
2139 fd = (struct presto_file_data *)file->private_data;
2140 if (fd) {
2141 open_ngroups = fd->fd_ngroups;
2142 for (i = 0; i < fd->fd_ngroups; i++)
2143 open_groups[i] = (__u32) fd->fd_groups[i];
2144 open_mode = fd->fd_mode;
2145 open_uid = fd->fd_uid;
2146 open_gid = fd->fd_gid;
2147 open_fsuid = fd->fd_fsuid;
2148 open_fsgid = fd->fd_fsgid;
2149 } else {
2150 open_ngroups = current->ngroups;
2151 for (i=0; i<current->ngroups; i++)
2152 open_groups[i] = (__u32) current->groups[i];
2153 open_mode = dentry->d_inode->i_mode;
2154 open_uid = dentry->d_inode->i_uid;
2155 open_gid = dentry->d_inode->i_gid;
2156 open_fsuid = current->fsuid;
2157 open_fsgid = current->fsgid;
2159 BUFF_ALLOC(buffer, NULL);
2160 path = presto_path(dentry, root, buffer, PAGE_SIZE);
2161 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
2162 ino = cpu_to_le64(dentry->d_inode->i_ino);
2163 generation = cpu_to_le32(dentry->d_inode->i_generation);
2164 size = sizeof(__u32) * open_ngroups +
2165 sizeof(open_mode) + sizeof(open_uid) + sizeof(open_gid) +
2166 sizeof(struct kml_prefix_hdr) + sizeof(*old_file_ver) +
2167 sizeof(*new_file_ver) + sizeof(ino) + sizeof(generation) +
2168 sizeof(pathlen) + sizeof(struct kml_suffix);
2170 if ( size > sizeof(record) )
2171 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2173 rec->is_kml = 1;
2174 rec->size = size + size_round(le32_to_cpu(pathlen));
2176 logrecord = journal_log_prefix_with_groups_and_ids(
2177 record, opcode, rec, open_ngroups, open_groups,
2178 open_fsuid, open_fsgid);
2179 logrecord = logit(logrecord, &open_mode, sizeof(open_mode));
2180 logrecord = logit(logrecord, &open_uid, sizeof(open_uid));
2181 logrecord = logit(logrecord, &open_gid, sizeof(open_gid));
2182 logrecord = log_version(logrecord, old_file_ver);
2183 logrecord = log_version(logrecord, new_file_ver);
2184 logrecord = logit(logrecord, &ino, sizeof(ino));
2185 logrecord = logit(logrecord, &generation, sizeof(generation));
2186 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2187 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
2189 error = presto_log(fset, rec, record, size,
2190 path, size_round(le32_to_cpu(pathlen)),
2191 NULL, 0, NULL, 0);
2192 BUFF_FREE(buffer);
2194 EXIT;
2195 return error;
2198 int presto_rewrite_close(struct rec_info *rec, struct presto_file_set *fset,
2199 char *path, __u32 pathlen,
2200 int ngroups, __u32 *groups,
2201 __u64 ino, __u32 generation,
2202 struct presto_version *new_file_ver)
2204 int opcode = KML_OPCODE_CLOSE;
2205 char *logrecord, record[292];
2206 struct dentry *root;
2207 int error, size;
2209 ENTRY;
2211 if ( presto_no_journal(fset) ) {
2212 EXIT;
2213 return 0;
2216 root = fset->fset_dentry;
2218 size = sizeof(__u32) * ngroups +
2219 sizeof(struct kml_prefix_hdr) + sizeof(*new_file_ver) +
2220 sizeof(ino) + sizeof(generation) +
2221 sizeof(le32_to_cpu(pathlen)) +
2222 sizeof(struct kml_suffix);
2224 if ( size > sizeof(record) )
2225 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2227 rec->is_kml = 1;
2228 rec->size = size + size_round(le32_to_cpu(pathlen));
2230 logrecord = journal_log_prefix_with_groups(record, opcode, rec,
2231 ngroups, groups);
2232 logrecord = log_version(logrecord, new_file_ver);
2233 logrecord = logit(logrecord, &ino, sizeof(ino));
2234 logrecord = logit(logrecord, &generation, sizeof(generation));
2235 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2236 logrecord = journal_log_suffix(logrecord, record, fset, NULL, rec);
2238 error = presto_log(fset, rec, record, size,
2239 path, size_round(le32_to_cpu(pathlen)),
2240 NULL, 0, NULL, 0);
2242 EXIT;
2243 return error;
2247 /* write closes for the local close records in the LML */
2248 int presto_complete_lml(struct presto_file_set *fset)
2250 __u32 groups[NGROUPS_MAX];
2251 loff_t lml_offset;
2252 loff_t read_offset;
2253 char *buffer;
2254 void *handle;
2255 struct rec_info rec;
2256 struct close_rec {
2257 struct presto_version new_file_ver;
2258 __u64 ino;
2259 __u32 generation;
2260 __u32 pathlen;
2261 __u64 remote_ino;
2262 __u32 remote_generation;
2263 __u32 remote_version;
2264 __u64 lml_offset;
2265 } close_rec;
2266 struct file *file = fset->fset_lml.fd_file;
2267 struct kml_prefix_hdr prefix;
2268 int rc = 0;
2269 ENTRY;
2271 lml_offset = 0;
2272 again:
2273 if (lml_offset >= file->f_dentry->d_inode->i_size) {
2274 EXIT;
2275 return rc;
2278 read_offset = lml_offset;
2279 rc = presto_fread(file, (char *)&prefix,
2280 sizeof(prefix), &read_offset);
2281 if ( rc != sizeof(prefix) ) {
2282 EXIT;
2283 CERROR("presto_complete_lml: ioerror - 1, tell Peter\n");
2284 return -EIO;
2287 if ( prefix.opcode == KML_OPCODE_NOOP ) {
2288 lml_offset += prefix.len;
2289 goto again;
2292 rc = presto_fread(file, (char *)groups,
2293 prefix.ngroups * sizeof(__u32), &read_offset);
2294 if ( rc != prefix.ngroups * sizeof(__u32) ) {
2295 EXIT;
2296 CERROR("presto_complete_lml: ioerror - 2, tell Peter\n");
2297 return -EIO;
2300 rc = presto_fread(file, (char *)&close_rec,
2301 sizeof(close_rec), &read_offset);
2302 if ( rc != sizeof(close_rec) ) {
2303 EXIT;
2304 CERROR("presto_complete_lml: ioerror - 3, tell Peter\n");
2305 return -EIO;
2308 /* is this a backfetch or a close record? */
2309 if ( le64_to_cpu(close_rec.remote_ino) != 0 ) {
2310 lml_offset += prefix.len;
2311 goto again;
2314 BUFF_ALLOC(buffer, NULL);
2315 rc = presto_fread(file, (char *)buffer,
2316 le32_to_cpu(close_rec.pathlen), &read_offset);
2317 if ( rc != le32_to_cpu(close_rec.pathlen) ) {
2318 EXIT;
2319 CERROR("presto_complete_lml: ioerror - 4, tell Peter\n");
2320 return -EIO;
2323 handle = presto_trans_start(fset, file->f_dentry->d_inode,
2324 KML_OPCODE_RELEASE);
2325 if ( IS_ERR(handle) ) {
2326 EXIT;
2327 return -ENOMEM;
2330 rc = presto_clear_lml_close(fset, lml_offset);
2331 if ( rc ) {
2332 CERROR("error during clearing: %d\n", rc);
2333 presto_trans_commit(fset, handle);
2334 EXIT;
2335 return rc;
2338 rc = presto_rewrite_close(&rec, fset, buffer, close_rec.pathlen,
2339 prefix.ngroups, groups,
2340 close_rec.ino, close_rec.generation,
2341 &close_rec.new_file_ver);
2342 if ( rc ) {
2343 CERROR("error during rewrite close: %d\n", rc);
2344 presto_trans_commit(fset, handle);
2345 EXIT;
2346 return rc;
2349 presto_trans_commit(fset, handle);
2350 if ( rc ) {
2351 CERROR("error during truncation: %d\n", rc);
2352 EXIT;
2353 return rc;
2356 lml_offset += prefix.len;
2357 CDEBUG(D_JOURNAL, "next LML record at: %ld\n", (long)lml_offset);
2358 goto again;
2360 EXIT;
2361 return -EINVAL;
2365 #ifdef CONFIG_FS_EXT_ATTR
2366 /* Journal an ea operation. A NULL buffer implies the attribute is
2367 * getting deleted. In this case we simply change the opcode, but nothing
2368 * else is affected.
2370 int presto_journal_set_ext_attr (struct rec_info *rec,
2371 struct presto_file_set *fset,
2372 struct dentry *dentry,
2373 struct presto_version *ver, const char *name,
2374 const char *buffer, int buffer_len,
2375 int flags)
2377 int opcode = (buffer == NULL) ?
2378 KML_OPCODE_DELEXTATTR :
2379 KML_OPCODE_SETEXTATTR ;
2380 char *temp, *path, *logrecord, record[292];
2381 struct dentry *root;
2382 int error, size;
2383 __u32 namelen=cpu_to_le32(strnlen(name,PRESTO_EXT_ATTR_NAME_MAX));
2384 __u32 buflen=(buffer != NULL)? cpu_to_le32(buffer_len): cpu_to_le32(0);
2385 __u32 mode, pathlen;
2387 ENTRY;
2388 if ( presto_no_journal(fset) ) {
2389 EXIT;
2390 return 0;
2393 if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0)
2394 || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
2395 EXIT;
2396 return 0;
2399 root = fset->fset_dentry;
2401 BUFF_ALLOC(temp, NULL);
2402 path = presto_path(dentry, root, temp, PAGE_SIZE);
2403 pathlen = cpu_to_le32(MYPATHLEN(temp, path));
2405 flags=cpu_to_le32(flags);
2406 /* Ugly, but needed. posix ACLs change the mode without using
2407 * setattr, we need to record these changes. The EA code per se
2408 * is not really affected.
2410 mode=cpu_to_le32(dentry->d_inode->i_mode);
2412 size = sizeof(__u32) * current->ngroups +
2413 sizeof(struct kml_prefix_hdr) +
2414 2 * sizeof(struct presto_version) +
2415 sizeof(flags) + sizeof(mode) + sizeof(namelen) +
2416 sizeof(buflen) + sizeof(pathlen) +
2417 sizeof(struct kml_suffix);
2419 if ( size > sizeof(record) )
2420 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2422 rec->is_kml = 1;
2423 /* Make space for a path, a attr name and value*/
2424 /* We use the buflen instead of buffer_len to make sure that we
2425 * journal the right length. This may be a little paranoid, but
2426 * with 64 bits round the corner, I would rather be safe than sorry!
2427 * Also this handles deletes with non-zero buffer_lengths correctly.
2428 * SHP
2430 rec->size = size + size_round(le32_to_cpu(pathlen)) +
2431 size_round(le32_to_cpu(namelen)) +
2432 size_round(le32_to_cpu(buflen));
2434 logrecord = journal_log_prefix(record, opcode, rec);
2435 logrecord = log_version(logrecord, ver);
2436 logrecord = log_dentry_version(logrecord, dentry);
2437 logrecord = logit(logrecord, &flags, sizeof(flags));
2438 logrecord = logit(logrecord, &mode, sizeof(flags));
2439 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2440 logrecord = logit(logrecord, &namelen, sizeof(namelen));
2441 logrecord = logit(logrecord, &buflen, sizeof(buflen));
2442 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
2444 error = presto_log(fset, rec, record, size,
2445 path, size_round(le32_to_cpu(pathlen)),
2446 name, size_round(le32_to_cpu(namelen)),
2447 buffer, size_round(le32_to_cpu(buflen)));
2449 BUFF_FREE(temp);
2450 EXIT;
2451 return error;
2453 #endif