📄 journal.c
字号:
int presto_fread(struct file *file, char *str, int len, loff_t *off){ int rc; mm_segment_t old_fs; ENTRY; if ( len > 512 ) { printk("presto_fread: read at %Ld for %d bytes, ino %ld\n", *off, len, file->f_dentry->d_inode->i_ino); } rc = -EINVAL; if ( !off ) { EXIT; return rc; } if ( ! file ) { EXIT; return rc; } if ( ! file->f_op ) { EXIT; return rc; } if ( ! file->f_op->read ) { EXIT; return rc; } old_fs = get_fs(); set_fs(get_ds()); rc = file->f_op->read(file, str, len, off); if (rc != len) { printk("presto_fread: read %d bytes instead of " "%d at %ld\n", rc, len, (long)*off); rc = -EIO; } set_fs(old_fs); return rc;}static int presto_kml_dispatch(struct presto_file_set *fset){ int rc = 0; unsigned int kml_recno; struct presto_log_fd *fd = &fset->fset_kml; loff_t offset; ENTRY; write_lock(&fd->fd_lock); /* Determine the largest valid offset, i.e. up until the first * reservation held on the file. */ if ( !list_empty(&fd->fd_reservations) ) { struct presto_reservation_data *rd; rd = list_entry(fd->fd_reservations.next, struct presto_reservation_data, ri_list); offset = rd->ri_offset; kml_recno = rd->ri_recno; } else { offset = fd->fd_file->f_dentry->d_inode->i_size; kml_recno = fset->fset_kml.fd_recno; } if ( kml_recno < fset->fset_lento_recno ) { printk("presto_kml_dispatch: smoke is coming\n"); write_unlock(&fd->fd_lock); return 0; } else if ( kml_recno == fset->fset_lento_recno ) { write_unlock(&fd->fd_lock); EXIT; return 0; } CDEBUG(D_PIOCTL, "fset: %s\n", fset->fset_name); rc = lento_kml(fset->fset_cache->cache_psdev->uc_minor, fset->fset_lento_off, fset->fset_lento_recno, offset, kml_recno, strlen(fset->fset_name), fset->fset_name); if ( rc ) { write_unlock(&fd->fd_lock); EXIT; return rc; } fset->fset_lento_off = offset; fset->fset_lento_recno = kml_recno; write_unlock(&fd->fd_lock); EXIT; return 0;}/* structure of an extended log record: buf-prefix buf-body [string1 [string2 [string3]]] buf-suffix note: moves offset forward*/static inline int presto_write_record(struct file *f, loff_t *off, const char *buf, size_t size, const char *string1, int len1, const char *string2, int len2, const char *string3, int len3){ size_t prefix_size; int rc; prefix_size = size - sizeof(struct journal_suffix); rc = presto_fwrite(f, buf, prefix_size, off); if ( rc != prefix_size ) { printk("Write error!\n"); EXIT; return -EIO; } if ( string1 && len1 ) { rc = presto_fwrite(f, string1, len1, off); if ( rc != len1 ) { printk("Write error!\n"); EXIT; return -EIO; } } if ( string2 && len2 ) { rc = presto_fwrite(f, string2, len2, off); if ( rc != len2 ) { printk("Write error!\n"); EXIT; return -EIO; } } if ( string3 && len3 ) { rc = presto_fwrite(f, string3, len3, off); if ( rc != len3 ) { printk("Write error!\n"); EXIT; return -EIO; } } rc = presto_fwrite(f, buf + prefix_size, sizeof(struct journal_suffix), off); if ( rc != sizeof(struct journal_suffix) ) { printk("Write error!\n"); EXIT; return -EIO; } return 0;}/* * rec->size must be valid prior to calling this function. */static int presto_log(struct presto_file_set *fset, struct rec_info *rec, const char *buf, size_t size, const char *string1, int len1, const char *string2, int len2, const char *string3, int len3){ int rc; struct presto_reservation_data rd; loff_t offset; struct presto_log_fd *fd; struct journal_suffix *s; int prefix_size; ENTRY; /* buf is NULL when no_journal is in effect */ if (!buf) { EXIT; return -EINVAL; } if (rec->is_kml) { fd = &fset->fset_kml; } else { fd = &fset->fset_lml; } presto_reserve_record(fset, fd, rec, &rd); offset = rec->offset; /* now we know the record number */ prefix_size = size - sizeof(struct journal_suffix); s = (struct journal_suffix *) (buf + prefix_size); s->recno = cpu_to_le32(rec->recno); rc = presto_write_record(fd->fd_file, &offset, buf, size, string1, len1, string2, len2, string3, len3); if (rc) { printk("presto: error writing record to %s\n", rec->is_kml ? "KML" : "LML"); return rc; } presto_release_record(fd, &rd); rc = presto_kml_dispatch(fset); EXIT; return rc;}/* read from the record at tail */static int presto_last_record(struct presto_log_fd *fd, loff_t *size, loff_t *tail_offset, __u32 *recno, loff_t tail){ struct journal_suffix suffix; int rc; loff_t zeroes; *recno = 0; *tail_offset = 0; *size = 0; if (tail < sizeof(struct journal_prefix) + sizeof(suffix)) { EXIT; return 0; } zeroes = tail - sizeof(int); while ( zeroes >= 0 ) { int data; rc = presto_fread(fd->fd_file, (char *)&data, sizeof(data), &zeroes); if ( rc != sizeof(data) ) { rc = -EIO; return rc; } if (data) break; zeroes -= 2 * sizeof(data); } /* zeroes at the begining of file. this is needed to prevent presto_fread errors -SHP */ if (zeroes <= 0) return 0; zeroes -= sizeof(suffix); rc = presto_fread(fd->fd_file, (char *)&suffix, sizeof(suffix), &zeroes); if ( rc != sizeof(suffix) ) { EXIT; return rc; } if ( suffix.len > 500 ) { printk("PRESTO: Warning long record tail at %ld, rec tail_offset at %ld (size %d)\n", (long) zeroes, (long)*tail_offset, suffix.len); } *recno = suffix.recno; *size = suffix.len; *tail_offset = zeroes; return 0;}static int presto_kml_last_recno(struct presto_file_set *fset){ int rc; loff_t size; loff_t tail_offset; int recno; loff_t tail = fset->fset_kml.fd_file->f_dentry->d_inode->i_size; if ((rc = presto_last_record(&fset->fset_kml, &size, &tail_offset, &recno, tail)) ) { EXIT; return rc; } fset->fset_kml.fd_offset = tail_offset; fset->fset_kml.fd_recno = recno; CDEBUG(D_JOURNAL, "setting fset_kml->fd_recno to %d, offset %Ld\n", recno, tail_offset); EXIT; return 0;}static struct file *presto_log_open(struct presto_file_set *fset, char *name, int flags){ struct presto_cache *cache = fset->fset_cache; struct file *f; int error; int mtpt_len, path_len; char *path; ENTRY; mtpt_len = strlen(cache->cache_mtpt); path_len = mtpt_len + strlen("/.intermezzo/") + strlen(fset->fset_name) + strlen(name); error = -ENOMEM; PRESTO_ALLOC(path, char *, path_len + 1); if ( !path ) { EXIT; return ERR_PTR(-ENOMEM); } sprintf(path, "%s/.intermezzo/%s/%s", cache->cache_mtpt, fset->fset_name, name); CDEBUG(D_INODE, "opening file %s\n", path); f = filp_open(path, flags, 0); error = PTR_ERR(f); if (IS_ERR(f)) { CDEBUG(D_INODE, "Error %d\n", error); EXIT; goto out_free; } error = -EINVAL; if ( cache != presto_get_cache(f->f_dentry->d_inode) ) { printk("PRESTO: %s cache does not match fset cache!\n", name); fset->fset_kml.fd_file = NULL; filp_close(f, NULL); goto out_free; } if (cache->cache_filter && cache->cache_filter->o_trops && cache->cache_filter->o_trops->tr_journal_data) { CDEBUG(D_INODE, "\n"); cache->cache_filter->o_trops->tr_journal_data (f->f_dentry->d_inode); } else { printk("WARNING: InterMezzo no file data logging!\n"); } out_free: PRESTO_FREE(path, path_len + 1); EXIT; return f;}int presto_init_kml_file(struct presto_file_set *fset){ int error = 0; struct file *f; ENTRY; if (fset->fset_kml.fd_file) { CDEBUG(D_INODE, "fset already has KML open\n"); EXIT; return 0; } fset->fset_kml.fd_lock = RW_LOCK_UNLOCKED; INIT_LIST_HEAD(&fset->fset_kml.fd_reservations); f = presto_log_open(fset, "kml", O_RDWR | O_CREAT); if ( IS_ERR(f) ) { error = PTR_ERR(f); return error; } fset->fset_kml.fd_file = f; error = presto_kml_last_recno(fset); if ( error ) { EXIT; fset->fset_kml.fd_file = NULL; filp_close(f, NULL); printk("presto: IO error in KML of fset %s\n", fset->fset_name); } fset->fset_lento_off = fset->fset_kml.fd_offset; fset->fset_lento_recno = fset->fset_kml.fd_recno; EXIT; return error;}int presto_init_last_rcvd_file(struct presto_file_set *fset){ int error = 0; struct file *f; ENTRY; if (fset->fset_last_rcvd) { CDEBUG(D_INODE, "fset already has last_rcvd open\n"); EXIT; return 0; } f = presto_log_open(fset, "last_rcvd", O_RDWR | O_CREAT); if ( IS_ERR(f) ) { error = PTR_ERR(f); return error; } fset->fset_last_rcvd = f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -