int pmfs_set_blocksize_hint(struct super_block *sb, struct pmfs_inode *pi, loff_t new_size) { unsigned short block_type; if (!pmfs_can_set_blocksize_hint(pi, new_size)) return 0; if (new_size >= 0x40000000) { /* 1G */ block_type = PMFS_BLOCK_TYPE_1G; goto hint_set; } if (new_size >= 0x200000) { /* 2M */ block_type = PMFS_BLOCK_TYPE_2M; goto hint_set; } /* defaulting to 4K */ block_type = PMFS_BLOCK_TYPE_4K; hint_set: pmfs_dbg_verbose( "Hint: new_size 0x%llx, i_size 0x%llx, root 0x%llx\n", new_size, pi->i_size, le64_to_cpu(pi->root)); pmfs_dbg_verbose("Setting the hint to 0x%x\n", block_type); pmfs_memunlock_inode(sb, pi); pi->i_blk_type = block_type; pmfs_memlock_inode(sb, pi); return 0; }
/* This function is called by both msync() and fsync(). * TODO: Check if we can avoid calling pmfs_flush_buffer() for fsync. We use * movnti to write data to files, so we may want to avoid doing unnecessary * pmfs_flush_buffer() on fsync() */ int pmfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) { /* Sync from start to end[inclusive] */ struct address_space *mapping = file->f_mapping; struct inode *inode = mapping->host; loff_t isize; int error; /* if the file is not mmap'ed, there is no need to do clflushes */ if (mapping_mapped(mapping) == 0) goto persist; end += 1; /* end is inclusive. We like our indices normal please ! */ isize = i_size_read(inode); if ((unsigned long)end > (unsigned long)isize) end = isize; if (!isize || (start >= end)) { pmfs_dbg_verbose("[%s:%d] : (ERR) isize(%llx), start(%llx)," " end(%llx)\n", __func__, __LINE__, isize, start, end); return -ENODATA; } /* Align start and end to cacheline boundaries */ start = start & CACHELINE_MASK; end = CACHELINE_ALIGN(end); do { void *xip_mem; pgoff_t pgoff; loff_t offset; unsigned long xip_pfn, nr_flush_bytes; pgoff = start >> PAGE_CACHE_SHIFT; offset = start & ~PAGE_CACHE_MASK; nr_flush_bytes = PAGE_CACHE_SIZE - offset; if (nr_flush_bytes > (end - start)) nr_flush_bytes = end - start; error = mapping->a_ops->get_xip_mem(mapping, pgoff, 0, &xip_mem, &xip_pfn); if (unlikely(error)) { /* sparse files could have such holes */ pmfs_dbg_verbose("[%s:%d] : start(%llx), end(%llx)," " pgoff(%lx)\n", __func__, __LINE__, start, end, pgoff); } else { /* flush the range */ pmfs_flush_buffer(xip_mem+offset, nr_flush_bytes, 0); } start += nr_flush_bytes; } while (start < end); persist: PERSISTENT_MARK(); PERSISTENT_BARRIER(); return 0; }
static struct dentry *pmfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct inode *inode = NULL; struct pmfs_dir_logentry *de; ino_t ino; timing_t lookup_time; PMFS_START_TIMING(lookup_t, lookup_time); if (dentry->d_name.len > PMFS_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); pmfs_dbg_verbose("%s: %s\n", __func__, dentry->d_name.name); ino = pmfs_inode_by_name(dir, &dentry->d_name, &de); pmfs_dbg_verbose("%s: ino %lu\n", __func__, ino); if (ino) { inode = pmfs_iget(dir->i_sb, ino); if (inode == ERR_PTR(-ESTALE)) { pmfs_err(dir->i_sb, __func__, "deleted inode referenced: %lu", (unsigned long)ino); return ERR_PTR(-EIO); } } PMFS_END_TIMING(lookup_t, lookup_time); return d_splice_alias(inode, dentry); }
/* Returns new tail after append */ int pmfs_append_link_change_entry(struct super_block *sb, struct pmfs_inode *pi, struct inode *inode, u64 tail, u64 *new_tail) { struct pmfs_inode_info *si = PMFS_I(inode); struct pmfs_inode_info_header *sih = si->header; struct pmfs_link_change_entry *entry; u64 curr_p; size_t size = sizeof(struct pmfs_link_change_entry); timing_t append_time; PMFS_START_TIMING(append_entry_t, append_time); pmfs_dbg_verbose("%s: inode %lu attr change\n", __func__, inode->i_ino); curr_p = pmfs_get_append_head(sb, pi, sih, tail, size, 0, 1); if (curr_p == 0) return -ENOMEM; entry = (struct pmfs_link_change_entry *)pmfs_get_block(sb, curr_p); entry->entry_type = LINK_CHANGE; entry->links = cpu_to_le16(inode->i_nlink); entry->ctime = cpu_to_le32(inode->i_ctime.tv_sec); entry->flags = cpu_to_le32(inode->i_flags); entry->generation = cpu_to_le32(inode->i_generation); pmfs_flush_buffer(entry, size, 0); *new_tail = curr_p + size; PMFS_END_TIMING(append_entry_t, append_time); return 0; }
void pmfs_print_lite_transaction(struct pmfs_lite_journal_entry *entry) { int i; for (i = 0; i < 4; i++) pmfs_dbg_verbose("Entry %d: addr 0x%llx, value 0x%llx\n", i, entry->addrs[i], entry->values[i]); }
static ssize_t pmfs_read_backing_store(struct file *flp, char *dest, ssize_t bytes, loff_t *roff) { mm_segment_t old_fs; ssize_t len = 0; if (bytes > 0) { old_fs = get_fs(); set_fs(get_ds()); len = vfs_read(flp, dest, bytes, roff); set_fs(old_fs); if (len <= 0) pmfs_dbg_verbose("Could not read file or corrupted pmfs\n"); } return len; }
static ssize_t pmfs_write_backing_store(struct file *flp, char *src, ssize_t bytes, loff_t *woff) { mm_segment_t old_fs; ssize_t len = 0; if (bytes > 0) { old_fs = get_fs(); set_fs(get_ds()); len = vfs_write(flp, src, bytes, woff); set_fs(old_fs); if (len <= 0) pmfs_dbg_verbose("Could not write file or corrupted pmfs\n"); } return len; }
int pmfs_lite_journal_hard_init(struct super_block *sb) { struct pmfs_inode *pi; unsigned long blocknr = 0; unsigned long pmfs_ino; int allocated; u64 block; pi = pmfs_get_inode_by_ino(sb, PMFS_LITEJOURNAL_INO); pmfs_ino = PMFS_LITEJOURNAL_INO; allocated = pmfs_new_log_blocks(sb, pmfs_ino, &blocknr, 1, PMFS_BLOCK_TYPE_4K, 1); pmfs_dbg_verbose("%s: allocate log @ 0x%lx\n", __func__, blocknr); if (allocated != 1 || blocknr == 0) return -ENOSPC; pi->i_blocks = 1; block = pmfs_get_block_off(sb, blocknr, PMFS_BLOCK_TYPE_4K); pi->log_head = pi->log_tail = block; pmfs_flush_buffer(&pi->log_head, CACHELINE_SIZE, 1); return pmfs_lite_journal_soft_init(sb); }