diff options
author | Timothy Pearson <tpearson@raptorengineering.com> | 2017-08-23 14:45:25 -0500 |
---|---|---|
committer | Timothy Pearson <tpearson@raptorengineering.com> | 2017-08-23 14:45:25 -0500 |
commit | fcbb27b0ec6dcbc5a5108cb8fb19eae64593d204 (patch) | |
tree | 22962a4387943edc841c72a4e636a068c66d58fd /fs/unionfs/subr.c | |
download | ast2050-linux-kernel-fcbb27b0ec6dcbc5a5108cb8fb19eae64593d204.zip ast2050-linux-kernel-fcbb27b0ec6dcbc5a5108cb8fb19eae64593d204.tar.gz |
Initial import of modified Linux 2.6.28 tree
Original upstream URL:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git | branch linux-2.6.28.y
Diffstat (limited to 'fs/unionfs/subr.c')
-rw-r--r-- | fs/unionfs/subr.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c new file mode 100644 index 0000000..018b4fd --- /dev/null +++ b/fs/unionfs/subr.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003-2009 Erez Zadok + * Copyright (c) 2003-2006 Charles P. Wright + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek + * Copyright (c) 2005-2006 Junjiro Okajima + * Copyright (c) 2005 Arun M. Krishnakumar + * Copyright (c) 2004-2006 David P. Quigley + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair + * Copyright (c) 2003 Puja Gupta + * Copyright (c) 2003 Harikesavan Krishnan + * Copyright (c) 2003-2009 Stony Brook University + * Copyright (c) 2003-2009 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 "union.h" + +/* + * returns the right n_link value based on the inode type + */ +int unionfs_get_nlinks(const struct inode *inode) +{ + /* don't bother to do all the work since we're unlinked */ + if (inode->i_nlink == 0) + return 0; + + if (!S_ISDIR(inode->i_mode)) + return unionfs_lower_inode(inode)->i_nlink; + + /* + * For directories, we return 1. The only place that could cares + * about links is readdir, and there's d_type there so even that + * doesn't matter. + */ + return 1; +} + +/* copy a/m/ctime from the lower branch with the newest times */ +void unionfs_copy_attr_times(struct inode *upper) +{ + int bindex; + struct inode *lower; + + if (!upper) + return; + if (ibstart(upper) < 0) { +#ifdef CONFIG_UNION_FS_DEBUG + WARN_ON(ibstart(upper) < 0); +#endif /* CONFIG_UNION_FS_DEBUG */ + return; + } + for (bindex = ibstart(upper); bindex <= ibend(upper); bindex++) { + lower = unionfs_lower_inode_idx(upper, bindex); + if (!lower) + continue; /* not all lower dir objects may exist */ + if (unlikely(timespec_compare(&upper->i_mtime, + &lower->i_mtime) < 0)) + upper->i_mtime = lower->i_mtime; + if (unlikely(timespec_compare(&upper->i_ctime, + &lower->i_ctime) < 0)) + upper->i_ctime = lower->i_ctime; + if (unlikely(timespec_compare(&upper->i_atime, + &lower->i_atime) < 0)) + upper->i_atime = lower->i_atime; + } +} + +/* + * A unionfs/fanout version of fsstack_copy_attr_all. Uses a + * unionfs_get_nlinks to properly calcluate the number of links to a file. + * Also, copies the max() of all a/m/ctimes for all lower inodes (which is + * important if the lower inode is a directory type) + */ +void unionfs_copy_attr_all(struct inode *dest, + const struct inode *src) +{ + dest->i_mode = src->i_mode; + dest->i_uid = src->i_uid; + dest->i_gid = src->i_gid; + dest->i_rdev = src->i_rdev; + + unionfs_copy_attr_times(dest); + + dest->i_blkbits = src->i_blkbits; + dest->i_flags = src->i_flags; + + /* + * Update the nlinks AFTER updating the above fields, because the + * get_links callback may depend on them. + */ + dest->i_nlink = unionfs_get_nlinks(dest); +} |