Push to branch refs/heads/master: 6790258d5eb866545cdaa305fe1075560cb0857f --> 2d20120bba8475c963a8d28dd0ffa13637fa3ad7
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index 47f3788..8042050 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX @@ -118,8 +118,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 b36f0ae1..6a6e4ac 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9507,15 +9507,6 @@ F: include/linux/workqueue.h F: kernel/workqueue.c F: Documentation/workqueue.txt -WRAP FILE SYSTEM -M: Erez Zadok <e...@cs.sunysb.edu> -L: wra...@filesystems.org -W: http://wrapfs.filesystems.org/ -T: git git://git.fsl.cs.sunysb.edu/wrapfs-latest.git -S: Maintained -F: Documentation/filesystems/wrapfs.txt -F: fs/wrapfs/ - X.25 NETWORK LAYER M: Andrew Hendry <andrew.hen...@gmail.com> L: linux-...@vger.kernel.org diff --git a/fs/Kconfig b/fs/Kconfig index ef2b6c0..c229f82 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -188,7 +188,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 b0baa95..4fe6df3 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -82,7 +82,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/wrapfs/Kconfig b/fs/wrapfs/Kconfig deleted file mode 100644 index a495c7d..0000000 --- a/fs/wrapfs/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -config WRAP_FS - tristate "Wrapfs stackable file system (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 f2b3ac1..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, unsigned int flags) -{ - struct path lower_path; - struct dentry *lower_dentry; - int err = 1; - - if (flags & LOOKUP_RCU) - return -ECHILD; - - wrapfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) - goto out; - err = lower_dentry->d_op->d_revalidate(lower_dentry, flags); -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 7737892..0000000 --- a/fs/wrapfs/file.c +++ /dev/null @@ -1,379 +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, - file_inode(lower_file)); - - return err; -} - -static ssize_t wrapfs_write(struct file *file, const 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_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, - file_inode(lower_file)); - fsstack_copy_attr_times(dentry->d_inode, - file_inode(lower_file)); - } - - return err; -} - -static int wrapfs_readdir(struct file *file, struct dir_context *ctx) -{ - int err; - struct file *lower_file = NULL; - struct dentry *dentry = file->f_path.dentry; - - lower_file = wrapfs_lower_file(file); - err = iterate_dir(lower_file, ctx); - file->f_pos = lower_file->f_pos; - if (err >= 0) /* copy the atime */ - fsstack_copy_attr_atime(dentry->d_inode, - file_inode(lower_file)); - return err; -} - -static long wrapfs_unlocked_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); - - /* some ioctls can change inode attributes (EXT2_IOC_SETFLAGS) */ - if (!err) - fsstack_copy_attr_all(file_inode(file), - file_inode(lower_file)); -out: - return err; -} - -#ifdef CONFIG_COMPAT -static long wrapfs_compat_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->compat_ioctl) - err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); - -out: - return err; -} -#endif - -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; - - 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, file->f_flags, current_cred()); - path_put(&lower_path); - 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)); -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) { - filemap_write_and_wait(file->f_mapping); - 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, loff_t start, loff_t end, - int datasync) -{ - int err; - struct file *lower_file; - struct path lower_path; - struct dentry *dentry = file->f_path.dentry; - - err = generic_file_fsync(file, start, end, datasync); - if (err) - goto out; - lower_file = wrapfs_lower_file(file); - wrapfs_get_lower_path(dentry, &lower_path); - err = vfs_fsync_range(lower_file, start, end, datasync); - wrapfs_put_lower_path(dentry, &lower_path); -out: - return err; -} - -static int wrapfs_fasync(int fd, struct file *file, int flag) -{ - int err = 0; - struct file *lower_file = NULL; - - 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); - - 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, - file_inode(lower_file)); -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, - file_inode(lower_file)); - fsstack_copy_attr_times(file->f_path.dentry->d_inode, - file_inode(lower_file)); - } -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_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = wrapfs_compat_ioctl, -#endif - .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, - .iterate = wrapfs_readdir, - .unlocked_ioctl = wrapfs_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = wrapfs_compat_ioctl, -#endif - .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 ef7e497..0000000 --- a/fs/wrapfs/inode.c +++ /dev/null @@ -1,584 +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, - umode_t mode, bool want_excl) -{ - int err; - 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 = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, - want_excl); - 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: - 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 = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, - lower_new_dentry, NULL); - 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); - set_nlink(old_dentry->d_inode, - wrapfs_lower_inode(old_dentry->d_inode)->i_nlink); - i_size_write(new_dentry->d_inode, file_size_save); -out: - 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 = vfs_unlink(lower_dir_inode, lower_dentry, NULL); - - /* - * 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); - set_nlink(dentry->d_inode, - 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: - 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; - 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 = 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: - unlock_dir(lower_parent_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - int err; - 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 = 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 */ - set_nlink(dir, wrapfs_lower_inode(dir)->i_nlink); - -out: - 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 = 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); - set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); - -out: - unlock_dir(lower_dir_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t dev) -{ - int err; - 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 = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev); - 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: - unlock_dir(lower_parent_dentry); - wrapfs_put_lower_path(dentry, &lower_path); - return err; -} - -/* - * The locking rules in wrapfs_rename are complex. We could use a simpler - * superblock-level name-space lock for renames and copy-ups. - */ -static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - int err = 0; - struct dentry *lower_old_dentry = NULL; - struct dentry *lower_new_dentry = NULL; - struct dentry *lower_old_dir_dentry = NULL; - struct dentry *lower_new_dir_dentry = NULL; - struct dentry *trap = NULL; - struct path lower_old_path, lower_new_path; - - 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_old_dir_dentry = dget_parent(lower_old_dentry); - lower_new_dir_dentry = dget_parent(lower_new_dentry); - - trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); - /* source should not be ancestor of target */ - if (trap == lower_old_dentry) { - err = -EINVAL; - goto out; - } - /* target should not be ancestor of source */ - if (trap == lower_new_dentry) { - err = -ENOTEMPTY; - goto out; - } - - err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, - lower_new_dir_dentry->d_inode, lower_new_dentry, - NULL); - if (err) - goto out; - - fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); - fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode); - if (new_dir != old_dir) { - fsstack_copy_attr_all(old_dir, - lower_old_dir_dentry->d_inode); - fsstack_copy_inode_size(old_dir, - lower_old_dir_dentry->d_inode); - } - -out: - unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); - dput(lower_old_dir_dentry); - dput(lower_new_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_readlink(struct dentry *dentry, char __user *buf, int bufsiz) -{ - int err; - struct dentry *lower_dentry; _______________________________________________ unionfs-cvs mailing list: http://unionfs.filesystems.org/ unionfs-cvs@fsl.cs.sunysb.edu http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs