📄 aux.c
字号:
/* * Copyright (c) 1997-2003 Erez Zadok * Copyright (c) 2001-2003 Stony Brook University * Copyright (c) 1997-2000 Columbia University * * For specific licensing information, see the COPYING file distributed with * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. * * This Copyright notice must be kept intact and distributed with all * fistgen sources INCLUDING sources generated by fistgen. *//* * $Id: aux.c,v 1.12 2002/12/27 20:19:04 ezk Exp $ */#ifdef HAVE_CONFIG_H# include <config.h>#endif /* HAVE_CONFIG_H */#ifdef FISTGEN# include "fist_wrapfs.h"#endif /* FISTGEN */#include "fist.h"#include "wrapfs.h"#ifdef FIST_USE_AUX_SRC/* * Read "len" bytes from "filename" into "buf". * "buf" is in kernel space. */intwrapfs_read_file(const char *filename, void *buf, int len){ file_t *filp; mm_segment_t oldfs; int bytes; /* Chroot? Maybe NULL isn't right here */ filp = filp_open(filename, O_RDONLY, 0); if (!filp || IS_ERR(filp)) { printk("wrapfs_read_file err %d\n", (int) PTR_ERR(filp)); return -1; /* or do something else */ } if (!filp->f_op->read) return -2; /* file(system) doesn't allow reads */ /* now read len bytes from offset 0 */ filp->f_pos = 0; /* start offset */ oldfs = get_fs(); set_fs(KERNEL_DS); bytes = filp->f_op->read(filp, buf, len, &filp->f_pos); set_fs(oldfs); /* close the file */ fput(filp); return bytes;}/* * Write "len" bytes from "buf" to "filename" * "buf" is in kernel space. */intwrapfs_write_file(const char *filename, void *buf, int len){ file_t *filp; mm_segment_t oldfs; int bytes; /* Chroot? Maybe NULL isn't right here */ filp = filp_open(filename, O_RDWR|O_CREAT, 0640); if (!filp || IS_ERR(filp)) { printk("wrapfs_write_file err %d\n", (int) PTR_ERR(filp)); return -1; /* or do something else */ } if (!filp->f_op->write) return -2; /* file(system) doesn't allow writes */ /* now write len bytes from offset 0 */ filp->f_pos = 0; /* start offset */ oldfs = get_fs(); set_fs(KERNEL_DS); bytes = filp->f_op->write(filp, buf, len, &filp->f_pos); set_fs(oldfs); /* close the file */ fput(filp); return bytes;}/* * perform a special lookup with special permissions */dentry_t *fist_lookup(dentry_t *dir, const char *name, vnode_t **out, uid_t uid, gid_t gid){ uid_t saved_uid; gid_t saved_gid; dentry_t *new_dentry; saved_uid = dir->d_inode->i_uid; saved_gid = dir->d_inode->i_gid; dir->d_inode->i_uid = uid; dir->d_inode->i_gid = gid; new_dentry = lookup_one_len(name, dir, strlen(name)); dir->d_inode->i_uid = saved_uid; dir->d_inode->i_gid = saved_gid; return new_dentry;}#endif /* FIST_USE_AUX_SRC */#ifdef FIST_FILTER_SCA/* lookup an index file, given a hidden dentry */dentry_t *wrapfs_idx_lookup(dentry_t *hidden_dentry){ unsigned int namelen; dentry_t *idx_dentry = NULL, *dir_dentry; char *name; int err = 0; print_entry_location(); namelen = hidden_dentry->d_name.len; name = kmalloc(namelen + INDEX_EXTENSION_LEN, GFP_KERNEL); if (!name) { err = -ENOMEM; goto out; } memcpy(name, hidden_dentry->d_name.name, namelen); memcpy(name + namelen, INDEX_EXTENSION, INDEX_EXTENSION_LEN); dir_dentry = dget(hidden_dentry->d_parent); idx_dentry = lookup_one_len(name, dir_dentry, namelen + INDEX_EXTENSION_LEN - 1); if (IS_ERR(idx_dentry)) { printk("ERR from lookup_dentry on idx_dentry!\n"); err = PTR_ERR(idx_dentry); goto out; } /* note that returned idx_dentry may be a negative dentry */ out: if (err) idx_dentry = ERR_PTR(err); print_exit_status(err); return idx_dentry;}/* create a new index inode */intwrapfs_idx_create(inode_t *hidden_dir, dentry_t *dentry, int mode){ int err; print_entry_location(); /* we don't have to lock hidden_dir. already locked in wrapfs_create */ err = vfs_create(hidden_dir, dtopd(dentry)->idx_dentry, mode); print_exit_status(err); return err;}/* open an index file (that should exist) given a regular file dentry */intwrapfs_idx_open(dentry_t *dentry, unsigned int flags){ int err = 0; file_t *idx_file; dentry_t *idx_dentry; print_entry_location(); /* don't reopen an existing idx file */ if (itopd(dentry->d_inode)->idx_file) goto out; idx_dentry = dtopd(dentry)->idx_dentry; dget(idx_dentry); /* * dentry_open will decrement mnt refcnt if err. * otherwise fput() will do an mntput() for us upon file close. */ mntget(stopd(dentry->d_sb)->hidden_mnt); idx_file = dentry_open(idx_dentry, stopd(dentry->d_sb)->hidden_mnt, flags); if (IS_ERR(idx_file)) { printk("Error opening (flags %d) index file %s\n", flags, idx_dentry->d_name.name); err = PTR_ERR(idx_file); goto out; } itopd(dentry->d_inode)->idx_file = idx_file; /* all is ok */out: print_exit_status(err); return err;}/* XXX this is inefficient, for stat() it really doesn't need the entire index table *//* This function return 0 on success, negative on error */intwrapfs_idx_read(inode_t *inode){ mm_segment_t oldfs; int len, err = 0, i; struct scafs_header *hdr = NULL; file_t *idx_file; print_entry_location(); idx_file = itopd(inode)->idx_file; ASSERT(idx_file != NULL); if (!idx_file->f_op->read) { /* This is highly unlikely, but... */ err = -ENOSYS; goto out; } len = idx_file->f_dentry->d_inode->i_size; /* Special case for empty file */ if (len == 0 && itohi(inode)->i_size == 0) { inode->i_size = inode->i_blocks = 0; goto out; } /* small (corrupted) index? */ if (len < (3 * sizeof(off_t))) { err = -EIO; goto out; } oldfs = get_fs(); set_fs(KERNEL_DS); hdr = &(itopd(inode)->hdr); /* Read in the number of pages and the real size */ err = idx_file->f_op->read(idx_file, (void *) &hdr->num_chunks, sizeof(off_t) << 1, &idx_file->f_pos); if (err < 0) { printk("Error in read\n"); goto out_setfs; } /* XXX check to see that we got all 2 * sizeof(off_t) bytes */ /* separate flags from num_chunks */ hdr->flags = hdr->num_chunks & SCA_FLAG_MASK; hdr->num_chunks &= ~SCA_FLAG_MASK; hdr->num_pageslots = (hdr->num_chunks + OFFSET_MASK) >> OFFSET_SHIFT; /* allocate page pointers array */ hdr->offsets = (off_t **)kmalloc(sizeof(off_t *) * hdr->num_pageslots, GFP_KERNEL); if (hdr->offsets == NULL) { err = -ENOMEM; goto out; } hdr->num_alloc = hdr->num_pageslots << OFFSET_SHIFT; for (i = 0; i < hdr->num_pageslots; i++) { hdr->offsets[i] = (off_t *)__get_free_page(GFP_KERNEL); if (hdr->offsets[i] == NULL) { err = -ENOMEM; goto out; } /* Read in the offsets into an array */ err = idx_file->f_op->read(idx_file, (void *) hdr->offsets[i], PAGE_CACHE_SIZE, &idx_file->f_pos); if (err < 0) { printk("Error in read\n"); goto out_setfs; } /* XXX check to see that we got all needed bytes */ } /* Sanity checking: Make sure underlying file size matches index table */ /* XXX These checks need to be fixed for fast_append! XXX */ if (hdr->num_chunks > 0) { if(SCA_OFFSET(hdr, hdr->num_chunks - 1) != itohi(inode)->i_size) { printk("Final offset does not equal file size\n"); err = -EIO; goto out_setfs; } } else { if (itohi(inode)->i_size > 0) { printk("No offsets, but index file is not empty\n"); err = -EIO; goto out_setfs; } } /* All is well */ err = 0; fist_print_scafs_header("idx_read", hdr); copy_inode_size(inode, itohi(inode)); out_setfs: set_fs(oldfs); out: print_exit_status(err); return(err);}/* This function return 0 on success, negative on error */intwrapfs_idx_write(inode_t *inode){ int err = 0; mm_segment_t oldfs; int i, bytes; unsigned int chunks_left; struct scafs_header *hdr = &(itopd(inode)->hdr); file_t *idx_file = itopd(inode)->idx_file; struct iattr attr; print_entry_location(); ASSERT(hdr != NULL); /* don't write header if not modified */ if ((hdr->flags & SCA_FLAG_MODIFIED) == 0) { fist_dprint(8, "idx_write: not writing unmodified header\n"); goto out; } if (idx_file == NULL) { printk("idx_file is NULL, cannot write\n"); goto out; } /* truncate index file to length 0 */ attr.ia_size = 0; attr.ia_valid = ATTR_SIZE; err = notify_change(idx_file->f_dentry, &attr); if (err < 0) goto out; if (hdr->num_chunks == 0) /* don't write anything */ goto out; /* combine num_chunks and flags */ hdr->num_chunks |= hdr->flags & SCA_FLAG_MASK; oldfs = get_fs(); set_fs(KERNEL_DS); idx_file->f_pos = 0; err = idx_file->f_op->write(idx_file, (void *) hdr, sizeof(off_t) << 1, &idx_file->f_pos); /* remove flags from num_chunks */ hdr->num_chunks &= ~SCA_FLAG_MASK; if (err < 0) { // XXX: check that err==num_bytes2write printk("error %d in write idx file hdr\n", err); goto out_setfs; } chunks_left = hdr->num_chunks; for (i = 0; 1; i++) { bytes = MIN(chunks_left, INDEX_ENTRIES_PER_PAGE) * sizeof(off_t); fist_dprint(8, "%s: %d bytes for page %d\n", __FUNCTION__, bytes, i); err = idx_file->f_op->write(idx_file, (void *) hdr->offsets[i], bytes, &idx_file->f_pos); if (err < 0) { // XXX: check that err==bytes printk("error %d in write idx file entries\n", err); goto out_setfs; } if (chunks_left <= INDEX_ENTRIES_PER_PAGE) break; chunks_left -= INDEX_ENTRIES_PER_PAGE; } /* reset modified counter */ hdr->flags &= ~SCA_FLAG_MODIFIED; out_setfs: set_fs(oldfs); out: print_exit_status(err); return err;}/* * Sets the value for an "entry" into an existing SCA header structure, * potentially allocating space for it and any preceding entries * * chunk_idx starts from 0. encoded_chunk_offset is what * this chunk will encode to. * * Note that holes are supported: they are defined in the index table * as a page that encodes to 0 bytes (i.e. the entry for that page will * be equal to the previous one) * * Returns 0 on success, or -errno on failure. */intwrapfs_idx_set_entry(struct scafs_header *hdr, int chunk_idx, off_t encoded_chunk_offset){ int err = 0, i; off_t offset; unsigned long pageslots; print_entry_location(); /* XXX: remove this after debugging */ fist_dprint(8, "%s: chunk_idx=%d encoded_chunk_offset=%d\n", __FUNCTION__, chunk_idx, encoded_chunk_offset); /* sanity checks */ ASSERT(hdr != NULL); ASSERT(chunk_idx >= 0); ASSERT(hdr->num_chunks <= hdr->num_alloc); /* check if we need to (re)allocate new space */ if (chunk_idx >= hdr->num_alloc) { pageslots = (chunk_idx + 1 + OFFSET_MASK) >> OFFSET_SHIFT; fist_dprint(8, "Allocating space for %d pages\n", pageslots); hdr->offsets = (off_t **) wrapfs_krealloc(hdr->offsets, sizeof(off_t *) * hdr->num_pageslots, sizeof(off_t *) * pageslots); if (hdr->offsets == NULL) { err = -ENOMEM; goto out; } for (i = hdr->num_pageslots; i < pageslots; i++) { hdr->offsets[i] = (off_t *)__get_free_page(GFP_KERNEL); if (hdr->offsets[i] == NULL) { err = -ENOMEM; goto out; } } hdr->num_pageslots = pageslots; hdr->num_alloc = pageslots << OFFSET_SHIFT; } /* support holes */ if (hdr->num_chunks > 0) offset = SCA_OFFSET(hdr, hdr->num_chunks - 1); else offset = 0; for (i = hdr->num_chunks; i < chunk_idx; i++) SCA_OFFSET(hdr, i) = offset; if (hdr->num_chunks > 0 && chunk_idx > 0 && encoded_chunk_offset < SCA_OFFSET(hdr, chunk_idx - 1)) { printk("idx_set_entry: lower offset %ld < %ld for chunk_idx %d\n", encoded_chunk_offset, SCA_OFFSET(hdr, chunk_idx-1), chunk_idx); } /* now insert new entry */ SCA_OFFSET(hdr, chunk_idx) = encoded_chunk_offset; hdr->num_chunks = MAX(hdr->num_chunks, chunk_idx + 1); hdr->flags |= SCA_FLAG_MODIFIED;out: fist_print_scafs_header("SAE", hdr); print_exit_status(err); /* XXX: remove this after debugging */ return err;}/* update index table entries by delta, starting at entry */voidwrapfs_idx_update(struct scafs_header *hdr, unsigned long entry, int delta){ unsigned long l; if (delta == 0) return; for (l = entry; l < hdr->num_chunks; l++) SCA_OFFSET(hdr, l) += delta; hdr->flags |= SCA_FLAG_MODIFIED;}/* * Given a page_index of our layer, find out the range of pages of the lower * layer that we need to read to satisfy the encoding request for our page. * The range of pages is from hidden_page_index and goes for the number of * pages being returned from this function. */intwrapfs_count_hidden_pages(unsigned long page_index, inode_t *inode, int *hidden_page_index, void **opaque){ struct scafs_header *hdr; int start,end,cnt=0; unsigned int start_page, end_page; print_entry_location(); hdr = &(itopd(inode)->hdr); if (page_index >= hdr->num_chunks) { /* XXX: fix page/chunk confusion */ //printk("count_hidden_pages: request for page %ld, file only has %ld chunks\n", // page_index, hdr->num_chunks); goto out; } start = HIDDEN_PAGE_STARTING_OFFSET(page_index, inode); end = HIDDEN_PAGE_STARTING_OFFSET(page_index + 1, inode); if (start == end) goto out; /* Hole, return 0 */ *hidden_page_index = start_page = start >> PAGE_CACHE_SHIFT; end_page = end >> PAGE_CACHE_SHIFT; *((int *)opaque) = start & ~PAGE_CACHE_MASK; cnt = end_page - start_page; if ((end & ~PAGE_CACHE_MASK) != 0) cnt++; out: print_exit_status(cnt); return cnt;}/* * A kernel based realloc(3). * * Oldsize must be original allocated size of oldptr. * Returns new pointer, or the old pointer if any error occured. */void *wrapfs_krealloc(void *oldptr, size_t oldsize, size_t newsize){ void *newptr = NULL; /* check if given sizes were valid */ if (newsize <= 0) { printk("error: krealloc was called with newsize %d\n", newsize); goto out; } if (oldsize < 0) { printk("error: krealloc was called with oldsize %d\n", oldsize); goto out; } if (newsize <= oldsize) printk("warning: wrapfs_krealloc newsize %d <= oldsize %d\n", newsize, oldsize); /* allocate and copy bytes */ newptr = kmalloc(newsize, GFP_KERNEL); if (newptr == NULL) { printk("krealloc: no more memory\n"); goto out; } if (oldsize > 0) { if (newsize > oldsize) { /* extending size */ memcpy(newptr, oldptr, oldsize); memset(newptr + oldsize, 0, newsize - oldsize); /* be safe */ } else { memcpy(newptr, oldptr, newsize); } /* free old allocation */ /* XXX: be safe and zero out oldptr's bytes first? */ kfree(oldptr); } out: return newptr;}#endif /* FIST_FILTER_SCA *//* * Local variables: * c-basic-offset: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -