aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_iops.c')
-rw-r--r--fs/xfs/xfs_iops.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 9ddfb8190ca1..36d630319a27 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -39,6 +39,7 @@
39#include "xfs_da_btree.h" 39#include "xfs_da_btree.h"
40#include "xfs_dir2_priv.h" 40#include "xfs_dir2_priv.h"
41#include "xfs_dinode.h" 41#include "xfs_dinode.h"
42#include "xfs_trans_space.h"
42 43
43#include <linux/capability.h> 44#include <linux/capability.h>
44#include <linux/xattr.h> 45#include <linux/xattr.h>
@@ -48,6 +49,18 @@
48#include <linux/fiemap.h> 49#include <linux/fiemap.h>
49#include <linux/slab.h> 50#include <linux/slab.h>
50 51
52/*
53 * Directories have different lock order w.r.t. mmap_sem compared to regular
54 * files. This is due to readdir potentially triggering page faults on a user
55 * buffer inside filldir(), and this happens with the ilock on the directory
56 * held. For regular files, the lock order is the other way around - the
57 * mmap_sem is taken during the page fault, and then we lock the ilock to do
58 * block mapping. Hence we need a different class for the directory ilock so
59 * that lockdep can tell them apart.
60 */
61static struct lock_class_key xfs_nondir_ilock_class;
62static struct lock_class_key xfs_dir_ilock_class;
63
51static int 64static int
52xfs_initxattrs( 65xfs_initxattrs(
53 struct inode *inode, 66 struct inode *inode,
@@ -59,8 +72,8 @@ xfs_initxattrs(
59 int error = 0; 72 int error = 0;
60 73
61 for (xattr = xattr_array; xattr->name != NULL; xattr++) { 74 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
62 error = xfs_attr_set(ip, xattr->name, xattr->value, 75 error = -xfs_attr_set(ip, xattr->name, xattr->value,
63 xattr->value_len, ATTR_SECURE); 76 xattr->value_len, ATTR_SECURE);
64 if (error < 0) 77 if (error < 0)
65 break; 78 break;
66 } 79 }
@@ -80,8 +93,8 @@ xfs_init_security(
80 struct inode *dir, 93 struct inode *dir,
81 const struct qstr *qstr) 94 const struct qstr *qstr)
82{ 95{
83 return security_inode_init_security(inode, dir, qstr, 96 return -security_inode_init_security(inode, dir, qstr,
84 &xfs_initxattrs, NULL); 97 &xfs_initxattrs, NULL);
85} 98}
86 99
87static void 100static void
@@ -111,15 +124,15 @@ xfs_cleanup_inode(
111 xfs_dentry_to_name(&teardown, dentry, 0); 124 xfs_dentry_to_name(&teardown, dentry, 0);
112 125
113 xfs_remove(XFS_I(dir), &teardown, XFS_I(inode)); 126 xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
114 iput(inode);
115} 127}
116 128
117STATIC int 129STATIC int
118xfs_vn_mknod( 130xfs_generic_create(
119 struct inode *dir, 131 struct inode *dir,
120 struct dentry *dentry, 132 struct dentry *dentry,
121 umode_t mode, 133 umode_t mode,
122 dev_t rdev) 134 dev_t rdev,
135 bool tmpfile) /* unnamed file */
123{ 136{
124 struct inode *inode; 137 struct inode *inode;
125 struct xfs_inode *ip = NULL; 138 struct xfs_inode *ip = NULL;
@@ -143,8 +156,12 @@ xfs_vn_mknod(
143 if (error) 156 if (error)
144 return error; 157 return error;
145 158
146 xfs_dentry_to_name(&name, dentry, mode); 159 if (!tmpfile) {
147 error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); 160 xfs_dentry_to_name(&name, dentry, mode);
161 error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
162 } else {
163 error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip);
164 }
148 if (unlikely(error)) 165 if (unlikely(error))
149 goto out_free_acl; 166 goto out_free_acl;
150 167
@@ -156,18 +173,22 @@ xfs_vn_mknod(
156 173
157#ifdef CONFIG_XFS_POSIX_ACL 174#ifdef CONFIG_XFS_POSIX_ACL
158 if (default_acl) { 175 if (default_acl) {
159 error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); 176 error = -xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
160 if (error) 177 if (error)
161 goto out_cleanup_inode; 178 goto out_cleanup_inode;
162 } 179 }
163 if (acl) { 180 if (acl) {
164 error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS); 181 error = -xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
165 if (error) 182 if (error)
166 goto out_cleanup_inode; 183 goto out_cleanup_inode;
167 } 184 }
168#endif 185#endif
169 186
170 d_instantiate(dentry, inode); 187 if (tmpfile)
188 d_tmpfile(dentry, inode);
189 else
190 d_instantiate(dentry, inode);
191
171 out_free_acl: 192 out_free_acl:
172 if (default_acl) 193 if (default_acl)
173 posix_acl_release(default_acl); 194 posix_acl_release(default_acl);
@@ -176,11 +197,23 @@ xfs_vn_mknod(
176 return -error; 197 return -error;
177 198
178 out_cleanup_inode: 199 out_cleanup_inode:
179 xfs_cleanup_inode(dir, inode, dentry); 200 if (!tmpfile)
201 xfs_cleanup_inode(dir, inode, dentry);
202 iput(inode);
180 goto out_free_acl; 203 goto out_free_acl;
181} 204}
182 205
183STATIC int 206STATIC int
207xfs_vn_mknod(
208 struct inode *dir,
209 struct dentry *dentry,
210 umode_t mode,
211 dev_t rdev)
212{
213 return xfs_generic_create(dir, dentry, mode, rdev, false);
214}
215
216STATIC int
184xfs_vn_create( 217xfs_vn_create(
185 struct inode *dir, 218 struct inode *dir,
186 struct dentry *dentry, 219 struct dentry *dentry,
@@ -340,6 +373,7 @@ xfs_vn_symlink(
340 373
341 out_cleanup_inode: 374 out_cleanup_inode:
342 xfs_cleanup_inode(dir, inode, dentry); 375 xfs_cleanup_inode(dir, inode, dentry);
376 iput(inode);
343 out: 377 out:
344 return -error; 378 return -error;
345} 379}
@@ -1034,6 +1068,15 @@ xfs_vn_fiemap(
1034 return 0; 1068 return 0;
1035} 1069}
1036 1070
1071STATIC int
1072xfs_vn_tmpfile(
1073 struct inode *dir,
1074 struct dentry *dentry,
1075 umode_t mode)
1076{
1077 return xfs_generic_create(dir, dentry, mode, 0, true);
1078}
1079
1037static const struct inode_operations xfs_inode_operations = { 1080static const struct inode_operations xfs_inode_operations = {
1038 .get_acl = xfs_get_acl, 1081 .get_acl = xfs_get_acl,
1039 .set_acl = xfs_set_acl, 1082 .set_acl = xfs_set_acl,
@@ -1072,6 +1115,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
1072 .removexattr = generic_removexattr, 1115 .removexattr = generic_removexattr,
1073 .listxattr = xfs_vn_listxattr, 1116 .listxattr = xfs_vn_listxattr,
1074 .update_time = xfs_vn_update_time, 1117 .update_time = xfs_vn_update_time,
1118 .tmpfile = xfs_vn_tmpfile,
1075}; 1119};
1076 1120
1077static const struct inode_operations xfs_dir_ci_inode_operations = { 1121static const struct inode_operations xfs_dir_ci_inode_operations = {
@@ -1099,6 +1143,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
1099 .removexattr = generic_removexattr, 1143 .removexattr = generic_removexattr,
1100 .listxattr = xfs_vn_listxattr, 1144 .listxattr = xfs_vn_listxattr,
1101 .update_time = xfs_vn_update_time, 1145 .update_time = xfs_vn_update_time,
1146 .tmpfile = xfs_vn_tmpfile,
1102}; 1147};
1103 1148
1104static const struct inode_operations xfs_symlink_inode_operations = { 1149static const struct inode_operations xfs_symlink_inode_operations = {
@@ -1191,6 +1236,7 @@ xfs_setup_inode(
1191 xfs_diflags_to_iflags(inode, ip); 1236 xfs_diflags_to_iflags(inode, ip);
1192 1237
1193 ip->d_ops = ip->i_mount->m_nondir_inode_ops; 1238 ip->d_ops = ip->i_mount->m_nondir_inode_ops;
1239 lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class);
1194 switch (inode->i_mode & S_IFMT) { 1240 switch (inode->i_mode & S_IFMT) {
1195 case S_IFREG: 1241 case S_IFREG:
1196 inode->i_op = &xfs_inode_operations; 1242 inode->i_op = &xfs_inode_operations;
@@ -1198,6 +1244,7 @@ xfs_setup_inode(
1198 inode->i_mapping->a_ops = &xfs_address_space_operations; 1244 inode->i_mapping->a_ops = &xfs_address_space_operations;
1199 break; 1245 break;
1200 case S_IFDIR: 1246 case S_IFDIR:
1247 lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class);
1201 if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) 1248 if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
1202 inode->i_op = &xfs_dir_ci_inode_operations; 1249 inode->i_op = &xfs_dir_ci_inode_operations;
1203 else 1250 else