aboutsummaryrefslogtreecommitdiffstats
path: root/mm/shmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/shmem.c')
-rw-r--r--mm/shmem.c117
1 files changed, 106 insertions, 11 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index eda907c3a86a..bb8ca7ef7094 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -26,6 +26,8 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/fs.h> 28#include <linux/fs.h>
29#include <linux/xattr.h>
30#include <linux/generic_acl.h>
29#include <linux/mm.h> 31#include <linux/mm.h>
30#include <linux/mman.h> 32#include <linux/mman.h>
31#include <linux/file.h> 33#include <linux/file.h>
@@ -177,6 +179,7 @@ static const struct address_space_operations shmem_aops;
177static struct file_operations shmem_file_operations; 179static struct file_operations shmem_file_operations;
178static struct inode_operations shmem_inode_operations; 180static struct inode_operations shmem_inode_operations;
179static struct inode_operations shmem_dir_inode_operations; 181static struct inode_operations shmem_dir_inode_operations;
182static struct inode_operations shmem_special_inode_operations;
180static struct vm_operations_struct shmem_vm_ops; 183static struct vm_operations_struct shmem_vm_ops;
181 184
182static struct backing_dev_info shmem_backing_dev_info __read_mostly = { 185static struct backing_dev_info shmem_backing_dev_info __read_mostly = {
@@ -637,7 +640,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
637 struct page *page = NULL; 640 struct page *page = NULL;
638 int error; 641 int error;
639 642
640 if (attr->ia_valid & ATTR_SIZE) { 643 if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
641 if (attr->ia_size < inode->i_size) { 644 if (attr->ia_size < inode->i_size) {
642 /* 645 /*
643 * If truncating down to a partial page, then 646 * If truncating down to a partial page, then
@@ -670,6 +673,10 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
670 error = inode_change_ok(inode, attr); 673 error = inode_change_ok(inode, attr);
671 if (!error) 674 if (!error)
672 error = inode_setattr(inode, attr); 675 error = inode_setattr(inode, attr);
676#ifdef CONFIG_TMPFS_POSIX_ACL
677 if (!error && (attr->ia_valid & ATTR_MODE))
678 error = generic_acl_chmod(inode, &shmem_acl_ops);
679#endif
673 if (page) 680 if (page)
674 page_cache_release(page); 681 page_cache_release(page);
675 return error; 682 return error;
@@ -1362,6 +1369,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1362 1369
1363 switch (mode & S_IFMT) { 1370 switch (mode & S_IFMT) {
1364 default: 1371 default:
1372 inode->i_op = &shmem_special_inode_operations;
1365 init_special_inode(inode, mode, dev); 1373 init_special_inode(inode, mode, dev);
1366 break; 1374 break;
1367 case S_IFREG: 1375 case S_IFREG:
@@ -1371,7 +1379,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1371 &sbinfo->policy_nodes); 1379 &sbinfo->policy_nodes);
1372 break; 1380 break;
1373 case S_IFDIR: 1381 case S_IFDIR:
1374 inode->i_nlink++; 1382 inc_nlink(inode);
1375 /* Some things misbehave if size == 0 on a directory */ 1383 /* Some things misbehave if size == 0 on a directory */
1376 inode->i_size = 2 * BOGO_DIRENT_SIZE; 1384 inode->i_size = 2 * BOGO_DIRENT_SIZE;
1377 inode->i_op = &shmem_dir_inode_operations; 1385 inode->i_op = &shmem_dir_inode_operations;
@@ -1682,7 +1690,11 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
1682 iput(inode); 1690 iput(inode);
1683 return error; 1691 return error;
1684 } 1692 }
1685 error = 0; 1693 }
1694 error = shmem_acl_init(inode, dir);
1695 if (error) {
1696 iput(inode);
1697 return error;
1686 } 1698 }
1687 if (dir->i_mode & S_ISGID) { 1699 if (dir->i_mode & S_ISGID) {
1688 inode->i_gid = dir->i_gid; 1700 inode->i_gid = dir->i_gid;
@@ -1703,7 +1715,7 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1703 1715
1704 if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0))) 1716 if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
1705 return error; 1717 return error;
1706 dir->i_nlink++; 1718 inc_nlink(dir);
1707 return 0; 1719 return 0;
1708} 1720}
1709 1721
@@ -1738,7 +1750,7 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
1738 1750
1739 dir->i_size += BOGO_DIRENT_SIZE; 1751 dir->i_size += BOGO_DIRENT_SIZE;
1740 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; 1752 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1741 inode->i_nlink++; 1753 inc_nlink(inode);
1742 atomic_inc(&inode->i_count); /* New dentry reference */ 1754 atomic_inc(&inode->i_count); /* New dentry reference */
1743 dget(dentry); /* Extra pinning count for the created dentry */ 1755 dget(dentry); /* Extra pinning count for the created dentry */
1744 d_instantiate(dentry, inode); 1756 d_instantiate(dentry, inode);
@@ -1760,7 +1772,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
1760 1772
1761 dir->i_size -= BOGO_DIRENT_SIZE; 1773 dir->i_size -= BOGO_DIRENT_SIZE;
1762 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; 1774 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1763 inode->i_nlink--; 1775 drop_nlink(inode);
1764 dput(dentry); /* Undo the count from "create" - this does all the work */ 1776 dput(dentry); /* Undo the count from "create" - this does all the work */
1765 return 0; 1777 return 0;
1766} 1778}
@@ -1770,8 +1782,8 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
1770 if (!simple_empty(dentry)) 1782 if (!simple_empty(dentry))
1771 return -ENOTEMPTY; 1783 return -ENOTEMPTY;
1772 1784
1773 dentry->d_inode->i_nlink--; 1785 drop_nlink(dentry->d_inode);
1774 dir->i_nlink--; 1786 drop_nlink(dir);
1775 return shmem_unlink(dir, dentry); 1787 return shmem_unlink(dir, dentry);
1776} 1788}
1777 1789
@@ -1792,10 +1804,10 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct
1792 if (new_dentry->d_inode) { 1804 if (new_dentry->d_inode) {
1793 (void) shmem_unlink(new_dir, new_dentry); 1805 (void) shmem_unlink(new_dir, new_dentry);
1794 if (they_are_dirs) 1806 if (they_are_dirs)
1795 old_dir->i_nlink--; 1807 drop_nlink(old_dir);
1796 } else if (they_are_dirs) { 1808 } else if (they_are_dirs) {
1797 old_dir->i_nlink--; 1809 drop_nlink(old_dir);
1798 new_dir->i_nlink++; 1810 inc_nlink(new_dir);
1799 } 1811 }
1800 1812
1801 old_dir->i_size -= BOGO_DIRENT_SIZE; 1813 old_dir->i_size -= BOGO_DIRENT_SIZE;
@@ -1897,6 +1909,53 @@ static struct inode_operations shmem_symlink_inode_operations = {
1897 .put_link = shmem_put_link, 1909 .put_link = shmem_put_link,
1898}; 1910};
1899 1911
1912#ifdef CONFIG_TMPFS_POSIX_ACL
1913/**
1914 * Superblocks without xattr inode operations will get security.* xattr
1915 * support from the VFS "for free". As soon as we have any other xattrs
1916 * like ACLs, we also need to implement the security.* handlers at
1917 * filesystem level, though.
1918 */
1919
1920static size_t shmem_xattr_security_list(struct inode *inode, char *list,
1921 size_t list_len, const char *name,
1922 size_t name_len)
1923{
1924 return security_inode_listsecurity(inode, list, list_len);
1925}
1926
1927static int shmem_xattr_security_get(struct inode *inode, const char *name,
1928 void *buffer, size_t size)
1929{
1930 if (strcmp(name, "") == 0)
1931 return -EINVAL;
1932 return security_inode_getsecurity(inode, name, buffer, size,
1933 -EOPNOTSUPP);
1934}
1935
1936static int shmem_xattr_security_set(struct inode *inode, const char *name,
1937 const void *value, size_t size, int flags)
1938{
1939 if (strcmp(name, "") == 0)
1940 return -EINVAL;
1941 return security_inode_setsecurity(inode, name, value, size, flags);
1942}
1943
1944struct xattr_handler shmem_xattr_security_handler = {
1945 .prefix = XATTR_SECURITY_PREFIX,
1946 .list = shmem_xattr_security_list,
1947 .get = shmem_xattr_security_get,
1948 .set = shmem_xattr_security_set,
1949};
1950
1951static struct xattr_handler *shmem_xattr_handlers[] = {
1952 &shmem_xattr_acl_access_handler,
1953 &shmem_xattr_acl_default_handler,
1954 &shmem_xattr_security_handler,
1955 NULL
1956};
1957#endif
1958
1900static int shmem_parse_options(char *options, int *mode, uid_t *uid, 1959static int shmem_parse_options(char *options, int *mode, uid_t *uid,
1901 gid_t *gid, unsigned long *blocks, unsigned long *inodes, 1960 gid_t *gid, unsigned long *blocks, unsigned long *inodes,
1902 int *policy, nodemask_t *policy_nodes) 1961 int *policy, nodemask_t *policy_nodes)
@@ -2094,6 +2153,10 @@ static int shmem_fill_super(struct super_block *sb,
2094 sb->s_magic = TMPFS_MAGIC; 2153 sb->s_magic = TMPFS_MAGIC;
2095 sb->s_op = &shmem_ops; 2154 sb->s_op = &shmem_ops;
2096 sb->s_time_gran = 1; 2155 sb->s_time_gran = 1;
2156#ifdef CONFIG_TMPFS_POSIX_ACL
2157 sb->s_xattr = shmem_xattr_handlers;
2158 sb->s_flags |= MS_POSIXACL;
2159#endif
2097 2160
2098 inode = shmem_get_inode(sb, S_IFDIR | mode, 0); 2161 inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
2099 if (!inode) 2162 if (!inode)
@@ -2130,6 +2193,7 @@ static void shmem_destroy_inode(struct inode *inode)
2130 /* only struct inode is valid if it's an inline symlink */ 2193 /* only struct inode is valid if it's an inline symlink */
2131 mpol_free_shared_policy(&SHMEM_I(inode)->policy); 2194 mpol_free_shared_policy(&SHMEM_I(inode)->policy);
2132 } 2195 }
2196 shmem_acl_destroy_inode(inode);
2133 kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode)); 2197 kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
2134} 2198}
2135 2199
@@ -2141,6 +2205,10 @@ static void init_once(void *foo, struct kmem_cache *cachep,
2141 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 2205 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
2142 SLAB_CTOR_CONSTRUCTOR) { 2206 SLAB_CTOR_CONSTRUCTOR) {
2143 inode_init_once(&p->vfs_inode); 2207 inode_init_once(&p->vfs_inode);
2208#ifdef CONFIG_TMPFS_POSIX_ACL
2209 p->i_acl = NULL;
2210 p->i_default_acl = NULL;
2211#endif
2144 } 2212 }
2145} 2213}
2146 2214
@@ -2184,6 +2252,14 @@ static struct inode_operations shmem_inode_operations = {
2184 .truncate = shmem_truncate, 2252 .truncate = shmem_truncate,
2185 .setattr = shmem_notify_change, 2253 .setattr = shmem_notify_change,
2186 .truncate_range = shmem_truncate_range, 2254 .truncate_range = shmem_truncate_range,
2255#ifdef CONFIG_TMPFS_POSIX_ACL
2256 .setxattr = generic_setxattr,
2257 .getxattr = generic_getxattr,
2258 .listxattr = generic_listxattr,
2259 .removexattr = generic_removexattr,
2260 .permission = shmem_permission,
2261#endif
2262
2187}; 2263};
2188 2264
2189static struct inode_operations shmem_dir_inode_operations = { 2265static struct inode_operations shmem_dir_inode_operations = {
@@ -2198,6 +2274,25 @@ static struct inode_operations shmem_dir_inode_operations = {
2198 .mknod = shmem_mknod, 2274 .mknod = shmem_mknod,
2199 .rename = shmem_rename, 2275 .rename = shmem_rename,
2200#endif 2276#endif
2277#ifdef CONFIG_TMPFS_POSIX_ACL
2278 .setattr = shmem_notify_change,
2279 .setxattr = generic_setxattr,
2280 .getxattr = generic_getxattr,
2281 .listxattr = generic_listxattr,
2282 .removexattr = generic_removexattr,
2283 .permission = shmem_permission,
2284#endif
2285};
2286
2287static struct inode_operations shmem_special_inode_operations = {
2288#ifdef CONFIG_TMPFS_POSIX_ACL
2289 .setattr = shmem_notify_change,
2290 .setxattr = generic_setxattr,
2291 .getxattr = generic_getxattr,
2292 .listxattr = generic_listxattr,
2293 .removexattr = generic_removexattr,
2294 .permission = shmem_permission,
2295#endif
2201}; 2296};
2202 2297
2203static struct super_operations shmem_ops = { 2298static struct super_operations shmem_ops = {