diff options
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index bb8ca7ef7094..b378f66cf2f9 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1362,6 +1362,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) | |||
1362 | inode->i_mapping->a_ops = &shmem_aops; | 1362 | inode->i_mapping->a_ops = &shmem_aops; |
1363 | inode->i_mapping->backing_dev_info = &shmem_backing_dev_info; | 1363 | inode->i_mapping->backing_dev_info = &shmem_backing_dev_info; |
1364 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 1364 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
1365 | inode->i_generation = get_seconds(); | ||
1365 | info = SHMEM_I(inode); | 1366 | info = SHMEM_I(inode); |
1366 | memset(info, 0, (char *)inode - (char *)info); | 1367 | memset(info, 0, (char *)inode - (char *)info); |
1367 | spin_lock_init(&info->lock); | 1368 | spin_lock_init(&info->lock); |
@@ -1956,6 +1957,85 @@ static struct xattr_handler *shmem_xattr_handlers[] = { | |||
1956 | }; | 1957 | }; |
1957 | #endif | 1958 | #endif |
1958 | 1959 | ||
1960 | static struct dentry *shmem_get_parent(struct dentry *child) | ||
1961 | { | ||
1962 | return ERR_PTR(-ESTALE); | ||
1963 | } | ||
1964 | |||
1965 | static int shmem_match(struct inode *ino, void *vfh) | ||
1966 | { | ||
1967 | __u32 *fh = vfh; | ||
1968 | __u64 inum = fh[2]; | ||
1969 | inum = (inum << 32) | fh[1]; | ||
1970 | return ino->i_ino == inum && fh[0] == ino->i_generation; | ||
1971 | } | ||
1972 | |||
1973 | static struct dentry *shmem_get_dentry(struct super_block *sb, void *vfh) | ||
1974 | { | ||
1975 | struct dentry *de = NULL; | ||
1976 | struct inode *inode; | ||
1977 | __u32 *fh = vfh; | ||
1978 | __u64 inum = fh[2]; | ||
1979 | inum = (inum << 32) | fh[1]; | ||
1980 | |||
1981 | inode = ilookup5(sb, (unsigned long)(inum+fh[0]), shmem_match, vfh); | ||
1982 | if (inode) { | ||
1983 | de = d_find_alias(inode); | ||
1984 | iput(inode); | ||
1985 | } | ||
1986 | |||
1987 | return de? de: ERR_PTR(-ESTALE); | ||
1988 | } | ||
1989 | |||
1990 | static struct dentry *shmem_decode_fh(struct super_block *sb, __u32 *fh, | ||
1991 | int len, int type, | ||
1992 | int (*acceptable)(void *context, struct dentry *de), | ||
1993 | void *context) | ||
1994 | { | ||
1995 | if (len < 3) | ||
1996 | return ERR_PTR(-ESTALE); | ||
1997 | |||
1998 | return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, | ||
1999 | context); | ||
2000 | } | ||
2001 | |||
2002 | static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, | ||
2003 | int connectable) | ||
2004 | { | ||
2005 | struct inode *inode = dentry->d_inode; | ||
2006 | |||
2007 | if (*len < 3) | ||
2008 | return 255; | ||
2009 | |||
2010 | if (hlist_unhashed(&inode->i_hash)) { | ||
2011 | /* Unfortunately insert_inode_hash is not idempotent, | ||
2012 | * so as we hash inodes here rather than at creation | ||
2013 | * time, we need a lock to ensure we only try | ||
2014 | * to do it once | ||
2015 | */ | ||
2016 | static DEFINE_SPINLOCK(lock); | ||
2017 | spin_lock(&lock); | ||
2018 | if (hlist_unhashed(&inode->i_hash)) | ||
2019 | __insert_inode_hash(inode, | ||
2020 | inode->i_ino + inode->i_generation); | ||
2021 | spin_unlock(&lock); | ||
2022 | } | ||
2023 | |||
2024 | fh[0] = inode->i_generation; | ||
2025 | fh[1] = inode->i_ino; | ||
2026 | fh[2] = ((__u64)inode->i_ino) >> 32; | ||
2027 | |||
2028 | *len = 3; | ||
2029 | return 1; | ||
2030 | } | ||
2031 | |||
2032 | static struct export_operations shmem_export_ops = { | ||
2033 | .get_parent = shmem_get_parent, | ||
2034 | .get_dentry = shmem_get_dentry, | ||
2035 | .encode_fh = shmem_encode_fh, | ||
2036 | .decode_fh = shmem_decode_fh, | ||
2037 | }; | ||
2038 | |||
1959 | static int shmem_parse_options(char *options, int *mode, uid_t *uid, | 2039 | static int shmem_parse_options(char *options, int *mode, uid_t *uid, |
1960 | gid_t *gid, unsigned long *blocks, unsigned long *inodes, | 2040 | gid_t *gid, unsigned long *blocks, unsigned long *inodes, |
1961 | int *policy, nodemask_t *policy_nodes) | 2041 | int *policy, nodemask_t *policy_nodes) |
@@ -2128,6 +2208,7 @@ static int shmem_fill_super(struct super_block *sb, | |||
2128 | &inodes, &policy, &policy_nodes)) | 2208 | &inodes, &policy, &policy_nodes)) |
2129 | return -EINVAL; | 2209 | return -EINVAL; |
2130 | } | 2210 | } |
2211 | sb->s_export_op = &shmem_export_ops; | ||
2131 | #else | 2212 | #else |
2132 | sb->s_flags |= MS_NOUSER; | 2213 | sb->s_flags |= MS_NOUSER; |
2133 | #endif | 2214 | #endif |