📄 journal.c
字号:
EXIT; return error;}int presto_init_lml_file(struct presto_file_set *fset){ int error = 0; struct file *f; ENTRY; if (fset->fset_lml.fd_file) { CDEBUG(D_INODE, "fset already has lml open\n"); EXIT; return 0; } fset->fset_lml.fd_lock = RW_LOCK_UNLOCKED; INIT_LIST_HEAD(&fset->fset_lml.fd_reservations); f = presto_log_open(fset, "lml", O_RDWR | O_CREAT); if ( IS_ERR(f) ) { error = PTR_ERR(f); return error; } fset->fset_lml.fd_file = f; fset->fset_lml.fd_offset = fset->fset_lml.fd_file->f_dentry->d_inode->i_size; EXIT; return error;}/* Write the last_rcvd values to the last)_rcvd file */int presto_write_last_rcvd(struct rec_info *recinfo, struct presto_file_set *fset, struct lento_vfs_context *info){ int ret; loff_t off = info->slot_offset; struct { __u32 remote_recno; __u64 remote_offset; __u32 local_recno; __u64 local_offset; } rcvd_rec; rcvd_rec.remote_recno = cpu_to_le32(info->recno); rcvd_rec.remote_offset = cpu_to_le64(info->kml_offset); rcvd_rec.local_recno = cpu_to_le32(recinfo->recno); rcvd_rec.local_offset = cpu_to_le64(recinfo->offset + recinfo->size); ret = presto_fwrite(fset->fset_last_rcvd, (char *)(&rcvd_rec), sizeof(rcvd_rec), &off); if (ret == sizeof(rcvd_rec)) ret = 0; return ret;}/* LML records here *//* this writes the LML records for close, in conjunction with the KML */int presto_write_lml_close(struct rec_info *rec, struct presto_file_set *fset, struct file *file, __u64 remote_ino, __u32 remote_generation, __u32 remote_version, struct presto_version *new_file_ver){ int opcode = PRESTO_OP_CLOSE; char *buffer; struct dentry *dentry = file->f_dentry; __u64 ino; __u32 pathlen; char *path; __u32 generation; int size; char *logrecord; char record[292]; struct dentry *root; int error; ENTRY; if ( presto_no_journal(fset) ) { EXIT; return 0; } root = fset->fset_mtpt; BUFF_ALLOC(buffer, NULL); path = presto_path(dentry, root, buffer, PAGE_SIZE); CDEBUG(D_INODE, "Path: %s\n", path); pathlen = cpu_to_le32(MYPATHLEN(buffer, path)); ino = cpu_to_le64(dentry->d_inode->i_ino); generation = cpu_to_le32(dentry->d_inode->i_generation); size = sizeof(__u32) * current->ngroups + sizeof(struct journal_prefix) + sizeof(*new_file_ver) + sizeof(ino) + sizeof(generation) + sizeof(pathlen) + sizeof(remote_ino) + sizeof(remote_generation) + sizeof(remote_version) + sizeof(rec->offset) + sizeof(struct journal_suffix); if ( size > sizeof(record) ) { printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__); } rec->is_kml = 0; rec->size = size + size_round(le32_to_cpu(pathlen)); logrecord = journal_log_prefix(record, opcode, rec); logrecord = logit(logrecord, new_file_ver, sizeof(*new_file_ver)); logrecord = logit(logrecord, &ino, sizeof(ino)); logrecord = logit(logrecord, &generation, sizeof(generation)); logrecord = logit(logrecord, &pathlen, sizeof(pathlen)); logrecord = logit(logrecord, &remote_ino, sizeof(remote_ino)); logrecord = logit(logrecord, &remote_generation, sizeof(remote_generation)); logrecord = logit(logrecord, &remote_version, sizeof(remote_version)); logrecord = logit(logrecord, &rec->offset, sizeof(rec->offset)); logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec); error = presto_log(fset, rec, record, size, path, size_round(le32_to_cpu(pathlen)), NULL, 0, NULL, 0); BUFF_FREE(buffer); EXIT; return error;}int presto_journal_write(struct rec_info *rec, struct presto_file_set *fset, struct file *file){ struct presto_version file_version; int rc; ENTRY; presto_getversion(&file_version, file->f_dentry->d_inode); /* append this record */ rc = presto_write_lml_close (rec, fset, file, 0, /* remote_ino */ 0, /* remote_generation */ 0, /* remote_version */ &file_version); EXIT; return rc;}/* * Check if the given record is at the end of the file. If it is, truncate * the lml to the record's offset, removing it. Repeat on prior record, * until we reach an active record or a reserved record (as defined by the * reservations list). */static int presto_truncate_lml_tail(struct presto_file_set *fset){ loff_t lml_tail; loff_t lml_last_rec; loff_t lml_last_recsize; loff_t local_offset; int recno; struct journal_prefix prefix; struct inode *inode = fset->fset_lml.fd_file->f_dentry->d_inode; void *handle; int rc; ENTRY; /* If someone else is already truncating the LML, return. */ write_lock(&fset->fset_lml.fd_lock); if (fset->fset_lml.fd_truncating == 1 ) { write_unlock(&fset->fset_lml.fd_lock); EXIT; return 0; } /* someone is about to write to the end of the LML */ if ( !list_empty(&fset->fset_lml.fd_reservations) ) { write_unlock(&fset->fset_lml.fd_lock); EXIT; return 0; } lml_tail = fset->fset_lml.fd_file->f_dentry->d_inode->i_size; /* Nothing to truncate?*/ if (lml_tail == 0) { write_unlock(&fset->fset_lml.fd_lock); EXIT; return 0; } fset->fset_lml.fd_truncating = 1; write_unlock(&fset->fset_lml.fd_lock); presto_last_record(&fset->fset_lml, &lml_last_recsize, &lml_last_rec, &recno, lml_tail); /* Do we have a record to check? If not we have zeroes at the beginning of the file. -SHP */ if (lml_last_recsize != 0) { local_offset = lml_last_rec - lml_last_recsize; rc = presto_fread(fset->fset_lml.fd_file, (char *)&prefix, sizeof(prefix), &local_offset); if (rc != sizeof(prefix)) { EXIT; goto tr_out; } if ( prefix.opcode != PRESTO_OP_NOOP ) { EXIT; rc = 0; /* We may have zeroes at the end of the file, should we clear them out? -SHP */ goto tr_out; } } else lml_last_rec=0; handle = presto_trans_start(fset, inode, PRESTO_OP_TRUNC); if ( !handle ) { EXIT; rc = -ENOMEM; goto tr_out; } rc = presto_do_truncate(fset, fset->fset_lml.fd_file->f_dentry, lml_last_rec - lml_last_recsize, lml_tail); presto_trans_commit(fset, handle); if ( rc == 0 ) { rc = 1; } EXIT; tr_out: CDEBUG(D_JOURNAL, "rc = %d\n", rc); write_lock(&fset->fset_lml.fd_lock); fset->fset_lml.fd_truncating = 0; write_unlock(&fset->fset_lml.fd_lock); return rc;}int presto_truncate_lml(struct presto_file_set *fset){ int rc; ENTRY; while ( (rc = presto_truncate_lml_tail(fset)) > 0); if ( rc < 0 && rc != -EALREADY) { printk("truncate_lml error %d\n", rc); } EXIT; return rc;}int presto_clear_lml_close(struct presto_file_set *fset, loff_t lml_offset){ int rc; struct journal_prefix record; loff_t offset = lml_offset; ENTRY; if ( presto_no_journal(fset) ) { EXIT; return 0; } CDEBUG(D_JOURNAL, "reading prefix: off %ld, size %Zd\n", (long)lml_offset, sizeof(record)); rc = presto_fread(fset->fset_lml.fd_file, (char *)&record, sizeof(record), &offset); if ( rc != sizeof(record) ) { printk("presto: clear_lml io error %d\n", rc); EXIT; return -EIO; } /* overwrite the prefix */ CDEBUG(D_JOURNAL, "overwriting prefix: off %ld\n", (long)lml_offset); record.opcode = PRESTO_OP_NOOP; offset = lml_offset; /* note: this does just a single transaction in the cache */ rc = presto_fwrite(fset->fset_lml.fd_file, (char *)(&record), sizeof(record), &offset); if ( rc != sizeof(record) ) { EXIT; return -EIO; } EXIT; return 0; }/* now a journal function for every operation */int presto_journal_setattr(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dentry, struct presto_version *old_ver, struct iattr *iattr){ int opcode = PRESTO_OP_SETATTR; char *buffer; char *path; __u32 pathlen; int size; char *logrecord; char record[292]; struct dentry *root; __u32 uid, gid, mode, valid, flags; __u64 fsize, mtime, ctime; int error; ENTRY; if ( presto_no_journal(fset) ) { EXIT; return 0; } if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0) ) { EXIT; return 0; } root = fset->fset_mtpt; BUFF_ALLOC(buffer, NULL); path = presto_path(dentry, root, buffer, PAGE_SIZE); pathlen = cpu_to_le32(MYPATHLEN(buffer, path)); size = sizeof(__u32) * current->ngroups + sizeof(struct journal_prefix) + sizeof(*old_ver) + sizeof(valid) + sizeof(mode) + sizeof(uid) + sizeof(gid) + sizeof(fsize) + sizeof(mtime) + sizeof(ctime) + sizeof(flags) + sizeof(pathlen) + sizeof(struct journal_suffix); if ( size > sizeof(record) ) { printk("PRESTO: BUFFER OVERFLOW in %s!\n", __FUNCTION__); } /* Only journal one kind of mtime, and not atime at all. Also don't * journal bogus data in iattr, to make the journal more compressible. */ if (iattr->ia_valid & ATTR_MTIME_SET) iattr->ia_valid = iattr->ia_valid | ATTR_MTIME; valid = cpu_to_le32(iattr->ia_valid & ~(ATTR_ATIME | ATTR_MTIME_SET | ATTR_ATIME_SET)); mode = iattr->ia_valid & ATTR_MODE ? cpu_to_le32(iattr->ia_mode): 0; uid = iattr->ia_valid & ATTR_UID ? cpu_to_le32(iattr->ia_uid): 0; gid = iattr->ia_valid & ATTR_GID ? cpu_to_le32(iattr->ia_gid): 0; fsize = iattr->ia_valid & ATTR_SIZE ? cpu_to_le64(iattr->ia_size): 0; mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime): 0; ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime): 0; flags = iattr->ia_valid & ATTR_ATTR_FLAG ? cpu_to_le32(iattr->ia_attr_flags): 0; rec->is_kml = 1; rec->size = size + size_round(le32_to_cpu(pathlen)); logrecord = journal_log_prefix(record, opcode, rec); logrecord = logit(logrecord, old_ver, sizeof(*old_ver)); logrecord = logit(logrecord, &valid, sizeof(valid)); logrecord = logit(logrecord, &mode, sizeof(mode)); logrecord = logit(logrecord, &uid, sizeof(uid)); logrecord = logit(logrecord, &gid, sizeof(gid)); logrecord = logit(logrecord, &fsize, sizeof(fsize)); logrecord = logit(logrecord, &mtime, sizeof(mtime)); logrecord = logit(logrecord, &ctime, sizeof(ctime)); logrecord = logit(logrecord, &flags, sizeof(flags)); logrecord = logit(logrecord, &pathlen, sizeof(pathlen)); logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec); error = presto_log(fset, rec, record, size, path, size_round(le32_to_cpu(pathlen)), NULL, 0, NULL, 0); BUFF_FREE(buffer); EXIT; return error;}int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset, struct dentry *dentry, struct presto_version *tgt_dir_ver, struct presto_version *new_file_ver, int mode){ int opcode = PRESTO_OP_CREATE; char *buffer; char *path; __u32 pathlen; int size; char *logrecord;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -