journal.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:66k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Intermezzo. (C) 1998 Peter J. Braam
  3.  *
  4.  * Support for journalling extended attributes
  5.  * (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
  6.  */
  7. #include <linux/types.h>
  8. #include <linux/kernel.h>
  9. #include <linux/fs.h>
  10. #include <linux/slab.h>
  11. #include <linux/vmalloc.h>
  12. #include <linux/time.h>
  13. #include <linux/errno.h>
  14. #include <linux/locks.h>
  15. #include <asm/segment.h>
  16. #include <asm/uaccess.h>
  17. #include <linux/string.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/intermezzo_fs.h>
  20. #include <linux/intermezzo_upcall.h>
  21. #include <linux/intermezzo_psdev.h>
  22. #include <linux/intermezzo_kml.h>
  23. static int presto_log(struct presto_file_set *fset, struct rec_info *rec,
  24.                       const char *buf, size_t size,
  25.                       const char *string1, int len1, 
  26.                       const char *string2, int len2,
  27.                       const char *string3, int len3);
  28. /*
  29.  *  reserve record space and/or atomically request state of the log
  30.  *  rec will hold the location reserved record upon return
  31.  *  this reservation will be placed in the queue
  32.  */ 
  33. static void presto_reserve_record(struct presto_file_set *fset, 
  34.                            struct presto_log_fd *fd, 
  35.                            struct rec_info *rec,
  36.                            struct presto_reservation_data *rd)
  37. {
  38.         int chunked_record = 0; 
  39.         ENTRY;
  40.         
  41.         write_lock(&fd->fd_lock);
  42.         if ( rec->is_kml ) { 
  43.                 int chunk = 1 << fset->fset_chunkbits;
  44.                 int chunk_mask = ~(chunk -1); 
  45.                 loff_t boundary; 
  46.                 boundary =  (fd->fd_offset + chunk - 1) & chunk_mask;
  47.                 if ( fd->fd_offset + rec->size >= boundary ) {
  48.                         chunked_record = 1;
  49.                         fd->fd_offset = boundary; 
  50.                 }
  51.         }
  52.         fd->fd_recno++;
  53.         
  54.         /* this move the fd_offset back after truncation */ 
  55.         if ( list_empty(&fd->fd_reservations) && 
  56.              !chunked_record) { 
  57.                 fd->fd_offset = fd->fd_file->f_dentry->d_inode->i_size;
  58.         }
  59.         rec->offset = fd->fd_offset;
  60.         rec->recno = fd->fd_recno;
  61.         fd->fd_offset += rec->size;
  62.         /* add the reservation data to the end of the list */
  63.         list_add(&rd->ri_list, fd->fd_reservations.prev);
  64.         rd->ri_offset = rec->offset;
  65.         rd->ri_size = rec->size;
  66.         rd->ri_recno = rec->recno; 
  67.         write_unlock(&fd->fd_lock); 
  68.         EXIT;
  69. }
  70. static inline void presto_release_record(struct presto_log_fd *fd,
  71.                                          struct presto_reservation_data *rd)
  72. {
  73.         write_lock(&fd->fd_lock);
  74.         list_del(&rd->ri_list);
  75.         write_unlock(&fd->fd_lock);
  76. }
  77. static int presto_do_truncate(struct presto_file_set *fset, 
  78.                               struct dentry *dentry, loff_t length, 
  79.                               loff_t size_check)
  80. {
  81.         struct inode *inode = dentry->d_inode;
  82.         struct inode_operations *op; 
  83.         int error;
  84.         struct iattr newattrs;
  85.         ENTRY;
  86.         /* Not pretty: "inode->i_size" shouldn't really be "loff_t". */
  87.         if ((off_t) length < 0)
  88.                 return -EINVAL;
  89.         fs_down(&inode->i_sem);
  90.         lock_kernel();
  91.         
  92.         if (size_check != inode->i_size) { 
  93.                 unlock_kernel();
  94.                 fs_up(&inode->i_sem);
  95.                 EXIT;
  96.                 return -EALREADY; 
  97.         }
  98.         newattrs.ia_size = length;
  99.         newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
  100.         op = filter_c2cfiops(fset->fset_cache->cache_filter);
  101.         if (op != NULL && op->setattr != NULL)
  102.                 error = op->setattr(dentry, &newattrs);
  103.         else {
  104.                 inode_setattr(dentry->d_inode, &newattrs);
  105.                 /* Some filesystems, e.g. ext2 and older versions of ext3
  106.                    legitimately do not have a <fs>_setattr method. -SHP
  107.                 */
  108.                 /*
  109.                 printk ("Warning:: int presto_do_truncate(xxx), op->setattr == NULL");
  110. error = -EOPNOTSUPP; 
  111. */
  112. error = 0;
  113.         }
  114.         unlock_kernel();
  115.         fs_up(&inode->i_sem);
  116.         EXIT;
  117.         return error;
  118. }
  119. void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,
  120.                          int op)
  121. {
  122.         ENTRY;
  123.         if ( !fset->fset_cache->cache_filter->o_trops )
  124.                 return NULL;
  125.         EXIT;
  126.         return fset->fset_cache->cache_filter->o_trops->tr_start
  127.                 (fset, inode, op);
  128. }
  129. void presto_trans_commit(struct presto_file_set *fset, void *handle)
  130. {
  131.         ENTRY;
  132.         if (!fset->fset_cache->cache_filter->o_trops )
  133.                 return;
  134.         EXIT;
  135.         return fset->fset_cache->cache_filter->o_trops->tr_commit(fset, handle);
  136. }
  137. inline int presto_no_journal(struct presto_file_set *fset)
  138. {
  139.         int minor = fset->fset_cache->cache_psdev->uc_minor;
  140.         return upc_comms[minor].uc_no_journal;
  141. }
  142. #define size_round(x)  (((x)+3) & ~0x3)
  143. #define BUFF_FREE(buf) PRESTO_FREE(buf, PAGE_SIZE)
  144. #define BUFF_ALLOC(newbuf, oldbuf)                      
  145.         PRESTO_ALLOC(newbuf, char *, PAGE_SIZE);        
  146.         if ( !newbuf ) {                                
  147.                 if (oldbuf)                             
  148.                         BUFF_FREE(oldbuf);              
  149.                 return -ENOMEM;                         
  150.         }
  151. /*
  152.  * "buflen" should be PAGE_SIZE or more.
  153.  * Give relative path wrt to a fsetroot
  154.  */
  155. char * presto_path(struct dentry *dentry, struct dentry *root,
  156.                    char *buffer, int buflen)
  157. {
  158.         char * end = buffer+buflen;
  159.         char * retval;
  160.         *--end = '';
  161.         buflen--;
  162.         if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
  163.                 buflen -= 10;
  164.                 end -= 10;
  165.                 memcpy(end, " (deleted)", 10);
  166.         }
  167.         /* Get '/' right */
  168.         retval = end-1;
  169.         *retval = '/';
  170.         for (;;) {
  171.                 struct dentry * parent;
  172.                 int namelen;
  173.                 if (dentry == root)
  174.                         break;
  175.                 parent = dentry->d_parent;
  176.                 if (dentry == parent)
  177.                         break;
  178.                 namelen = dentry->d_name.len;
  179.                 buflen -= namelen + 1;
  180.                 if (buflen < 0)
  181.                         break;
  182.                 end -= namelen;
  183.                 memcpy(end, dentry->d_name.name, namelen);
  184.                 *--end = '/';
  185.                 retval = end;
  186.                 dentry = parent;
  187.         }
  188.         return retval;
  189. }
  190. static inline char *logit(char *buf, const void *value, int size)
  191. {
  192.         char *ptr = (char *)value;
  193.         memcpy(buf, ptr, size);
  194.         buf += size;
  195.         return buf;
  196. }
  197. static inline char *
  198. journal_log_prefix_with_groups_and_ids(char *buf, int opcode, 
  199.                                        struct rec_info *rec,
  200.                                        __u32 ngroups, gid_t *groups,
  201.                                        __u32 fsuid, __u32 fsgid)
  202. {
  203.         struct big_journal_prefix p;
  204.         int i; 
  205.         p.len = cpu_to_le32(rec->size);
  206.         p.version = PRESTO_KML_MAJOR_VERSION | PRESTO_KML_MINOR_VERSION;
  207.         p.pid = cpu_to_le32(current->pid);
  208.         p.uid = cpu_to_le32(current->uid);
  209.         p.fsuid = cpu_to_le32(fsuid);
  210.         p.fsgid = cpu_to_le32(fsgid);
  211.         p.ngroups = cpu_to_le32(ngroups);
  212.         p.opcode = cpu_to_le32(opcode);
  213.         for (i=0 ; i < ngroups ; i++)
  214.                 p.groups[i] = cpu_to_le32((__u32) groups[i]);
  215.         buf = logit(buf, &p, sizeof(struct journal_prefix) + 
  216.                     sizeof(__u32) * ngroups);
  217.         return buf;
  218. }
  219. static inline char *
  220. journal_log_prefix(char *buf, int opcode, struct rec_info *rec)
  221. {
  222. __u32 groups[NGROUPS_MAX]; 
  223. int i; 
  224. /* convert 16 bit gid's to 32 bit gid's */
  225. for (i=0; i<current->ngroups; i++) 
  226. groups[i] = (__u32) current->groups[i];
  227.         return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
  228.                                                       (__u32)current->ngroups,
  229.       groups,
  230.                                                       (__u32)current->fsuid,
  231.                                                       (__u32)current->fsgid);
  232. }
  233. static inline char *
  234. journal_log_prefix_with_groups(char *buf, int opcode, struct rec_info *rec, 
  235.                                __u32 ngroups, gid_t *groups)
  236. {
  237.         return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
  238.                                                       ngroups, groups,
  239.                                                       (__u32)current->fsuid,
  240.                                                       (__u32)current->fsgid);
  241. }
  242. static inline char *log_version(char *buf, struct dentry *dentry)
  243. {
  244.         struct presto_version version;
  245.         presto_getversion(&version, dentry->d_inode);
  246.         return logit(buf, &version, sizeof(version));
  247. }
  248. static inline char *journal_log_suffix(char *buf, char *log,
  249.                                        struct presto_file_set *fset,
  250.                                        struct dentry *dentry,
  251.                                        struct rec_info *rec)
  252. {
  253.         struct journal_suffix s;
  254.         struct journal_prefix *p = (struct journal_prefix *)log;
  255. #if 0
  256. /* XXX needs to be done after reservation, 
  257.    disable ths until version 1.2 */
  258.         if ( dentry ) { 
  259.                 s.prevrec = cpu_to_le32(rec->offset - dentry->d_time);
  260.                 dentry->d_time = (unsigned long) rec->offset;
  261.         } else { 
  262.                 s.prevrec = -1;
  263.         }
  264. #endif
  265. s.prevrec = 0; 
  266.         /* record number needs to be filled in after reservation 
  267.            s.recno = cpu_to_le32(rec->recno); */ 
  268.         s.time = cpu_to_le32(CURRENT_TIME);
  269.         s.len = cpu_to_le32(p->len);
  270.         return logit(buf, &s, sizeof(s));
  271. }
  272. int presto_close_journal_file(struct presto_file_set *fset)
  273. {
  274.         int rc = 0;
  275.         int rc2 = 0;
  276.         int rc3 = 0;
  277.         ENTRY;
  278.         if ( fset->fset_kml.fd_file) {
  279.                 rc =filp_close(fset->fset_kml.fd_file, 0);
  280.                 fset->fset_kml.fd_file = NULL;
  281.         } else {
  282.                 printk("hehehehe no filpn");
  283.         }
  284.         if ( rc ) {
  285.                 printk("presto: close files: kml filp won't close %dn", rc);
  286.         }
  287.         if ( fset->fset_last_rcvd) {
  288.                 rc2 = filp_close(fset->fset_last_rcvd, 0);
  289.                 fset->fset_last_rcvd = NULL;
  290.         } else {
  291.                 printk("hehehehe no filpn");
  292.         }
  293.         if ( rc2 ) {
  294.                 if ( !rc )
  295.                         rc = rc2;
  296.                 printk("presto: close files: last_rcvd filp won't close %dn", rc2);
  297.         }
  298.         if ( fset->fset_lml.fd_file) {
  299.                 rc3 = filp_close(fset->fset_lml.fd_file, 0);
  300.                 fset->fset_lml.fd_file = NULL;
  301.         } else {
  302.                 printk("hehehehe no filpn");
  303.         }
  304.         if ( rc3 ) {
  305.                 if ( (!rc) && (!rc2) )
  306.                         rc = rc3;
  307.                 printk("presto: close files: lml filp won't close %dn", rc3);
  308.         }
  309.         return rc;
  310. }
  311. int presto_fwrite(struct file *file, const char *str, int len, loff_t *off)
  312. {
  313.         int rc;
  314.         mm_segment_t old_fs;
  315.         ENTRY;
  316.         rc = -EINVAL;
  317.         if ( !off ) {
  318.                 EXIT;
  319.                 return rc;
  320.         }
  321.         if ( ! file ) {
  322.                 EXIT;
  323.                 return rc;
  324.         }
  325.         if ( ! file->f_op ) {
  326.                 EXIT;
  327.                 return rc;
  328.         }
  329.         if ( ! file->f_op->write ) {
  330.                 EXIT;
  331.                 return rc;
  332.         }
  333.         old_fs = get_fs();
  334.         set_fs(get_ds());
  335.         rc = file->f_op->write(file, str, len, off);
  336.         if (rc != len) {
  337.                 printk("presto_fwrite: wrote %d bytes instead of "
  338.                        "%d at %ldn", rc, len, (long)*off);
  339.                 rc = -EIO; 
  340.         }
  341.         set_fs(old_fs);
  342.         EXIT;
  343.         return rc;
  344. }
  345. int presto_fread(struct file *file, char *str, int len, loff_t *off)
  346. {
  347.         int rc;
  348.         mm_segment_t old_fs;
  349.         ENTRY;
  350.         if ( len > 512 ) {
  351.                 printk("presto_fread: read at %Ld for %d bytes, ino %ldn",
  352.                        *off, len, file->f_dentry->d_inode->i_ino); 
  353.         }
  354.         rc = -EINVAL;
  355.         if ( !off ) {
  356.                 EXIT;
  357.                 return rc;
  358.         }
  359.         if ( ! file ) {
  360.                 EXIT;
  361.                 return rc;
  362.         }
  363.         if ( ! file->f_op ) {
  364.                 EXIT;
  365.                 return rc;
  366.         }
  367.         if ( ! file->f_op->read ) {
  368.                 EXIT;
  369.                 return rc;
  370.         }
  371.         old_fs = get_fs();
  372.         set_fs(get_ds());
  373.         rc = file->f_op->read(file, str, len, off);
  374.         if (rc != len) {
  375.                 printk("presto_fread: read %d bytes instead of "
  376.                        "%d at %ldn", rc, len, (long)*off);
  377.                 rc = -EIO; 
  378.         }
  379.         set_fs(old_fs);
  380.         return rc;
  381. }
  382. static int presto_kml_dispatch(struct presto_file_set *fset)
  383. {
  384.         int rc = 0;
  385.         unsigned int kml_recno;
  386.         struct presto_log_fd *fd = &fset->fset_kml;
  387.         loff_t  offset;
  388.         ENTRY;
  389.         write_lock(&fd->fd_lock); 
  390.         /* Determine the largest valid offset, i.e. up until the first
  391.          * reservation held on the file. */
  392.         if ( !list_empty(&fd->fd_reservations) ) {
  393.                 struct presto_reservation_data *rd;
  394.                 rd = list_entry(fd->fd_reservations.next, 
  395.                                 struct presto_reservation_data, 
  396.                                 ri_list);
  397.                 offset = rd->ri_offset;
  398.                 kml_recno = rd->ri_recno;
  399.         } else {
  400.                 offset = fd->fd_file->f_dentry->d_inode->i_size;
  401.                 kml_recno = fset->fset_kml.fd_recno; 
  402.         }
  403.         if ( kml_recno < fset->fset_lento_recno ) {
  404.                 printk("presto_kml_dispatch: smoke is comingn"); 
  405.                 write_unlock(&fd->fd_lock);
  406.                 return 0; 
  407.         } else if ( kml_recno == fset->fset_lento_recno ) {
  408.                 write_unlock(&fd->fd_lock);
  409.                 EXIT;
  410.                 return 0; 
  411.         }
  412.         CDEBUG(D_PIOCTL, "fset: %sn", fset->fset_name);
  413.         rc = lento_kml(fset->fset_cache->cache_psdev->uc_minor,
  414.                        fset->fset_lento_off, fset->fset_lento_recno,
  415.                        offset, kml_recno, strlen(fset->fset_name),
  416.                        fset->fset_name);
  417.         if ( rc ) {
  418.                 write_unlock(&fd->fd_lock);
  419.                 EXIT;
  420.                 return rc;
  421.         }
  422.         fset->fset_lento_off = offset;
  423.         fset->fset_lento_recno = kml_recno; 
  424.         write_unlock(&fd->fd_lock);
  425.         EXIT;
  426.         return 0;
  427. }
  428. /* structure of an extended log record:
  429.    buf-prefix  buf-body [string1 [string2 [string3]]] buf-suffix
  430.    note: moves offset forward
  431. */
  432. static inline int presto_write_record(struct file *f, loff_t *off,
  433.                         const char *buf, size_t size,
  434.                         const char *string1, int len1, 
  435.                         const char *string2, int len2,
  436.                         const char *string3, int len3)
  437. {
  438.         size_t prefix_size; 
  439.         int rc;
  440.         prefix_size = size - sizeof(struct journal_suffix);
  441.         rc = presto_fwrite(f, buf, prefix_size, off);
  442.         if ( rc != prefix_size ) {
  443.                 printk("Write error!n");
  444.                 EXIT;
  445.                 return -EIO;
  446.         }
  447.         if  ( string1  && len1 ) {
  448.                 rc = presto_fwrite(f, string1, len1, off);
  449.                 if ( rc != len1 ) {
  450.                         printk("Write error!n");
  451.                         EXIT;
  452.                         return -EIO;
  453.                 }
  454.         }
  455.         if  ( string2 && len2 ) {
  456.                 rc = presto_fwrite(f, string2, len2, off);
  457.                 if ( rc != len2 ) {
  458.                         printk("Write error!n");
  459.                         EXIT;
  460.                         return -EIO;
  461.                 }
  462.         }
  463.         if  ( string3 && len3 ) {
  464.                 rc = presto_fwrite(f, string3, len3, off);
  465.                 if ( rc != len3 ) {
  466.                         printk("Write error!n");
  467.                         EXIT;
  468.                         return -EIO;
  469.                 }
  470.         }
  471.         rc = presto_fwrite(f, buf + prefix_size,
  472.                            sizeof(struct journal_suffix), off);
  473.         if ( rc != sizeof(struct journal_suffix) ) {
  474.                 printk("Write error!n");
  475.                 EXIT;
  476.                 return -EIO;
  477.         }
  478.         return 0;
  479. }
  480. /*
  481.  * rec->size must be valid prior to calling this function.
  482.  */
  483. static int presto_log(struct presto_file_set *fset, struct rec_info *rec,
  484.                       const char *buf, size_t size,
  485.                       const char *string1, int len1, 
  486.                       const char *string2, int len2,
  487.                       const char *string3, int len3)
  488. {
  489.         int rc;
  490.         struct presto_reservation_data rd;
  491.         loff_t offset;
  492.         struct presto_log_fd *fd;
  493.         struct journal_suffix *s;
  494.         int prefix_size; 
  495.         ENTRY;
  496.         /* buf is NULL when no_journal is in effect */
  497.         if (!buf) {
  498.                 EXIT;
  499.                 return -EINVAL;
  500.         }
  501.         if (rec->is_kml) {
  502.                 fd = &fset->fset_kml;
  503.         } else {
  504.                 fd = &fset->fset_lml;
  505.         }
  506.         presto_reserve_record(fset, fd, rec, &rd);
  507.         offset = rec->offset;
  508.         /* now we know the record number */ 
  509.         prefix_size = size - sizeof(struct journal_suffix);
  510.         s = (struct journal_suffix *) (buf + prefix_size); 
  511.         s->recno =  cpu_to_le32(rec->recno); 
  512.         rc = presto_write_record(fd->fd_file, &offset, buf, size, 
  513.                                  string1, len1, string2, len2, string3, len3); 
  514.         if (rc) {
  515.                 printk("presto: error writing record to %sn",
  516.                         rec->is_kml ? "KML" : "LML"); 
  517.                 return rc;
  518.         }
  519.         presto_release_record(fd, &rd);
  520.         rc = presto_kml_dispatch(fset);
  521.         EXIT;
  522.         return rc;
  523. }
  524. /* read from the record at tail */
  525. static int presto_last_record(struct presto_log_fd *fd, loff_t *size, 
  526.                              loff_t *tail_offset, __u32 *recno, loff_t tail)
  527. {
  528.         struct journal_suffix suffix;
  529.         int rc;
  530.         loff_t zeroes;
  531.         *recno = 0;
  532.         *tail_offset = 0;
  533.         *size = 0;
  534.         
  535.         if (tail < sizeof(struct journal_prefix) + sizeof(suffix)) {
  536.                 EXIT;
  537.                 return 0;
  538.         }
  539.         zeroes = tail - sizeof(int);
  540.         while ( zeroes >= 0 ) {
  541.                 int data;
  542.                 rc = presto_fread(fd->fd_file, (char *)&data, sizeof(data), 
  543.                                   &zeroes);
  544.                 if ( rc != sizeof(data) ) { 
  545.                         rc = -EIO;
  546.                         return rc;
  547.                 }
  548.                 if (data)
  549.                         break;
  550.                 zeroes -= 2 * sizeof(data);
  551.         }
  552.         /* zeroes at the begining of file. this is needed to prevent
  553.    presto_fread errors  -SHP
  554. */
  555.         if (zeroes <= 0) return 0;
  556.                        
  557.         zeroes -= sizeof(suffix);
  558.         rc = presto_fread(fd->fd_file, (char *)&suffix, sizeof(suffix), &zeroes);
  559.         if ( rc != sizeof(suffix) ) {
  560.                 EXIT;
  561.                 return rc;
  562.         }
  563.         if ( suffix.len > 500 ) {
  564.                 printk("PRESTO: Warning long record tail at %ld, rec tail_offset at %ld (size %d)n", 
  565.                         (long) zeroes, (long)*tail_offset, suffix.len); 
  566.         }
  567.         *recno = suffix.recno;
  568.         *size = suffix.len;
  569.         *tail_offset = zeroes;
  570.         return 0;
  571. }
  572. static int presto_kml_last_recno(struct presto_file_set *fset)
  573. {
  574.         int rc; 
  575.         loff_t size;
  576.         loff_t tail_offset;
  577.         int recno;
  578.         loff_t tail = fset->fset_kml.fd_file->f_dentry->d_inode->i_size;
  579.         if ((rc = presto_last_record(&fset->fset_kml, &size, 
  580.                                         &tail_offset, &recno, tail)) ) {
  581.                 EXIT;
  582.                 return rc;
  583.         }
  584.         fset->fset_kml.fd_offset = tail_offset;
  585.         fset->fset_kml.fd_recno = recno;
  586.         CDEBUG(D_JOURNAL, "setting fset_kml->fd_recno to %d, offset  %Ldn",
  587.                recno, tail_offset); 
  588.         EXIT;
  589.         return 0;
  590. }
  591. static struct file *presto_log_open(struct presto_file_set *fset, char *name, int flags)
  592. {
  593.         struct presto_cache *cache = fset->fset_cache;
  594.         struct file *f;
  595.         int error;
  596.         int mtpt_len, path_len;
  597.         char *path;
  598.         ENTRY;
  599.         mtpt_len = strlen(cache->cache_mtpt);
  600.         path_len = mtpt_len + strlen("/.intermezzo/") +
  601.                 strlen(fset->fset_name) + strlen(name);
  602.         error = -ENOMEM;
  603.         PRESTO_ALLOC(path, char *, path_len + 1);
  604.         if ( !path ) {
  605.                 EXIT;
  606.                 return ERR_PTR(-ENOMEM);
  607.         }
  608.         sprintf(path, "%s/.intermezzo/%s/%s", cache->cache_mtpt,
  609.                 fset->fset_name, name);
  610.         CDEBUG(D_INODE, "opening file %sn", path);
  611.         f = filp_open(path, flags, 0);
  612.         error = PTR_ERR(f);
  613.         if (IS_ERR(f)) {
  614.                 CDEBUG(D_INODE, "Error %dn", error);
  615.                 EXIT;
  616.                 goto out_free;
  617.         }
  618.         error = -EINVAL;
  619.         if ( cache != presto_get_cache(f->f_dentry->d_inode) ) {
  620.                 printk("PRESTO: %s cache does not match fset cache!n", name);
  621.                 fset->fset_kml.fd_file = NULL;
  622.                 filp_close(f, NULL);
  623.                 goto out_free;
  624.         }
  625.         if (cache->cache_filter &&  cache->cache_filter->o_trops &&
  626.     cache->cache_filter->o_trops->tr_journal_data) {
  627. CDEBUG(D_INODE, "n");
  628.                 cache->cache_filter->o_trops->tr_journal_data
  629.                         (f->f_dentry->d_inode);
  630.         } else {
  631.                 printk("WARNING: InterMezzo no file data logging!n"); 
  632.         }
  633.  out_free:
  634.         PRESTO_FREE(path, path_len + 1);
  635.         EXIT;
  636.         return f;
  637. }
  638. int presto_init_kml_file(struct presto_file_set *fset)
  639. {
  640.         int error = 0;
  641.         struct file *f;
  642.         ENTRY;
  643.         if (fset->fset_kml.fd_file) {
  644.                 CDEBUG(D_INODE, "fset already has KML openn");
  645.                 EXIT;
  646.                 return 0;
  647.         }
  648.         fset->fset_kml.fd_lock = RW_LOCK_UNLOCKED;
  649.         INIT_LIST_HEAD(&fset->fset_kml.fd_reservations); 
  650.         f = presto_log_open(fset, "kml",  O_RDWR | O_CREAT);
  651.         if ( IS_ERR(f) ) {
  652.                 error = PTR_ERR(f);
  653.                 return error;
  654.         }
  655.         fset->fset_kml.fd_file = f;
  656.         error = presto_kml_last_recno(fset);
  657.         if ( error ) {
  658.                 EXIT;
  659.                 fset->fset_kml.fd_file = NULL;
  660.                 filp_close(f, NULL);
  661.                 printk("presto: IO error in KML of fset %sn", 
  662.                        fset->fset_name);
  663.         }
  664.         fset->fset_lento_off = fset->fset_kml.fd_offset;
  665.         fset->fset_lento_recno = fset->fset_kml.fd_recno;
  666.         EXIT;
  667.         return error;
  668. }
  669. int presto_init_last_rcvd_file(struct presto_file_set *fset)
  670. {
  671.         int error = 0;
  672.         struct file *f;
  673.         ENTRY;
  674.         if (fset->fset_last_rcvd) {
  675.                 CDEBUG(D_INODE, "fset already has last_rcvd openn");
  676.                 EXIT;
  677.                 return 0;
  678.         }
  679.         f = presto_log_open(fset, "last_rcvd", O_RDWR | O_CREAT);
  680.         if ( IS_ERR(f) ) {
  681.                 error = PTR_ERR(f);
  682.                 return error;
  683.         }
  684.         fset->fset_last_rcvd = f;
  685.         EXIT;
  686.         return error;
  687. }
  688. int presto_init_lml_file(struct presto_file_set *fset)
  689. {
  690.         int error = 0;
  691.         struct file *f;
  692.         ENTRY;
  693.         if (fset->fset_lml.fd_file) {
  694.                 CDEBUG(D_INODE, "fset already has lml openn");
  695.                 EXIT;
  696.                 return 0;
  697.         }
  698.         fset->fset_lml.fd_lock = RW_LOCK_UNLOCKED;
  699.         INIT_LIST_HEAD(&fset->fset_lml.fd_reservations); 
  700.         f = presto_log_open(fset, "lml", O_RDWR | O_CREAT);
  701.         if ( IS_ERR(f) ) {
  702.                 error = PTR_ERR(f);
  703.                 return error;
  704.         }
  705.         fset->fset_lml.fd_file = f;
  706.         fset->fset_lml.fd_offset = 
  707.                 fset->fset_lml.fd_file->f_dentry->d_inode->i_size;
  708.         EXIT;
  709.         return error;
  710. }
  711. /* Write the last_rcvd values to the last)_rcvd file */
  712. int presto_write_last_rcvd(struct rec_info *recinfo,
  713.                            struct presto_file_set *fset,
  714.                            struct lento_vfs_context *info)
  715. {
  716.         int ret;
  717.         loff_t off = info->slot_offset;
  718.         struct {
  719.                 __u32 remote_recno;
  720.                 __u64 remote_offset;
  721.                 __u32 local_recno;
  722.                 __u64 local_offset;
  723.         } rcvd_rec;
  724.         rcvd_rec.remote_recno = cpu_to_le32(info->recno);
  725.         rcvd_rec.remote_offset = cpu_to_le64(info->kml_offset);
  726.         rcvd_rec.local_recno = cpu_to_le32(recinfo->recno);
  727.         rcvd_rec.local_offset = cpu_to_le64(recinfo->offset + recinfo->size);
  728.         ret = presto_fwrite(fset->fset_last_rcvd, (char *)(&rcvd_rec),
  729.                             sizeof(rcvd_rec), &off);
  730.         if (ret == sizeof(rcvd_rec))
  731.                 ret = 0;
  732.         return ret;
  733. }
  734. /* LML records here */
  735. /* this writes the LML records for close, in conjunction with the KML  */
  736. int presto_write_lml_close(struct rec_info *rec,
  737.                            struct presto_file_set *fset, 
  738.                            struct file *file,
  739.                            __u64 remote_ino,
  740.                            __u32 remote_generation,
  741.                            __u32 remote_version,
  742.                            struct presto_version *new_file_ver)
  743. {
  744.         int opcode = PRESTO_OP_CLOSE;
  745.         char *buffer;
  746.         struct dentry *dentry = file->f_dentry; 
  747.         __u64 ino;
  748.         __u32 pathlen;
  749.         char *path;
  750.         __u32 generation;
  751.         int size;
  752.         char *logrecord;
  753.         char record[292];
  754.         struct dentry *root;
  755.         int error;
  756.         ENTRY;
  757.         if ( presto_no_journal(fset) ) {
  758.           EXIT;
  759.           return 0;
  760.         }
  761.         root = fset->fset_mtpt;
  762.         BUFF_ALLOC(buffer, NULL);
  763.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  764.         CDEBUG(D_INODE, "Path: %sn", path);
  765.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  766.         ino = cpu_to_le64(dentry->d_inode->i_ino);
  767.         generation = cpu_to_le32(dentry->d_inode->i_generation);
  768.         size =  sizeof(__u32) * current->ngroups + 
  769.                 sizeof(struct journal_prefix) + sizeof(*new_file_ver) +
  770.                 sizeof(ino) + sizeof(generation) + sizeof(pathlen) +
  771.                 sizeof(remote_ino) + sizeof(remote_generation) + 
  772.                 sizeof(remote_version) + sizeof(rec->offset) +
  773.                 sizeof(struct journal_suffix);
  774.         if ( size > sizeof(record) ) {
  775.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  776.         }
  777.         rec->is_kml = 0;
  778.         rec->size = size + size_round(le32_to_cpu(pathlen));
  779.         logrecord = journal_log_prefix(record, opcode, rec);
  780.         logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));
  781.         logrecord = logit(logrecord, &ino, sizeof(ino));
  782.         logrecord = logit(logrecord, &generation, sizeof(generation));
  783.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  784.         logrecord = logit(logrecord, &remote_ino, sizeof(remote_ino));
  785.         logrecord = logit(logrecord, &remote_generation,
  786.                           sizeof(remote_generation));
  787.         logrecord = logit(logrecord, &remote_version, sizeof(remote_version));
  788.         logrecord = logit(logrecord, &rec->offset, sizeof(rec->offset));
  789.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  790.         error = presto_log(fset, rec, record, size,
  791.                            path, size_round(le32_to_cpu(pathlen)),
  792.                            NULL, 0, NULL, 0);
  793.         BUFF_FREE(buffer);
  794.         EXIT;
  795.         return error;
  796. }
  797. int presto_journal_write(struct rec_info *rec,
  798.                          struct presto_file_set *fset, 
  799.                          struct file *file)
  800. {
  801.         struct presto_version file_version;
  802.         int rc;
  803.         ENTRY;
  804.         presto_getversion(&file_version, file->f_dentry->d_inode); 
  805.         /* append this record */
  806.         rc = presto_write_lml_close
  807.                 (rec, 
  808.                  fset, 
  809.                  file,
  810.                  0, /* remote_ino */
  811.                  0, /* remote_generation */
  812.                  0, /* remote_version */
  813.                  &file_version);
  814.         EXIT;
  815.         return rc;
  816. }
  817. /* 
  818.  * Check if the given record is at the end of the file. If it is, truncate
  819.  * the lml to the record's offset, removing it. Repeat on prior record,
  820.  * until we reach an active record or a reserved record (as defined by the
  821.  * reservations list).
  822.  */
  823. static int presto_truncate_lml_tail(struct presto_file_set *fset)
  824. {
  825.         loff_t lml_tail;
  826.         loff_t lml_last_rec;
  827.         loff_t lml_last_recsize;
  828.         loff_t local_offset;
  829.         int recno;
  830.         struct journal_prefix prefix;
  831.         struct inode *inode = fset->fset_lml.fd_file->f_dentry->d_inode;
  832.         void *handle;
  833.         int rc;
  834.         ENTRY;
  835.         /* If someone else is already truncating the LML, return. */
  836.         write_lock(&fset->fset_lml.fd_lock); 
  837.         if (fset->fset_lml.fd_truncating == 1 ) {
  838.                 write_unlock(&fset->fset_lml.fd_lock); 
  839.                 EXIT;
  840.                 return 0;
  841.         }
  842.         /* someone is about to write to the end of the LML */ 
  843.         if ( !list_empty(&fset->fset_lml.fd_reservations) ) {
  844.                 write_unlock(&fset->fset_lml.fd_lock); 
  845.                 EXIT;
  846.                 return 0;
  847.         }
  848.        lml_tail = fset->fset_lml.fd_file->f_dentry->d_inode->i_size;
  849.        /* Nothing to truncate?*/
  850.        if (lml_tail == 0) {
  851.                 write_unlock(&fset->fset_lml.fd_lock); 
  852.                 EXIT;
  853.                 return 0;
  854.        }
  855.        fset->fset_lml.fd_truncating = 1;
  856.        write_unlock(&fset->fset_lml.fd_lock); 
  857.        presto_last_record(&fset->fset_lml, &lml_last_recsize,
  858.                           &lml_last_rec, &recno, lml_tail);
  859.        /* Do we have a record to check? If not we have zeroes at the
  860.           beginning of the file. -SHP
  861.        */
  862.        if (lml_last_recsize != 0) {
  863.         local_offset = lml_last_rec - lml_last_recsize;
  864.         rc = presto_fread(fset->fset_lml.fd_file, (char *)&prefix,  
  865.                            sizeof(prefix), &local_offset); 
  866.          if (rc != sizeof(prefix)) {
  867.                  EXIT;
  868.                  goto tr_out;
  869.          }
  870.        
  871.          if ( prefix.opcode != PRESTO_OP_NOOP ) {
  872.                  EXIT;
  873.                  rc = 0;
  874.                         /* We may have zeroes at the end of the file, should
  875.    we clear them out? -SHP
  876.                         */
  877.                  goto tr_out;
  878.          }
  879. } else 
  880.   lml_last_rec=0;
  881.         handle = presto_trans_start(fset, inode, PRESTO_OP_TRUNC);
  882.         if ( !handle ) {
  883.                 EXIT;
  884.                 rc = -ENOMEM;
  885.                 goto tr_out;
  886.         }
  887.         rc = presto_do_truncate(fset, fset->fset_lml.fd_file->f_dentry, 
  888.                                 lml_last_rec - lml_last_recsize, lml_tail);
  889.         presto_trans_commit(fset, handle); 
  890.         if ( rc == 0 ) {
  891.                 rc = 1;
  892.         }
  893.         EXIT;
  894.  tr_out:
  895.         CDEBUG(D_JOURNAL, "rc = %dn", rc);
  896.         write_lock(&fset->fset_lml.fd_lock);
  897.         fset->fset_lml.fd_truncating = 0;
  898.         write_unlock(&fset->fset_lml.fd_lock);
  899.         return rc;
  900. }
  901. int presto_truncate_lml(struct presto_file_set *fset)
  902. {
  903.         int rc; 
  904.         ENTRY;
  905.         
  906.         while ( (rc = presto_truncate_lml_tail(fset)) > 0);
  907.         if ( rc < 0 && rc != -EALREADY) {
  908.                 printk("truncate_lml error %dn", rc); 
  909.         }
  910.         EXIT;
  911.         return rc;
  912. }
  913. int presto_clear_lml_close(struct presto_file_set *fset, 
  914.                            loff_t  lml_offset)
  915. {
  916.         int rc;
  917.         struct journal_prefix record;
  918.         loff_t offset = lml_offset;
  919.         ENTRY;
  920.         if ( presto_no_journal(fset) ) {
  921.                 EXIT;
  922.                 return 0;
  923.         }
  924.         CDEBUG(D_JOURNAL, "reading prefix: off %ld, size %Zdn", 
  925.                (long)lml_offset, sizeof(record));
  926.         rc = presto_fread(fset->fset_lml.fd_file, (char *)&record,
  927.                           sizeof(record), &offset);
  928.         if ( rc != sizeof(record) ) {
  929.                 printk("presto: clear_lml io error %dn", rc); 
  930.                 EXIT;
  931.                 return -EIO;
  932.         }
  933.         /* overwrite the prefix */ 
  934.         CDEBUG(D_JOURNAL, "overwriting prefix: off %ldn", (long)lml_offset);
  935.         record.opcode = PRESTO_OP_NOOP;
  936.         offset = lml_offset;
  937.         /* note: this does just a single transaction in the cache */
  938.         rc = presto_fwrite(fset->fset_lml.fd_file, (char *)(&record), 
  939.                               sizeof(record), &offset);
  940.         if ( rc != sizeof(record) ) {
  941.                 EXIT;
  942.                 return -EIO;
  943.         }
  944.         EXIT;
  945.         return 0; 
  946. }
  947. /* now a journal function for every operation */
  948. int presto_journal_setattr(struct rec_info *rec, 
  949.                            struct presto_file_set *fset, 
  950.                            struct dentry *dentry,
  951.                            struct presto_version *old_ver, struct iattr *iattr)
  952. {
  953.         int opcode = PRESTO_OP_SETATTR;
  954.         char *buffer;
  955.         char *path;
  956.         __u32 pathlen;
  957.         int size;
  958.         char *logrecord;
  959.         char record[292];
  960.         struct dentry *root;
  961.         __u32 uid, gid, mode, valid, flags;
  962.         __u64 fsize, mtime, ctime;
  963.         int error;
  964.         ENTRY;
  965.         if ( presto_no_journal(fset) ) {
  966.                 EXIT;
  967.                 return 0;
  968.         }
  969.         if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) ) {
  970.                 EXIT;
  971.                 return 0;
  972.         }
  973.         root = fset->fset_mtpt;
  974.         BUFF_ALLOC(buffer, NULL);
  975.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  976.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  977.         size =  sizeof(__u32) * current->ngroups + 
  978.                 sizeof(struct journal_prefix) + sizeof(*old_ver) +
  979.                 sizeof(valid) + sizeof(mode) + sizeof(uid) + sizeof(gid) +
  980.                 sizeof(fsize) + sizeof(mtime) + sizeof(ctime) + sizeof(flags) +
  981.                 sizeof(pathlen) + sizeof(struct journal_suffix);
  982.         if ( size > sizeof(record) ) {
  983.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  984.         }
  985.         /* Only journal one kind of mtime, and not atime at all.  Also don't
  986.          * journal bogus data in iattr, to make the journal more compressible.
  987.          */
  988.         if (iattr->ia_valid & ATTR_MTIME_SET)
  989.                 iattr->ia_valid = iattr->ia_valid | ATTR_MTIME;
  990.         valid = cpu_to_le32(iattr->ia_valid & ~(ATTR_ATIME | ATTR_MTIME_SET |
  991.                                                 ATTR_ATIME_SET));
  992.         mode = iattr->ia_valid & ATTR_MODE ? cpu_to_le32(iattr->ia_mode): 0;
  993.         uid = iattr->ia_valid & ATTR_UID ? cpu_to_le32(iattr->ia_uid): 0;
  994.         gid = iattr->ia_valid & ATTR_GID ? cpu_to_le32(iattr->ia_gid): 0;
  995.         fsize = iattr->ia_valid & ATTR_SIZE ? cpu_to_le64(iattr->ia_size): 0;
  996.         mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime): 0;
  997.         ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime): 0;
  998.         flags = iattr->ia_valid & ATTR_ATTR_FLAG ?
  999.                 cpu_to_le32(iattr->ia_attr_flags): 0;
  1000.         rec->is_kml = 1;
  1001.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1002.         logrecord = journal_log_prefix(record, opcode, rec);
  1003.         logrecord = logit(logrecord, old_ver, sizeof(*old_ver));
  1004.         logrecord = logit(logrecord, &valid, sizeof(valid));
  1005.         logrecord = logit(logrecord, &mode, sizeof(mode));
  1006.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1007.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1008.         logrecord = logit(logrecord, &fsize, sizeof(fsize));
  1009.         logrecord = logit(logrecord, &mtime, sizeof(mtime));
  1010.         logrecord = logit(logrecord, &ctime, sizeof(ctime));
  1011.         logrecord = logit(logrecord, &flags, sizeof(flags));
  1012.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1013.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1014.         error = presto_log(fset, rec, record, size,
  1015.                            path, size_round(le32_to_cpu(pathlen)),
  1016.                            NULL, 0, NULL, 0);
  1017.         BUFF_FREE(buffer);
  1018.         EXIT;
  1019.         return error;
  1020. }
  1021. int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset,
  1022.                           struct dentry *dentry,
  1023.                           struct presto_version *tgt_dir_ver,
  1024.                           struct presto_version *new_file_ver, int mode)
  1025. {
  1026.         int opcode = PRESTO_OP_CREATE;
  1027.         char *buffer;
  1028.         char *path;
  1029.         __u32 pathlen;
  1030.         int size;
  1031.         char *logrecord;
  1032.         char record[292];
  1033.         struct dentry *root;
  1034.         __u32 uid, gid, lmode;
  1035.         int error;
  1036.         ENTRY;
  1037.         if ( presto_no_journal(fset) ) {
  1038.                 EXIT;
  1039.                 return 0;
  1040.         }
  1041.         root = fset->fset_mtpt;
  1042.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1043.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1044.         lmode = cpu_to_le32(mode);
  1045.  
  1046.         BUFF_ALLOC(buffer, NULL);
  1047.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1048.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1049.         size =  sizeof(__u32) * current->ngroups + 
  1050.                 sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
  1051.                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
  1052.                 sizeof(struct journal_suffix);
  1053.         if ( size > sizeof(record) ) {
  1054.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1055.         }
  1056.         rec->is_kml = 1;
  1057.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1058.         logrecord = journal_log_prefix(record, opcode, rec);
  1059.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1060.         logrecord = log_version(logrecord, dentry->d_parent);
  1061.         logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));
  1062.         logrecord = logit(logrecord, &lmode, sizeof(lmode));
  1063.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1064.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1065.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1066.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1067.         error = presto_log(fset, rec, record, size,
  1068.                            path, size_round(le32_to_cpu(pathlen)),
  1069.                            NULL, 0, NULL, 0);
  1070.         BUFF_FREE(buffer);
  1071.         EXIT;
  1072.         return error;
  1073. }
  1074. int presto_journal_symlink(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dentry,
  1075.                            const char *target,
  1076.                            struct presto_version *tgt_dir_ver,
  1077.                            struct presto_version *new_link_ver)
  1078. {
  1079.         int opcode = PRESTO_OP_SYMLINK;
  1080.         char *buffer;
  1081.         char *path;
  1082.         __u32 pathlen;
  1083.         int size;
  1084.         char *logrecord;
  1085.         char record[292];
  1086.         __u32 targetlen = cpu_to_le32(strlen(target));
  1087.         struct dentry *root;
  1088.         __u32 uid, gid;
  1089.         int error;
  1090.         ENTRY;
  1091.         if ( presto_no_journal(fset) ) {
  1092.                 EXIT;
  1093.                 return 0;
  1094.         }
  1095.         root = fset->fset_mtpt;
  1096.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1097.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1098.         BUFF_ALLOC(buffer, NULL);
  1099.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1100.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1101.         size =  sizeof(__u32) * current->ngroups + 
  1102.                 sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
  1103.                 sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
  1104.                 sizeof(targetlen) + sizeof(struct journal_suffix);
  1105.         if ( size > sizeof(record) ) {
  1106.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1107.         }
  1108.         rec->is_kml = 1;
  1109.         rec->size = size + size_round(le32_to_cpu(pathlen)) +
  1110.                 size_round(le32_to_cpu(targetlen));
  1111.         logrecord = journal_log_prefix(record, opcode, rec);
  1112.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1113.         logrecord = log_version(logrecord, dentry->d_parent);
  1114.         logrecord = logit(logrecord, new_link_ver, sizeof(*new_link_ver));
  1115.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1116.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1117.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1118.         logrecord = logit(logrecord, &targetlen, sizeof(targetlen));
  1119.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1120.         error = presto_log(fset, rec, record, size,
  1121.                            path, size_round(le32_to_cpu(pathlen)),
  1122.                            target, size_round(le32_to_cpu(targetlen)),
  1123.                            NULL, 0);
  1124.         BUFF_FREE(buffer);
  1125.         EXIT;
  1126.         return error;
  1127. }
  1128. int presto_journal_mkdir(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dentry,
  1129.                          struct presto_version *tgt_dir_ver,
  1130.                          struct presto_version *new_dir_ver, int mode)
  1131. {
  1132.         int opcode = PRESTO_OP_MKDIR;
  1133.         char *buffer;
  1134.         char *path;
  1135.         __u32 pathlen;
  1136.         int size;
  1137.         char *logrecord;
  1138.         char record[292];
  1139.         struct dentry *root;
  1140.         __u32 uid, gid, lmode;
  1141.         int error;
  1142.         ENTRY;
  1143.         if ( presto_no_journal(fset) ) {
  1144.                 EXIT;
  1145.                 return 0;
  1146.         }
  1147.         root = fset->fset_mtpt;
  1148.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1149.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1150.         lmode = cpu_to_le32(mode);
  1151.         BUFF_ALLOC(buffer, NULL);
  1152.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1153.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1154.         size = sizeof(__u32) * current->ngroups + 
  1155.                 sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
  1156.                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
  1157.                 sizeof(struct journal_suffix);
  1158.         if ( size > sizeof(record) ) {
  1159.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1160.         }
  1161.         rec->is_kml = 1;
  1162.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1163.         logrecord = journal_log_prefix(record, opcode, rec);
  1164.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1165.         logrecord = log_version(logrecord, dentry->d_parent);
  1166.         logrecord = logit(logrecord, new_dir_ver, sizeof(*new_dir_ver));
  1167.         logrecord = logit(logrecord, &lmode, sizeof(lmode));
  1168.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1169.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1170.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1171.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1172.         error = presto_log(fset, rec, record, size,
  1173.                            path, size_round(le32_to_cpu(pathlen)),
  1174.                            NULL, 0, NULL, 0);
  1175.         BUFF_FREE(buffer);
  1176.         EXIT;
  1177.         return error;
  1178. }
  1179. int
  1180. presto_journal_rmdir(struct rec_info *rec, struct presto_file_set *fset,
  1181.                      struct dentry *dir, struct presto_version *tgt_dir_ver,
  1182.                      struct presto_version *old_dir_ver, int len,
  1183.                      const char *name)
  1184. {
  1185.         int opcode = PRESTO_OP_RMDIR;
  1186.         char *buffer;
  1187.         char *path;
  1188.         __u32 pathlen, llen;
  1189.         int size;
  1190.         char *logrecord;
  1191.         char record[292];
  1192.         struct dentry *root;
  1193.         int error;
  1194.         ENTRY;
  1195.         if ( presto_no_journal(fset) ) {
  1196.                 EXIT;
  1197.                 return 0;
  1198.         }
  1199.         root = fset->fset_mtpt;
  1200.         llen = cpu_to_le32(len);
  1201.         BUFF_ALLOC(buffer, NULL);
  1202.         path = presto_path(dir, root, buffer, PAGE_SIZE);
  1203.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1204.         size =  sizeof(__u32) * current->ngroups + 
  1205.                 sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
  1206.                 sizeof(pathlen) + sizeof(llen) + sizeof(struct journal_suffix);
  1207.         if ( size > sizeof(record) ) {
  1208.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1209.         }
  1210.         CDEBUG(D_JOURNAL, "path: %s (%d), name: %s (%d), size %dn",
  1211.                path, pathlen, name, len, size);
  1212.         rec->is_kml = 1;
  1213.         rec->size = size + size_round(le32_to_cpu(pathlen)) + 
  1214.                 size_round(len);
  1215.         logrecord = journal_log_prefix(record, opcode, rec);
  1216.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1217.         logrecord = log_version(logrecord, dir);
  1218.         logrecord = logit(logrecord, old_dir_ver, sizeof(*old_dir_ver));
  1219.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1220.         logrecord = logit(logrecord, &llen, sizeof(llen));
  1221.         logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
  1222.         error = presto_log(fset, rec, record, size,
  1223.                            path, size_round(le32_to_cpu(pathlen)),
  1224.                            name, size_round(len),
  1225.                            NULL, 0);
  1226.         BUFF_FREE(buffer);
  1227.         EXIT;
  1228.         return error;
  1229. }
  1230. int
  1231. presto_journal_mknod(struct rec_info *rec, struct presto_file_set *fset,
  1232.                      struct dentry *dentry, struct presto_version *tgt_dir_ver,
  1233.                      struct presto_version *new_node_ver, int mode,
  1234.                      int dmajor, int dminor )
  1235. {
  1236.         int opcode = PRESTO_OP_MKNOD;
  1237.         char *buffer;
  1238.         char *path;
  1239.         __u32 pathlen;
  1240.         int size;
  1241.         char *logrecord;
  1242.         char record[292];
  1243.         struct dentry *root;
  1244.         __u32 uid, gid, lmode, lmajor, lminor;
  1245.         int error;
  1246.         ENTRY;
  1247.         if ( presto_no_journal(fset) ) {
  1248.                 EXIT;
  1249.                 return 0;
  1250.         }
  1251.         root = fset->fset_mtpt;
  1252.         uid = cpu_to_le32(dentry->d_inode->i_uid);
  1253.         gid = cpu_to_le32(dentry->d_inode->i_gid);
  1254.         lmode = cpu_to_le32(mode);
  1255.         lmajor = cpu_to_le32(dmajor);
  1256.         lminor = cpu_to_le32(dminor);
  1257.         BUFF_ALLOC(buffer, NULL);
  1258.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1259.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1260.         size = sizeof(__u32) * current->ngroups + 
  1261.                 sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
  1262.                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(lmajor) +
  1263.                 sizeof(lminor) + sizeof(pathlen) +
  1264.                 sizeof(struct journal_suffix);
  1265.         if ( size > sizeof(record) ) {
  1266.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1267.         }
  1268.         rec->is_kml = 1;
  1269.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1270.         logrecord = journal_log_prefix(record, opcode, rec);
  1271.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1272.         logrecord = log_version(logrecord, dentry->d_parent);
  1273.         logrecord = logit(logrecord, new_node_ver, sizeof(*new_node_ver));
  1274.         logrecord = logit(logrecord, &lmode, sizeof(lmode));
  1275.         logrecord = logit(logrecord, &uid, sizeof(uid));
  1276.         logrecord = logit(logrecord, &gid, sizeof(gid));
  1277.         logrecord = logit(logrecord, &lmajor, sizeof(lmajor));
  1278.         logrecord = logit(logrecord, &lminor, sizeof(lminor));
  1279.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1280.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1281.         error = presto_log(fset, rec, record, size,
  1282.                            path, size_round(le32_to_cpu(pathlen)),
  1283.                            NULL, 0, NULL, 0);
  1284.         BUFF_FREE(buffer);
  1285.         EXIT;
  1286.         return error;
  1287. }
  1288. int
  1289. presto_journal_link(struct rec_info *rec, struct presto_file_set *fset,
  1290.                     struct dentry *src, struct dentry *tgt,
  1291.                     struct presto_version *tgt_dir_ver,
  1292.                     struct presto_version *new_link_ver)
  1293. {
  1294.         int opcode = PRESTO_OP_LINK;
  1295.         char *buffer, *srcbuffer;
  1296.         char *path, *srcpath;
  1297.         __u32 pathlen, srcpathlen;
  1298.         int size;
  1299.         char *logrecord;
  1300.         char record[292];
  1301.         struct dentry *root;
  1302.         int error;
  1303.         ENTRY;
  1304.         if ( presto_no_journal(fset) ) {
  1305.                 EXIT;
  1306.                 return 0;
  1307.         }
  1308.         root = fset->fset_mtpt;
  1309.         BUFF_ALLOC(srcbuffer, NULL);
  1310.         srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
  1311.         srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
  1312.         BUFF_ALLOC(buffer, srcbuffer);
  1313.         path = presto_path(tgt, root, buffer, PAGE_SIZE);
  1314.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1315.         size =  sizeof(__u32) * current->ngroups + 
  1316.                 sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
  1317.                 sizeof(srcpathlen) + sizeof(pathlen) +
  1318.                 sizeof(struct journal_suffix);
  1319.         if ( size > sizeof(record) ) {
  1320.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1321.         }
  1322.         rec->is_kml = 1;
  1323.         rec->size = size + size_round(le32_to_cpu(pathlen)) + 
  1324.                 size_round(le32_to_cpu(srcpathlen));
  1325.         logrecord = journal_log_prefix(record, opcode, rec);
  1326.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1327.         logrecord = log_version(logrecord, tgt->d_parent);
  1328.         logrecord = logit(logrecord, new_link_ver, sizeof(*new_link_ver));
  1329.         logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
  1330.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1331.         logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
  1332.         error = presto_log(fset, rec, record, size,
  1333.                            srcpath, size_round(le32_to_cpu(srcpathlen)),
  1334.                            path, size_round(le32_to_cpu(pathlen)),
  1335.                            NULL, 0);
  1336.         BUFF_FREE(srcbuffer);
  1337.         BUFF_FREE(buffer);
  1338.         EXIT;
  1339.         return error;
  1340. }
  1341. int presto_journal_rename(struct rec_info *rec, struct presto_file_set *fset, struct dentry *src,
  1342.                           struct dentry *tgt,
  1343.                           struct presto_version *src_dir_ver,
  1344.                           struct presto_version *tgt_dir_ver)
  1345. {
  1346.         int opcode = PRESTO_OP_RENAME;
  1347.         char *buffer, *srcbuffer;
  1348.         char *path, *srcpath;
  1349.         __u32 pathlen, srcpathlen;
  1350.         int size;
  1351.         char *logrecord;
  1352.         char record[292];
  1353.         struct dentry *root;
  1354.         int error;
  1355.         ENTRY;
  1356.         if ( presto_no_journal(fset) ) {
  1357.                 EXIT;
  1358.                 return 0;
  1359.         }
  1360.         root = fset->fset_mtpt;
  1361.         BUFF_ALLOC(srcbuffer, NULL);
  1362.         srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
  1363.         srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
  1364.         BUFF_ALLOC(buffer, srcbuffer);
  1365.         path = presto_path(tgt, root, buffer, PAGE_SIZE);
  1366.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1367.         size =  sizeof(__u32) * current->ngroups + 
  1368.                 sizeof(struct journal_prefix) + 4 * sizeof(*src_dir_ver) +
  1369.                 sizeof(srcpathlen) + sizeof(pathlen) +
  1370.                 sizeof(struct journal_suffix);
  1371.         if ( size > sizeof(record) ) {
  1372.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1373.         }
  1374.         rec->is_kml = 1;
  1375.         rec->size = size + size_round(le32_to_cpu(pathlen)) + 
  1376.                 size_round(le32_to_cpu(srcpathlen));
  1377.         logrecord = journal_log_prefix(record, opcode, rec);
  1378.         logrecord = logit(logrecord, src_dir_ver, sizeof(*src_dir_ver));
  1379.         logrecord = log_version(logrecord, src->d_parent);
  1380.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1381.         logrecord = log_version(logrecord, tgt->d_parent);
  1382.         logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
  1383.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1384.         logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
  1385.         error = presto_log(fset, rec, record, size,
  1386.                            srcpath, size_round(le32_to_cpu(srcpathlen)),
  1387.                            path, size_round(le32_to_cpu(pathlen)),
  1388.                            NULL, 0);
  1389.         BUFF_FREE(buffer);
  1390.         BUFF_FREE(srcbuffer);
  1391.         EXIT;
  1392.         return error;
  1393. }
  1394. int presto_journal_unlink(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dir,
  1395.                           struct presto_version *tgt_dir_ver,
  1396.                           struct presto_version *old_file_ver, int len,
  1397.                           const char *name)
  1398. {
  1399.         int opcode = PRESTO_OP_UNLINK;
  1400.         char *buffer;
  1401.         char *path;
  1402.         __u32 pathlen, llen;
  1403.         int size;
  1404.         char *logrecord;
  1405.         char record[292];
  1406.         struct dentry *root;
  1407.         int error;
  1408.         ENTRY;
  1409.         if ( presto_no_journal(fset) ) {
  1410.                 EXIT;
  1411.                 return 0;
  1412.         }
  1413.         root = fset->fset_mtpt;
  1414.         llen = cpu_to_le32(len);
  1415.         BUFF_ALLOC(buffer, NULL);
  1416.         path = presto_path(dir, root, buffer, PAGE_SIZE);
  1417.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1418.         size =  sizeof(__u32) * current->ngroups + 
  1419.                 sizeof(struct journal_prefix) + 3 * sizeof(*tgt_dir_ver) +
  1420.                 sizeof(pathlen) + sizeof(llen) + sizeof(struct journal_suffix);
  1421.         if ( size > sizeof(record) ) {
  1422.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1423.         }
  1424.         rec->is_kml = 1;
  1425.         rec->size = size + size_round(le32_to_cpu(pathlen)) + size_round(len);
  1426.         logrecord = journal_log_prefix(record, opcode, rec);
  1427.         logrecord = logit(logrecord, tgt_dir_ver, sizeof(*tgt_dir_ver));
  1428.         logrecord = log_version(logrecord, dir);
  1429.         logrecord = logit(logrecord, old_file_ver, sizeof(*old_file_ver));
  1430.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1431.         logrecord = logit(logrecord, &llen, sizeof(llen));
  1432.         logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
  1433.         error = presto_log(fset, rec, record, size,
  1434.                            path, size_round(le32_to_cpu(pathlen)),
  1435.                            name, size_round(len), 
  1436.                            NULL, 0);
  1437.         BUFF_FREE(buffer);
  1438.         EXIT;
  1439.         return error;
  1440. }
  1441. int
  1442. presto_journal_close(struct rec_info *rec, struct presto_file_set *fset,
  1443.                      struct file *file, struct dentry *dentry,
  1444.      struct presto_version *new_file_ver)
  1445. {
  1446.         int opcode = PRESTO_OP_CLOSE;
  1447.         struct presto_file_data *fd;
  1448.         char *buffer;
  1449.         char *path;
  1450.         __u64 ino;
  1451.         __u32 pathlen;
  1452.         __u32 generation;
  1453.         int size;
  1454.         char *logrecord;
  1455.         char record[292];
  1456.         struct dentry *root;
  1457.         int error;
  1458.         __u32 open_fsuid;
  1459.         __u32 open_fsgid;
  1460.         __u32 open_ngroups;
  1461.         __u32 open_groups[NGROUPS_MAX];
  1462.         __u32 open_mode;
  1463.         __u32 open_uid;
  1464.         __u32 open_gid;
  1465.         int i;
  1466.         ENTRY;
  1467.         if ( presto_no_journal(fset) ) {
  1468.                 EXIT;
  1469.                 return 0;
  1470.         }
  1471.         if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) ) {
  1472.                 EXIT;
  1473.                 return 0;
  1474.         }
  1475.         root = fset->fset_mtpt;
  1476.         fd = (struct presto_file_data *)file->private_data;
  1477.         if (fd) {
  1478.                 open_ngroups = fd->fd_ngroups;
  1479.                 for (i = 0; i < fd->fd_ngroups; i++)
  1480. open_groups[i] = (__u32) fd->fd_groups[i];
  1481.                 open_mode = fd->fd_mode;
  1482.                 open_uid = fd->fd_uid;
  1483.                 open_gid = fd->fd_gid;
  1484.                 open_fsuid = fd->fd_fsuid;
  1485.                 open_fsgid = fd->fd_fsgid;
  1486.         } else {
  1487.                 open_ngroups = current->ngroups;
  1488.                 for (i=0; i<current->ngroups; i++)
  1489. open_groups[i] =  (__u32) current->groups[i]; 
  1490.                 open_mode = dentry->d_inode->i_mode;
  1491.                 open_uid = dentry->d_inode->i_uid;
  1492.                 open_gid = dentry->d_inode->i_gid;
  1493.                 open_fsuid = current->fsuid;
  1494.                 open_fsgid = current->fsgid;
  1495.         }
  1496.         BUFF_ALLOC(buffer, NULL);
  1497.         path = presto_path(dentry, root, buffer, PAGE_SIZE);
  1498.         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
  1499.         ino = cpu_to_le64(dentry->d_inode->i_ino);
  1500.         generation = cpu_to_le32(dentry->d_inode->i_generation);
  1501.         size =  sizeof(__u32) * open_ngroups +
  1502.                 sizeof(open_mode) + sizeof(open_uid) + sizeof(open_gid) +
  1503.                 sizeof(struct journal_prefix) + sizeof(*new_file_ver) +
  1504.                 sizeof(ino) + sizeof(generation) + sizeof(pathlen) +
  1505.                 sizeof(struct journal_suffix);
  1506.         if ( size > sizeof(record) ) {
  1507.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1508.         }
  1509.         rec->is_kml = 1;
  1510.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1511.         logrecord = journal_log_prefix_with_groups_and_ids(
  1512.                 record, opcode, rec, open_ngroups, open_groups,
  1513.                 open_fsuid, open_fsgid);
  1514.         logrecord = logit(logrecord, &open_mode, sizeof(open_mode));
  1515.         logrecord = logit(logrecord, &open_uid, sizeof(open_uid));
  1516.         logrecord = logit(logrecord, &open_gid, sizeof(open_gid));
  1517.         logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));
  1518.         logrecord = logit(logrecord, &ino, sizeof(ino));
  1519.         logrecord = logit(logrecord, &generation, sizeof(generation));
  1520.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1521.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1522.         error = presto_log(fset, rec, record, size,
  1523.                            path, size_round(le32_to_cpu(pathlen)),
  1524.                            NULL, 0, NULL, 0);
  1525.         BUFF_FREE(buffer);
  1526.         EXIT;
  1527.         return error;
  1528. }
  1529. int presto_rewrite_close(struct rec_info *rec, struct presto_file_set *fset, 
  1530.                          char *path, __u32 pathlen, 
  1531.                          int ngroups, __u32 *groups, 
  1532.                          __u64 ino,     __u32 generation, 
  1533.                          struct presto_version *new_file_ver)
  1534. {
  1535.         int opcode = PRESTO_OP_CLOSE;
  1536.         int size;
  1537.         char *logrecord;
  1538.         char record[292];
  1539.         struct dentry *root;
  1540.         int error;
  1541.         ENTRY;
  1542.         if ( presto_no_journal(fset) ) {
  1543.                 EXIT;
  1544.                 return 0;
  1545.         }
  1546.         root = fset->fset_mtpt;
  1547.         size =  sizeof(__u32) * ngroups + 
  1548.                 sizeof(struct journal_prefix) + sizeof(*new_file_ver) +
  1549.                 sizeof(ino) + sizeof(generation) + 
  1550.                 sizeof(le32_to_cpu(pathlen)) +
  1551.                 sizeof(struct journal_suffix);
  1552.         if ( size > sizeof(record) ) {
  1553.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1554.         }
  1555.         rec->is_kml = 1;
  1556.         rec->size = size + size_round(le32_to_cpu(pathlen));
  1557.         logrecord = journal_log_prefix_with_groups(record, opcode, rec,
  1558.                                                    ngroups, groups);
  1559.         logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver));
  1560.         logrecord = logit(logrecord, &ino, sizeof(ino));
  1561.         logrecord = logit(logrecord, &generation, sizeof(generation));
  1562.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1563.         logrecord = journal_log_suffix(logrecord, record, fset, NULL, rec);
  1564.         error = presto_log(fset, rec, record, size,
  1565.                            path, size_round(le32_to_cpu(pathlen)),
  1566.                            NULL, 0, NULL, 0);
  1567.         EXIT;
  1568.         return error;
  1569. }
  1570. /* write closes for the local close records in the LML */ 
  1571. int presto_complete_lml(struct presto_file_set *fset)
  1572. {
  1573.         __u32 groups[NGROUPS_MAX];
  1574.         loff_t lml_offset;
  1575.         loff_t read_offset; 
  1576.         char *buffer;
  1577.         void *handle;
  1578.         struct rec_info rec;
  1579.         struct close_rec { 
  1580.                 struct presto_version new_file_ver;
  1581.                 __u64 ino;
  1582.                 __u32 generation;
  1583.                 __u32 pathlen;
  1584.                 __u64 remote_ino;
  1585.                 __u32 remote_generation;
  1586.                 __u32 remote_version;
  1587.                 __u64 lml_offset;
  1588.         } close_rec; 
  1589.         struct file *file = fset->fset_lml.fd_file;
  1590.         struct journal_prefix prefix;
  1591.         int rc = 0;
  1592.         ENTRY;
  1593.         lml_offset = 0; 
  1594.  again: 
  1595.         if (lml_offset >= file->f_dentry->d_inode->i_size) {
  1596.                 EXIT;
  1597.                 return rc;
  1598.         }
  1599.         read_offset = lml_offset;
  1600.         rc = presto_fread(file, (char *)&prefix,
  1601.                           sizeof(prefix), &read_offset);
  1602.         if ( rc != sizeof(prefix) ) {
  1603.                 EXIT;
  1604.                 printk("presto_complete_lml: ioerror - 1, tell Petern");
  1605.                 return -EIO;
  1606.         }
  1607.         if ( prefix.opcode == PRESTO_OP_NOOP ) {
  1608.                 lml_offset += prefix.len; 
  1609.                 goto again; 
  1610.         }
  1611.         rc = presto_fread(file, (char *)groups, 
  1612.                           prefix.ngroups * sizeof(__u32), &read_offset); 
  1613.         if ( rc != prefix.ngroups * sizeof(__u32) ) {
  1614.                 EXIT;
  1615.                 printk("presto_complete_lml: ioerror - 2, tell Petern");
  1616.                 return -EIO;
  1617.         }
  1618.         rc = presto_fread(file, (char *)&close_rec, 
  1619.                           sizeof(close_rec), &read_offset); 
  1620.         if ( rc != sizeof(close_rec) ) {
  1621.                 EXIT;
  1622.                 printk("presto_complete_lml: ioerror - 3, tell Petern");
  1623.                 return -EIO;
  1624.         }
  1625.         /* is this a backfetch or a close record? */ 
  1626.         if ( le64_to_cpu(close_rec.remote_ino) != 0 ) { 
  1627.                 lml_offset += prefix.len;
  1628.                 goto again; 
  1629.         }
  1630.         BUFF_ALLOC(buffer, NULL);
  1631.         rc = presto_fread(file, (char *)buffer, 
  1632.                           le32_to_cpu(close_rec.pathlen), &read_offset); 
  1633.         if ( rc != le32_to_cpu(close_rec.pathlen) ) {
  1634.                 EXIT;
  1635.                 printk("presto_complete_lml: ioerror - 4, tell Petern");
  1636.                 return -EIO;
  1637.         }
  1638.         
  1639.         handle = presto_trans_start(fset, file->f_dentry->d_inode, 
  1640.                                     PRESTO_OP_RELEASE);
  1641.         if ( !handle ) {
  1642.                 EXIT;
  1643.                 return -ENOMEM; 
  1644.         }
  1645.         rc = presto_clear_lml_close(fset, lml_offset); 
  1646.         if ( rc ) {
  1647.                 printk("error during clearing: %dn", rc);
  1648.                 presto_trans_commit(fset, handle);
  1649.                 EXIT; 
  1650.                 return rc; 
  1651.         }
  1652.         rc = presto_rewrite_close(&rec, fset, buffer, close_rec.pathlen, 
  1653.                                   prefix.ngroups, groups, 
  1654.                                   close_rec.ino, close_rec.generation,
  1655.                                   &close_rec.new_file_ver); 
  1656.         if ( rc ) {
  1657.                 printk("error during rewrite close: %dn", rc);
  1658.                 presto_trans_commit(fset, handle);
  1659.                 EXIT; 
  1660.                 return rc; 
  1661.         }
  1662.         presto_trans_commit(fset, handle); 
  1663.         if ( rc ) { 
  1664.                 printk("error during truncation: %dn", rc);
  1665.                 EXIT; 
  1666.                 return rc;
  1667.         }
  1668.         
  1669.         lml_offset += prefix.len; 
  1670.         CDEBUG(D_JOURNAL, "next LML record at: %ldn", (long)lml_offset);
  1671.         goto again;
  1672.         EXIT;
  1673.         return -EINVAL;
  1674. }
  1675. #ifdef CONFIG_FS_EXT_ATTR
  1676. /* Journal an ea operation. A NULL buffer implies the attribute is 
  1677.  * getting deleted. In this case we simply change the opcode, but nothing
  1678.  * else is affected.
  1679.  */
  1680. int presto_journal_set_ext_attr (struct rec_info *rec, 
  1681.                                  struct presto_file_set *fset, 
  1682.                                  struct dentry *dentry, 
  1683.                                  struct presto_version *ver, const char *name, 
  1684.                                  const char *buffer, int buffer_len, 
  1685.                                  int flags) 
  1686.         int opcode = (buffer == NULL) ? 
  1687.                      PRESTO_OP_DELEXTATTR : 
  1688.                      PRESTO_OP_SETEXTATTR ;
  1689.         char *temp;
  1690.         char *path;
  1691.         __u32 pathlen;
  1692.         int size;
  1693.         char *logrecord;
  1694.         char record[292];
  1695.         struct dentry *root;
  1696.         int error;
  1697.         __u32 namelen=cpu_to_le32(strnlen(name,PRESTO_EXT_ATTR_NAME_MAX));
  1698.         __u32 buflen=(buffer != NULL)? cpu_to_le32(buffer_len): cpu_to_le32(0);
  1699.         __u32 mode;
  1700.         ENTRY;
  1701.         if ( presto_no_journal(fset) ) {
  1702.                 EXIT;
  1703.                 return 0;
  1704.         }
  1705.         if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) ) {
  1706.                 EXIT;
  1707.                 return 0;
  1708.         }
  1709.         root = fset->fset_mtpt;
  1710.         BUFF_ALLOC(temp, NULL);
  1711.         path = presto_path(dentry, root, temp, PAGE_SIZE);
  1712.         pathlen = cpu_to_le32(MYPATHLEN(temp, path));
  1713.         flags=cpu_to_le32(flags);
  1714.         /* Ugly, but needed. posix ACLs change the mode without using
  1715.          * setattr, we need to record these changes. The EA code per se
  1716.          * is not really affected.
  1717.          */
  1718.         mode=cpu_to_le32(dentry->d_inode->i_mode);
  1719.         size =  sizeof(__u32) * current->ngroups + 
  1720.                 sizeof(struct journal_prefix) + 
  1721.                 2 * sizeof(struct presto_version) +
  1722.                 sizeof(flags) + sizeof(mode) + sizeof(namelen) + 
  1723.                 sizeof(buflen) + sizeof(pathlen) + 
  1724.                 sizeof(struct journal_suffix);
  1725.         if ( size > sizeof(record) ) {
  1726.                 printk("PRESTO: BUFFER OVERFLOW in %s!n", __FUNCTION__);
  1727.         }
  1728.         rec->is_kml = 1;
  1729.         /* Make space for a path, a attr name and value*/
  1730.         /* We use the buflen instead of buffer_len to make sure that we 
  1731.          * journal the right length. This may be a little paranoid, but
  1732.          * with 64 bits round the corner, I would rather be safe than sorry!
  1733.          * Also this handles deletes with non-zero buffer_lengths correctly.
  1734.          * SHP
  1735.          */
  1736.         rec->size = size + size_round(le32_to_cpu(pathlen)) +
  1737.                     size_round(le32_to_cpu(namelen)) + 
  1738.                     size_round(le32_to_cpu(buflen));
  1739.         logrecord = journal_log_prefix(record, opcode, rec);
  1740.         logrecord = logit(logrecord, ver, sizeof(*ver));
  1741.         logrecord = log_version(logrecord, dentry);
  1742.         logrecord = logit(logrecord, &flags, sizeof(flags));
  1743.         logrecord = logit(logrecord, &mode, sizeof(flags));
  1744.         logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
  1745.         logrecord = logit(logrecord, &namelen, sizeof(namelen));
  1746.         logrecord = logit(logrecord, &buflen, sizeof(buflen));
  1747.         logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
  1748.         error = presto_log(fset, rec, record, size,
  1749.                            path, size_round(le32_to_cpu(pathlen)),
  1750.                            name, size_round(le32_to_cpu(namelen)),
  1751.                            buffer, size_round(le32_to_cpu(buflen)));
  1752.         BUFF_FREE(temp);
  1753.         EXIT;
  1754.         return error;
  1755. }
  1756. #endif