journal.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:80k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  2.  * vim:expandtab:shiftwidth=8:tabstop=8:
  3.  *
  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>
  7.  *
  8.  *  Support for journalling extended attributes
  9.  *  Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
  10.  * 
  11.  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
  12.  *
  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.
  16.  *
  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.
  21.  *
  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.
  25.  */
  26. #include <linux/types.h>
  27. #include <linux/kernel.h>
  28. #include <linux/sched.h>
  29. #include <linux/fs.h>
  30. #include <linux/slab.h>
  31. #include <linux/vmalloc.h>
  32. #include <linux/time.h>
  33. #include <linux/errno.h>
  34. #include <linux/locks.h>
  35. #include <asm/segment.h>
  36. #include <asm/uaccess.h>
  37. #include <linux/string.h>
  38. #include <linux/smp_lock.h>
  39. #include <linux/intermezzo_fs.h>
  40. #include <linux/intermezzo_psdev.h>
  41. struct presto_reservation_data {
  42.         unsigned int ri_recno;
  43.         loff_t ri_offset;
  44.         loff_t ri_size;
  45.         struct list_head ri_list;
  46. };
  47. /* 
  48.  *  Locking Semantics
  49.  * 
  50.  * write lock in struct presto_log_fd: 
  51.  *  - name: fd_lock
  52.  *  - required for: accessing any field in a presto_log_fd 
  53.  *  - may not be held across I/O
  54.  *  - 
  55.  *  
  56.  */
  57. /*
  58.  *  reserve record space and/or atomically request state of the log
  59.  *  rec will hold the location reserved record upon return
  60.  *  this reservation will be placed in the queue
  61.  */ 
  62. static void presto_reserve_record(struct presto_file_set *fset, 
  63.                            struct presto_log_fd *fd, 
  64.                            struct rec_info *rec,
  65.                            struct presto_reservation_data *rd)
  66. {
  67.         int chunked_record = 0; 
  68.         ENTRY;
  69.         
  70.         write_lock(&fd->fd_lock);
  71.         if ( rec->is_kml ) { 
  72.                 int chunk = 1 << fset->fset_chunkbits;
  73.                 int chunk_mask = ~(chunk -1); 
  74.                 loff_t boundary; 
  75.                 boundary =  (fd->fd_offset + chunk - 1) & chunk_mask;
  76.                 if ( fd->fd_offset + rec->size >= boundary ) {
  77.                         chunked_record = 1;
  78.                         fd->fd_offset = boundary; 
  79.                 }
  80.         }
  81.         fd->fd_recno++;
  82.         
  83.         /* this moves the fd_offset back after truncation */ 
  84.         if ( list_empty(&fd->fd_reservations) && 
  85.              !chunked_record) { 
  86.                 fd->fd_offset = fd->fd_file->f_dentry->d_inode->i_size;
  87.         }
  88.         rec->offset = fd->fd_offset;
  89.         if (rec->is_kml)
  90.                 rec->offset += fset->fset_kml_logical_off;
  91.         rec->recno = fd->fd_recno;
  92.         /* add the reservation data to the end of the list */
  93.         rd->ri_offset = fd->fd_offset;
  94.         rd->ri_size = rec->size;
  95.         rd->ri_recno = rec->recno; 
  96.         list_add(&rd->ri_list, fd->fd_reservations.prev);
  97.         fd->fd_offset += rec->size;
  98.         write_unlock(&fd->fd_lock); 
  99.         EXIT;
  100. }
  101. static inline void presto_release_record(struct presto_log_fd *fd,
  102.                                          struct presto_reservation_data *rd)
  103. {
  104.         write_lock(&fd->fd_lock);
  105.         list_del(&rd->ri_list);
  106.         write_unlock(&fd->fd_lock);
  107. }
  108. /* XXX should we ask for do_truncate to be exported? */
  109. int izo_do_truncate(struct presto_file_set *fset, struct dentry *dentry,
  110.                     loff_t length,  loff_t size_check)
  111. {
  112.         struct inode *inode = dentry->d_inode;
  113.         int error;
  114.         struct iattr newattrs;
  115.         ENTRY;
  116.         if (length < 0) {
  117.                 EXIT;
  118.                 return -EINVAL;
  119.         }
  120.         down(&inode->i_sem);
  121.         lock_kernel();
  122.         
  123.         if (size_check != inode->i_size) { 
  124.                 unlock_kernel();
  125.                 up(&inode->i_sem);
  126.                 EXIT;
  127.                 return -EALREADY; 
  128.         }
  129.         newattrs.ia_size = length;
  130.         newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
  131.         if (inode->i_op && inode->i_op->setattr)
  132.                 error = inode->i_op->setattr(dentry, &newattrs);
  133.         else {
  134.                 inode_setattr(dentry->d_inode, &newattrs);
  135.                 error = 0;
  136.         }
  137.         unlock_kernel();
  138.         up(&inode->i_sem);
  139.         EXIT;
  140.         return error;
  141. }
  142. static void presto_kml_truncate(struct presto_file_set *fset)
  143. {
  144.         int rc;
  145.         ENTRY;
  146.         write_lock(&fset->fset_kml.fd_lock);
  147.         if (fset->fset_kml.fd_truncating == 1 ) {
  148.                 write_unlock(&fset->fset_kml.fd_lock);
  149.                 EXIT;
  150.                 return;
  151.         }
  152.         fset->fset_kml.fd_truncating = 1;
  153.         write_unlock(&fset->fset_kml.fd_lock);
  154.         CERROR("islento: %d, count: %dn",
  155.                ISLENTO(presto_i2m(fset->fset_dentry->d_inode)),
  156.                fset->fset_permit_count);
  157.         rc = izo_upc_kml_truncate(fset->fset_cache->cache_psdev->uc_minor,
  158.                                 fset->fset_lento_off, fset->fset_lento_recno,
  159.                                 fset->fset_name);
  160.         /* Userspace is the only permitholder now, and will retain an exclusive
  161.          * hold on the permit until KML truncation completes. */
  162.         /* FIXME: double check this code path now that the precise semantics of
  163.          * fset->fset_permit_count have changed. */
  164.         if (rc != 0) {
  165.                 write_lock(&fset->fset_kml.fd_lock);
  166.                 fset->fset_kml.fd_truncating = 0;
  167.                 write_unlock(&fset->fset_kml.fd_lock);
  168.         }
  169.         EXIT;
  170. }
  171. void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,
  172.                          int op)
  173. {
  174.         ENTRY;
  175.         if ( !fset->fset_cache->cache_filter->o_trops ) {
  176.                 EXIT;
  177.                 return NULL;
  178.         }
  179.         EXIT;
  180.         return fset->fset_cache->cache_filter->o_trops->tr_start
  181.                 (fset, inode, op);
  182. }
  183. void presto_trans_commit(struct presto_file_set *fset, void *handle)
  184. {
  185.         ENTRY;
  186.         if (!fset->fset_cache->cache_filter->o_trops ) {
  187.                 EXIT;
  188.                 return;
  189.         }
  190.         fset->fset_cache->cache_filter->o_trops->tr_commit(fset, handle);
  191.         /* Check to see if the KML needs truncated. */
  192.         if (fset->kml_truncate_size > 0 &&
  193.             !fset->fset_kml.fd_truncating &&
  194.             fset->fset_kml.fd_offset > fset->kml_truncate_size) {
  195.                 CDEBUG(D_JOURNAL, "kml size: %lu; truncatingn",
  196.                        (unsigned long)fset->fset_kml.fd_offset);
  197.                 presto_kml_truncate(fset);
  198.         }
  199.         EXIT;
  200. }
  201. inline int presto_no_journal(struct presto_file_set *fset)
  202. {
  203.         int minor = fset->fset_cache->cache_psdev->uc_minor;
  204.         return izo_channels[minor].uc_no_journal;
  205. }
  206. #define size_round(x)  (((x)+3) & ~0x3)
  207. #define BUFF_FREE(buf) PRESTO_FREE(buf, PAGE_SIZE)
  208. #define BUFF_ALLOC(newbuf, oldbuf)              
  209.         PRESTO_ALLOC(newbuf, PAGE_SIZE);        
  210.         if ( !newbuf ) {                        
  211.                 if (oldbuf)                     
  212.                         BUFF_FREE(oldbuf);      
  213.                 return -ENOMEM;                 
  214.         }
  215. /*
  216.  * "buflen" should be PAGE_SIZE or more.
  217.  * Give relative path wrt to a fsetroot
  218.  */
  219. char * presto_path(struct dentry *dentry, struct dentry *root,
  220.                    char *buffer, int buflen)
  221. {
  222.         char * end = buffer+buflen;
  223.         char * retval;
  224.         *--end = '';
  225.         buflen--;
  226.         if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
  227.                 buflen -= 10;
  228.                 end -= 10;
  229.                 memcpy(end, " (deleted)", 10);
  230.         }
  231.         /* Get '/' right */
  232.         retval = end-1;
  233.         *retval = '/';
  234.         for (;;) {
  235.                 struct dentry * parent;
  236.                 int namelen;
  237.                 if (dentry == root)
  238.                         break;
  239.                 parent = dentry->d_parent;
  240.                 if (dentry == parent)
  241.                         break;
  242.                 namelen = dentry->d_name.len;
  243.                 buflen -= namelen + 1;
  244.                 if (buflen < 0)
  245.                         break;
  246.                 end -= namelen;
  247.                 memcpy(end, dentry->d_name.name, namelen);
  248.                 *--end = '/';
  249.                 retval = end;
  250.                 dentry = parent;
  251.         }
  252.         return retval;
  253. }
  254. static inline char *logit(char *buf, const void *value, int size)
  255. {
  256.         char *ptr = (char *)value;
  257.         memcpy(buf, ptr, size);
  258.         buf += size;
  259.         return buf;
  260. }
  261. static inline char *
  262. journal_log_prefix_with_groups_and_ids(char *buf, int opcode, 
  263.                                        struct rec_info *rec,
  264.                                        __u32 ngroups, gid_t *groups,
  265.                                        __u32 fsuid, __u32 fsgid)
  266. {
  267.         struct kml_prefix_hdr p;
  268.         u32 loggroups[NGROUPS_MAX];
  269.         int i; 
  270.         p.len = cpu_to_le32(rec->size);
  271.         p.version = KML_MAJOR_VERSION | KML_MINOR_VERSION;
  272.         p.pid = cpu_to_le32(current->pid);
  273.         p.auid = cpu_to_le32(current->uid);
  274.         p.fsuid = cpu_to_le32(fsuid);
  275.         p.fsgid = cpu_to_le32(fsgid);
  276.         p.ngroups = cpu_to_le32(ngroups);
  277.         p.opcode = cpu_to_le32(opcode);
  278.         for (i=0 ; i < ngroups ; i++)
  279.                 loggroups[i] = cpu_to_le32((__u32) groups[i]);
  280.         buf = logit(buf, &p, sizeof(struct kml_prefix_hdr));
  281.         buf = logit(buf, &loggroups, sizeof(__u32) * ngroups);
  282.         return buf;
  283. }
  284. static inline char *
  285. journal_log_prefix(char *buf, int opcode, struct rec_info *rec)
  286. {
  287.         __u32 groups[NGROUPS_MAX]; 
  288.         int i; 
  289.         /* convert 16 bit gid's to 32 bit gid's */
  290.         for (i=0; i<current->ngroups; i++) 
  291.                 groups[i] = (__u32) current->groups[i];
  292.         
  293.         return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
  294.                                                       (__u32)current->ngroups,
  295.                                                       groups,
  296.                                                       (__u32)current->fsuid,
  297.                                                       (__u32)current->fsgid);
  298. }
  299. static inline char *
  300. journal_log_prefix_with_groups(char *buf, int opcode, struct rec_info *rec, 
  301.                                __u32 ngroups, gid_t *groups)
  302. {
  303.         return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
  304.                                                       ngroups, groups,
  305.                                                       (__u32)current->fsuid,
  306.                                                       (__u32)current->fsgid);
  307. }
  308. static inline char *log_dentry_version(char *buf, struct dentry *dentry)
  309. {
  310.         struct presto_version version;
  311.         presto_getversion(&version, dentry->d_inode);
  312.         
  313.         version.pv_mtime = HTON__u64(version.pv_mtime);
  314.         version.pv_ctime = HTON__u64(version.pv_ctime);
  315.         version.pv_size = HTON__u64(version.pv_size);
  316.         return logit(buf, &version, sizeof(version));
  317. }
  318. static inline char *log_version(char *buf, struct presto_version *pv)
  319. {
  320.         struct presto_version version;
  321.         memcpy(&version, pv, sizeof(version));
  322.         
  323.         version.pv_mtime = HTON__u64(version.pv_mtime);
  324.         version.pv_ctime = HTON__u64(version.pv_ctime);
  325.         version.pv_size = HTON__u64(version.pv_size);
  326.         return logit(buf, &version, sizeof(version));
  327. }
  328. static inline char *log_rollback(char *buf, struct izo_rollback_data *rb)
  329. {
  330.         struct izo_rollback_data rollback;
  331.         memcpy(&rollback, rb, sizeof(rollback));
  332.         
  333.         rollback.rb_mode = HTON__u32(rollback.rb_mode);
  334.         rollback.rb_rdev = HTON__u32(rollback.rb_rdev);
  335.         rollback.rb_uid = HTON__u64(rollback.rb_uid);
  336.         rollback.rb_gid = HTON__u64(rollback.rb_gid);
  337.         return logit(buf, &rollback, sizeof(rollback));
  338. }
  339. static inline char *journal_log_suffix(char *buf, char *log,
  340.                                        struct presto_file_set *fset,
  341.                                        struct dentry *dentry,
  342.                                        struct rec_info *rec)
  343. {
  344.         struct kml_suffix s;
  345.         struct kml_prefix_hdr *p = (struct kml_prefix_hdr *)log;
  346. #if 0
  347.         /* XXX needs to be done after reservation, 
  348.            disable ths until version 1.2 */
  349.         if ( dentry ) { 
  350.                 s.prevrec = cpu_to_le32(rec->offset - 
  351.                                         presto_d2d(dentry)->dd_kml_offset);
  352.                 presto_d2d(dentry)->dd_kml_offset = rec->offset;
  353.         } else { 
  354.                 s.prevrec = -1;
  355.         }
  356. #endif
  357.         s.prevrec = 0; 
  358.         /* record number needs to be filled in after reservation 
  359.            s.recno = cpu_to_le32(rec->recno); */ 
  360.         s.time = cpu_to_le32(CURRENT_TIME);
  361.         s.len = p->len;
  362.         return logit(buf, &s, sizeof(s));
  363. }
  364. int izo_log_close(struct presto_log_fd *logfd)
  365. {
  366.         int rc = 0;
  367.         if (logfd->fd_file) {
  368.                 rc = filp_close(logfd->fd_file, 0);
  369.                 logfd->fd_file = NULL;
  370.         } else
  371.                 CERROR("InterMezzo: %s: no filpn", __FUNCTION__);
  372.         if (rc != 0)
  373.                 CERROR("InterMezzo: close files: filp won't close: %dn", rc);
  374.         return rc;
  375. }
  376. int presto_fwrite(struct file *file, const char *str, int len, loff_t *off)
  377. {
  378.         int rc;
  379.         mm_segment_t old_fs;
  380.         ENTRY;
  381.         rc = -EINVAL;
  382.         if ( !off ) {
  383.                 EXIT;
  384.                 return rc;
  385.         }
  386.         if ( ! file ) {
  387.                 EXIT;
  388.                 return rc;
  389.         }
  390.         if ( ! file->f_op ) {
  391.                 EXIT;
  392.                 return rc;
  393.         }
  394.         if ( ! file->f_op->write ) {
  395.                 EXIT;
  396.                 return rc;
  397.         }
  398.         old_fs = get_fs();
  399.         set_fs(get_ds());
  400.         rc = file->f_op->write(file, str, len, off);
  401.         if (rc != len) {
  402.                 CERROR("presto_fwrite: wrote %d bytes instead of "
  403.                        "%d at %ldn", rc, len, (long)*off);
  404.                 rc = -EIO; 
  405.         }
  406.         set_fs(old_fs);
  407.         EXIT;
  408.         return rc;
  409. }
  410. int presto_fread(struct file *file, char *str, int len, loff_t *off)
  411. {
  412.         int rc;
  413.         mm_segment_t old_fs;
  414.         ENTRY;
  415.         if (len > 512)
  416.                 CERROR("presto_fread: read at %Ld for %d bytes, ino %ldn",
  417.                        *off, len, file->f_dentry->d_inode->i_ino); 
  418.         rc = -EINVAL;
  419.         if ( !off ) {
  420.                 EXIT;
  421.                 return rc;
  422.         }
  423.         if ( ! file ) {
  424.                 EXIT;
  425.                 return rc;
  426.         }
  427.         if ( ! file->f_op ) {
  428.                 EXIT;
  429.                 return rc;
  430.         }
  431.         if ( ! file->f_op->read ) {
  432.                 EXIT;
  433.                 return rc;
  434.         }
  435.         old_fs = get_fs();
  436.         set_fs(get_ds());
  437.         rc = file->f_op->read(file, str, len, off);
  438.         if (rc != len) {
  439.                 CDEBUG(D_FILE, "presto_fread: read %d bytes instead of "
  440.                        "%d at %Ldn", rc, len, *off);
  441.                 rc = -EIO; 
  442.         }
  443.         set_fs(old_fs);
  444.         EXIT;
  445.         return rc;
  446. }
  447. loff_t presto_kml_offset(struct presto_file_set *fset)
  448. {
  449.         unsigned int kml_recno;
  450.         struct presto_log_fd *fd = &fset->fset_kml;
  451.         loff_t  offset;
  452.         ENTRY;
  453.         write_lock(&fd->fd_lock); 
  454.         /* Determine the largest valid offset, i.e. up until the first
  455.          * reservation held on the file. */
  456.         if ( !list_empty(&fd->fd_reservations) ) {
  457.                 struct presto_reservation_data *rd;
  458.                 rd = list_entry(fd->fd_reservations.next, 
  459.                                 struct presto_reservation_data, 
  460.                                 ri_list);
  461.                 offset = rd->ri_offset;
  462.                 kml_recno = rd->ri_recno;
  463.         } else {
  464.                 offset = fd->fd_file->f_dentry->d_inode->i_size;
  465.                 kml_recno = fset->fset_kml.fd_recno; 
  466.         }
  467.         write_unlock(&fd->fd_lock); 
  468.         return offset; 
  469. }
  470. static int presto_kml_dispatch(struct presto_file_set *fset)
  471. {
  472.         int rc = 0;
  473.         unsigned int kml_recno;
  474.         struct presto_log_fd *fd = &fset->fset_kml;
  475.         loff_t offset;
  476.         ENTRY;
  477.         write_lock(&fd->fd_lock); 
  478.         /* Determine the largest valid offset, i.e. up until the first
  479.          * reservation held on the file. */
  480.         if ( !list_empty(&fd->fd_reservations) ) {
  481.                 struct presto_reservation_data *rd;
  482.                 rd = list_entry(fd->fd_reservations.next, 
  483.                                 struct presto_reservation_data, 
  484.                                 ri_list);
  485.                 offset = rd->ri_offset;
  486.                 kml_recno = rd->ri_recno;
  487.         } else {
  488.                 offset = fd->fd_file->f_dentry->d_inode->i_size;
  489.                 kml_recno = fset->fset_kml.fd_recno; 
  490.         }
  491.         if ( kml_recno < fset->fset_lento_recno ) {
  492.                 CERROR("presto_kml_dispatch: smoke is comingn"); 
  493.                 write_unlock(&fd->fd_lock);
  494.                 EXIT;
  495.                 return 0; 
  496.         } else if ( kml_recno == fset->fset_lento_recno ) {
  497.                 write_unlock(&fd->fd_lock);
  498.                 EXIT;
  499.                 return 0; 
  500.                 /* XXX add a further "if" here to delay the KML upcall */ 
  501. #if 0
  502.         } else if ( kml_recno < fset->fset_lento_recno + 100) {
  503.                 write_unlock(&fd->fd_lock);
  504.                 EXIT;
  505.                 return 0;
  506. #endif
  507.         }
  508.         CDEBUG(D_PIOCTL, "fset: %sn", fset->fset_name);
  509.         rc = izo_upc_kml(fset->fset_cache->cache_psdev->uc_minor,
  510.                        fset->fset_lento_off, fset->fset_lento_recno,
  511.                        offset + fset->fset_kml_logical_off, kml_recno,
  512.                        fset->fset_name);
  513.         if ( rc ) {
  514.                 write_unlock(&fd->fd_lock);
  515.                 EXIT;
  516.                 return rc;
  517.         }
  518.         fset->fset_lento_off = offset;
  519.         fset->fset_lento_recno = kml_recno; 
  520.         write_unlock(&fd->fd_lock);
  521.         EXIT;
  522.         return 0;
  523. }
  524. int izo_lookup_file(struct presto_file_set *fset, char *path,
  525.                     struct nameidata *nd)
  526. {
  527.         int error = 0;
  528.         CDEBUG(D_CACHE, "looking up: %sn", path);
  529.         if (path_init(path, LOOKUP_PARENT, nd))
  530.                 error = path_walk(path, nd);
  531.         if (error) {
  532.                 EXIT;
  533.                 return error;
  534.         }
  535.         return 0;
  536. }
  537. /* FIXME: this function is a mess of locking and error handling.  There's got to
  538.  * be a better way. */
  539. static int do_truncate_rename(struct presto_file_set *fset, char *oldname,
  540.                               char *newname)
  541. {
  542.         struct dentry *old_dentry, *new_dentry;
  543.         struct nameidata oldnd, newnd;
  544.         char *oldpath, *newpath;
  545.         int error;
  546.         ENTRY;
  547.         oldpath = izo_make_path(fset, oldname);
  548.         if (oldpath == NULL) {
  549.                 EXIT;
  550.                 return -ENOENT;
  551.         }
  552.         newpath = izo_make_path(fset, newname);
  553.         if (newpath == NULL) {
  554.                 error = -ENOENT;
  555.                 EXIT;
  556.                 goto exit;
  557.         }
  558.         if ((error = izo_lookup_file(fset, oldpath, &oldnd)) != 0) {
  559.                 EXIT;
  560.                 goto exit1;
  561.         }
  562.         if ((error = izo_lookup_file(fset, newpath, &newnd)) != 0) {
  563.                 EXIT;
  564.                 goto exit2;
  565.         }
  566.         double_lock(newnd.dentry, oldnd.dentry);
  567.         old_dentry = lookup_hash(&oldnd.last, oldnd.dentry);
  568.         error = PTR_ERR(old_dentry);
  569.         if (IS_ERR(old_dentry)) {
  570.                 EXIT;
  571.                 goto exit3;
  572.         }
  573.         error = -ENOENT;
  574.         if (!old_dentry->d_inode) {
  575.                 EXIT;
  576.                 goto exit4;
  577.         }
  578.         new_dentry = lookup_hash(&newnd.last, newnd.dentry);
  579.         error = PTR_ERR(new_dentry);
  580.         if (IS_ERR(new_dentry)) {
  581.                 EXIT;
  582.                 goto exit4;
  583.         }
  584.         {
  585.         extern int presto_rename(struct inode *old_dir,struct dentry *old_dentry,
  586.                                 struct inode *new_dir,struct dentry *new_dentry);
  587.         error = presto_rename(old_dentry->d_parent->d_inode, old_dentry,
  588.                               new_dentry->d_parent->d_inode, new_dentry);
  589.         }
  590.         dput(new_dentry);
  591.         EXIT;
  592.  exit4:
  593.         dput(old_dentry);
  594.  exit3:
  595.         double_up(&newnd.dentry->d_inode->i_sem, &oldnd.dentry->d_inode->i_sem);
  596.         path_release(&newnd);
  597.  exit2:
  598.         path_release(&oldnd);
  599.  exit1:
  600.         PRESTO_FREE(newpath, strlen(newpath) + 1);
  601.  exit:
  602.         PRESTO_FREE(oldpath, strlen(oldpath) + 1);
  603.         return error;
  604. }
  605. /* This function is called with the fset->fset_kml.fd_lock held */
  606. int presto_finish_kml_truncate(struct presto_file_set *fset,
  607.                                unsigned long int offset)
  608. {
  609.         struct lento_vfs_context info;
  610.         void *handle;
  611.         struct file *f;
  612.         struct dentry *dentry;
  613.         int error = 0, len;
  614.         struct nameidata nd;
  615.         char *kmlpath = NULL, *smlpath = NULL;
  616.         ENTRY;
  617.         if (offset == 0) {
  618.                 /* Lento couldn't do what it needed to; abort the truncation. */
  619.                 fset->fset_kml.fd_truncating = 0;
  620.                 EXIT;
  621.                 return 0;
  622.         }
  623.         /* someone is about to write to the end of the KML; try again later. */
  624.         if ( !list_empty(&fset->fset_kml.fd_reservations) ) {
  625.                 EXIT;
  626.                 return -EAGAIN;
  627.         }
  628.         f = presto_copy_kml_tail(fset, offset);
  629.         if (IS_ERR(f)) {
  630.                 EXIT;
  631.                 return PTR_ERR(f);
  632.         }                        
  633.         /* In a single transaction:
  634.          *
  635.          *   - unlink 'kml'
  636.          *   - rename 'kml_tmp' to 'kml'
  637.          *   - unlink 'sml'
  638.          *   - rename 'sml_tmp' to 'sml'
  639.          *   - rewrite the first record of last_rcvd with the new kml
  640.          *     offset.
  641.          */
  642.         handle = presto_trans_start(fset, fset->fset_dentry->d_inode,
  643.                                     KML_OPCODE_KML_TRUNC);
  644.         if (IS_ERR(handle)) {
  645.                 presto_release_space(fset->fset_cache, PRESTO_REQLOW);
  646.                 CERROR("ERROR: presto_finish_kml_truncate: no space for transactionn");
  647.                 EXIT;
  648.                 return -ENOMEM;
  649.         }
  650.         memset(&info, 0, sizeof(info));
  651.         info.flags = LENTO_FL_IGNORE_TIME;
  652.         kmlpath = izo_make_path(fset, "kml");
  653.         if (kmlpath == NULL) {
  654.                 error = -ENOMEM;
  655.                 CERROR("make_path failed: ENOMEMn");
  656.                 EXIT;
  657.                 goto exit_commit;
  658.         }
  659.         if ((error = izo_lookup_file(fset, kmlpath, &nd)) != 0) {
  660.                 CERROR("izo_lookup_file(kml) failed: %d.n", error);
  661.                 EXIT;
  662.                 goto exit_commit;
  663.         }
  664.         down(&nd.dentry->d_inode->i_sem);
  665.         dentry = lookup_hash(&nd.last, nd.dentry);
  666.         error = PTR_ERR(dentry);
  667.         if (IS_ERR(dentry)) {
  668.                 up(&nd.dentry->d_inode->i_sem);
  669.                 path_release(&nd);
  670.                 CERROR("lookup_hash failedn");
  671.                 EXIT;
  672.                 goto exit_commit;
  673.         }
  674.         error = presto_do_unlink(fset, dentry->d_parent, dentry, &info);
  675.         dput(dentry);
  676.         up(&nd.dentry->d_inode->i_sem);
  677.         path_release(&nd);
  678.         if (error != 0) {
  679.                 CERROR("presto_do_unlink(kml) failed: %d.n", error);
  680.                 EXIT;
  681.                 goto exit_commit;
  682.         }
  683.         smlpath = izo_make_path(fset, "sml");
  684.         if (smlpath == NULL) {
  685.                 error = -ENOMEM;
  686.                 CERROR("make_path() failed: ENOMEMn");
  687.                 EXIT;
  688.                 goto exit_commit;
  689.         }
  690.         if ((error = izo_lookup_file(fset, smlpath, &nd)) != 0) {
  691.                 CERROR("izo_lookup_file(sml) failed: %d.n", error);
  692.                 EXIT;
  693.                 goto exit_commit;
  694.         }
  695.         down(&nd.dentry->d_inode->i_sem);
  696.         dentry = lookup_hash(&nd.last, nd.dentry);
  697.         error = PTR_ERR(dentry);
  698.         if (IS_ERR(dentry)) {
  699.                 up(&nd.dentry->d_inode->i_sem);
  700.                 path_release(&nd);
  701.                 CERROR("lookup_hash failedn");
  702.                 EXIT;
  703.                 goto exit_commit;
  704.         }
  705.         error = presto_do_unlink(fset, dentry->d_parent, dentry, &info);
  706.         dput(dentry);
  707.         up(&nd.dentry->d_inode->i_sem);
  708.         path_release(&nd);
  709.         if (error != 0) {
  710.                 CERROR("presto_do_unlink(sml) failed: %d.n", error);
  711.                 EXIT;
  712.                 goto exit_commit;
  713.         }
  714.         error = do_truncate_rename(fset, "kml_tmp", "kml");
  715.         if (error != 0)
  716.                 CERROR("do_truncate_rename(kml_tmp, kml) failed: %dn", error);
  717.         error = do_truncate_rename(fset, "sml_tmp", "sml");
  718.         if (error != 0)
  719.                 CERROR("do_truncate_rename(sml_tmp, sml) failed: %dn", error);
  720.         /* Write a new 'last_rcvd' record with the new KML offset */
  721.         fset->fset_kml_logical_off += offset;
  722.         CDEBUG(D_CACHE, "new kml_logical_offset: %Lun",
  723.                fset->fset_kml_logical_off);
  724.         if (presto_write_kml_logical_offset(fset) != 0) {
  725.                 CERROR("presto_write_kml_logical_offset failedn");
  726.         }
  727.         presto_trans_commit(fset, handle);
  728.         /* Everything was successful, so swap the KML file descriptors */
  729.         filp_close(fset->fset_kml.fd_file, NULL);
  730.         fset->fset_kml.fd_file = f;
  731.         fset->fset_kml.fd_offset -= offset;
  732.         fset->fset_kml.fd_truncating = 0;
  733.         EXIT;
  734.         return 0;
  735.  exit_commit:
  736.         presto_trans_commit(fset, handle);
  737.         len = strlen("/.intermezzo/") + strlen(fset->fset_name) +strlen("sml");
  738.         if (kmlpath != NULL)
  739.                 PRESTO_FREE(kmlpath, len);
  740.         if (smlpath != NULL)
  741.                 PRESTO_FREE(smlpath, len);
  742.         return error;
  743. }
  744. /* structure of an extended log record:
  745.    buf-prefix  buf-body [string1 [string2 [string3]]] buf-suffix
  746.    note: moves offset forward
  747. */
  748. static inline int presto_write_record(struct file *f, loff_t *off,
  749.                         const char *buf, size_t size,
  750.                         const char *string1, int len1, 
  751.                         const char *string2, int len2,
  752.                         const char *string3, int len3)
  753. {
  754.         size_t prefix_size; 
  755.         int rc;
  756.         prefix_size = size - sizeof(struct kml_suffix);
  757.         rc = presto_fwrite(f, buf, prefix_size, off);
  758.         if ( rc != prefix_size ) {
  759.                 CERROR("Write error!n");
  760.                 EXIT;
  761.                 return -EIO;
  762.         }
  763.         if  ( string1  && len1 ) {
  764.                 rc = presto_fwrite(f, string1, len1, off);
  765.                 if ( rc != len1 ) {
  766.                         CERROR("Write error!n");
  767.                         EXIT;
  768.                         return -EIO;
  769.                 }
  770.         }
  771.         if  ( string2 && len2 ) {
  772.                 rc = presto_fwrite(f, string2, len2, off);
  773.                 if ( rc != len2 ) {
  774.                         CERROR("Write error!n");
  775.                         EXIT;
  776.                         return -EIO;
  777.                 }
  778.         }
  779.         if  ( string3 && len3 ) {
  780.                 rc = presto_fwrite(f, string3, len3, off);
  781.                 if ( rc != len3 ) {
  782.                         CERROR("Write error!n");
  783.                         EXIT;
  784.                         return -EIO;
  785.                 }
  786.         }
  787.         rc = presto_fwrite(f, buf + prefix_size,
  788.                            sizeof(struct kml_suffix), off);
  789.         if ( rc != sizeof(struct kml_suffix) ) {
  790.                 CERROR("Write error!n");
  791.                 EXIT;
  792.                 return -EIO;
  793.         }
  794.         return 0;
  795. }
  796. /*
  797.  * rec->size must be valid prior to calling this function.
  798.  *
  799.  * had to export this for branch_reinter in kml_reint.c 
  800.  */
  801. int presto_log(struct presto_file_set *fset, struct rec_info *rec,
  802.                const char *buf, size_t size,
  803.                const char *string1, int len1, 
  804.                const char *string2, int len2,
  805.                const char *string3, int len3)
  806. {
  807.         int rc;
  808.         struct presto_reservation_data rd;
  809.         loff_t offset;
  810.         struct presto_log_fd *fd;
  811.         struct kml_suffix *s;
  812.         int prefix_size; 
  813.         ENTRY;
  814.         /* buf is NULL when no_journal is in effect */
  815.         if (!buf) {
  816.                 EXIT;
  817.                 return -EINVAL;
  818.         }
  819.         if (rec->is_kml) {
  820.                 fd = &fset->fset_kml;
  821.         } else {
  822.                 fd = &fset->fset_lml;
  823.         }
  824.         presto_reserve_record(fset, fd, rec, &rd);
  825.         if (rec->is_kml) {
  826.                 if (rec->offset < fset->fset_kml_logical_off) {
  827.                         CERROR("record with pre-trunc offset.  tell phil.n");
  828.                         BUG();
  829.                 }
  830.                 offset = rec->offset - fset->fset_kml_logical_off;
  831.         } else {
  832.                 offset = rec->offset;
  833.         }
  834.         /* now we know the record number */ 
  835.         prefix_size = size - sizeof(struct kml_suffix);
  836.         s = (struct kml_suffix *) (buf + prefix_size); 
  837.         s->recno = cpu_to_le32(rec->recno); 
  838.         rc = presto_write_record(fd->fd_file, &offset, buf, size, 
  839.                                  string1, len1, string2, len2, string3, len3); 
  840.         if (rc) {
  841.                 CERROR("presto: error writing record to %sn",
  842.                         rec->is_kml ? "KML" : "LML"); 
  843.                 return rc;
  844.         }
  845.         presto_release_record(fd, &rd);
  846.         rc = presto_kml_dispatch(fset);
  847.         EXIT;
  848.         return rc;
  849. }
  850. /* read from the record at tail */
  851. static int presto_last_record(struct presto_log_fd *fd, loff_t *size, 
  852.                              loff_t *tail_offset, __u32 *recno, loff_t tail)
  853. {
  854.         struct kml_suffix suffix;
  855.         int rc;
  856.         loff_t zeroes;
  857.         *recno = 0;
  858.         *tail_offset = 0;
  859.         *size = 0;
  860.         
  861.         if (tail < sizeof(struct kml_prefix_hdr) + sizeof(suffix)) {
  862.                 EXIT;
  863.                 return 0;
  864.         }
  865.         zeroes = tail - sizeof(int);
  866.         while ( zeroes >= 0 ) {
  867.                 int data;
  868.                 rc = presto_fread(fd->fd_file, (char *)&data, sizeof(data), 
  869.                                   &zeroes);
  870.                 if ( rc != sizeof(data) ) { 
  871.                         rc = -EIO;
  872.                         return rc;
  873.                 }
  874.                 if (data)
  875.                         break;
  876.                 zeroes -= 2 * sizeof(data);
  877.         }
  878.         /* zeroes at the begining of file. this is needed to prevent
  879.            presto_fread errors  -SHP
  880.         */
  881.         if (zeroes <= 0) return 0;
  882.                        
  883.         zeroes -= sizeof(suffix) + sizeof(int);
  884.         rc = presto_fread(fd->fd_file, (char *)&suffix, sizeof(suffix), &zeroes);
  885.         if ( rc != sizeof(suffix) ) {
  886.                 EXIT;
  887.                 return rc;
  888.         }
  889.         if ( suffix.len > 500 ) {
  890.                 CERROR("InterMezzo: Warning long record tail at %ld, rec tail_offset at %ld (size %d)n", 
  891.                         (long) zeroes, (long)*tail_offset, suffix.len); 
  892.         }
  893.         *recno = suffix.recno;
  894.         *size = suffix.len;
  895.         *tail_offset = zeroes;
  896.         return 0;
  897. }
  898. static int izo_kml_last_recno(struct presto_log_fd *logfd)
  899. {
  900.         int rc; 
  901.         loff_t size;
  902.         loff_t tail_offset;
  903.         int recno;
  904.         loff_t tail = logfd->fd_file->f_dentry->d_inode->i_size;
  905.         rc = presto_last_record(logfd, &size, &tail_offset, &recno, tail);
  906.         if (rc != 0) {
  907.                 EXIT;
  908.                 return rc;
  909.         }
  910.         logfd->fd_offset = tail_offset;
  911.         logfd->fd_recno = recno;
  912.         CDEBUG(D_JOURNAL, "setting fset_kml->fd_recno to %d, offset  %Ldn",
  913.                recno, tail_offset); 
  914.         EXIT;
  915.         return 0;
  916. }
  917. struct file *izo_log_open(struct presto_file_set *fset, char *name, int flags)
  918. {
  919.         struct presto_cache *cache = fset->fset_cache;
  920.         struct file *f;
  921.         int error;
  922.         ENTRY;
  923.         f = izo_fset_open(fset, name, flags, 0644);
  924.         error = PTR_ERR(f);
  925.         if (IS_ERR(f)) {
  926.                 EXIT;
  927.                 return f;
  928.         }
  929.         error = -EINVAL;
  930.         if ( cache != presto_get_cache(f->f_dentry->d_inode) ) {
  931.                 CERROR("InterMezzo: %s cache does not match fset cache!n",name);
  932.                 fset->fset_kml.fd_file = NULL;
  933.                 filp_close(f, NULL);
  934.                 f = NULL;
  935.                 EXIT;
  936.                 return f;
  937.         }
  938.         if (cache->cache_filter &&  cache->cache_filter->o_trops &&
  939.             cache->cache_filter->o_trops->tr_journal_data) {
  940.                 cache->cache_filter->o_trops->tr_journal_data
  941.                         (f->f_dentry->d_inode);
  942.         } else {
  943.                 CERROR("InterMezzo WARNING: no file data logging!n"); 
  944.         }
  945.         EXIT;
  946.         return f;
  947. }
  948. int izo_init_kml_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
  949. {
  950.         int error = 0;
  951.         struct file *f;
  952.         ENTRY;
  953.         if (logfd->fd_file) {
  954.                 CDEBUG(D_INODE, "fset already has KML openn");
  955.                 EXIT;
  956.                 return 0;
  957.         }
  958.         logfd->fd_lock = RW_LOCK_UNLOCKED;
  959.         INIT_LIST_HEAD(&logfd->fd_reservations); 
  960.         f = izo_log_open(fset, "kml",  O_RDWR | O_CREAT);
  961.         if (IS_ERR(f)) {
  962.                 error = PTR_ERR(f);
  963.                 return error;
  964.         }
  965.         logfd->fd_file = f;
  966.         error = izo_kml_last_recno(logfd);
  967.         if (error) {
  968.                 logfd->fd_file = NULL;
  969.                 filp_close(f, NULL);
  970.                 CERROR("InterMezzo: IO error in KML of fset %sn",
  971.                        fset->fset_name);
  972.                 EXIT;
  973.                 return error;
  974.         }
  975.         fset->fset_lento_off = logfd->fd_offset;
  976.         fset->fset_lento_recno = logfd->fd_recno;
  977.         EXIT;
  978.         return error;
  979. }
  980. int izo_init_last_rcvd_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
  981. {
  982.         int error = 0;
  983.         struct file *f;
  984.         struct rec_info recinfo;
  985.         ENTRY;
  986.         if (logfd->fd_file != NULL) {
  987.                 CDEBUG(D_INODE, "fset already has last_rcvd openn");
  988.                 EXIT;
  989.                 return 0;
  990.         }
  991.         logfd->fd_lock = RW_LOCK_UNLOCKED;
  992.         INIT_LIST_HEAD(&logfd->fd_reservations); 
  993.         f = izo_log_open(fset, "last_rcvd", O_RDWR | O_CREAT);
  994.         if (IS_ERR(f)) {
  995.                 error = PTR_ERR(f);
  996.                 return error;
  997.         }
  998.         logfd->fd_file = f;
  999.         logfd->fd_offset = f->f_dentry->d_inode->i_size;
  1000.         error = izo_rep_cache_init(fset);
  1001.         if (presto_read_kml_logical_offset(&recinfo, fset) == 0) {
  1002.                 fset->fset_kml_logical_off = recinfo.offset;
  1003.         } else {
  1004.                 /* The 'last_rcvd' file doesn't contain a kml offset record,
  1005.                  * probably because we just created 'last_rcvd'.  Write one. */
  1006.                 fset->fset_kml_logical_off = 0;
  1007.                 presto_write_kml_logical_offset(fset);
  1008.         }
  1009.         EXIT;
  1010.         return error;
  1011. }
  1012. int izo_init_lml_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
  1013. {
  1014.         int error = 0;
  1015.         struct file *f;
  1016.         ENTRY;
  1017.         if (logfd->fd_file) {
  1018.                 CDEBUG(D_INODE, "fset already has lml openn");
  1019.                 EXIT;
  1020.                 return 0;
  1021.         }
  1022.         logfd->fd_lock = RW_LOCK_UNLOCKED;
  1023.         INIT_LIST_HEAD(&logfd->fd_reservations); 
  1024.         f = izo_log_open(fset, "lml", O_RDWR | O_CREAT);
  1025.         if (IS_ERR(f)) {
  1026.                 error = PTR_ERR(f);
  1027.                 return error;
  1028.         }
  1029.         logfd->fd_file = f;
  1030.         logfd->fd_offset = f->f_dentry->d_inode->i_size;
  1031.         EXIT;
  1032.         return error;
  1033. }
  1034. /* Get the KML-offset record from the last_rcvd file */
  1035. int presto_read_kml_logical_offset(struct rec_info *recinfo,
  1036.                                    struct presto_file_set *fset)
  1037. {
  1038.         loff_t off;
  1039.         struct izo_rcvd_rec rec;
  1040.         char uuid[16] = {0};
  1041.         off = izo_rcvd_get(&rec, fset, uuid);
  1042.         if (off < 0)
  1043.                 return -1;
  1044.         recinfo->offset = rec.lr_local_offset;
  1045.         return 0;
  1046. }
  1047. int presto_write_kml_logical_offset(struct presto_file_set *fset)
  1048. {
  1049.         loff_t rc;
  1050.         struct izo_rcvd_rec rec;
  1051.         char uuid[16] = {0};
  1052.         rc = izo_rcvd_get(&rec, fset, uuid);
  1053.         if (rc < 0)
  1054.                 memset(&rec, 0, sizeof(rec));
  1055.         rec.lr_local_offset =
  1056.                 cpu_to_le64(fset->fset_kml_logical_off);
  1057.         return izo_rcvd_write(fset, &rec);
  1058. }
  1059. struct file * presto_copy_kml_tail(struct presto_file_set *fset,
  1060.                                    unsigned long int start)
  1061. {
  1062.         struct file *f;
  1063.         int len;
  1064.         loff_t read_off, write_off, bytes;
  1065.         ENTRY;
  1066.         /* Copy the tail of 'kml' to 'kml_tmp' */
  1067.         f = izo_log_open(fset, "kml_tmp", O_RDWR);
  1068.         if (IS_ERR(f)) {
  1069.                 EXIT;
  1070.                 return f;
  1071.         }
  1072.         write_off = 0;
  1073.         read_off = start;
  1074.         bytes = fset->fset_kml.fd_offset - start;
  1075.         while (bytes > 0) {
  1076.                 char buf[4096];
  1077.                 int toread;
  1078.                 if (bytes > sizeof(buf))
  1079.                         toread = sizeof(buf);
  1080.                 else
  1081.                         toread = bytes;
  1082.                 len = presto_fread(fset->fset_kml.fd_file, buf, toread,
  1083.                                    &read_off);
  1084.                 if (len <= 0)
  1085.                         break;
  1086.                 if (presto_fwrite(f, buf, len, &write_off) != len) {
  1087.                         filp_close(f, NULL);
  1088.                         EXIT;
  1089.                         return ERR_PTR(-EIO);
  1090.                 }
  1091.                 bytes -= len;
  1092.         }
  1093.         EXIT;
  1094.         return f;
  1095. }
  1096. /* LML records here */
  1097. /* this writes an LML record to the LML file (rec->is_kml =0)  */
  1098. int presto_write_lml_close(struct rec_info *rec,
  1099.                            struct presto_file_set *fset, 
  1100.                            struct file *file,
  1101.                            __u64 remote_ino,
  1102.                            __u64 remote_generation,
  1103.                            struct presto_version *remote_version,
  1104.                            struct presto_version *new_file_ver)
  1105. {
  1106.         int opcode = KML_OPCODE_CLOSE;
  1107.         char *buffer;
  1108.         struct dentry *dentry = file->f_dentry; 
  1109.         __u64 ino;
  1110.         __u32 pathlen;
  1111.         char *path;
  1112.         __u32 generation;
  1113.         int size;
  1114.         char *logrecord;
  1115.         char record[292];
  1116.         struct dentry *root;
  1117.         int error;
  1118.         ENTRY;
  1119.         if ( presto_no_journal(fset) ) {
  1120.           EXIT;
  1121.           return 0;
  1122.         }
  1123.         root = fset->fset_dentry;
  1124.         BUFF_ALLOC(buffer, NULL);
  1125.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1126.         CDEBUG(D_INODE, "Path: %sn", path);
  1127.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1128.         ino = cpu_to_le64(dentry->d_inode->i_ino);
  1129.         generation = cpu_to_le32(dentry->d_inode->i_generation);
  1130.         size =  sizeof(__u32) * current->ngroups + 
  1131.                 sizeof(struct kml_prefix_hdr) + sizeof(*new_file_ver) +
  1132.                 sizeof(ino) + sizeof(generation) + sizeof(pathlen) +
  1133.                 sizeof(remote_ino) + sizeof(remote_generation) + 
  1134.                 sizeof(remote_version) + sizeof(rec->offset) +
  1135.                 sizeof(struct kml_suffix);
  1136.         if ( size > sizeof(record) )
  1137.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1138.         
  1139.         rec->is_kml = 0;
  1140.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1141.         logrecord = journal_log_prefix(record, opcode, rec);
  1142.         logrecord = log_version(logrecord, new_file_ver);
  1143.         logrecord = logit(logrecord, &ino, sizeof(ino));
  1144.         logrecord = logit(logrecord, &generation, sizeof(generation));
  1145.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1146.         logrecord = logit(logrecord, &remote_ino, sizeof(remote_ino));
  1147.         logrecord = logit(logrecord, &remote_generation,
  1148.                           sizeof(remote_generation));
  1149.         logrecord = log_version(logrecord, remote_version);
  1150.         logrecord = logit(logrecord, &rec->offset, sizeof(rec->offset));
  1151.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1152.         error = presto_log(fset, rec, record, size,
  1153.                            path, size_round(le32_to_cpu(pathlen)),
  1154.                            NULL, 0, NULL, 0);
  1155.         BUFF_FREE(buffer);
  1156.         EXIT;
  1157.         return error;
  1158. }
  1159. /* 
  1160.  * Check if the given record is at the end of the file. If it is, truncate
  1161.  * the lml to the record's offset, removing it. Repeat on prior record,
  1162.  * until we reach an active record or a reserved record (as defined by the
  1163.  * reservations list).
  1164.  */
  1165. static int presto_truncate_lml_tail(struct presto_file_set *fset)
  1166. {
  1167.         loff_t lml_tail;
  1168.         loff_t lml_last_rec;
  1169.         loff_t lml_last_recsize;
  1170.         loff_t local_offset;
  1171.         int recno;
  1172.         struct kml_prefix_hdr prefix;
  1173.         struct inode *inode = fset->fset_lml.fd_file->f_dentry->d_inode;
  1174.         void *handle;
  1175.         int rc;
  1176.         ENTRY;
  1177.         /* If someone else is already truncating the LML, return. */
  1178.         write_lock(&fset->fset_lml.fd_lock); 
  1179.         if (fset->fset_lml.fd_truncating == 1 ) {
  1180.                 write_unlock(&fset->fset_lml.fd_lock); 
  1181.                 EXIT;
  1182.                 return 0;
  1183.         }
  1184.         /* someone is about to write to the end of the LML */ 
  1185.         if ( !list_empty(&fset->fset_lml.fd_reservations) ) {
  1186.                 write_unlock(&fset->fset_lml.fd_lock); 
  1187.                 EXIT;
  1188.                 return 0;
  1189.         }
  1190.        lml_tail = fset->fset_lml.fd_file->f_dentry->d_inode->i_size;
  1191.        /* Nothing to truncate?*/
  1192.        if (lml_tail == 0) {
  1193.                 write_unlock(&fset->fset_lml.fd_lock); 
  1194.                 EXIT;
  1195.                 return 0;
  1196.        }
  1197.        fset->fset_lml.fd_truncating = 1;
  1198.        write_unlock(&fset->fset_lml.fd_lock); 
  1199.        presto_last_record(&fset->fset_lml, &lml_last_recsize,
  1200.                           &lml_last_rec, &recno, lml_tail);
  1201.        /* Do we have a record to check? If not we have zeroes at the
  1202.           beginning of the file. -SHP
  1203.        */
  1204.        if (lml_last_recsize != 0) {
  1205.                 local_offset = lml_last_rec - lml_last_recsize;
  1206.                 rc = presto_fread(fset->fset_lml.fd_file, (char *)&prefix,  
  1207.                                         sizeof(prefix), &local_offset); 
  1208.                 if (rc != sizeof(prefix)) {
  1209.                         EXIT;
  1210.                         goto tr_out;
  1211.                 }
  1212.        
  1213.                 if ( prefix.opcode != KML_OPCODE_NOOP ) {
  1214.                         EXIT;
  1215.                         rc = 0;
  1216.                         /* We may have zeroes at the end of the file, should
  1217.                            we clear them out? -SHP
  1218.                         */
  1219.                         goto tr_out;
  1220.                 }
  1221.         } else 
  1222.                 lml_last_rec=0;
  1223.         handle = presto_trans_start(fset, inode, KML_OPCODE_TRUNC);
  1224.         if ( IS_ERR(handle) ) {
  1225.                 EXIT;
  1226.                 rc = -ENOMEM;
  1227.                 goto tr_out;
  1228.         }
  1229.         rc = izo_do_truncate(fset, fset->fset_lml.fd_file->f_dentry, 
  1230.                                 lml_last_rec - lml_last_recsize, lml_tail);
  1231.         presto_trans_commit(fset, handle); 
  1232.         if ( rc == 0 ) {
  1233.                 rc = 1;
  1234.         }
  1235.         EXIT;
  1236.  tr_out:
  1237.         CDEBUG(D_JOURNAL, "rc = %dn", rc);
  1238.         write_lock(&fset->fset_lml.fd_lock);
  1239.         fset->fset_lml.fd_truncating = 0;
  1240.         write_unlock(&fset->fset_lml.fd_lock);
  1241.         return rc;
  1242. }
  1243. int presto_truncate_lml(struct presto_file_set *fset)
  1244. {
  1245.         int rc; 
  1246.         ENTRY;
  1247.         
  1248.         while ( (rc = presto_truncate_lml_tail(fset)) > 0);
  1249.         if ( rc < 0 && rc != -EALREADY) {
  1250.                 CERROR("truncate_lml error %dn", rc); 
  1251.         }
  1252.         EXIT;
  1253.         return rc;
  1254. }
  1255. int presto_clear_lml_close(struct presto_file_set *fset, loff_t lml_offset)
  1256. {
  1257.         int rc;
  1258.         struct kml_prefix_hdr record;
  1259.         loff_t offset = lml_offset;
  1260.         ENTRY;
  1261.         if ( presto_no_journal(fset) ) {
  1262.                 EXIT;
  1263.                 return 0;
  1264.         }
  1265.         CDEBUG(D_JOURNAL, "reading prefix: off %ld, size %dn", 
  1266.                (long)lml_offset, sizeof(record));
  1267.         rc = presto_fread(fset->fset_lml.fd_file, (char *)&record,
  1268.                           sizeof(record), &offset);
  1269.         if ( rc != sizeof(record) ) {
  1270.                 CERROR("presto: clear_lml io error %dn", rc); 
  1271.                 EXIT;
  1272.                 return -EIO;
  1273.         }
  1274.         /* overwrite the prefix */ 
  1275.         CDEBUG(D_JOURNAL, "overwriting prefix: off %ldn", (long)lml_offset);
  1276.         record.opcode = KML_OPCODE_NOOP;
  1277.         offset = lml_offset;
  1278.         /* note: this does just a single transaction in the cache */
  1279.         rc = presto_fwrite(fset->fset_lml.fd_file, (char *)(&record), 
  1280.                               sizeof(record), &offset);
  1281.         if ( rc != sizeof(record) ) {
  1282.                 EXIT;
  1283.                 return -EIO;
  1284.         }
  1285.         EXIT;
  1286.         return 0; 
  1287. }
  1288. /* now a journal function for every operation */
  1289. int presto_journal_setattr(struct rec_info *rec, struct presto_file_set *fset,
  1290.                            struct dentry *dentry, struct presto_version *old_ver,
  1291.                            struct izo_rollback_data *rb, struct iattr *iattr)
  1292. {
  1293.         int opcode = KML_OPCODE_SETATTR;
  1294.         char *buffer, *path, *logrecord, record[316];
  1295.         struct dentry *root;
  1296.         __u32 uid, gid, mode, valid, flags, pathlen;
  1297.         __u64 fsize, mtime, ctime;
  1298.         int error, size;
  1299.         ENTRY;
  1300.         if ( presto_no_journal(fset) ) {
  1301.                 EXIT;
  1302.                 return 0;
  1303.         }
  1304.         if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) 
  1305.             || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
  1306.                 EXIT;
  1307.                 return 0;
  1308.         }
  1309.         root = fset->fset_dentry;
  1310.         BUFF_ALLOC(buffer, NULL);
  1311.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1312.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1313.         size =  sizeof(__u32) * current->ngroups + 
  1314.                 sizeof(struct kml_prefix_hdr) + sizeof(*old_ver) +
  1315.                 sizeof(valid) + sizeof(mode) + sizeof(uid) + sizeof(gid) +
  1316.                 sizeof(fsize) + sizeof(mtime) + sizeof(ctime) + sizeof(flags) +
  1317.                 sizeof(pathlen) + sizeof(*rb) + sizeof(struct kml_suffix);
  1318.         if ( size > sizeof(record) )
  1319.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1320.         /* Only journal one kind of mtime, and not atime at all.  Also don't
  1321.          * journal bogus data in iattr, to make the journal more compressible.
  1322.          */
  1323.         if (iattr->ia_valid & ATTR_MTIME_SET)
  1324.                 iattr->ia_valid = iattr->ia_valid | ATTR_MTIME;
  1325.         valid = cpu_to_le32(iattr->ia_valid & ~(ATTR_ATIME | ATTR_MTIME_SET |
  1326.                                                 ATTR_ATIME_SET));
  1327.         mode = iattr->ia_valid & ATTR_MODE ? cpu_to_le32(iattr->ia_mode): 0;
  1328.         uid = iattr->ia_valid & ATTR_UID ? cpu_to_le32(iattr->ia_uid): 0;
  1329.         gid = iattr->ia_valid & ATTR_GID ? cpu_to_le32(iattr->ia_gid): 0;
  1330.         fsize = iattr->ia_valid & ATTR_SIZE ? cpu_to_le64(iattr->ia_size): 0;
  1331.         mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime): 0;
  1332.         ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime): 0;
  1333.         flags = iattr->ia_valid & ATTR_ATTR_FLAG ?
  1334.                 cpu_to_le32(iattr->ia_attr_flags): 0;
  1335.         rec->is_kml = 1;
  1336.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1337.         logrecord = journal_log_prefix(record, opcode, rec);
  1338.         logrecord = log_version(logrecord, old_ver);
  1339.         logrecord = logit(logrecord, &valid, sizeof(valid));
  1340.         logrecord = logit(logrecord, &mode, sizeof(mode));
  1341.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1342.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1343.         logrecord = logit(logrecord, &fsize, sizeof(fsize));
  1344.         logrecord = logit(logrecord, &mtime, sizeof(mtime));
  1345.         logrecord = logit(logrecord, &ctime, sizeof(ctime));
  1346.         logrecord = logit(logrecord, &flags, sizeof(flags));
  1347.         logrecord = log_rollback(logrecord, rb);
  1348.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1349.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1350.         error = presto_log(fset, rec, record, size,
  1351.                            path, size_round(le32_to_cpu(pathlen)),
  1352.                            NULL, 0, NULL, 0);
  1353.         BUFF_FREE(buffer);
  1354.         EXIT;
  1355.         return error;
  1356. }
  1357. int presto_get_fileid(int minor, struct presto_file_set *fset,
  1358.                       struct dentry *dentry)
  1359. {
  1360.         int opcode = KML_OPCODE_GET_FILEID;
  1361.         struct rec_info rec;
  1362.         char *buffer, *path, *logrecord, record[4096]; /*include path*/
  1363.         struct dentry *root;
  1364.         __u32 uid, gid, pathlen;
  1365.         int error, size;
  1366.         struct kml_suffix *suffix;
  1367.         ENTRY;
  1368.         root = fset->fset_dentry;
  1369.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1370.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1371.         BUFF_ALLOC(buffer, NULL);
  1372.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1373.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1374.         size =  sizeof(__u32) * current->ngroups + 
  1375.                 sizeof(struct kml_prefix_hdr) + sizeof(pathlen) +
  1376.                 size_round(le32_to_cpu(pathlen)) +
  1377.                 sizeof(struct kml_suffix);
  1378.         CDEBUG(D_FILE, "kml size: %dn", size);
  1379.         if ( size > sizeof(record) )
  1380.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1381.         memset(&rec, 0, sizeof(rec));
  1382.         rec.is_kml = 1;
  1383.         rec.size = size;
  1384.         logrecord = journal_log_prefix(record, opcode, &rec);
  1385.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1386.         logrecord = logit(logrecord, path, size_round(le32_to_cpu(pathlen)));
  1387.         suffix = (struct kml_suffix *)logrecord;
  1388.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, &rec);
  1389.         /* journal_log_suffix expects journal_log to set this */
  1390.         suffix->recno = 0;
  1391.         CDEBUG(D_FILE, "actual kml size: %dn", logrecord - record);
  1392.         CDEBUG(D_FILE, "get fileid: uid %d, gid %d, path: %sn", uid, gid,path);
  1393.         error = izo_upc_get_fileid(minor, size, record, 
  1394.                                    size_round(le32_to_cpu(pathlen)), path,
  1395.                                    fset->fset_name);
  1396.         BUFF_FREE(buffer);
  1397.         EXIT;
  1398.         return error;
  1399. }
  1400. int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset,
  1401.                           struct dentry *dentry,
  1402.                           struct presto_version *tgt_dir_ver,
  1403.                           struct presto_version *new_file_ver, int mode)
  1404. {
  1405.         int opcode = KML_OPCODE_CREATE;
  1406.         char *buffer, *path, *logrecord, record[292];
  1407.         struct dentry *root;
  1408.         __u32 uid, gid, lmode, pathlen;
  1409.         int error, size;
  1410.         ENTRY;
  1411.         if ( presto_no_journal(fset) ) {
  1412.                 EXIT;
  1413.                 return 0;
  1414.         }
  1415.         root = fset->fset_dentry;
  1416.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1417.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1418.         lmode = cpu_to_le32(mode);
  1419.  
  1420.         BUFF_ALLOC(buffer, NULL);
  1421.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1422.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1423.         size =  sizeof(__u32) * current->ngroups + 
  1424.                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
  1425.                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
  1426.                 sizeof(struct kml_suffix);
  1427.         if ( size > sizeof(record) )
  1428.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1429.         rec->is_kml = 1;
  1430.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1431.         logrecord = journal_log_prefix(record, opcode, rec);
  1432.         logrecord = log_version(logrecord, tgt_dir_ver);
  1433.         logrecord = log_dentry_version(logrecord, dentry->d_parent);
  1434.         logrecord = log_version(logrecord, new_file_ver);
  1435.         logrecord = logit(logrecord, &lmode, sizeof(lmode));
  1436.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1437.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1438.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1439.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1440.         error = presto_log(fset, rec, record, size,
  1441.                            path, size_round(le32_to_cpu(pathlen)),
  1442.                            NULL, 0, NULL, 0);
  1443.         BUFF_FREE(buffer);
  1444.         EXIT;
  1445.         return error;
  1446. }
  1447. int presto_journal_symlink(struct rec_info *rec, struct presto_file_set *fset,
  1448.                            struct dentry *dentry, const char *target,
  1449.                            struct presto_version *tgt_dir_ver,
  1450.                            struct presto_version *new_link_ver)
  1451. {
  1452.         int opcode = KML_OPCODE_SYMLINK;
  1453.         char *buffer, *path, *logrecord, record[292];
  1454.         struct dentry *root;
  1455.         __u32 uid, gid, pathlen;
  1456.         __u32 targetlen = cpu_to_le32(strlen(target));
  1457.         int error, size;
  1458.         ENTRY;
  1459.         if ( presto_no_journal(fset) ) {
  1460.                 EXIT;
  1461.                 return 0;
  1462.         }
  1463.         root = fset->fset_dentry;
  1464.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1465.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1466.         BUFF_ALLOC(buffer, NULL);
  1467.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1468.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1469.         size =  sizeof(__u32) * current->ngroups + 
  1470.                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
  1471.                 sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
  1472.                 sizeof(targetlen) + sizeof(struct kml_suffix);
  1473.         if ( size > sizeof(record) )
  1474.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1475.         rec->is_kml = 1;
  1476.         rec->size = size + size_round(le32_to_cpu(pathlen)) +
  1477.                 size_round(le32_to_cpu(targetlen));
  1478.         logrecord = journal_log_prefix(record, opcode, rec);
  1479.         logrecord = log_version(logrecord, tgt_dir_ver);
  1480.         logrecord = log_dentry_version(logrecord, dentry->d_parent);
  1481.         logrecord = log_version(logrecord, new_link_ver);
  1482.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1483.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1484.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1485.         logrecord = logit(logrecord, &targetlen, sizeof(targetlen));
  1486.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1487.         error = presto_log(fset, rec, record, size,
  1488.                            path, size_round(le32_to_cpu(pathlen)),
  1489.                            target, size_round(le32_to_cpu(targetlen)),
  1490.                            NULL, 0);
  1491.         BUFF_FREE(buffer);
  1492.         EXIT;
  1493.         return error;
  1494. }
  1495. int presto_journal_mkdir(struct rec_info *rec, struct presto_file_set *fset,
  1496.                          struct dentry *dentry,
  1497.                          struct presto_version *tgt_dir_ver,
  1498.                          struct presto_version *new_dir_ver, int mode)
  1499. {
  1500.         int opcode = KML_OPCODE_MKDIR;
  1501.         char *buffer, *path, *logrecord, record[292];
  1502.         struct dentry *root;
  1503.         __u32 uid, gid, lmode, pathlen;
  1504.         int error, size;
  1505.         ENTRY;
  1506.         if ( presto_no_journal(fset) ) {
  1507.                 EXIT;
  1508.                 return 0;
  1509.         }
  1510.         root = fset->fset_dentry;
  1511.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1512.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1513.         lmode = cpu_to_le32(mode);
  1514.         BUFF_ALLOC(buffer, NULL);
  1515.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1516.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1517.         size = sizeof(__u32) * current->ngroups + 
  1518.                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
  1519.                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
  1520.                 sizeof(struct kml_suffix);
  1521.         if ( size > sizeof(record) )
  1522.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1523.         rec->is_kml = 1;
  1524.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1525.         logrecord = journal_log_prefix(record, opcode, rec);
  1526.         logrecord = log_version(logrecord, tgt_dir_ver);
  1527.         logrecord = log_dentry_version(logrecord, dentry->d_parent);
  1528.         logrecord = log_version(logrecord, new_dir_ver);
  1529.         logrecord = logit(logrecord, &lmode, sizeof(lmode));
  1530.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1531.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1532.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1533.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1534.         error = presto_log(fset, rec, record, size,
  1535.                            path, size_round(le32_to_cpu(pathlen)),
  1536.                            NULL, 0, NULL, 0);
  1537.         BUFF_FREE(buffer);
  1538.         EXIT;
  1539.         return error;
  1540. }
  1541. int
  1542. presto_journal_rmdir(struct rec_info *rec, struct presto_file_set *fset,
  1543.                      struct dentry *dir, struct presto_version *tgt_dir_ver,
  1544.                      struct presto_version *old_dir_ver,
  1545.                      struct izo_rollback_data *rb, int len, const char *name)
  1546. {
  1547.         int opcode = KML_OPCODE_RMDIR;
  1548.         char *buffer, *path, *logrecord, record[316];
  1549.         __u32 pathlen, llen;
  1550.         struct dentry *root;
  1551.         int error, size;
  1552.         ENTRY;
  1553.         if ( presto_no_journal(fset) ) {
  1554.                 EXIT;
  1555.                 return 0;
  1556.         }
  1557.         root = fset->fset_dentry;
  1558.         llen = cpu_to_le32(len);
  1559.         BUFF_ALLOC(buffer, NULL);
  1560.         path = presto_path(dir, root, buffer, PAGE_SIZE);
  1561.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1562.         size =  sizeof(__u32) * current->ngroups + 
  1563.                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
  1564.                 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
  1565.                 sizeof(struct kml_suffix);
  1566.         if ( size > sizeof(record) )
  1567.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1568.         CDEBUG(D_JOURNAL, "path: %s (%d), name: %s (%d), size %dn",
  1569.                path, pathlen, name, len, size);
  1570.         rec->is_kml = 1;
  1571.         rec->size = size + size_round(le32_to_cpu(pathlen)) + 
  1572.                 size_round(len);
  1573.         logrecord = journal_log_prefix(record, opcode, rec);
  1574.         logrecord = log_version(logrecord, tgt_dir_ver);
  1575.         logrecord = log_dentry_version(logrecord, dir);
  1576.         logrecord = log_version(logrecord, old_dir_ver);
  1577.         logrecord = logit(logrecord, rb, sizeof(*rb));
  1578.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1579.         logrecord = logit(logrecord, &llen, sizeof(llen));
  1580.         logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
  1581.         error = presto_log(fset, rec, record, size,
  1582.                            path, size_round(le32_to_cpu(pathlen)),
  1583.                            name, size_round(len),
  1584.                            NULL, 0);
  1585.         BUFF_FREE(buffer);
  1586.         EXIT;
  1587.         return error;
  1588. }
  1589. int
  1590. presto_journal_mknod(struct rec_info *rec, struct presto_file_set *fset,
  1591.                      struct dentry *dentry, struct presto_version *tgt_dir_ver,
  1592.                      struct presto_version *new_node_ver, int mode,
  1593.                      int dmajor, int dminor )
  1594. {
  1595.         int opcode = KML_OPCODE_MKNOD;
  1596.         char *buffer, *path, *logrecord, record[292];
  1597.         struct dentry *root;
  1598.         __u32 uid, gid, lmode, lmajor, lminor, pathlen;
  1599.         int error, size;
  1600.         ENTRY;
  1601.         if ( presto_no_journal(fset) ) {
  1602.                 EXIT;
  1603.                 return 0;
  1604.         }
  1605.         root = fset->fset_dentry;
  1606.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1607.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1608.         lmode = cpu_to_le32(mode);
  1609.         lmajor = cpu_to_le32(dmajor);
  1610.         lminor = cpu_to_le32(dminor);
  1611.         BUFF_ALLOC(buffer, NULL);
  1612.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1613.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1614.         size = sizeof(__u32) * current->ngroups + 
  1615.                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
  1616.                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(lmajor) +
  1617.                 sizeof(lminor) + sizeof(pathlen) +
  1618.                 sizeof(struct kml_suffix);
  1619.         if ( size > sizeof(record) )
  1620.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1621.         rec->is_kml = 1;
  1622.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1623.         logrecord = journal_log_prefix(record, opcode, rec);
  1624.         logrecord = log_version(logrecord, tgt_dir_ver);
  1625.         logrecord = log_dentry_version(logrecord, dentry->d_parent);
  1626.         logrecord = log_version(logrecord, new_node_ver);
  1627.         logrecord = logit(logrecord, &lmode, sizeof(lmode));
  1628.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1629.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1630.         logrecord = logit(logrecord, &lmajor, sizeof(lmajor));
  1631.         logrecord = logit(logrecord, &lminor, sizeof(lminor));
  1632.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1633.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1634.         error = presto_log(fset, rec, record, size,
  1635.                            path, size_round(le32_to_cpu(pathlen)),
  1636.                            NULL, 0, NULL, 0);
  1637.         BUFF_FREE(buffer);
  1638.         EXIT;
  1639.         return error;
  1640. }
  1641. int
  1642. presto_journal_link(struct rec_info *rec, struct presto_file_set *fset,
  1643.                     struct dentry *src, struct dentry *tgt,
  1644.                     struct presto_version *tgt_dir_ver,
  1645.                     struct presto_version *new_link_ver)
  1646. {
  1647.         int opcode = KML_OPCODE_LINK;
  1648.         char *buffer, *srcbuffer, *path, *srcpath, *logrecord, record[292];
  1649.         __u32 pathlen, srcpathlen;
  1650.         struct dentry *root;
  1651.         int error, size;
  1652.         ENTRY;
  1653.         if ( presto_no_journal(fset) ) {
  1654.                 EXIT;
  1655.                 return 0;
  1656.         }
  1657.         root = fset->fset_dentry;
  1658.         BUFF_ALLOC(srcbuffer, NULL);
  1659.         srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
  1660.         srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
  1661.         BUFF_ALLOC(buffer, srcbuffer);
  1662.         path = presto_path(tgt, root, buffer, PAGE_SIZE);
  1663.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1664.         size =  sizeof(__u32) * current->ngroups + 
  1665.                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
  1666.                 sizeof(srcpathlen) + sizeof(pathlen) +
  1667.                 sizeof(struct kml_suffix);
  1668.         if ( size > sizeof(record) )
  1669.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1670.         rec->is_kml = 1;
  1671.         rec->size = size + size_round(le32_to_cpu(pathlen)) + 
  1672.                 size_round(le32_to_cpu(srcpathlen));
  1673.         logrecord = journal_log_prefix(record, opcode, rec);
  1674.         logrecord = log_version(logrecord, tgt_dir_ver);
  1675.         logrecord = log_dentry_version(logrecord, tgt->d_parent);
  1676.         logrecord = log_version(logrecord, new_link_ver);
  1677.         logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
  1678.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1679.         logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
  1680.         error = presto_log(fset, rec, record, size,
  1681.                            srcpath, size_round(le32_to_cpu(srcpathlen)),
  1682.                            path, size_round(le32_to_cpu(pathlen)),
  1683.                            NULL, 0);
  1684.         BUFF_FREE(srcbuffer);
  1685.         BUFF_FREE(buffer);
  1686.         EXIT;
  1687.         return error;
  1688. }
  1689. int presto_journal_rename(struct rec_info *rec, struct presto_file_set *fset,
  1690.                           struct dentry *src, struct dentry *tgt,
  1691.                           struct presto_version *src_dir_ver,
  1692.                           struct presto_version *tgt_dir_ver)
  1693. {
  1694.         int opcode = KML_OPCODE_RENAME;
  1695.         char *buffer, *srcbuffer, *path, *srcpath, *logrecord, record[292];
  1696.         __u32 pathlen, srcpathlen;
  1697.         struct dentry *root;
  1698.         int error, size;
  1699.         ENTRY;
  1700.         if ( presto_no_journal(fset) ) {
  1701.                 EXIT;
  1702.                 return 0;
  1703.         }
  1704.         root = fset->fset_dentry;
  1705.         BUFF_ALLOC(srcbuffer, NULL);
  1706.         srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
  1707.         srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
  1708.         BUFF_ALLOC(buffer, srcbuffer);
  1709.         path = presto_path(tgt, root, buffer, PAGE_SIZE);
  1710.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1711.         size =  sizeof(__u32) * current->ngroups + 
  1712.                 sizeof(struct kml_prefix_hdr) + 4 * sizeof(*src_dir_ver) +
  1713.                 sizeof(srcpathlen) + sizeof(pathlen) +
  1714.                 sizeof(struct kml_suffix);
  1715.         if ( size > sizeof(record) )
  1716.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1717.         rec->is_kml = 1;
  1718.         rec->size = size + size_round(le32_to_cpu(pathlen)) + 
  1719.                 size_round(le32_to_cpu(srcpathlen));
  1720.         logrecord = journal_log_prefix(record, opcode, rec);
  1721.         logrecord = log_version(logrecord, src_dir_ver);
  1722.         logrecord = log_dentry_version(logrecord, src->d_parent);
  1723.         logrecord = log_version(logrecord, tgt_dir_ver);
  1724.         logrecord = log_dentry_version(logrecord, tgt->d_parent);
  1725.         logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
  1726.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1727.         logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
  1728.         error = presto_log(fset, rec, record, size,
  1729.                            srcpath, size_round(le32_to_cpu(srcpathlen)),
  1730.                            path, size_round(le32_to_cpu(pathlen)),
  1731.                            NULL, 0);
  1732.         BUFF_FREE(buffer);
  1733.         BUFF_FREE(srcbuffer);
  1734.         EXIT;
  1735.         return error;
  1736. }
  1737. int presto_journal_unlink(struct rec_info *rec, struct presto_file_set *fset,
  1738.                           struct dentry *dir, struct presto_version *tgt_dir_ver,
  1739.                           struct presto_version *old_file_ver,
  1740.                           struct izo_rollback_data *rb, struct dentry *dentry,
  1741.                           char *old_target, int old_targetlen)
  1742. {
  1743.         int opcode = KML_OPCODE_UNLINK;
  1744.         char *buffer, *path, *logrecord, record[316];
  1745.         const char *name;
  1746.         __u32 pathlen, llen;
  1747.         struct dentry *root;
  1748.         int error, size, len;
  1749.         ENTRY;
  1750.         if ( presto_no_journal(fset) ) {
  1751.                 EXIT;
  1752.                 return 0;
  1753.         }
  1754.         root = fset->fset_dentry;
  1755.         name = dentry->d_name.name;
  1756.         len = dentry->d_name.len;
  1757.         llen = cpu_to_le32(len);
  1758.         BUFF_ALLOC(buffer, NULL);
  1759.         path = presto_path(dir, root, buffer, PAGE_SIZE);
  1760.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1761.         size = sizeof(__u32) * current->ngroups + 
  1762.                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
  1763.                 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
  1764.                 sizeof(old_targetlen) + sizeof(struct kml_suffix);
  1765.         if ( size > sizeof(record) )
  1766.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1767.         rec->is_kml = 1;
  1768.         rec->size = size + size_round(le32_to_cpu(pathlen)) + size_round(len) +
  1769.                 size_round(old_targetlen);
  1770.         logrecord = journal_log_prefix(record, opcode, rec);
  1771.         logrecord = log_version(logrecord, tgt_dir_ver);
  1772.         logrecord = log_dentry_version(logrecord, dir);
  1773.         logrecord = log_version(logrecord, old_file_ver);
  1774.         logrecord = log_rollback(logrecord, rb);
  1775.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1776.         logrecord = logit(logrecord, &llen, sizeof(llen));
  1777.         logrecord = logit(logrecord, &old_targetlen, sizeof(old_targetlen));
  1778.         logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
  1779.         error = presto_log(fset, rec, record, size,
  1780.                            path, size_round(le32_to_cpu(pathlen)),
  1781.                            name, size_round(len),
  1782.                            old_target, size_round(old_targetlen));
  1783.         BUFF_FREE(buffer);
  1784.         EXIT;
  1785.         return error;
  1786. }
  1787. int
  1788. presto_journal_close(struct rec_info *rec, struct presto_file_set *fset,
  1789.                      struct file *file, struct dentry *dentry,
  1790.                      struct presto_version *old_file_ver,
  1791.                      struct presto_version *new_file_ver)
  1792. {
  1793.         int opcode = KML_OPCODE_CLOSE;
  1794.         struct presto_file_data *fd;
  1795.         char *buffer, *path, *logrecord, record[316];
  1796.         struct dentry *root;
  1797.         int error, size, i;
  1798.         __u32 pathlen, generation;
  1799.         __u64 ino;
  1800.         __u32 open_fsuid;
  1801.         __u32 open_fsgid;
  1802.         __u32 open_ngroups;
  1803.         __u32 open_groups[NGROUPS_MAX];
  1804.         __u32 open_mode;
  1805.         __u32 open_uid;
  1806.         __u32 open_gid;
  1807.         ENTRY;
  1808.         if ( presto_no_journal(fset) ) {
  1809.                 EXIT;
  1810.                 return 0;
  1811.         }
  1812.         if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) 
  1813.             || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
  1814.                 EXIT;
  1815.                 return 0;
  1816.         }
  1817.         root = fset->fset_dentry;
  1818.         fd = (struct presto_file_data *)file->private_data;
  1819.         if (fd) {
  1820.                 open_ngroups = fd->fd_ngroups;
  1821.                 for (i = 0; i < fd->fd_ngroups; i++)
  1822.                         open_groups[i] = (__u32) fd->fd_groups[i];
  1823.                 open_mode = fd->fd_mode;
  1824.                 open_uid = fd->fd_uid;
  1825.                 open_gid = fd->fd_gid;
  1826.                 open_fsuid = fd->fd_fsuid;
  1827.                 open_fsgid = fd->fd_fsgid;
  1828.         } else {
  1829.                 open_ngroups = current->ngroups;
  1830.                 for (i=0; i<current->ngroups; i++)
  1831.                         open_groups[i] =  (__u32) current->groups[i]; 
  1832.                 open_mode = dentry->d_inode->i_mode;
  1833.                 open_uid = dentry->d_inode->i_uid;
  1834.                 open_gid = dentry->d_inode->i_gid;
  1835.                 open_fsuid = current->fsuid;
  1836.                 open_fsgid = current->fsgid;
  1837.         }
  1838.         BUFF_ALLOC(buffer, NULL);
  1839.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1840.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1841.         ino = cpu_to_le64(dentry->d_inode->i_ino);
  1842.         generation = cpu_to_le32(dentry->d_inode->i_generation);
  1843.         size =  sizeof(__u32) * open_ngroups +
  1844.                 sizeof(open_mode) + sizeof(open_uid) + sizeof(open_gid) +
  1845.                 sizeof(struct kml_prefix_hdr) + sizeof(*old_file_ver) +
  1846.                 sizeof(*new_file_ver) + sizeof(ino) + sizeof(generation) +
  1847.                 sizeof(pathlen) + sizeof(struct kml_suffix);
  1848.         if ( size > sizeof(record) )
  1849.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1850.         rec->is_kml = 1;
  1851.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1852.         logrecord = journal_log_prefix_with_groups_and_ids(
  1853.                 record, opcode, rec, open_ngroups, open_groups,
  1854.                 open_fsuid, open_fsgid);
  1855.         logrecord = logit(logrecord, &open_mode, sizeof(open_mode));
  1856.         logrecord = logit(logrecord, &open_uid, sizeof(open_uid));
  1857.         logrecord = logit(logrecord, &open_gid, sizeof(open_gid));
  1858.         logrecord = log_version(logrecord, old_file_ver);
  1859.         logrecord = log_version(logrecord, new_file_ver);
  1860.         logrecord = logit(logrecord, &ino, sizeof(ino));
  1861.         logrecord = logit(logrecord, &generation, sizeof(generation));
  1862.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1863.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1864.         error = presto_log(fset, rec, record, size,
  1865.                            path, size_round(le32_to_cpu(pathlen)),
  1866.                            NULL, 0, NULL, 0);
  1867.         BUFF_FREE(buffer);
  1868.         EXIT;
  1869.         return error;
  1870. }
  1871. int presto_rewrite_close(struct rec_info *rec, struct presto_file_set *fset, 
  1872.                          char *path, __u32 pathlen, 
  1873.                          int ngroups, __u32 *groups, 
  1874.                          __u64 ino,     __u32 generation, 
  1875.                          struct presto_version *new_file_ver)
  1876. {
  1877.         int opcode = KML_OPCODE_CLOSE;
  1878.         char *logrecord, record[292];
  1879.         struct dentry *root;
  1880.         int error, size;
  1881.         ENTRY;
  1882.         if ( presto_no_journal(fset) ) {
  1883.                 EXIT;
  1884.                 return 0;
  1885.         }
  1886.         root = fset->fset_dentry;
  1887.         size =  sizeof(__u32) * ngroups + 
  1888.                 sizeof(struct kml_prefix_hdr) + sizeof(*new_file_ver) +
  1889.                 sizeof(ino) + sizeof(generation) + 
  1890.                 sizeof(le32_to_cpu(pathlen)) +
  1891.                 sizeof(struct kml_suffix);
  1892.         if ( size > sizeof(record) )
  1893.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1894.         rec->is_kml = 1;
  1895.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1896.         logrecord = journal_log_prefix_with_groups(record, opcode, rec,
  1897.                                                    ngroups, groups);
  1898.         logrecord = log_version(logrecord, new_file_ver);
  1899.         logrecord = logit(logrecord, &ino, sizeof(ino));
  1900.         logrecord = logit(logrecord, &generation, sizeof(generation));
  1901.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1902.         logrecord = journal_log_suffix(logrecord, record, fset, NULL, rec);
  1903.         error = presto_log(fset, rec, record, size,
  1904.                            path, size_round(le32_to_cpu(pathlen)),
  1905.                            NULL, 0, NULL, 0);
  1906.         EXIT;
  1907.         return error;
  1908. }
  1909. /* write closes for the local close records in the LML */ 
  1910. int presto_complete_lml(struct presto_file_set *fset)
  1911. {
  1912.         __u32 groups[NGROUPS_MAX];
  1913.         loff_t lml_offset;
  1914.         loff_t read_offset; 
  1915.         char *buffer;
  1916.         void *handle;
  1917.         struct rec_info rec;
  1918.         struct close_rec { 
  1919.                 struct presto_version new_file_ver;
  1920.                 __u64 ino;
  1921.                 __u32 generation;
  1922.                 __u32 pathlen;
  1923.                 __u64 remote_ino;
  1924.                 __u32 remote_generation;
  1925.                 __u32 remote_version;
  1926.                 __u64 lml_offset;
  1927.         } close_rec; 
  1928.         struct file *file = fset->fset_lml.fd_file;
  1929.         struct kml_prefix_hdr prefix;
  1930.         int rc = 0;
  1931.         ENTRY;
  1932.         lml_offset = 0; 
  1933.  again: 
  1934.         if (lml_offset >= file->f_dentry->d_inode->i_size) {
  1935.                 EXIT;
  1936.                 return rc;
  1937.         }
  1938.         read_offset = lml_offset;
  1939.         rc = presto_fread(file, (char *)&prefix,
  1940.                           sizeof(prefix), &read_offset);
  1941.         if ( rc != sizeof(prefix) ) {
  1942.                 EXIT;
  1943.                 CERROR("presto_complete_lml: ioerror - 1, tell Petern");
  1944.                 return -EIO;
  1945.         }
  1946.         if ( prefix.opcode == KML_OPCODE_NOOP ) {
  1947.                 lml_offset += prefix.len; 
  1948.                 goto again; 
  1949.         }
  1950.         rc = presto_fread(file, (char *)groups, 
  1951.                           prefix.ngroups * sizeof(__u32), &read_offset); 
  1952.         if ( rc != prefix.ngroups * sizeof(__u32) ) {
  1953.                 EXIT;
  1954.                 CERROR("presto_complete_lml: ioerror - 2, tell Petern");
  1955.                 return -EIO;
  1956.         }
  1957.         rc = presto_fread(file, (char *)&close_rec, 
  1958.                           sizeof(close_rec), &read_offset); 
  1959.         if ( rc != sizeof(close_rec) ) {
  1960.                 EXIT;
  1961.                 CERROR("presto_complete_lml: ioerror - 3, tell Petern");
  1962.                 return -EIO;
  1963.         }
  1964.         /* is this a backfetch or a close record? */ 
  1965.         if ( le64_to_cpu(close_rec.remote_ino) != 0 ) { 
  1966.                 lml_offset += prefix.len;
  1967.                 goto again; 
  1968.         }
  1969.         BUFF_ALLOC(buffer, NULL);
  1970.         rc = presto_fread(file, (char *)buffer, 
  1971.                           le32_to_cpu(close_rec.pathlen), &read_offset); 
  1972.         if ( rc != le32_to_cpu(close_rec.pathlen) ) {
  1973.                 EXIT;
  1974.                 CERROR("presto_complete_lml: ioerror - 4, tell Petern");
  1975.                 return -EIO;
  1976.         }
  1977.         
  1978.         handle = presto_trans_start(fset, file->f_dentry->d_inode, 
  1979.                                     KML_OPCODE_RELEASE);
  1980.         if ( IS_ERR(handle) ) {
  1981.                 EXIT;
  1982.                 return -ENOMEM; 
  1983.         }
  1984.         rc = presto_clear_lml_close(fset, lml_offset); 
  1985.         if ( rc ) {
  1986.                 CERROR("error during clearing: %dn", rc);
  1987.                 presto_trans_commit(fset, handle);
  1988.                 EXIT; 
  1989.                 return rc; 
  1990.         }
  1991.         rc = presto_rewrite_close(&rec, fset, buffer, close_rec.pathlen, 
  1992.                                   prefix.ngroups, groups, 
  1993.                                   close_rec.ino, close_rec.generation,
  1994.                                   &close_rec.new_file_ver); 
  1995.         if ( rc ) {
  1996.                 CERROR("error during rewrite close: %dn", rc);
  1997.                 presto_trans_commit(fset, handle);
  1998.                 EXIT; 
  1999.                 return rc; 
  2000.         }
  2001.         presto_trans_commit(fset, handle); 
  2002.         if ( rc ) { 
  2003.                 CERROR("error during truncation: %dn", rc);
  2004.                 EXIT; 
  2005.                 return rc;
  2006.         }
  2007.         
  2008.         lml_offset += prefix.len; 
  2009.         CDEBUG(D_JOURNAL, "next LML record at: %ldn", (long)lml_offset);
  2010.         goto again;
  2011.         EXIT;
  2012.         return -EINVAL;
  2013. }
  2014. #ifdef CONFIG_FS_EXT_ATTR
  2015. /* Journal an ea operation. A NULL buffer implies the attribute is 
  2016.  * getting deleted. In this case we simply change the opcode, but nothing
  2017.  * else is affected.
  2018.  */
  2019. int presto_journal_set_ext_attr (struct rec_info *rec, 
  2020.                                  struct presto_file_set *fset, 
  2021.                                  struct dentry *dentry, 
  2022.                                  struct presto_version *ver, const char *name, 
  2023.                                  const char *buffer, int buffer_len, 
  2024.                                  int flags) 
  2025.         int opcode = (buffer == NULL) ? 
  2026.                      KML_OPCODE_DELEXTATTR : 
  2027.                      KML_OPCODE_SETEXTATTR ;
  2028.         char *temp, *path, *logrecord, record[292];
  2029.         struct dentry *root;
  2030.         int error, size;
  2031.         __u32 namelen=cpu_to_le32(strnlen(name,PRESTO_EXT_ATTR_NAME_MAX));
  2032.         __u32 buflen=(buffer != NULL)? cpu_to_le32(buffer_len): cpu_to_le32(0);
  2033.         __u32 mode, pathlen;
  2034.         ENTRY;
  2035.         if ( presto_no_journal(fset) ) {
  2036.                 EXIT;
  2037.                 return 0;
  2038.         }
  2039.         if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) 
  2040.             || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
  2041.                 EXIT;
  2042.                 return 0;
  2043.         }
  2044.         root = fset->fset_dentry;
  2045.         BUFF_ALLOC(temp, NULL);
  2046.         path = presto_path(dentry, root, temp, PAGE_SIZE);
  2047.         pathlen = cpu_to_le32(MYPATHLEN(temp, path));
  2048.         flags=cpu_to_le32(flags);
  2049.         /* Ugly, but needed. posix ACLs change the mode without using
  2050.          * setattr, we need to record these changes. The EA code per se
  2051.          * is not really affected.
  2052.          */
  2053.         mode=cpu_to_le32(dentry->d_inode->i_mode);
  2054.         size =  sizeof(__u32) * current->ngroups + 
  2055.                 sizeof(struct kml_prefix_hdr) + 
  2056.                 2 * sizeof(struct presto_version) +
  2057.                 sizeof(flags) + sizeof(mode) + sizeof(namelen) + 
  2058.                 sizeof(buflen) + sizeof(pathlen) + 
  2059.                 sizeof(struct kml_suffix);
  2060.         if ( size > sizeof(record) )
  2061.                 CERROR("InterMezzo: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  2062.         rec->is_kml = 1;
  2063.         /* Make space for a path, a attr name and value*/
  2064.         /* We use the buflen instead of buffer_len to make sure that we 
  2065.          * journal the right length. This may be a little paranoid, but
  2066.          * with 64 bits round the corner, I would rather be safe than sorry!
  2067.          * Also this handles deletes with non-zero buffer_lengths correctly.
  2068.          * SHP
  2069.          */
  2070.         rec->size = size + size_round(le32_to_cpu(pathlen)) +
  2071.                     size_round(le32_to_cpu(namelen)) + 
  2072.                     size_round(le32_to_cpu(buflen));
  2073.         logrecord = journal_log_prefix(record, opcode, rec);
  2074.         logrecord = log_version(logrecord, ver);
  2075.         logrecord = log_dentry_version(logrecord, dentry);
  2076.         logrecord = logit(logrecord, &flags, sizeof(flags));
  2077.         logrecord = logit(logrecord, &mode, sizeof(flags));
  2078.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  2079.         logrecord = logit(logrecord, &namelen, sizeof(namelen));
  2080.         logrecord = logit(logrecord, &buflen, sizeof(buflen));
  2081.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  2082.         error = presto_log(fset, rec, record, size,
  2083.                            path, size_round(le32_to_cpu(pathlen)),
  2084.                            name, size_round(le32_to_cpu(namelen)),
  2085.                            buffer, size_round(le32_to_cpu(buflen)));
  2086.         BUFF_FREE(temp);
  2087.         EXIT;
  2088.         return error;
  2089. }
  2090. #endif