Push to branch refs/heads/master: 1ab57e43fb455b8d154588f4d3f48121b0cd7411 --> 2896b357f6d1619f8ed767fe816ced87dbf5abe4
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index 3ca3a7e..f15621e 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX @@ -116,8 +116,6 @@ vfat.txt - info on using the VFAT filesystem used in Windows NT and Windows 95 vfs.txt - overview of the Virtual File System -wrapfs.txt - - info and mount options for the stackable wrapper file system xfs.txt - info and mount options for the XFS filesystem. xip.txt diff --git a/Documentation/filesystems/wrapfs.txt b/Documentation/filesystems/wrapfs.txt deleted file mode 100644 index daa313b..0000000 --- a/Documentation/filesystems/wrapfs.txt +++ /dev/null @@ -1,172 +0,0 @@ -Wrapfs: a null-layer (aka wrapper) stackable file system - -Maintainer: Erez Zadok <ezk AT cs DOT stonybrook DOT edu> -Web Site: <http://wrapfs.filesystems.org/> - ------------------------------------------------------------------------------- -MOTIVATION: - -Wrapfs is a small null-layer stackable file system, similar to BSD's Nullfs. -Wrapfs is small, under 1,800 lines of code. Compare that to, say, eCryptfs -(in mainline since 2.6.19) and Unionfs, each of which are over 10,000 LoC. -As such, Wrapfs is simple, easy to read and understand, and very easy to -code-review. Wrapfs is useful for several reasons: - -1. Many people like to experiment with in-kernel file system ideas. Wrapfs - is an ideal small template that one can modify to incrementally create - new file system functionalities. - -2. As a platform to test and debug generic stacking problems in other Linux - stackable file systems (e.g., eCryptfs) more easily. - -3. As a way to test VFS enhancements to better support stacking in Linux. - -4. Wrapfs is also a very useful instructional tool, often used as a starting - point for course assignments, for people who want a small example of how - the Linux VFS works, or for those who want to learn how to write new - Linux file systems. - -5. As an alternative to bind mounts. Wrapfs acts similarly to BSD's - loopback mount file system (lofs). - -Various versions of Wrapfs appeared as part of the "fistgen" package since -1994, and have been used by numerous users world-wide. This latest version -was rewritten entirely from scratch in 2010 and had supported every kernel -as of 2.6.32. All versions of wrapfs have been thoroughly tested using LTP, -FSX, racer, and other test-suites. Wrapfs code uses the latest VFS API -changes of the corresponding kernel. For a more detailed history of Wrapfs, -and list of most of its known users, see the section marked "HISTORY" below. - ------------------------------------------------------------------------------- -OPERATION: - -This is a brief description of how Wrapfs operates. For more information, -see the full paper published in Linux Expo 1999, titled "A Stackable File -System Interface For Linux": - - <http://www.fsl.cs.sunysb.edu/docs/linux-stacking/linux.pdf> - -The basic function of a stackable file system is to pass an operation and -its arguments to the lower-level file system. For every VFS object (inode, -dentry, file, superblock, etc.), Wrapfs keeps a one-to-one mapping of a -Wrapfs-level object to the lower one. We call the Wrapfs object the "upper" -one, and the one below we call the "lower" one. Wrapfs stores these -mappings as simple pointers inside the private field of the existing VFS -objects (e.g., dentry->d_fsdata, sb->s_fs_info, and a container for inodes). - -There are two kinds of stackable operations: those that create new VFS -objects and those that don't. - -The following distilled code snippet shows a method which doesn't create a -new object. The method just has to pass it to the lower layer and propagate -any errors back up the VFS: - -int wrapfs_unlink(struct inode *dir, struct dentry *dentry) -{ - int err; - struct inode *lower_dir; - struct dentry *lower_dentry; - lower_dir = get_lower_inode(dir); - lower_dentry = get_lower_dentry(dentry); - err = lower_dir->i_op->unlink(lower_dir, lower_dentry); - return err; -} - -The following code snippet shows a method which creates a new object. After -a lower object gets created, Wrapfs has to also create its own object, and -make the pointer connections between the upper and lower objects (the latter -is done via a helper routine called "interpose"): - -int wrapfs_create(struct inode *dir, struct dentry *dentry, int mode) -{ - int err; - struct dentry *lower_dentry; - struct inode *lower_dir; - lower_dir = wrapfs_lower_inode(dir); - lower_dentry = wrapfs_lower_dentry(dentry); - err = vfs_create(lower_dir, lower_dentry, mode); - if (!err) - err = wrapfs_interpose(dentry, dir->i_sb); - return err; -} - -The wrapfs_unlink code snippet above can be easily modified to change the -behavior of unlink(2). For example, if an ->unlink operation is changed to -->rename, this could become the basis for an "undo" file system; or if the -lower_dentry's name gets encrypted before calling the lower ->unlink, this -could be part of an encryption file system. - ------------------------------------------------------------------------------- -USAGE: - -First, you have to have some pre-existing directory already mounted from any -other file system, say /some/lower/path. Then, to mount wrapfs in -/mnt/wrapfs, on that lower directory, issue this command: - -# mount -t wrapfs /some/lower/path /mnt/wrapfs - -To access the files via Wrapfs, use the mount point /mnt/wrapfs. - ------------------------------------------------------------------------------- -CAVEATS: - -Stacking on NFS. Wrapfs has been tested with LTP, racer, fsx, parallel -compile, and more. It's been tested on top of ext2, ext3, xfs, reiserfs, -and tmpfs -- and passed all tests. However, on top of nfs3, wrapfs has to -treat silly-deleted files as if they don't exist: in ->unlink, if we try to -vfs_unlink an NFS silly-deleted file, NFS returns EBUSY; so we simply ignore -it and return 0 (success) to the VFS. NFS will delete this file later on -anyway. As the VFS also has special handling for silly-deleted files, this -isn't unusual. A cleaner way to handle this in the future is if the VFS -were to handle silly-deleted (aka "delayed-delete") files entirely at the -VFS. - ------------------------------------------------------------------------------- -HISTORY: - -Wrapfs was developed initially in 1994 for Linux 2.1, as part of Erez -Zadok's graduate work at Columbia University. It was designed to be a -flexible null-layer, pass-through, stackable file system, from which other -file systems would be developed and even instantiated automatically using a -high-level language. One of the first file systems developed from Wrapfs -was a simple encryption file system called Cryptfs (eCryptfs is based on -Cryptfs). Other examples include Gzipfs, a stackable compression file -system, and Unionfs, a stackable unification file system. Wrapfs was -integrated into a larger package called fistgen (see www.filesystems.org), -and ported to FreeBSD and Solaris. Wrapfs and fistgen continued to be -maintained for newer versions of kernels, but remained largely standalone -until recently: this release of Wrapfs for Linux represents a clean version -written from scratch. - -Over the past 15+ years, versions of Wrapfs had been used by many users and -companies. At one point or another, the following groups have used stacking -code based on Wrapfs. - -1. PROJECTS: eCryptfs, Unionfs, mini_fo, Aufs, FindFS, StoreCompress, - TestFS, ToPAS, and MFS. - -2. COMPANIES AND RESEARCH LABS: Bell Labs's Plan 9 group, EMC, - Hewlett-Packard, IBM Research Almaden, IBM Research Austin, Red Hat, - SuSE, Sun Microsystems, Veritas, Booyaka, CalSoft (India), Computer Farm, - Deutsche Bank (Germany), DreamWorks LLC, Eli Lilly and Company, FAME - Information Services, GMX AG (Germany), IBM global services (India), IDA - Center for Communications Research, Indra Networks, Inc., Kavi - Corporation, Mendepie, Mitsubishi Electric (Japan), Mobile-Mind, Monster - Labs, Morning Network (Russia), NeST Technologies, Packet General - Networks, Inc., Outstep Technologies, Reflective Systems Group, River - Styx Internet, SARAI Net, Saint-Petersburg Official Web Site (Russia), - Shadow Island Games, TISCover (Germany), Trymedia Systems, Uber Admin, - Videsh Sanchar Nigam Limited (India), Wanadoo (France), and iNsu - Innovations. - -3. UNIVERSITIES: Georgia Institute of Technology, Stanford University, UC - Berkeley, UCLA, University of Maryland, College Park, University of - Michigan, Ben Gurion University (Israel), Clarkson University, Clemson - University, Deutsches Elektronen Synchrotron (Germany), Electronics and - Telecommunications Research Institute (South Korea), Indian Institute of - Technology (India), National Taiwan University, Pune University (India), - The College of William \& Mary, Trinity College (Ireland), Universitaet - Frankfurt am Main (Germany), University Hospital Olomouc (Czech - Republic), and University of Salermo (Italy). - ------------------------------------------------------------------------------- diff --git a/MAINTAINERS b/MAINTAINERS index 25d0ac35..334258c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5870,13 +5870,6 @@ F: include/linux/mfd/wm8400/ F: sound/soc/codecs/wm8350.c F: sound/soc/codecs/wm8400.c -WRAPFS -M: Erez Zadok <e...@cs.sunysb.edu> -L: wra...@filesystems.org -W: http://wrapfs.filesystems.org/ -T: git git.kernel.org/pub/scm/linux/kernel/git/ezk/wrapfs.git -S: Maintained - X.25 NETWORK LAYER M: Henner Eisen <e...@baty.hanse.de> L: linux-...@vger.kernel.org diff --git a/fs/Kconfig b/fs/Kconfig index 30f8e58..64d44ef 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -169,7 +169,6 @@ if MISC_FILESYSTEMS source "fs/adfs/Kconfig" source "fs/affs/Kconfig" source "fs/ecryptfs/Kconfig" -source "fs/wrapfs/Kconfig" source "fs/hfs/Kconfig" source "fs/hfsplus/Kconfig" source "fs/befs/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index ed30c07..af6d047 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -84,7 +84,6 @@ obj-$(CONFIG_ISO9660_FS) += isofs/ obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ obj-$(CONFIG_HFS_FS) += hfs/ obj-$(CONFIG_ECRYPT_FS) += ecryptfs/ -obj-$(CONFIG_WRAP_FS) += wrapfs/ obj-$(CONFIG_VXFS_FS) += freevxfs/ obj-$(CONFIG_NFS_FS) += nfs/ obj-$(CONFIG_EXPORTFS) += exportfs/ diff --git a/fs/stack.c b/fs/stack.c index 3d7f5c3..67716f6 100644 --- a/fs/stack.c +++ b/fs/stack.c @@ -9,54 +9,8 @@ */ void fsstack_copy_inode_size(struct inode *dst, const struct inode *src) { - loff_t i_size; - blkcnt_t i_blocks; - - /* - * i_size_read() includes its own seqlocking and protection from - * preemption (see include/linux/fs.h): we need nothing extra for - * that here, and prefer to avoid nesting locks than attempt to - * keep i_size and i_blocks in synch together. - */ - i_size = i_size_read(src); - - /* - * But if CONFIG_LSF (on 32-bit), we ought to make an effort to keep - * the two halves of i_blocks in synch despite SMP or PREEMPT - though - * stat's generic_fillattr() doesn't bother, and we won't be applying - * quotas (where i_blocks does become important) at the upper level. - * - * We don't actually know what locking is used at the lower level; but - * if it's a filesystem that supports quotas, it will be using i_lock - * as in inode_add_bytes(). tmpfs uses other locking, and its 32-bit - * is (just) able to exceed 2TB i_size with the aid of holes; but its - * i_blocks cannot carry into the upper long without almost 2TB swap - - * let's ignore that case. - */ - if (sizeof(i_blocks) > sizeof(long)) - spin_lock((spinlock_t *) &src->i_lock); - i_blocks = src->i_blocks; - if (sizeof(i_blocks) > sizeof(long)) - spin_unlock((spinlock_t *) &src->i_lock); - - /* - * If CONFIG_SMP on 32-bit, it's vital for fsstack_copy_inode_size() - * to hold some lock around i_size_write(), otherwise i_size_read() - * may spin forever (see include/linux/fs.h). We don't necessarily - * hold i_mutex when this is called, so take i_lock for that case. - * - * And if CONFIG_LSF (on 32-bit), continue our effort to keep the - * two halves of i_blocks in synch despite SMP or PREEMPT: use i_lock - * for that case too, and do both at once by combining the tests. - * - * There is none of this locking overhead in the 64-bit case. - */ - if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long)) - spin_lock(&dst->i_lock); - i_size_write(dst, i_size); - dst->i_blocks = i_blocks; - if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long)) - spin_unlock(&dst->i_lock); + i_size_write(dst, i_size_read((struct inode *)src)); + dst->i_blocks = src->i_blocks; } EXPORT_SYMBOL_GPL(fsstack_copy_inode_size); diff --git a/fs/super.c b/fs/super.c index ad6dc74..aff046b 100644 --- a/fs/super.c +++ b/fs/super.c @@ -95,7 +95,6 @@ static struct super_block *alloc_super(struct file_system_type *type) s->s_count = S_BIAS; atomic_set(&s->s_active, 1); mutex_init(&s->s_vfs_rename_mutex); - lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); mutex_init(&s->s_dquot.dqio_mutex); mutex_init(&s->s_dquot.dqonoff_mutex); init_rwsem(&s->s_dquot.dqptr_sem); diff --git a/fs/wrapfs/Kconfig b/fs/wrapfs/Kconfig deleted file mode 100644 index d790ccd..0000000 --- a/fs/wrapfs/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config WRAP_FS - tristate "Wrapfs stackable file system (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - Wrapfs is a stackable file system which simply passes its - operations to the lower layer. It is designed as a useful - template for developing or debugging other stackable file systems, - and more (see Documentation/filesystems/wrapfs.txt). See - <http://wrapfs.filesystems.org/> for details. diff --git a/fs/wrapfs/Makefile b/fs/wrapfs/Makefile deleted file mode 100644 index f318d11..0000000 --- a/fs/wrapfs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -WRAPFS_VERSION="0.1" - -EXTRA_CFLAGS += -DWRAPFS_VERSION=\"$(WRAPFS_VERSION)\" - -obj-$(CONFIG_WRAP_FS) += wrapfs.o - -wrapfs-y := dentry.o file.o inode.o main.o super.o lookup.o mmap.o diff --git a/fs/wrapfs/dentry.c b/fs/wrapfs/dentry.c deleted file mode 100644 index 3ecab8e..0000000 --- a/fs/wrapfs/dentry.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1998-2017 Erez Zadok - * Copyright (c) 2009 Shrikar Archak - * Copyright (c) 2003-2017 Stony Brook University - * Copyright (c) 2003-2017 The Research Foundation of SUNY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "wrapfs.h" - -/* - * returns: -ERRNO if error (returned to user) - * 0: tell VFS to invalidate dentry - * 1: dentry is valid - */ -static int wrapfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) -{ - struct path lower_path, saved_path; - struct dentry *lower_dentry; - int err = 1; - - wrapfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) - goto out; - pathcpy(&saved_path, &nd->path); - pathcpy(&nd->path, &lower_path); - err = lower_dentry->d_op->d_revalidate(lower_dentry, nd); - pathcpy(&nd->path, &saved_path); -out: - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static void wrapfs_d_release(struct dentry *dentry) -{ - /* release and reset the lower paths */ - wrapfs_put_reset_lower_path(dentry); - free_dentry_private_data(dentry); - return; -} - -const struct dentry_operations wrapfs_dops = { - .d_revalidate = wrapfs_d_revalidate, - .d_release = wrapfs_d_release, -}; diff --git a/fs/wrapfs/file.c b/fs/wrapfs/file.c deleted file mode 100644 index fc24a20..0000000 --- a/fs/wrapfs/file.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 1998-2017 Erez Zadok - * Copyright (c) 2009 Shrikar Archak - * Copyright (c) 2003-2017 Stony Brook University - * Copyright (c) 2003-2017 The Research Foundation of SUNY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "wrapfs.h" - -static ssize_t wrapfs_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int err; - struct file *lower_file; - struct dentry *dentry = file->f_path.dentry; - - lower_file = wrapfs_lower_file(file); - err = vfs_read(lower_file, buf, count, ppos); - /* update our inode atime upon a successful lower read */ - if (err >= 0) - fsstack_copy_attr_atime(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - - return err; -} - -static ssize_t wrapfs_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - int err = 0; - struct file *lower_file; - struct dentry *dentry = file->f_path.dentry; - - lower_file = wrapfs_lower_file(file); - err = vfs_write(lower_file, buf, count, ppos); - /* update our inode times+sizes upon a successful lower write */ - if (err >= 0) { - fsstack_copy_inode_size(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - fsstack_copy_attr_times(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - } - - return err; -} - -static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir) -{ - int err = 0; - struct file *lower_file = NULL; - struct dentry *dentry = file->f_path.dentry; - - lower_file = wrapfs_lower_file(file); - err = vfs_readdir(lower_file, filldir, dirent); - file->f_pos = lower_file->f_pos; - if (err >= 0) /* copy the atime */ - fsstack_copy_attr_atime(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - return err; -} - -static long wrapfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long err = -ENOTTY; - struct file *lower_file; - - lower_file = wrapfs_lower_file(file); - - /* XXX: use vfs_ioctl if/when VFS exports it */ - if (!lower_file || !lower_file->f_op) - goto out; - if (lower_file->f_op->unlocked_ioctl) { - err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); - } else if (lower_file->f_op->ioctl) { - lock_kernel(); - err = lower_file->f_op->ioctl( - lower_file->f_path.dentry->d_inode, - lower_file, cmd, arg); - unlock_kernel(); - } - - /* some ioctls can change inode attributes (EXT2_IOC_SETFLAGS) */ - if (!err) - fsstack_copy_attr_all(file->f_path.dentry->d_inode, - lower_file->f_path.dentry->d_inode, - NULL); -out: - return err; -} - -static int wrapfs_mmap(struct file *file, struct vm_area_struct *vma) -{ - int err = 0; - bool willwrite; - struct file *lower_file; - const struct vm_operations_struct *saved_vm_ops = NULL; - - /* this might be deferred to mmap's writepage */ - willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags); - - /* - * File systems which do not implement ->writepage may use - * generic_file_readonly_mmap as their ->mmap op. If you call - * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL. - * But we cannot call the lower ->mmap op, so we can't tell that - * writeable mappings won't work. Therefore, our only choice is to - * check if the lower file system supports the ->writepage, and if - * not, return EINVAL (the same error that - * generic_file_readonly_mmap returns in that case). - */ - lower_file = wrapfs_lower_file(file); - if (willwrite && !lower_file->f_mapping->a_ops->writepage) { - err = -EINVAL; - printk(KERN_ERR "wrapfs: lower file system does not " - "support writeable mmap\n"); - goto out; - } - - /* - * find and save lower vm_ops. - * - * XXX: the VFS should have a cleaner way of finding the lower vm_ops - */ - if (!WRAPFS_F(file)->lower_vm_ops) { - err = lower_file->f_op->mmap(lower_file, vma); - if (err) { - printk(KERN_ERR "wrapfs: lower mmap failed %d\n", err); - goto out; - } - saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */ - } - - /* - * Next 3 lines are all I need from generic_file_mmap. I definitely - * don't want its test for ->readpage which returns -ENOEXEC. - */ - file_accessed(file); - vma->vm_ops = &wrapfs_vm_ops; - vma->vm_flags |= VM_CAN_NONLINEAR; - - file->f_mapping->a_ops = &wrapfs_aops; /* set our aops */ - if (!WRAPFS_F(file)->lower_vm_ops) /* save for our ->fault */ - WRAPFS_F(file)->lower_vm_ops = saved_vm_ops; - -out: - return err; -} - -static int wrapfs_open(struct inode *inode, struct file *file) -{ - int err = 0; - struct file *lower_file = NULL; - struct path lower_path; - - /* don't open unhashed/deleted files */ - if (d_unhashed(file->f_path.dentry)) { - err = -ENOENT; - goto out_err; - } - - file->private_data = - kzalloc(sizeof(struct wrapfs_file_info), GFP_KERNEL); - if (!WRAPFS_F(file)) { - err = -ENOMEM; - goto out_err; - } - - /* open lower object and link wrapfs's file struct to lower's */ - wrapfs_get_lower_path(file->f_path.dentry, &lower_path); - lower_file = dentry_open(lower_path.dentry, lower_path.mnt, - file->f_flags, current_cred()); - if (IS_ERR(lower_file)) { - err = PTR_ERR(lower_file); - lower_file = wrapfs_lower_file(file); - if (lower_file) { - wrapfs_set_lower_file(file, NULL); - fput(lower_file); /* fput calls dput for lower_dentry */ - } - } else { - wrapfs_set_lower_file(file, lower_file); - } - - if (err) - kfree(WRAPFS_F(file)); - else - fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode), NULL); -out_err: - return err; -} - -static int wrapfs_flush(struct file *file, fl_owner_t id) -{ - int err = 0; - struct file *lower_file = NULL; - - lower_file = wrapfs_lower_file(file); - if (lower_file && lower_file->f_op && lower_file->f_op->flush) - err = lower_file->f_op->flush(lower_file, id); - - return err; -} - -/* release all lower object references & free the file info structure */ -static int wrapfs_file_release(struct inode *inode, struct file *file) -{ - struct file *lower_file; - - lower_file = wrapfs_lower_file(file); - if (lower_file) { - wrapfs_set_lower_file(file, NULL); - fput(lower_file); - } - - kfree(WRAPFS_F(file)); - return 0; -} - -static int wrapfs_fsync(struct file *file, struct dentry *dentry, int datasync) -{ - int err; - struct file *lower_file; - struct path lower_path; - - lower_file = wrapfs_lower_file(file); - wrapfs_get_lower_path(dentry, &lower_path); - err = vfs_fsync(lower_file, lower_path.dentry, datasync); - wrapfs_put_lower_path(dentry, &lower_path); - - return err; -} - -static int wrapfs_fasync(int fd, struct file *file, int flag) -{ - int err = 0; - struct file *lower_file = NULL; - - lock_kernel(); - lower_file = wrapfs_lower_file(file); - if (lower_file->f_op && lower_file->f_op->fasync) - err = lower_file->f_op->fasync(fd, lower_file, flag); - unlock_kernel(); - - return err; -} - -static ssize_t wrapfs_aio_read(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - int err = -EINVAL; - struct file *file, *lower_file; - - file = iocb->ki_filp; - lower_file = wrapfs_lower_file(file); - if (!lower_file->f_op->aio_read) - goto out; - /* - * It appears safe to rewrite this iocb, because in - * do_io_submit@fs/aio.c, iocb is a just copy from user. - */ - get_file(lower_file); /* prevent lower_file from being released */ - iocb->ki_filp = lower_file; - err = lower_file->f_op->aio_read(iocb, iov, nr_segs, pos); - iocb->ki_filp = file; - fput(lower_file); - /* update upper inode atime as needed */ - if (err >= 0 || err == -EIOCBQUEUED) - fsstack_copy_attr_atime(file->f_path.dentry->d_inode, - lower_file->f_path.dentry->d_inode); -out: - return err; -} - -static ssize_t wrapfs_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - int err = -EINVAL; - struct file *file, *lower_file; - - file = iocb->ki_filp; - lower_file = wrapfs_lower_file(file); - if (!lower_file->f_op->aio_write) - goto out; - /* - * It appears safe to rewrite this iocb, because in - * do_io_submit@fs/aio.c, iocb is a just copy from user. - */ - get_file(lower_file); /* prevent lower_file from being released */ - iocb->ki_filp = lower_file; - err = lower_file->f_op->aio_write(iocb, iov, nr_segs, pos); - iocb->ki_filp = file; - fput(lower_file); - /* update upper inode times/sizes as needed */ - if (err >= 0 || err == -EIOCBQUEUED) { - fsstack_copy_inode_size(file->f_path.dentry->d_inode, - lower_file->f_path.dentry->d_inode); - fsstack_copy_attr_times(file->f_path.dentry->d_inode, - lower_file->f_path.dentry->d_inode); - } -out: - return err; -} - -/* - * Wrapfs cannot use generic_file_llseek as ->llseek, because it would - * only set the offset of the upper file. So we have to implement our - * own method to set both the upper and lower file offsets - * consistently. - */ -static loff_t wrapfs_file_llseek(struct file *file, loff_t offset, int whence) -{ - int err; - struct file *lower_file; - - err = generic_file_llseek(file, offset, whence); - if (err < 0) - goto out; - - lower_file = wrapfs_lower_file(file); - err = generic_file_llseek(lower_file, offset, whence); - -out: - return err; -} - -const struct file_operations wrapfs_main_fops = { - .llseek = generic_file_llseek, - .read = wrapfs_read, - .write = wrapfs_write, - .unlocked_ioctl = wrapfs_ioctl, - .mmap = wrapfs_mmap, - .open = wrapfs_open, - .flush = wrapfs_flush, - .release = wrapfs_file_release, - .fsync = wrapfs_fsync, - .fasync = wrapfs_fasync, - .aio_read = wrapfs_aio_read, - .aio_write = wrapfs_aio_write, -}; - -/* trimmed directory options */ -const struct file_operations wrapfs_dir_fops = { - .llseek = wrapfs_file_llseek, - .read = generic_read_dir, - .readdir = wrapfs_readdir, - .unlocked_ioctl = wrapfs_ioctl, - .open = wrapfs_open, - .release = wrapfs_file_release, - .flush = wrapfs_flush, - .fsync = wrapfs_fsync, - .fasync = wrapfs_fasync, -}; diff --git a/fs/wrapfs/inode.c b/fs/wrapfs/inode.c deleted file mode 100644 index 4f6f46a..0000000 --- a/fs/wrapfs/inode.c +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright (c) 1998-2017 Erez Zadok - * Copyright (c) 2009 Shrikar Archak - * Copyright (c) 2003-2017 Stony Brook University - * Copyright (c) 2003-2017 The Research Foundation of SUNY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "wrapfs.h" - -static int wrapfs_create(struct inode *dir, struct dentry *dentry, - int mode, struct nameidata *nd) -{ - int err = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path, saved_path; - - wrapfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_parent_dentry = lock_parent(lower_dentry); - - err = mnt_want_write(lower_path.mnt); - if (err) - goto out_unlock; - - pathcpy(&saved_path, &nd->path); - pathcpy(&nd->path, &lower_path); - err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd); - pathcpy(&nd->path, &saved_path); - if (err) - goto out; - - err = wrapfs_interpose(dentry, dir->i_sb, &lower_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir)); - fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); - -out: - mnt_drop_write(lower_path.mnt); -out_unlock: - unlock_dir(lower_parent_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static int wrapfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) -{ - struct dentry *lower_old_dentry; - struct dentry *lower_new_dentry; - struct dentry *lower_dir_dentry; - u64 file_size_save; - int err; - struct path lower_old_path, lower_new_path; - - file_size_save = i_size_read(old_dentry->d_inode); - wrapfs_get_lower_path(old_dentry, &lower_old_path); - wrapfs_get_lower_path(new_dentry, &lower_new_path); - lower_old_dentry = lower_old_path.dentry; - lower_new_dentry = lower_new_path.dentry; - lower_dir_dentry = lock_parent(lower_new_dentry); - - err = mnt_want_write(lower_new_path.mnt); - if (err) - goto out_unlock; - - err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, - lower_new_dentry); - if (err || !lower_new_dentry->d_inode) - goto out; - - err = wrapfs_interpose(new_dentry, dir->i_sb, &lower_new_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, lower_new_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_new_dentry->d_inode); - old_dentry->d_inode->i_nlink = - wrapfs_lower_inode(old_dentry->d_inode)->i_nlink; - i_size_write(new_dentry->d_inode, file_size_save); -out: - mnt_drop_write(lower_new_path.mnt); -out_unlock: - unlock_dir(lower_dir_dentry); - wrapfs_put_lower_path(old_dentry, &lower_old_path); - wrapfs_put_lower_path(new_dentry, &lower_new_path); - return err; -} - -static int wrapfs_unlink(struct inode *dir, struct dentry *dentry) -{ - int err; - struct dentry *lower_dentry; - struct inode *lower_dir_inode = wrapfs_lower_inode(dir); - struct dentry *lower_dir_dentry; - struct path lower_path; - - wrapfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - dget(lower_dentry); - lower_dir_dentry = lock_parent(lower_dentry); - - err = mnt_want_write(lower_path.mnt); - if (err) - goto out_unlock; - err = vfs_unlink(lower_dir_inode, lower_dentry); - - /* - * Note: unlinking on top of NFS can cause silly-renamed files. - * Trying to delete such files results in EBUSY from NFS - * below. Silly-renamed files will get deleted by NFS later on, so - * we just need to detect them here and treat such EBUSY errors as - * if the upper file was successfully deleted. - */ - if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) - err = 0; - if (err) - goto out; - fsstack_copy_attr_times(dir, lower_dir_inode); - fsstack_copy_inode_size(dir, lower_dir_inode); - dentry->d_inode->i_nlink = - wrapfs_lower_inode(dentry->d_inode)->i_nlink; - dentry->d_inode->i_ctime = dir->i_ctime; - d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */ -out: - mnt_drop_write(lower_path.mnt); -out_unlock: - unlock_dir(lower_dir_dentry); - dput(lower_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static int wrapfs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int err = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - wrapfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_parent_dentry = lock_parent(lower_dentry); - - err = mnt_want_write(lower_path.mnt); - if (err) - goto out_unlock; - err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname); - if (err) - goto out; - err = wrapfs_interpose(dentry, dir->i_sb, &lower_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir)); - fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); - -out: - mnt_drop_write(lower_path.mnt); -out_unlock: - unlock_dir(lower_parent_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - int err = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - wrapfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_parent_dentry = lock_parent(lower_dentry); - - err = mnt_want_write(lower_path.mnt); - if (err) - goto out_unlock; - err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode); - if (err) - goto out; - - err = wrapfs_interpose(dentry, dir->i_sb, &lower_path); - if (err) - goto out; - - fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir)); - fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); - /* update number of links on parent directory */ - dir->i_nlink = wrapfs_lower_inode(dir)->i_nlink; - -out: - mnt_drop_write(lower_path.mnt); -out_unlock: - unlock_dir(lower_parent_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry) -{ - struct dentry *lower_dentry; - struct dentry *lower_dir_dentry; - int err; - struct path lower_path; - - wrapfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_dir_dentry = lock_parent(lower_dentry); - - err = mnt_want_write(lower_path.mnt); - if (err) - goto out_unlock; - err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); - if (err) - goto out; - - d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ - if (dentry->d_inode) - clear_nlink(dentry->d_inode); - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); - dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; - -out: - mnt_drop_write(lower_path.mnt); -out_unlock: - unlock_dir(lower_dir_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, int mode, - dev_t dev) -{ - int err = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; _______________________________________________ unionfs-cvs mailing list: http://unionfs.filesystems.org/ unionfs-cvs@fsl.cs.sunysb.edu http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs