📄 209-mini_fo.patch
字号:
+#else+mini_fo_d_revalidate(dentry_t *dentry, int flags)+#endif+{+ int err1 = 1; /* valid = 1, invalid = 0 */+ int err2 = 1;+ dentry_t *hidden_dentry;+ dentry_t *hidden_sto_dentry;+++ check_mini_fo_dentry(dentry);++ hidden_dentry = dtohd(dentry);+ hidden_sto_dentry = dtohd2(dentry);++ if(hidden_dentry &&+ hidden_dentry->d_op &&+ hidden_dentry->d_op->d_revalidate) {+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)+ err1 = hidden_dentry->d_op->d_revalidate(hidden_dentry, nd);+#else+ err1 = hidden_dentry->d_op->d_revalidate(hidden_dentry, flags);+#endif+ }+ if(hidden_sto_dentry &&+ hidden_sto_dentry->d_op &&+ hidden_sto_dentry->d_op->d_revalidate) {+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)+ err2 = hidden_sto_dentry->d_op->d_revalidate(hidden_sto_dentry, + nd);+#else+ err2 = hidden_sto_dentry->d_op->d_revalidate(hidden_sto_dentry, + flags);+#endif+ }++ /* mk: if one of the lower level dentries are valid,+ * the mini_fo dentry is too.+ */+ return (err1 || err2);+}+++STATIC int+mini_fo_d_hash(dentry_t *dentry, qstr_t *name)+{+ int err = 0;+ dentry_t *hidden_dentry;+ dentry_t *hidden_sto_dentry;++ /* hidden_dentry = mini_fo_hidden_dentry(dentry);+ * hidden_sto_dentry = mini_fo_hidden_sto_dentry(dentry); */++ /* state 1, 3, 4, 5: build the hash for the storage dentry */+ if((dtopd(dentry)->state == MODIFIED) ||+ (dtopd(dentry)->state == CREATED) ||+ (dtopd(dentry)->state == DEL_REWRITTEN) ||+ (dtopd(dentry)->state == DELETED)) {+ hidden_sto_dentry = dtohd2(dentry);+ if(hidden_sto_dentry &&+ hidden_sto_dentry->d_op &&+ hidden_sto_dentry->d_op->d_hash) {+ err = hidden_sto_dentry->d_op->d_hash(hidden_sto_dentry, name);+ }+ goto out;+ }+ /* state 2: build the hash for the base dentry */+ if(dtopd(dentry)->state == UNMODIFIED) {+ hidden_dentry = dtohd(dentry);+ if(hidden_dentry &&+ hidden_dentry->d_op &&+ hidden_dentry->d_op->d_hash) {+ err = hidden_dentry->d_op->d_hash(hidden_dentry, name);+ }+ goto out;+ }+ /* state 6: build hash for the dentry that exists */+ if(dtopd(dentry)->state == NON_EXISTANT) {+ hidden_sto_dentry = dtohd2(dentry);+ if(hidden_sto_dentry &&+ hidden_sto_dentry->d_op &&+ hidden_sto_dentry->d_op->d_hash) {+ err = hidden_sto_dentry->d_op->d_hash(hidden_sto_dentry, name);+ goto out;+ }+ hidden_dentry = dtohd(dentry);+ if(hidden_dentry &&+ hidden_dentry->d_op &&+ hidden_dentry->d_op->d_hash) {+ err = hidden_dentry->d_op->d_hash(hidden_dentry, name);+ goto out;+ }+ }++ printk(KERN_CRIT "mini_fo: d_hash: invalid state detected.\n");++ out:+ return err;+}+++STATIC int+mini_fo_d_compare(dentry_t *dentry, qstr_t *a, qstr_t *b)+{+ int err;+ dentry_t *hidden_dentry=NULL;++ /* hidden_dentry = mini_fo_hidden_dentry(dentry); */+ if(dtohd2(dentry))+ hidden_dentry = dtohd2(dentry);+ else if(dtohd(dentry))+ hidden_dentry = dtohd(dentry);++ if (hidden_dentry && hidden_dentry->d_op && hidden_dentry->d_op->d_compare) {+ err = hidden_dentry->d_op->d_compare(hidden_dentry, a, b);+ } else {+ err = ((a->len != b->len) || memcmp(a->name, b->name, b->len));+ }++ return err;+}+++int+mini_fo_d_delete(dentry_t *dentry)+{+ dentry_t *hidden_dentry;+ dentry_t *hidden_sto_dentry;+ int err = 0;++ /* this could be a negative dentry, so check first */+ if (!dtopd(dentry)) {+ printk(KERN_CRIT "mini_fo_d_delete: negative dentry passed.\n");+ goto out;+ }+ hidden_dentry = dtohd(dentry);+ hidden_sto_dentry = dtohd2(dentry);++ if(hidden_dentry) {+ if(hidden_dentry->d_op &&+ hidden_dentry->d_op->d_delete) {+ err = hidden_dentry->d_op->d_delete(hidden_dentry);+ }+ }+ if(hidden_sto_dentry) {+ if(hidden_sto_dentry->d_op &&+ hidden_sto_dentry->d_op->d_delete) {+ err = hidden_sto_dentry->d_op->d_delete(hidden_sto_dentry);+ }+ }++ out:+ return err;+}+++void+mini_fo_d_release(dentry_t *dentry)+{+ dentry_t *hidden_dentry;+ dentry_t *hidden_sto_dentry;+++ /* this could be a negative dentry, so check first */+ if (!dtopd(dentry)) {+ printk(KERN_CRIT "mini_fo_d_release: no private data.\n");+ goto out;+ }+ hidden_dentry = dtohd(dentry);+ hidden_sto_dentry = dtohd2(dentry);++ if(hidden_dentry) {+ /* decrement hidden dentry's counter and free its inode */+ dput(hidden_dentry);+ }+ if(hidden_sto_dentry) {+ /* decrement hidden dentry's counter and free its inode */+ dput(hidden_sto_dentry);+ }++ /* free private data (mini_fo_dentry_info) here */+ kfree(dtopd(dentry));+ __dtopd(dentry) = NULL; /* just to be safe */+ out:+ return;+}+++/*+ * we don't really need mini_fo_d_iput, because dentry_iput will call iput() if+ * mini_fo_d_iput is not defined. We left this implemented for ease of+ * tracing/debugging.+ */+void+mini_fo_d_iput(dentry_t *dentry, inode_t *inode)+{+ iput(inode);+}+++struct dentry_operations mini_fo_dops = {+ d_revalidate: mini_fo_d_revalidate,+ d_hash: mini_fo_d_hash,+ d_compare: mini_fo_d_compare,+ d_release: mini_fo_d_release,+ d_delete: mini_fo_d_delete,+ d_iput: mini_fo_d_iput,+};Index: linux-2.6.21.7/fs/mini_fo/file.c===================================================================--- /dev/null+++ linux-2.6.21.7/fs/mini_fo/file.c@@ -0,0 +1,713 @@+/*+ * Copyright (c) 1997-2003 Erez Zadok+ * Copyright (c) 2001-2003 Stony Brook 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.+ */+/*+ * Copyright (C) 2004, 2005 Markus Klotzbuecher <mk@creamnet.de>+ *+ * This program is free software; you can redistribute it and/or+ * modify it under the terms of the GNU General Public License+ * as published by the Free Software Foundation; either version+ * 2 of the License, or (at your option) any later version.+ */++/*+ * $Id$+ */++#ifdef HAVE_CONFIG_H+# include <config.h>+#endif++#include "fist.h"+#include "mini_fo.h"+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))++/*******************+ * File Operations *+ *******************/++STATIC loff_t+mini_fo_llseek(file_t *file, loff_t offset, int origin)+{+ loff_t err;+ file_t *hidden_file = NULL;++ if(S_ISDIR(file->f_dentry->d_inode->i_mode)) {+ /* Check if trying to llseek from a directory */+ err = -EISDIR;+ goto out;+ }+ if (ftopd(file) != NULL) {+ if(ftohf2(file)) {+ hidden_file = ftohf2(file);+ } else {+ hidden_file = ftohf(file);+ }+ }++ /* always set hidden position to this one */+ hidden_file->f_pos = file->f_pos;++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)+ memcpy(&(hidden_file->f_ra), + &(file->f_ra), + sizeof(struct file_ra_state));+#else+ if (file->f_reada) { /* update readahead information if needed */+ hidden_file->f_reada = file->f_reada;+ hidden_file->f_ramax = file->f_ramax;+ hidden_file->f_raend = file->f_raend;+ hidden_file->f_ralen = file->f_ralen;+ hidden_file->f_rawin = file->f_rawin;+ }+#endif+ if (hidden_file->f_op && hidden_file->f_op->llseek)+ err = hidden_file->f_op->llseek(hidden_file, offset, origin);+ else+ err = generic_file_llseek(hidden_file, offset, origin);++ if (err < 0)+ goto out;++ if (err != file->f_pos) {+ file->f_pos = err;+ // ION maybe this?+ // file->f_pos = hidden_file->f_pos;+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)+ file->f_reada = 0;+#endif+ file->f_version++;+ }++ out:+ return err;+}+++/* mk: fanout capable */+STATIC ssize_t+mini_fo_read(file_t *file, char *buf, size_t count, loff_t *ppos)+{+ int err = -EINVAL;+ file_t *hidden_file = NULL;+ loff_t pos = *ppos;++ if(S_ISDIR(file->f_dentry->d_inode->i_mode)) {+ /* Check if trying to read from a directory */+ /* printk(KERN_CRIT "mini_fo_read: ERROR: trying to read data from a directory.\n"); */+ err = -EISDIR;+ goto out;+ }++ if (ftopd(file) != NULL) {+ if(ftohf2(file)) {+ hidden_file = ftohf2(file);+ } else {+ hidden_file = ftohf(file);+ }+ }++ if (!hidden_file->f_op || !hidden_file->f_op->read)+ goto out;++ err = hidden_file->f_op->read(hidden_file, buf, count, &pos);+ *ppos = pos;++ if (err >= 0) {+ /* atime should also be updated for reads of size zero or more */+ fist_copy_attr_atime(file->f_dentry->d_inode,+ hidden_file->f_dentry->d_inode);+ }++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)+ /*+ * MAJOR HACK+ * because pread() does not have any way to tell us that it is+ * our caller, then we don't know for sure if we have to update+ * the file positions. This hack relies on read() having passed us+ * the "real" pointer of its struct file's f_pos field.+ */+ if (ppos == &file->f_pos)+ hidden_file->f_pos = *ppos = pos;+ if (hidden_file->f_reada) { /* update readahead information if needed */+ file->f_reada = hidden_file->f_reada;+ file->f_ramax = hidden_file->f_ramax;+ file->f_raend = hidden_file->f_raend;+ file->f_ralen = hidden_file->f_ralen;+ file->f_rawin = hidden_file->f_rawin;+ }+#else+ memcpy(&(file->f_ra),&(hidden_file->f_ra),sizeof(struct file_ra_state));+#endif++ out:+ return err;+}+++/* this mini_fo_write() does not modify data pages! */+STATIC ssize_t+mini_fo_write(file_t *file, const char *buf, size_t count, loff_t *ppos)+{+ int err = -EINVAL;+ file_t *hidden_file = NULL;+ inode_t *inode;+ inode_t *hidden_inode;+ loff_t pos = *ppos;++ /* mk: fan out: */+ if (ftopd(file) != NULL) {+ if(ftohf2(file)) {+ hidden_file = ftohf2(file);+ } else {+ /* This is bad! We have no storage file to write to. This+ * should never happen because if a file is opened for+ * writing, a copy should have been made earlier.+ */+ printk(KERN_CRIT "mini_fo: write : ERROR, no storage file to write.\n");+ err = -EINVAL;+ goto out;+ }+ }++ inode = file->f_dentry->d_inode;+ hidden_inode = itohi2(inode);+ if(!hidden_inode) {+ printk(KERN_CRIT "mini_fo: write: no sto inode found, not good.\n");+ goto out;+ }++ if (!hidden_file->f_op || !hidden_file->f_op->write)+ goto out;++ /* adjust for append -- seek to the end of the file */+ if (file->f_flags & O_APPEND)+ pos = inode->i_size;++ err = hidden_file->f_op->write(hidden_file, buf, count, &pos);++ /*+ * copy ctime and mtime from lower layer attributes+ * atime is unchanged for both layers+ */+ if (err >= 0)+ fist_copy_attr_times(inode, hidden_inode);+ + *ppos = pos;+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)+ /*+ * XXX: MAJOR HACK+ *+ * because pwrite() does not have any way to tell us that it is+ * our caller, then we don't know for sure if we have to update+ * the file positions. This hack relies on write() having passed us+ * the "real" pointer of its struct file's f_pos field.+ */+ if (ppos == &file->f_pos)+ hidden_file->f_pos = *ppos = pos;+#endif+ /* update this inode's size */+ if (pos > inode->i_size)+ inode->i_size = pos;++ out:+ return err;+}++/* Global variable to hold a file_t pointer.+ * This serves to allow mini_fo_filldir function to know which file is+ * beeing read, which is required for two reasons:+ *+ * - be able to call wol functions in order to avoid listing deleted+ * base files.+ * - if we're reading a directory which is in state 1, we need to+ * maintain a list (in mini_fo_filldir) of which files allready + * have been copied to userspace,to detect files existing in base+ * and storage and not list them twice.+ */+filldir_t mini_fo_filldir_orig;+file_t *mini_fo_filldir_file;++/* mainly copied from fs/readdir.c */+STATIC int+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)+mini_fo_filldir(void * __buf, const char * name, int namlen, loff_t offset,+ u64 ino, unsigned int d_type)+#else+mini_fo_filldir(void * __buf, const char * name, int namlen, loff_t offset,+ ino_t ino, unsigned int d_type)+#endif+{+ struct getdents_callback * buf = (struct getdents_callback *) __buf;+ file_t* file = mini_fo_filldir_file;++ /* In theses states we filter meta files in storage (WOL) */+ if(file && (dtopd(file->f_dentry)->state == MODIFIED ||+ dtopd(file->f_dentry)->state == CREATED ||+ dtopd(file->f_dentry)->state == DEL_REWRITTEN)) {++ int tmp = strlen(META_FILENAME);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -