diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/Kconfig | 1 | ||||
-rw-r--r-- | fs/gfs2/acl.c | 361 | ||||
-rw-r--r-- | fs/gfs2/acl.h | 24 | ||||
-rw-r--r-- | fs/gfs2/aops.c | 24 | ||||
-rw-r--r-- | fs/gfs2/bmap.c | 3 | ||||
-rw-r--r-- | fs/gfs2/dentry.c | 1 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 34 | ||||
-rw-r--r-- | fs/gfs2/export.c | 1 | ||||
-rw-r--r-- | fs/gfs2/file.c | 40 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 110 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 12 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 22 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 14 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 15 | ||||
-rw-r--r-- | fs/gfs2/lock_dlm.c | 17 | ||||
-rw-r--r-- | fs/gfs2/log.c | 5 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 8 | ||||
-rw-r--r-- | fs/gfs2/main.c | 28 | ||||
-rw-r--r-- | fs/gfs2/meta_io.c | 46 | ||||
-rw-r--r-- | fs/gfs2/meta_io.h | 12 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 174 | ||||
-rw-r--r-- | fs/gfs2/ops_inode.c | 118 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 400 | ||||
-rw-r--r-- | fs/gfs2/quota.h | 5 | ||||
-rw-r--r-- | fs/gfs2/recovery.c | 2 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 22 | ||||
-rw-r--r-- | fs/gfs2/rgrp.h | 2 | ||||
-rw-r--r-- | fs/gfs2/super.c | 143 | ||||
-rw-r--r-- | fs/gfs2/super.h | 4 | ||||
-rw-r--r-- | fs/gfs2/sys.c | 37 | ||||
-rw-r--r-- | fs/gfs2/util.c | 2 | ||||
-rw-r--r-- | fs/gfs2/util.h | 1 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 156 | ||||
-rw-r--r-- | fs/gfs2/xattr.h | 15 |
34 files changed, 1123 insertions, 736 deletions
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index 5971359d2090..a47b43107112 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig | |||
@@ -8,6 +8,7 @@ config GFS2_FS | |||
8 | select FS_POSIX_ACL | 8 | select FS_POSIX_ACL |
9 | select CRC32 | 9 | select CRC32 |
10 | select SLOW_WORK | 10 | select SLOW_WORK |
11 | select QUOTACTL | ||
11 | help | 12 | help |
12 | A cluster filesystem. | 13 | A cluster filesystem. |
13 | 14 | ||
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 3fc4e3ac7d84..87ee309d4c24 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 13 | #include <linux/completion.h> |
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/xattr.h> | ||
15 | #include <linux/posix_acl.h> | 16 | #include <linux/posix_acl.h> |
16 | #include <linux/posix_acl_xattr.h> | 17 | #include <linux/posix_acl_xattr.h> |
17 | #include <linux/gfs2_ondisk.h> | 18 | #include <linux/gfs2_ondisk.h> |
@@ -26,108 +27,44 @@ | |||
26 | #include "trans.h" | 27 | #include "trans.h" |
27 | #include "util.h" | 28 | #include "util.h" |
28 | 29 | ||
29 | #define ACL_ACCESS 1 | 30 | static const char *gfs2_acl_name(int type) |
30 | #define ACL_DEFAULT 0 | ||
31 | |||
32 | int gfs2_acl_validate_set(struct gfs2_inode *ip, int access, | ||
33 | struct gfs2_ea_request *er, int *remove, mode_t *mode) | ||
34 | { | 31 | { |
35 | struct posix_acl *acl; | 32 | switch (type) { |
36 | int error; | 33 | case ACL_TYPE_ACCESS: |
37 | 34 | return GFS2_POSIX_ACL_ACCESS; | |
38 | error = gfs2_acl_validate_remove(ip, access); | 35 | case ACL_TYPE_DEFAULT: |
39 | if (error) | 36 | return GFS2_POSIX_ACL_DEFAULT; |
40 | return error; | ||
41 | |||
42 | if (!er->er_data) | ||
43 | return -EINVAL; | ||
44 | |||
45 | acl = posix_acl_from_xattr(er->er_data, er->er_data_len); | ||
46 | if (IS_ERR(acl)) | ||
47 | return PTR_ERR(acl); | ||
48 | if (!acl) { | ||
49 | *remove = 1; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | error = posix_acl_valid(acl); | ||
54 | if (error) | ||
55 | goto out; | ||
56 | |||
57 | if (access) { | ||
58 | error = posix_acl_equiv_mode(acl, mode); | ||
59 | if (!error) | ||
60 | *remove = 1; | ||
61 | else if (error > 0) | ||
62 | error = 0; | ||
63 | } | 37 | } |
64 | 38 | return NULL; | |
65 | out: | ||
66 | posix_acl_release(acl); | ||
67 | return error; | ||
68 | } | ||
69 | |||
70 | int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access) | ||
71 | { | ||
72 | if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl) | ||
73 | return -EOPNOTSUPP; | ||
74 | if (!is_owner_or_cap(&ip->i_inode)) | ||
75 | return -EPERM; | ||
76 | if (S_ISLNK(ip->i_inode.i_mode)) | ||
77 | return -EOPNOTSUPP; | ||
78 | if (!access && !S_ISDIR(ip->i_inode.i_mode)) | ||
79 | return -EACCES; | ||
80 | |||
81 | return 0; | ||
82 | } | 39 | } |
83 | 40 | ||
84 | static int acl_get(struct gfs2_inode *ip, const char *name, | 41 | static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type) |
85 | struct posix_acl **acl, struct gfs2_ea_location *el, | ||
86 | char **datap, unsigned int *lenp) | ||
87 | { | 42 | { |
43 | struct posix_acl *acl; | ||
44 | const char *name; | ||
88 | char *data; | 45 | char *data; |
89 | unsigned int len; | 46 | int len; |
90 | int error; | ||
91 | |||
92 | el->el_bh = NULL; | ||
93 | 47 | ||
94 | if (!ip->i_eattr) | 48 | if (!ip->i_eattr) |
95 | return 0; | 49 | return NULL; |
96 | |||
97 | error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, el); | ||
98 | if (error) | ||
99 | return error; | ||
100 | if (!el->el_ea) | ||
101 | return 0; | ||
102 | if (!GFS2_EA_DATA_LEN(el->el_ea)) | ||
103 | goto out; | ||
104 | 50 | ||
105 | len = GFS2_EA_DATA_LEN(el->el_ea); | 51 | acl = get_cached_acl(&ip->i_inode, type); |
106 | data = kmalloc(len, GFP_NOFS); | 52 | if (acl != ACL_NOT_CACHED) |
107 | error = -ENOMEM; | 53 | return acl; |
108 | if (!data) | ||
109 | goto out; | ||
110 | 54 | ||
111 | error = gfs2_ea_get_copy(ip, el, data, len); | 55 | name = gfs2_acl_name(type); |
112 | if (error < 0) | 56 | if (name == NULL) |
113 | goto out_kfree; | 57 | return ERR_PTR(-EINVAL); |
114 | error = 0; | ||
115 | 58 | ||
116 | if (acl) { | 59 | len = gfs2_xattr_acl_get(ip, name, &data); |
117 | *acl = posix_acl_from_xattr(data, len); | 60 | if (len < 0) |
118 | if (IS_ERR(*acl)) | 61 | return ERR_PTR(len); |
119 | error = PTR_ERR(*acl); | 62 | if (len == 0) |
120 | } | 63 | return NULL; |
121 | 64 | ||
122 | out_kfree: | 65 | acl = posix_acl_from_xattr(data, len); |
123 | if (error || !datap) { | 66 | kfree(data); |
124 | kfree(data); | 67 | return acl; |
125 | } else { | ||
126 | *datap = data; | ||
127 | *lenp = len; | ||
128 | } | ||
129 | out: | ||
130 | return error; | ||
131 | } | 68 | } |
132 | 69 | ||
133 | /** | 70 | /** |
@@ -140,14 +77,12 @@ out: | |||
140 | 77 | ||
141 | int gfs2_check_acl(struct inode *inode, int mask) | 78 | int gfs2_check_acl(struct inode *inode, int mask) |
142 | { | 79 | { |
143 | struct gfs2_ea_location el; | 80 | struct posix_acl *acl; |
144 | struct posix_acl *acl = NULL; | ||
145 | int error; | 81 | int error; |
146 | 82 | ||
147 | error = acl_get(GFS2_I(inode), GFS2_POSIX_ACL_ACCESS, &acl, &el, NULL, NULL); | 83 | acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); |
148 | brelse(el.el_bh); | 84 | if (IS_ERR(acl)) |
149 | if (error) | 85 | return PTR_ERR(acl); |
150 | return error; | ||
151 | 86 | ||
152 | if (acl) { | 87 | if (acl) { |
153 | error = posix_acl_permission(inode, acl, mask); | 88 | error = posix_acl_permission(inode, acl, mask); |
@@ -158,57 +93,75 @@ int gfs2_check_acl(struct inode *inode, int mask) | |||
158 | return -EAGAIN; | 93 | return -EAGAIN; |
159 | } | 94 | } |
160 | 95 | ||
161 | static int munge_mode(struct gfs2_inode *ip, mode_t mode) | 96 | static int gfs2_set_mode(struct inode *inode, mode_t mode) |
162 | { | 97 | { |
163 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 98 | int error = 0; |
164 | struct buffer_head *dibh; | ||
165 | int error; | ||
166 | 99 | ||
167 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | 100 | if (mode != inode->i_mode) { |
168 | if (error) | 101 | struct iattr iattr; |
169 | return error; | ||
170 | 102 | ||
171 | error = gfs2_meta_inode_buffer(ip, &dibh); | 103 | iattr.ia_valid = ATTR_MODE; |
172 | if (!error) { | 104 | iattr.ia_mode = mode; |
173 | gfs2_assert_withdraw(sdp, | 105 | |
174 | (ip->i_inode.i_mode & S_IFMT) == (mode & S_IFMT)); | 106 | error = gfs2_setattr_simple(GFS2_I(inode), &iattr); |
175 | ip->i_inode.i_mode = mode; | ||
176 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
177 | gfs2_dinode_out(ip, dibh->b_data); | ||
178 | brelse(dibh); | ||
179 | } | 107 | } |
180 | 108 | ||
181 | gfs2_trans_end(sdp); | 109 | return error; |
110 | } | ||
111 | |||
112 | static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) | ||
113 | { | ||
114 | int error; | ||
115 | int len; | ||
116 | char *data; | ||
117 | const char *name = gfs2_acl_name(type); | ||
182 | 118 | ||
183 | return 0; | 119 | BUG_ON(name == NULL); |
120 | len = posix_acl_to_xattr(acl, NULL, 0); | ||
121 | if (len == 0) | ||
122 | return 0; | ||
123 | data = kmalloc(len, GFP_NOFS); | ||
124 | if (data == NULL) | ||
125 | return -ENOMEM; | ||
126 | error = posix_acl_to_xattr(acl, data, len); | ||
127 | if (error < 0) | ||
128 | goto out; | ||
129 | error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); | ||
130 | if (!error) | ||
131 | set_cached_acl(inode, type, acl); | ||
132 | out: | ||
133 | kfree(data); | ||
134 | return error; | ||
184 | } | 135 | } |
185 | 136 | ||
186 | int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) | 137 | int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode) |
187 | { | 138 | { |
188 | struct gfs2_ea_location el; | ||
189 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 139 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
190 | struct posix_acl *acl = NULL, *clone; | 140 | struct posix_acl *acl, *clone; |
191 | mode_t mode = ip->i_inode.i_mode; | 141 | mode_t mode = inode->i_mode; |
192 | char *data = NULL; | 142 | int error = 0; |
193 | unsigned int len; | ||
194 | int error; | ||
195 | 143 | ||
196 | if (!sdp->sd_args.ar_posix_acl) | 144 | if (!sdp->sd_args.ar_posix_acl) |
197 | return 0; | 145 | return 0; |
198 | if (S_ISLNK(ip->i_inode.i_mode)) | 146 | if (S_ISLNK(inode->i_mode)) |
199 | return 0; | 147 | return 0; |
200 | 148 | ||
201 | error = acl_get(dip, GFS2_POSIX_ACL_DEFAULT, &acl, &el, &data, &len); | 149 | acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT); |
202 | brelse(el.el_bh); | 150 | if (IS_ERR(acl)) |
203 | if (error) | 151 | return PTR_ERR(acl); |
204 | return error; | ||
205 | if (!acl) { | 152 | if (!acl) { |
206 | mode &= ~current_umask(); | 153 | mode &= ~current_umask(); |
207 | if (mode != ip->i_inode.i_mode) | 154 | if (mode != inode->i_mode) |
208 | error = munge_mode(ip, mode); | 155 | error = gfs2_set_mode(inode, mode); |
209 | return error; | 156 | return error; |
210 | } | 157 | } |
211 | 158 | ||
159 | if (S_ISDIR(inode->i_mode)) { | ||
160 | error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl); | ||
161 | if (error) | ||
162 | goto out; | ||
163 | } | ||
164 | |||
212 | clone = posix_acl_clone(acl, GFP_NOFS); | 165 | clone = posix_acl_clone(acl, GFP_NOFS); |
213 | error = -ENOMEM; | 166 | error = -ENOMEM; |
214 | if (!clone) | 167 | if (!clone) |
@@ -216,43 +169,32 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) | |||
216 | posix_acl_release(acl); | 169 | posix_acl_release(acl); |
217 | acl = clone; | 170 | acl = clone; |
218 | 171 | ||
219 | if (S_ISDIR(ip->i_inode.i_mode)) { | ||
220 | error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS, | ||
221 | GFS2_POSIX_ACL_DEFAULT, data, len, 0); | ||
222 | if (error) | ||
223 | goto out; | ||
224 | } | ||
225 | |||
226 | error = posix_acl_create_masq(acl, &mode); | 172 | error = posix_acl_create_masq(acl, &mode); |
227 | if (error < 0) | 173 | if (error < 0) |
228 | goto out; | 174 | goto out; |
229 | if (error == 0) | 175 | if (error == 0) |
230 | goto munge; | 176 | goto munge; |
231 | 177 | ||
232 | posix_acl_to_xattr(acl, data, len); | 178 | error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl); |
233 | error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS, | ||
234 | GFS2_POSIX_ACL_ACCESS, data, len, 0); | ||
235 | if (error) | 179 | if (error) |
236 | goto out; | 180 | goto out; |
237 | munge: | 181 | munge: |
238 | error = munge_mode(ip, mode); | 182 | error = gfs2_set_mode(inode, mode); |
239 | out: | 183 | out: |
240 | posix_acl_release(acl); | 184 | posix_acl_release(acl); |
241 | kfree(data); | ||
242 | return error; | 185 | return error; |
243 | } | 186 | } |
244 | 187 | ||
245 | int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) | 188 | int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) |
246 | { | 189 | { |
247 | struct posix_acl *acl = NULL, *clone; | 190 | struct posix_acl *acl, *clone; |
248 | struct gfs2_ea_location el; | ||
249 | char *data; | 191 | char *data; |
250 | unsigned int len; | 192 | unsigned int len; |
251 | int error; | 193 | int error; |
252 | 194 | ||
253 | error = acl_get(ip, GFS2_POSIX_ACL_ACCESS, &acl, &el, &data, &len); | 195 | acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS); |
254 | if (error) | 196 | if (IS_ERR(acl)) |
255 | goto out_brelse; | 197 | return PTR_ERR(acl); |
256 | if (!acl) | 198 | if (!acl) |
257 | return gfs2_setattr_simple(ip, attr); | 199 | return gfs2_setattr_simple(ip, attr); |
258 | 200 | ||
@@ -265,15 +207,138 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) | |||
265 | 207 | ||
266 | error = posix_acl_chmod_masq(acl, attr->ia_mode); | 208 | error = posix_acl_chmod_masq(acl, attr->ia_mode); |
267 | if (!error) { | 209 | if (!error) { |
210 | len = posix_acl_to_xattr(acl, NULL, 0); | ||
211 | data = kmalloc(len, GFP_NOFS); | ||
212 | error = -ENOMEM; | ||
213 | if (data == NULL) | ||
214 | goto out; | ||
268 | posix_acl_to_xattr(acl, data, len); | 215 | posix_acl_to_xattr(acl, data, len); |
269 | error = gfs2_ea_acl_chmod(ip, &el, attr, data); | 216 | error = gfs2_xattr_acl_chmod(ip, attr, data); |
217 | kfree(data); | ||
218 | set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl); | ||
270 | } | 219 | } |
271 | 220 | ||
272 | out: | 221 | out: |
273 | posix_acl_release(acl); | 222 | posix_acl_release(acl); |
274 | kfree(data); | ||
275 | out_brelse: | ||
276 | brelse(el.el_bh); | ||
277 | return error; | 223 | return error; |
278 | } | 224 | } |
279 | 225 | ||
226 | static int gfs2_acl_type(const char *name) | ||
227 | { | ||
228 | if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0) | ||
229 | return ACL_TYPE_ACCESS; | ||
230 | if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0) | ||
231 | return ACL_TYPE_DEFAULT; | ||
232 | return -EINVAL; | ||
233 | } | ||
234 | |||
235 | static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, | ||
236 | void *buffer, size_t size, int xtype) | ||
237 | { | ||
238 | struct inode *inode = dentry->d_inode; | ||
239 | struct posix_acl *acl; | ||
240 | int type; | ||
241 | int error; | ||
242 | |||
243 | type = gfs2_acl_type(name); | ||
244 | if (type < 0) | ||
245 | return type; | ||
246 | |||
247 | acl = gfs2_acl_get(GFS2_I(inode), type); | ||
248 | if (IS_ERR(acl)) | ||
249 | return PTR_ERR(acl); | ||
250 | if (acl == NULL) | ||
251 | return -ENODATA; | ||
252 | |||
253 | error = posix_acl_to_xattr(acl, buffer, size); | ||
254 | posix_acl_release(acl); | ||
255 | |||
256 | return error; | ||
257 | } | ||
258 | |||
259 | static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, | ||
260 | const void *value, size_t size, int flags, | ||
261 | int xtype) | ||
262 | { | ||
263 | struct inode *inode = dentry->d_inode; | ||
264 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
265 | struct posix_acl *acl = NULL; | ||
266 | int error = 0, type; | ||
267 | |||
268 | if (!sdp->sd_args.ar_posix_acl) | ||
269 | return -EOPNOTSUPP; | ||
270 | |||
271 | type = gfs2_acl_type(name); | ||
272 | if (type < 0) | ||
273 | return type; | ||
274 | if (flags & XATTR_CREATE) | ||
275 | return -EINVAL; | ||
276 | if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) | ||
277 | return value ? -EACCES : 0; | ||
278 | if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) | ||
279 | return -EPERM; | ||
280 | if (S_ISLNK(inode->i_mode)) | ||
281 | return -EOPNOTSUPP; | ||
282 | |||
283 | if (!value) | ||
284 | goto set_acl; | ||
285 | |||
286 | acl = posix_acl_from_xattr(value, size); | ||
287 | if (!acl) { | ||
288 | /* | ||
289 | * acl_set_file(3) may request that we set default ACLs with | ||
290 | * zero length -- defend (gracefully) against that here. | ||
291 | */ | ||
292 | goto out; | ||
293 | } | ||
294 | if (IS_ERR(acl)) { | ||
295 | error = PTR_ERR(acl); | ||
296 | goto out; | ||
297 | } | ||
298 | |||
299 | error = posix_acl_valid(acl); | ||
300 | if (error) | ||
301 | goto out_release; | ||
302 | |||
303 | error = -EINVAL; | ||
304 | if (acl->a_count > GFS2_ACL_MAX_ENTRIES) | ||
305 | goto out_release; | ||
306 | |||
307 | if (type == ACL_TYPE_ACCESS) { | ||
308 | mode_t mode = inode->i_mode; | ||
309 | error = posix_acl_equiv_mode(acl, &mode); | ||
310 | |||
311 | if (error <= 0) { | ||
312 | posix_acl_release(acl); | ||
313 | acl = NULL; | ||
314 | |||
315 | if (error < 0) | ||
316 | return error; | ||
317 | } | ||
318 | |||
319 | error = gfs2_set_mode(inode, mode); | ||
320 | if (error) | ||
321 | goto out_release; | ||
322 | } | ||
323 | |||
324 | set_acl: | ||
325 | error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); | ||
326 | if (!error) { | ||
327 | if (acl) | ||
328 | set_cached_acl(inode, type, acl); | ||
329 | else | ||
330 | forget_cached_acl(inode, type); | ||
331 | } | ||
332 | out_release: | ||
333 | posix_acl_release(acl); | ||
334 | out: | ||
335 | return error; | ||
336 | } | ||
337 | |||
338 | struct xattr_handler gfs2_xattr_system_handler = { | ||
339 | .prefix = XATTR_SYSTEM_PREFIX, | ||
340 | .flags = GFS2_EATYPE_SYS, | ||
341 | .get = gfs2_xattr_system_get, | ||
342 | .set = gfs2_xattr_system_set, | ||
343 | }; | ||
344 | |||
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h index 6751930bfb64..9306a2e6620c 100644 --- a/fs/gfs2/acl.h +++ b/fs/gfs2/acl.h | |||
@@ -13,26 +13,12 @@ | |||
13 | #include "incore.h" | 13 | #include "incore.h" |
14 | 14 | ||
15 | #define GFS2_POSIX_ACL_ACCESS "posix_acl_access" | 15 | #define GFS2_POSIX_ACL_ACCESS "posix_acl_access" |
16 | #define GFS2_POSIX_ACL_ACCESS_LEN 16 | ||
17 | #define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" | 16 | #define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" |
18 | #define GFS2_POSIX_ACL_DEFAULT_LEN 17 | 17 | #define GFS2_ACL_MAX_ENTRIES 25 |
19 | 18 | ||
20 | #define GFS2_ACL_IS_ACCESS(name, len) \ | 19 | extern int gfs2_check_acl(struct inode *inode, int mask); |
21 | ((len) == GFS2_POSIX_ACL_ACCESS_LEN && \ | 20 | extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode); |
22 | !memcmp(GFS2_POSIX_ACL_ACCESS, (name), (len))) | 21 | extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); |
23 | 22 | extern struct xattr_handler gfs2_xattr_system_handler; | |
24 | #define GFS2_ACL_IS_DEFAULT(name, len) \ | ||
25 | ((len) == GFS2_POSIX_ACL_DEFAULT_LEN && \ | ||
26 | !memcmp(GFS2_POSIX_ACL_DEFAULT, (name), (len))) | ||
27 | |||
28 | struct gfs2_ea_request; | ||
29 | |||
30 | int gfs2_acl_validate_set(struct gfs2_inode *ip, int access, | ||
31 | struct gfs2_ea_request *er, | ||
32 | int *remove, mode_t *mode); | ||
33 | int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access); | ||
34 | int gfs2_check_acl(struct inode *inode, int mask); | ||
35 | int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip); | ||
36 | int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); | ||
37 | 23 | ||
38 | #endif /* __ACL_DOT_H__ */ | 24 | #endif /* __ACL_DOT_H__ */ |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 694b5d48f036..0c1d0b82dcf1 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -269,7 +269,6 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping, | |||
269 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; | 269 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; |
270 | unsigned offset = i_size & (PAGE_CACHE_SIZE-1); | 270 | unsigned offset = i_size & (PAGE_CACHE_SIZE-1); |
271 | unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize); | 271 | unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize); |
272 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
273 | int i; | 272 | int i; |
274 | int ret; | 273 | int ret; |
275 | 274 | ||
@@ -313,11 +312,6 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping, | |||
313 | 312 | ||
314 | if (ret || (--(wbc->nr_to_write) <= 0)) | 313 | if (ret || (--(wbc->nr_to_write) <= 0)) |
315 | ret = 1; | 314 | ret = 1; |
316 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
317 | wbc->encountered_congestion = 1; | ||
318 | ret = 1; | ||
319 | } | ||
320 | |||
321 | } | 315 | } |
322 | gfs2_trans_end(sdp); | 316 | gfs2_trans_end(sdp); |
323 | return ret; | 317 | return ret; |
@@ -338,7 +332,6 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping, | |||
338 | static int gfs2_write_cache_jdata(struct address_space *mapping, | 332 | static int gfs2_write_cache_jdata(struct address_space *mapping, |
339 | struct writeback_control *wbc) | 333 | struct writeback_control *wbc) |
340 | { | 334 | { |
341 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
342 | int ret = 0; | 335 | int ret = 0; |
343 | int done = 0; | 336 | int done = 0; |
344 | struct pagevec pvec; | 337 | struct pagevec pvec; |
@@ -348,11 +341,6 @@ static int gfs2_write_cache_jdata(struct address_space *mapping, | |||
348 | int scanned = 0; | 341 | int scanned = 0; |
349 | int range_whole = 0; | 342 | int range_whole = 0; |
350 | 343 | ||
351 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
352 | wbc->encountered_congestion = 1; | ||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | pagevec_init(&pvec, 0); | 344 | pagevec_init(&pvec, 0); |
357 | if (wbc->range_cyclic) { | 345 | if (wbc->range_cyclic) { |
358 | index = mapping->writeback_index; /* Start from prev offset */ | 346 | index = mapping->writeback_index; /* Start from prev offset */ |
@@ -819,8 +807,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
819 | mark_inode_dirty(inode); | 807 | mark_inode_dirty(inode); |
820 | } | 808 | } |
821 | 809 | ||
822 | if (inode == sdp->sd_rindex) | 810 | if (inode == sdp->sd_rindex) { |
823 | adjust_fs_space(inode); | 811 | adjust_fs_space(inode); |
812 | ip->i_gh.gh_flags |= GL_NOCACHE; | ||
813 | } | ||
824 | 814 | ||
825 | brelse(dibh); | 815 | brelse(dibh); |
826 | gfs2_trans_end(sdp); | 816 | gfs2_trans_end(sdp); |
@@ -889,8 +879,10 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
889 | mark_inode_dirty(inode); | 879 | mark_inode_dirty(inode); |
890 | } | 880 | } |
891 | 881 | ||
892 | if (inode == sdp->sd_rindex) | 882 | if (inode == sdp->sd_rindex) { |
893 | adjust_fs_space(inode); | 883 | adjust_fs_space(inode); |
884 | ip->i_gh.gh_flags |= GL_NOCACHE; | ||
885 | } | ||
894 | 886 | ||
895 | brelse(dibh); | 887 | brelse(dibh); |
896 | gfs2_trans_end(sdp); | 888 | gfs2_trans_end(sdp); |
@@ -1069,8 +1061,8 @@ out: | |||
1069 | 1061 | ||
1070 | int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | 1062 | int gfs2_releasepage(struct page *page, gfp_t gfp_mask) |
1071 | { | 1063 | { |
1072 | struct inode *aspace = page->mapping->host; | 1064 | struct address_space *mapping = page->mapping; |
1073 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; | 1065 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); |
1074 | struct buffer_head *bh, *head; | 1066 | struct buffer_head *bh, *head; |
1075 | struct gfs2_bufdata *bd; | 1067 | struct gfs2_bufdata *bd; |
1076 | 1068 | ||
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 6d47379e794b..5e411d5f4697 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
12 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
13 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
@@ -541,7 +540,7 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock, | |||
541 | *ptr++ = cpu_to_be64(bn++); | 540 | *ptr++ = cpu_to_be64(bn++); |
542 | break; | 541 | break; |
543 | } | 542 | } |
544 | } while (state != ALLOC_DATA); | 543 | } while ((state != ALLOC_DATA) || !dblock); |
545 | 544 | ||
546 | ip->i_height = height; | 545 | ip->i_height = height; |
547 | gfs2_add_inode_blocks(&ip->i_inode, alloced); | 546 | gfs2_add_inode_blocks(&ip->i_inode, alloced); |
diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c index 91beddadd388..bb7907bde3d8 100644 --- a/fs/gfs2/dentry.c +++ b/fs/gfs2/dentry.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
12 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
13 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 297d7e5cebad..25fddc100f18 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -525,38 +525,6 @@ consist_inode: | |||
525 | return ERR_PTR(-EIO); | 525 | return ERR_PTR(-EIO); |
526 | } | 526 | } |
527 | 527 | ||
528 | |||
529 | /** | ||
530 | * dirent_first - Return the first dirent | ||
531 | * @dip: the directory | ||
532 | * @bh: The buffer | ||
533 | * @dent: Pointer to list of dirents | ||
534 | * | ||
535 | * return first dirent whether bh points to leaf or stuffed dinode | ||
536 | * | ||
537 | * Returns: IS_LEAF, IS_DINODE, or -errno | ||
538 | */ | ||
539 | |||
540 | static int dirent_first(struct gfs2_inode *dip, struct buffer_head *bh, | ||
541 | struct gfs2_dirent **dent) | ||
542 | { | ||
543 | struct gfs2_meta_header *h = (struct gfs2_meta_header *)bh->b_data; | ||
544 | |||
545 | if (be32_to_cpu(h->mh_type) == GFS2_METATYPE_LF) { | ||
546 | if (gfs2_meta_check(GFS2_SB(&dip->i_inode), bh)) | ||
547 | return -EIO; | ||
548 | *dent = (struct gfs2_dirent *)(bh->b_data + | ||
549 | sizeof(struct gfs2_leaf)); | ||
550 | return IS_LEAF; | ||
551 | } else { | ||
552 | if (gfs2_metatype_check(GFS2_SB(&dip->i_inode), bh, GFS2_METATYPE_DI)) | ||
553 | return -EIO; | ||
554 | *dent = (struct gfs2_dirent *)(bh->b_data + | ||
555 | sizeof(struct gfs2_dinode)); | ||
556 | return IS_DINODE; | ||
557 | } | ||
558 | } | ||
559 | |||
560 | static int dirent_check_reclen(struct gfs2_inode *dip, | 528 | static int dirent_check_reclen(struct gfs2_inode *dip, |
561 | const struct gfs2_dirent *d, const void *end_p) | 529 | const struct gfs2_dirent *d, const void *end_p) |
562 | { | 530 | { |
@@ -1006,7 +974,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
1006 | divider = (start + half_len) << (32 - dip->i_depth); | 974 | divider = (start + half_len) << (32 - dip->i_depth); |
1007 | 975 | ||
1008 | /* Copy the entries */ | 976 | /* Copy the entries */ |
1009 | dirent_first(dip, obh, &dent); | 977 | dent = (struct gfs2_dirent *)(obh->b_data + sizeof(struct gfs2_leaf)); |
1010 | 978 | ||
1011 | do { | 979 | do { |
1012 | next = dent; | 980 | next = dent; |
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index d15876e9aa26..c22c21174833 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
12 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
13 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 4eb308aa3234..e6dd2aec6f82 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -569,6 +569,40 @@ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
569 | return ret; | 569 | return ret; |
570 | } | 570 | } |
571 | 571 | ||
572 | /** | ||
573 | * gfs2_file_aio_write - Perform a write to a file | ||
574 | * @iocb: The io context | ||
575 | * @iov: The data to write | ||
576 | * @nr_segs: Number of @iov segments | ||
577 | * @pos: The file position | ||
578 | * | ||
579 | * We have to do a lock/unlock here to refresh the inode size for | ||
580 | * O_APPEND writes, otherwise we can land up writing at the wrong | ||
581 | * offset. There is still a race, but provided the app is using its | ||
582 | * own file locking, this will make O_APPEND work as expected. | ||
583 | * | ||
584 | */ | ||
585 | |||
586 | static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | ||
587 | unsigned long nr_segs, loff_t pos) | ||
588 | { | ||
589 | struct file *file = iocb->ki_filp; | ||
590 | |||
591 | if (file->f_flags & O_APPEND) { | ||
592 | struct dentry *dentry = file->f_dentry; | ||
593 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
594 | struct gfs2_holder gh; | ||
595 | int ret; | ||
596 | |||
597 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); | ||
598 | if (ret) | ||
599 | return ret; | ||
600 | gfs2_glock_dq_uninit(&gh); | ||
601 | } | ||
602 | |||
603 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
604 | } | ||
605 | |||
572 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM | 606 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM |
573 | 607 | ||
574 | /** | 608 | /** |
@@ -606,7 +640,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) | |||
606 | 640 | ||
607 | if (!(fl->fl_flags & FL_POSIX)) | 641 | if (!(fl->fl_flags & FL_POSIX)) |
608 | return -ENOLCK; | 642 | return -ENOLCK; |
609 | if (__mandatory_lock(&ip->i_inode)) | 643 | if (__mandatory_lock(&ip->i_inode) && fl->fl_type != F_UNLCK) |
610 | return -ENOLCK; | 644 | return -ENOLCK; |
611 | 645 | ||
612 | if (cmd == F_CANCELLK) { | 646 | if (cmd == F_CANCELLK) { |
@@ -711,7 +745,7 @@ const struct file_operations gfs2_file_fops = { | |||
711 | .read = do_sync_read, | 745 | .read = do_sync_read, |
712 | .aio_read = generic_file_aio_read, | 746 | .aio_read = generic_file_aio_read, |
713 | .write = do_sync_write, | 747 | .write = do_sync_write, |
714 | .aio_write = generic_file_aio_write, | 748 | .aio_write = gfs2_file_aio_write, |
715 | .unlocked_ioctl = gfs2_ioctl, | 749 | .unlocked_ioctl = gfs2_ioctl, |
716 | .mmap = gfs2_mmap, | 750 | .mmap = gfs2_mmap, |
717 | .open = gfs2_open, | 751 | .open = gfs2_open, |
@@ -741,7 +775,7 @@ const struct file_operations gfs2_file_fops_nolock = { | |||
741 | .read = do_sync_read, | 775 | .read = do_sync_read, |
742 | .aio_read = generic_file_aio_read, | 776 | .aio_read = generic_file_aio_read, |
743 | .write = do_sync_write, | 777 | .write = do_sync_write, |
744 | .aio_write = generic_file_aio_write, | 778 | .aio_write = gfs2_file_aio_write, |
745 | .unlocked_ioctl = gfs2_ioctl, | 779 | .unlocked_ioctl = gfs2_ioctl, |
746 | .mmap = gfs2_mmap, | 780 | .mmap = gfs2_mmap, |
747 | .open = gfs2_open, | 781 | .open = gfs2_open, |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 8b674b1f3a55..454d4b4eb36b 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/wait.h> | 20 | #include <linux/wait.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/rwsem.h> | ||
23 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
24 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
25 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
@@ -60,7 +59,6 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl); | |||
60 | #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) | 59 | #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) |
61 | static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); | 60 | static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); |
62 | 61 | ||
63 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | ||
64 | static struct dentry *gfs2_root; | 62 | static struct dentry *gfs2_root; |
65 | static struct workqueue_struct *glock_workqueue; | 63 | static struct workqueue_struct *glock_workqueue; |
66 | struct workqueue_struct *gfs2_delete_workqueue; | 64 | struct workqueue_struct *gfs2_delete_workqueue; |
@@ -154,12 +152,14 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp, | |||
154 | static void glock_free(struct gfs2_glock *gl) | 152 | static void glock_free(struct gfs2_glock *gl) |
155 | { | 153 | { |
156 | struct gfs2_sbd *sdp = gl->gl_sbd; | 154 | struct gfs2_sbd *sdp = gl->gl_sbd; |
157 | struct inode *aspace = gl->gl_aspace; | 155 | struct address_space *mapping = gfs2_glock2aspace(gl); |
156 | struct kmem_cache *cachep = gfs2_glock_cachep; | ||
158 | 157 | ||
159 | if (aspace) | 158 | GLOCK_BUG_ON(gl, mapping && mapping->nrpages); |
160 | gfs2_aspace_put(aspace); | ||
161 | trace_gfs2_glock_put(gl); | 159 | trace_gfs2_glock_put(gl); |
162 | sdp->sd_lockstruct.ls_ops->lm_put_lock(gfs2_glock_cachep, gl); | 160 | if (mapping) |
161 | cachep = gfs2_glock_aspace_cachep; | ||
162 | sdp->sd_lockstruct.ls_ops->lm_put_lock(cachep, gl); | ||
163 | } | 163 | } |
164 | 164 | ||
165 | /** | 165 | /** |
@@ -241,15 +241,14 @@ int gfs2_glock_put(struct gfs2_glock *gl) | |||
241 | int rv = 0; | 241 | int rv = 0; |
242 | 242 | ||
243 | write_lock(gl_lock_addr(gl->gl_hash)); | 243 | write_lock(gl_lock_addr(gl->gl_hash)); |
244 | if (atomic_dec_and_test(&gl->gl_ref)) { | 244 | if (atomic_dec_and_lock(&gl->gl_ref, &lru_lock)) { |
245 | hlist_del(&gl->gl_list); | 245 | hlist_del(&gl->gl_list); |
246 | write_unlock(gl_lock_addr(gl->gl_hash)); | ||
247 | spin_lock(&lru_lock); | ||
248 | if (!list_empty(&gl->gl_lru)) { | 246 | if (!list_empty(&gl->gl_lru)) { |
249 | list_del_init(&gl->gl_lru); | 247 | list_del_init(&gl->gl_lru); |
250 | atomic_dec(&lru_count); | 248 | atomic_dec(&lru_count); |
251 | } | 249 | } |
252 | spin_unlock(&lru_lock); | 250 | spin_unlock(&lru_lock); |
251 | write_unlock(gl_lock_addr(gl->gl_hash)); | ||
253 | GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); | 252 | GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); |
254 | glock_free(gl); | 253 | glock_free(gl); |
255 | rv = 1; | 254 | rv = 1; |
@@ -513,7 +512,6 @@ retry: | |||
513 | GLOCK_BUG_ON(gl, 1); | 512 | GLOCK_BUG_ON(gl, 1); |
514 | } | 513 | } |
515 | spin_unlock(&gl->gl_spin); | 514 | spin_unlock(&gl->gl_spin); |
516 | gfs2_glock_put(gl); | ||
517 | return; | 515 | return; |
518 | } | 516 | } |
519 | 517 | ||
@@ -524,8 +522,6 @@ retry: | |||
524 | if (glops->go_xmote_bh) { | 522 | if (glops->go_xmote_bh) { |
525 | spin_unlock(&gl->gl_spin); | 523 | spin_unlock(&gl->gl_spin); |
526 | rv = glops->go_xmote_bh(gl, gh); | 524 | rv = glops->go_xmote_bh(gl, gh); |
527 | if (rv == -EAGAIN) | ||
528 | return; | ||
529 | spin_lock(&gl->gl_spin); | 525 | spin_lock(&gl->gl_spin); |
530 | if (rv) { | 526 | if (rv) { |
531 | do_error(gl, rv); | 527 | do_error(gl, rv); |
@@ -540,7 +536,6 @@ out: | |||
540 | clear_bit(GLF_LOCK, &gl->gl_flags); | 536 | clear_bit(GLF_LOCK, &gl->gl_flags); |
541 | out_locked: | 537 | out_locked: |
542 | spin_unlock(&gl->gl_spin); | 538 | spin_unlock(&gl->gl_spin); |
543 | gfs2_glock_put(gl); | ||
544 | } | 539 | } |
545 | 540 | ||
546 | static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, | 541 | static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, |
@@ -600,7 +595,6 @@ __acquires(&gl->gl_spin) | |||
600 | 595 | ||
601 | if (!(ret & LM_OUT_ASYNC)) { | 596 | if (!(ret & LM_OUT_ASYNC)) { |
602 | finish_xmote(gl, ret); | 597 | finish_xmote(gl, ret); |
603 | gfs2_glock_hold(gl); | ||
604 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 598 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
605 | gfs2_glock_put(gl); | 599 | gfs2_glock_put(gl); |
606 | } else { | 600 | } else { |
@@ -672,12 +666,17 @@ out: | |||
672 | return; | 666 | return; |
673 | 667 | ||
674 | out_sched: | 668 | out_sched: |
669 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
670 | smp_mb__after_clear_bit(); | ||
675 | gfs2_glock_hold(gl); | 671 | gfs2_glock_hold(gl); |
676 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 672 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
677 | gfs2_glock_put_nolock(gl); | 673 | gfs2_glock_put_nolock(gl); |
674 | return; | ||
675 | |||
678 | out_unlock: | 676 | out_unlock: |
679 | clear_bit(GLF_LOCK, &gl->gl_flags); | 677 | clear_bit(GLF_LOCK, &gl->gl_flags); |
680 | goto out; | 678 | smp_mb__after_clear_bit(); |
679 | return; | ||
681 | } | 680 | } |
682 | 681 | ||
683 | static void delete_work_func(struct work_struct *work) | 682 | static void delete_work_func(struct work_struct *work) |
@@ -707,10 +706,12 @@ static void glock_work_func(struct work_struct *work) | |||
707 | { | 706 | { |
708 | unsigned long delay = 0; | 707 | unsigned long delay = 0; |
709 | struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); | 708 | struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); |
709 | int drop_ref = 0; | ||
710 | 710 | ||
711 | if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) | 711 | if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) { |
712 | finish_xmote(gl, gl->gl_reply); | 712 | finish_xmote(gl, gl->gl_reply); |
713 | down_read(&gfs2_umount_flush_sem); | 713 | drop_ref = 1; |
714 | } | ||
714 | spin_lock(&gl->gl_spin); | 715 | spin_lock(&gl->gl_spin); |
715 | if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && | 716 | if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && |
716 | gl->gl_state != LM_ST_UNLOCKED && | 717 | gl->gl_state != LM_ST_UNLOCKED && |
@@ -723,10 +724,11 @@ static void glock_work_func(struct work_struct *work) | |||
723 | } | 724 | } |
724 | run_queue(gl, 0); | 725 | run_queue(gl, 0); |
725 | spin_unlock(&gl->gl_spin); | 726 | spin_unlock(&gl->gl_spin); |
726 | up_read(&gfs2_umount_flush_sem); | ||
727 | if (!delay || | 727 | if (!delay || |
728 | queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) | 728 | queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) |
729 | gfs2_glock_put(gl); | 729 | gfs2_glock_put(gl); |
730 | if (drop_ref) | ||
731 | gfs2_glock_put(gl); | ||
730 | } | 732 | } |
731 | 733 | ||
732 | /** | 734 | /** |
@@ -746,10 +748,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
746 | const struct gfs2_glock_operations *glops, int create, | 748 | const struct gfs2_glock_operations *glops, int create, |
747 | struct gfs2_glock **glp) | 749 | struct gfs2_glock **glp) |
748 | { | 750 | { |
751 | struct super_block *s = sdp->sd_vfs; | ||
749 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; | 752 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; |
750 | struct gfs2_glock *gl, *tmp; | 753 | struct gfs2_glock *gl, *tmp; |
751 | unsigned int hash = gl_hash(sdp, &name); | 754 | unsigned int hash = gl_hash(sdp, &name); |
752 | int error; | 755 | struct address_space *mapping; |
753 | 756 | ||
754 | read_lock(gl_lock_addr(hash)); | 757 | read_lock(gl_lock_addr(hash)); |
755 | gl = search_bucket(hash, sdp, &name); | 758 | gl = search_bucket(hash, sdp, &name); |
@@ -761,10 +764,14 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
761 | if (!create) | 764 | if (!create) |
762 | return -ENOENT; | 765 | return -ENOENT; |
763 | 766 | ||
764 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | 767 | if (glops->go_flags & GLOF_ASPACE) |
768 | gl = kmem_cache_alloc(gfs2_glock_aspace_cachep, GFP_KERNEL); | ||
769 | else | ||
770 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | ||
765 | if (!gl) | 771 | if (!gl) |
766 | return -ENOMEM; | 772 | return -ENOMEM; |
767 | 773 | ||
774 | atomic_inc(&sdp->sd_glock_disposal); | ||
768 | gl->gl_flags = 0; | 775 | gl->gl_flags = 0; |
769 | gl->gl_name = name; | 776 | gl->gl_name = name; |
770 | atomic_set(&gl->gl_ref, 1); | 777 | atomic_set(&gl->gl_ref, 1); |
@@ -779,18 +786,18 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
779 | gl->gl_tchange = jiffies; | 786 | gl->gl_tchange = jiffies; |
780 | gl->gl_object = NULL; | 787 | gl->gl_object = NULL; |
781 | gl->gl_sbd = sdp; | 788 | gl->gl_sbd = sdp; |
782 | gl->gl_aspace = NULL; | ||
783 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | 789 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); |
784 | INIT_WORK(&gl->gl_delete, delete_work_func); | 790 | INIT_WORK(&gl->gl_delete, delete_work_func); |
785 | 791 | ||
786 | /* If this glock protects actual on-disk data or metadata blocks, | 792 | mapping = gfs2_glock2aspace(gl); |
787 | create a VFS inode to manage the pages/buffers holding them. */ | 793 | if (mapping) { |
788 | if (glops == &gfs2_inode_glops || glops == &gfs2_rgrp_glops) { | 794 | mapping->a_ops = &gfs2_meta_aops; |
789 | gl->gl_aspace = gfs2_aspace_get(sdp); | 795 | mapping->host = s->s_bdev->bd_inode; |
790 | if (!gl->gl_aspace) { | 796 | mapping->flags = 0; |
791 | error = -ENOMEM; | 797 | mapping_set_gfp_mask(mapping, GFP_NOFS); |
792 | goto fail; | 798 | mapping->assoc_mapping = NULL; |
793 | } | 799 | mapping->backing_dev_info = s->s_bdi; |
800 | mapping->writeback_index = 0; | ||
794 | } | 801 | } |
795 | 802 | ||
796 | write_lock(gl_lock_addr(hash)); | 803 | write_lock(gl_lock_addr(hash)); |
@@ -807,10 +814,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
807 | *glp = gl; | 814 | *glp = gl; |
808 | 815 | ||
809 | return 0; | 816 | return 0; |
810 | |||
811 | fail: | ||
812 | kmem_cache_free(gfs2_glock_cachep, gl); | ||
813 | return error; | ||
814 | } | 817 | } |
815 | 818 | ||
816 | /** | 819 | /** |
@@ -1361,10 +1364,6 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | |||
1361 | list_del_init(&gl->gl_lru); | 1364 | list_del_init(&gl->gl_lru); |
1362 | atomic_dec(&lru_count); | 1365 | atomic_dec(&lru_count); |
1363 | 1366 | ||
1364 | /* Check if glock is about to be freed */ | ||
1365 | if (atomic_read(&gl->gl_ref) == 0) | ||
1366 | continue; | ||
1367 | |||
1368 | /* Test for being demotable */ | 1367 | /* Test for being demotable */ |
1369 | if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { | 1368 | if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { |
1370 | gfs2_glock_hold(gl); | 1369 | gfs2_glock_hold(gl); |
@@ -1375,10 +1374,11 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | |||
1375 | handle_callback(gl, LM_ST_UNLOCKED, 0); | 1374 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1376 | nr--; | 1375 | nr--; |
1377 | } | 1376 | } |
1377 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
1378 | smp_mb__after_clear_bit(); | ||
1378 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 1379 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
1379 | gfs2_glock_put_nolock(gl); | 1380 | gfs2_glock_put_nolock(gl); |
1380 | spin_unlock(&gl->gl_spin); | 1381 | spin_unlock(&gl->gl_spin); |
1381 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
1382 | spin_lock(&lru_lock); | 1382 | spin_lock(&lru_lock); |
1383 | continue; | 1383 | continue; |
1384 | } | 1384 | } |
@@ -1508,35 +1508,13 @@ void gfs2_glock_thaw(struct gfs2_sbd *sdp) | |||
1508 | 1508 | ||
1509 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) | 1509 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) |
1510 | { | 1510 | { |
1511 | unsigned long t; | ||
1512 | unsigned int x; | 1511 | unsigned int x; |
1513 | int cont; | ||
1514 | 1512 | ||
1515 | t = jiffies; | 1513 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) |
1516 | 1514 | examine_bucket(clear_glock, sdp, x); | |
1517 | for (;;) { | 1515 | flush_workqueue(glock_workqueue); |
1518 | cont = 0; | 1516 | wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0); |
1519 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) { | 1517 | gfs2_dump_lockstate(sdp); |
1520 | if (examine_bucket(clear_glock, sdp, x)) | ||
1521 | cont = 1; | ||
1522 | } | ||
1523 | |||
1524 | if (!cont) | ||
1525 | break; | ||
1526 | |||
1527 | if (time_after_eq(jiffies, | ||
1528 | t + gfs2_tune_get(sdp, gt_stall_secs) * HZ)) { | ||
1529 | fs_warn(sdp, "Unmount seems to be stalled. " | ||
1530 | "Dumping lock state...\n"); | ||
1531 | gfs2_dump_lockstate(sdp); | ||
1532 | t = jiffies; | ||
1533 | } | ||
1534 | |||
1535 | down_write(&gfs2_umount_flush_sem); | ||
1536 | invalidate_inodes(sdp->sd_vfs); | ||
1537 | up_write(&gfs2_umount_flush_sem); | ||
1538 | msleep(10); | ||
1539 | } | ||
1540 | } | 1518 | } |
1541 | 1519 | ||
1542 | void gfs2_glock_finish_truncate(struct gfs2_inode *ip) | 1520 | void gfs2_glock_finish_truncate(struct gfs2_inode *ip) |
@@ -1680,7 +1658,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) | |||
1680 | dtime *= 1000000/HZ; /* demote time in uSec */ | 1658 | dtime *= 1000000/HZ; /* demote time in uSec */ |
1681 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1659 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) |
1682 | dtime = 0; | 1660 | dtime = 0; |
1683 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llu f:%s t:%s d:%s/%llu a:%d r:%d\n", | 1661 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d r:%d\n", |
1684 | state2str(gl->gl_state), | 1662 | state2str(gl->gl_state), |
1685 | gl->gl_name.ln_type, | 1663 | gl->gl_name.ln_type, |
1686 | (unsigned long long)gl->gl_name.ln_number, | 1664 | (unsigned long long)gl->gl_name.ln_number, |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index c609894ec0d0..2bda1911b156 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -123,7 +123,7 @@ struct lm_lockops { | |||
123 | int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); | 123 | int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); |
124 | void (*lm_unmount) (struct gfs2_sbd *sdp); | 124 | void (*lm_unmount) (struct gfs2_sbd *sdp); |
125 | void (*lm_withdraw) (struct gfs2_sbd *sdp); | 125 | void (*lm_withdraw) (struct gfs2_sbd *sdp); |
126 | void (*lm_put_lock) (struct kmem_cache *cachep, void *gl); | 126 | void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl); |
127 | unsigned int (*lm_lock) (struct gfs2_glock *gl, | 127 | unsigned int (*lm_lock) (struct gfs2_glock *gl, |
128 | unsigned int req_state, unsigned int flags); | 128 | unsigned int req_state, unsigned int flags); |
129 | void (*lm_cancel) (struct gfs2_glock *gl); | 129 | void (*lm_cancel) (struct gfs2_glock *gl); |
@@ -180,13 +180,11 @@ static inline int gfs2_glock_is_held_shrd(struct gfs2_glock *gl) | |||
180 | return gl->gl_state == LM_ST_SHARED; | 180 | return gl->gl_state == LM_ST_SHARED; |
181 | } | 181 | } |
182 | 182 | ||
183 | static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl) | 183 | static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl) |
184 | { | 184 | { |
185 | int ret; | 185 | if (gl->gl_ops->go_flags & GLOF_ASPACE) |
186 | spin_lock(&gl->gl_spin); | 186 | return (struct address_space *)(gl + 1); |
187 | ret = test_bit(GLF_DEMOTE, &gl->gl_flags); | 187 | return NULL; |
188 | spin_unlock(&gl->gl_spin); | ||
189 | return ret; | ||
190 | } | 188 | } |
191 | 189 | ||
192 | int gfs2_glock_get(struct gfs2_sbd *sdp, | 190 | int gfs2_glock_get(struct gfs2_sbd *sdp, |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 6985eef06c39..49f97d3bb690 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -7,12 +7,12 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
12 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
13 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
14 | #include <linux/gfs2_ondisk.h> | 13 | #include <linux/gfs2_ondisk.h> |
15 | #include <linux/bio.h> | 14 | #include <linux/bio.h> |
15 | #include <linux/posix_acl.h> | ||
16 | 16 | ||
17 | #include "gfs2.h" | 17 | #include "gfs2.h" |
18 | #include "incore.h" | 18 | #include "incore.h" |
@@ -86,7 +86,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
86 | 86 | ||
87 | static void rgrp_go_sync(struct gfs2_glock *gl) | 87 | static void rgrp_go_sync(struct gfs2_glock *gl) |
88 | { | 88 | { |
89 | struct address_space *metamapping = gl->gl_aspace->i_mapping; | 89 | struct address_space *metamapping = gfs2_glock2aspace(gl); |
90 | int error; | 90 | int error; |
91 | 91 | ||
92 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) | 92 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) |
@@ -112,7 +112,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl) | |||
112 | 112 | ||
113 | static void rgrp_go_inval(struct gfs2_glock *gl, int flags) | 113 | static void rgrp_go_inval(struct gfs2_glock *gl, int flags) |
114 | { | 114 | { |
115 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 115 | struct address_space *mapping = gfs2_glock2aspace(gl); |
116 | 116 | ||
117 | BUG_ON(!(flags & DIO_METADATA)); | 117 | BUG_ON(!(flags & DIO_METADATA)); |
118 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); | 118 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); |
@@ -133,7 +133,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags) | |||
133 | static void inode_go_sync(struct gfs2_glock *gl) | 133 | static void inode_go_sync(struct gfs2_glock *gl) |
134 | { | 134 | { |
135 | struct gfs2_inode *ip = gl->gl_object; | 135 | struct gfs2_inode *ip = gl->gl_object; |
136 | struct address_space *metamapping = gl->gl_aspace->i_mapping; | 136 | struct address_space *metamapping = gfs2_glock2aspace(gl); |
137 | int error; | 137 | int error; |
138 | 138 | ||
139 | if (ip && !S_ISREG(ip->i_inode.i_mode)) | 139 | if (ip && !S_ISREG(ip->i_inode.i_mode)) |
@@ -182,10 +182,12 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
182 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); | 182 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); |
183 | 183 | ||
184 | if (flags & DIO_METADATA) { | 184 | if (flags & DIO_METADATA) { |
185 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 185 | struct address_space *mapping = gfs2_glock2aspace(gl); |
186 | truncate_inode_pages(mapping, 0); | 186 | truncate_inode_pages(mapping, 0); |
187 | if (ip) | 187 | if (ip) { |
188 | set_bit(GIF_INVALID, &ip->i_flags); | 188 | set_bit(GIF_INVALID, &ip->i_flags); |
189 | forget_all_cached_acls(&ip->i_inode); | ||
190 | } | ||
189 | } | 191 | } |
190 | 192 | ||
191 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) | 193 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) |
@@ -279,7 +281,8 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
279 | 281 | ||
280 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) | 282 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) |
281 | { | 283 | { |
282 | return !gl->gl_aspace->i_mapping->nrpages; | 284 | const struct address_space *mapping = (const struct address_space *)(gl + 1); |
285 | return !mapping->nrpages; | ||
283 | } | 286 | } |
284 | 287 | ||
285 | /** | 288 | /** |
@@ -384,8 +387,7 @@ static void iopen_go_callback(struct gfs2_glock *gl) | |||
384 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | 387 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; |
385 | 388 | ||
386 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | 389 | if (gl->gl_demote_state == LM_ST_UNLOCKED && |
387 | gl->gl_state == LM_ST_SHARED && | 390 | gl->gl_state == LM_ST_SHARED && ip) { |
388 | ip && test_bit(GIF_USER, &ip->i_flags)) { | ||
389 | gfs2_glock_hold(gl); | 391 | gfs2_glock_hold(gl); |
390 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) | 392 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) |
391 | gfs2_glock_put_nolock(gl); | 393 | gfs2_glock_put_nolock(gl); |
@@ -404,6 +406,7 @@ const struct gfs2_glock_operations gfs2_inode_glops = { | |||
404 | .go_dump = inode_go_dump, | 406 | .go_dump = inode_go_dump, |
405 | .go_type = LM_TYPE_INODE, | 407 | .go_type = LM_TYPE_INODE, |
406 | .go_min_hold_time = HZ / 5, | 408 | .go_min_hold_time = HZ / 5, |
409 | .go_flags = GLOF_ASPACE, | ||
407 | }; | 410 | }; |
408 | 411 | ||
409 | const struct gfs2_glock_operations gfs2_rgrp_glops = { | 412 | const struct gfs2_glock_operations gfs2_rgrp_glops = { |
@@ -415,6 +418,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { | |||
415 | .go_dump = gfs2_rgrp_dump, | 418 | .go_dump = gfs2_rgrp_dump, |
416 | .go_type = LM_TYPE_RGRP, | 419 | .go_type = LM_TYPE_RGRP, |
417 | .go_min_hold_time = HZ / 5, | 420 | .go_min_hold_time = HZ / 5, |
421 | .go_flags = GLOF_ASPACE, | ||
418 | }; | 422 | }; |
419 | 423 | ||
420 | const struct gfs2_glock_operations gfs2_trans_glops = { | 424 | const struct gfs2_glock_operations gfs2_trans_glops = { |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 6edb423f90b3..3aac46f6853e 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -162,6 +162,8 @@ struct gfs2_glock_operations { | |||
162 | void (*go_callback) (struct gfs2_glock *gl); | 162 | void (*go_callback) (struct gfs2_glock *gl); |
163 | const int go_type; | 163 | const int go_type; |
164 | const unsigned long go_min_hold_time; | 164 | const unsigned long go_min_hold_time; |
165 | const unsigned long go_flags; | ||
166 | #define GLOF_ASPACE 1 | ||
165 | }; | 167 | }; |
166 | 168 | ||
167 | enum { | 169 | enum { |
@@ -225,7 +227,6 @@ struct gfs2_glock { | |||
225 | 227 | ||
226 | struct gfs2_sbd *gl_sbd; | 228 | struct gfs2_sbd *gl_sbd; |
227 | 229 | ||
228 | struct inode *gl_aspace; | ||
229 | struct list_head gl_ail_list; | 230 | struct list_head gl_ail_list; |
230 | atomic_t gl_ail_count; | 231 | atomic_t gl_ail_count; |
231 | struct delayed_work gl_work; | 232 | struct delayed_work gl_work; |
@@ -258,7 +259,6 @@ enum { | |||
258 | GIF_INVALID = 0, | 259 | GIF_INVALID = 0, |
259 | GIF_QD_LOCKED = 1, | 260 | GIF_QD_LOCKED = 1, |
260 | GIF_SW_PAGED = 3, | 261 | GIF_SW_PAGED = 3, |
261 | GIF_USER = 4, /* user inode, not metadata addr space */ | ||
262 | }; | 262 | }; |
263 | 263 | ||
264 | 264 | ||
@@ -429,7 +429,11 @@ struct gfs2_args { | |||
429 | unsigned int ar_meta:1; /* mount metafs */ | 429 | unsigned int ar_meta:1; /* mount metafs */ |
430 | unsigned int ar_discard:1; /* discard requests */ | 430 | unsigned int ar_discard:1; /* discard requests */ |
431 | unsigned int ar_errors:2; /* errors=withdraw | panic */ | 431 | unsigned int ar_errors:2; /* errors=withdraw | panic */ |
432 | unsigned int ar_nobarrier:1; /* do not send barriers */ | ||
432 | int ar_commit; /* Commit interval */ | 433 | int ar_commit; /* Commit interval */ |
434 | int ar_statfs_quantum; /* The fast statfs interval */ | ||
435 | int ar_quota_quantum; /* The quota interval */ | ||
436 | int ar_statfs_percent; /* The % change to force sync */ | ||
433 | }; | 437 | }; |
434 | 438 | ||
435 | struct gfs2_tune { | 439 | struct gfs2_tune { |
@@ -447,7 +451,6 @@ struct gfs2_tune { | |||
447 | unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ | 451 | unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ |
448 | unsigned int gt_new_files_jdata; | 452 | unsigned int gt_new_files_jdata; |
449 | unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ | 453 | unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ |
450 | unsigned int gt_stall_secs; /* Detects trouble! */ | ||
451 | unsigned int gt_complain_secs; | 454 | unsigned int gt_complain_secs; |
452 | unsigned int gt_statfs_quantum; | 455 | unsigned int gt_statfs_quantum; |
453 | unsigned int gt_statfs_slow; | 456 | unsigned int gt_statfs_slow; |
@@ -540,6 +543,8 @@ struct gfs2_sbd { | |||
540 | struct gfs2_holder sd_live_gh; | 543 | struct gfs2_holder sd_live_gh; |
541 | struct gfs2_glock *sd_rename_gl; | 544 | struct gfs2_glock *sd_rename_gl; |
542 | struct gfs2_glock *sd_trans_gl; | 545 | struct gfs2_glock *sd_trans_gl; |
546 | wait_queue_head_t sd_glock_wait; | ||
547 | atomic_t sd_glock_disposal; | ||
543 | 548 | ||
544 | /* Inode Stuff */ | 549 | /* Inode Stuff */ |
545 | 550 | ||
@@ -558,6 +563,7 @@ struct gfs2_sbd { | |||
558 | spinlock_t sd_statfs_spin; | 563 | spinlock_t sd_statfs_spin; |
559 | struct gfs2_statfs_change_host sd_statfs_master; | 564 | struct gfs2_statfs_change_host sd_statfs_master; |
560 | struct gfs2_statfs_change_host sd_statfs_local; | 565 | struct gfs2_statfs_change_host sd_statfs_local; |
566 | int sd_statfs_force_sync; | ||
561 | 567 | ||
562 | /* Resource group stuff */ | 568 | /* Resource group stuff */ |
563 | 569 | ||
@@ -610,7 +616,7 @@ struct gfs2_sbd { | |||
610 | unsigned int sd_log_blks_reserved; | 616 | unsigned int sd_log_blks_reserved; |
611 | unsigned int sd_log_commited_buf; | 617 | unsigned int sd_log_commited_buf; |
612 | unsigned int sd_log_commited_databuf; | 618 | unsigned int sd_log_commited_databuf; |
613 | unsigned int sd_log_commited_revoke; | 619 | int sd_log_commited_revoke; |
614 | 620 | ||
615 | unsigned int sd_log_num_buf; | 621 | unsigned int sd_log_num_buf; |
616 | unsigned int sd_log_num_revoke; | 622 | unsigned int sd_log_num_revoke; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index fb15d3b1f409..b1bf2694fb2b 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -45,7 +45,7 @@ static int iget_test(struct inode *inode, void *opaque) | |||
45 | struct gfs2_inode *ip = GFS2_I(inode); | 45 | struct gfs2_inode *ip = GFS2_I(inode); |
46 | u64 *no_addr = opaque; | 46 | u64 *no_addr = opaque; |
47 | 47 | ||
48 | if (ip->i_no_addr == *no_addr && test_bit(GIF_USER, &ip->i_flags)) | 48 | if (ip->i_no_addr == *no_addr) |
49 | return 1; | 49 | return 1; |
50 | 50 | ||
51 | return 0; | 51 | return 0; |
@@ -58,7 +58,6 @@ static int iget_set(struct inode *inode, void *opaque) | |||
58 | 58 | ||
59 | inode->i_ino = (unsigned long)*no_addr; | 59 | inode->i_ino = (unsigned long)*no_addr; |
60 | ip->i_no_addr = *no_addr; | 60 | ip->i_no_addr = *no_addr; |
61 | set_bit(GIF_USER, &ip->i_flags); | ||
62 | return 0; | 61 | return 0; |
63 | } | 62 | } |
64 | 63 | ||
@@ -84,7 +83,7 @@ static int iget_skip_test(struct inode *inode, void *opaque) | |||
84 | struct gfs2_inode *ip = GFS2_I(inode); | 83 | struct gfs2_inode *ip = GFS2_I(inode); |
85 | struct gfs2_skip_data *data = opaque; | 84 | struct gfs2_skip_data *data = opaque; |
86 | 85 | ||
87 | if (ip->i_no_addr == data->no_addr && test_bit(GIF_USER, &ip->i_flags)){ | 86 | if (ip->i_no_addr == data->no_addr) { |
88 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ | 87 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ |
89 | data->skipped = 1; | 88 | data->skipped = 1; |
90 | return 0; | 89 | return 0; |
@@ -103,7 +102,6 @@ static int iget_skip_set(struct inode *inode, void *opaque) | |||
103 | return 1; | 102 | return 1; |
104 | inode->i_ino = (unsigned long)(data->no_addr); | 103 | inode->i_ino = (unsigned long)(data->no_addr); |
105 | ip->i_no_addr = data->no_addr; | 104 | ip->i_no_addr = data->no_addr; |
106 | set_bit(GIF_USER, &ip->i_flags); | ||
107 | return 0; | 105 | return 0; |
108 | } | 106 | } |
109 | 107 | ||
@@ -125,7 +123,7 @@ static struct inode *gfs2_iget_skip(struct super_block *sb, | |||
125 | * directory entry when gfs2_inode_lookup() is invoked. Part of the code | 123 | * directory entry when gfs2_inode_lookup() is invoked. Part of the code |
126 | * segment inside gfs2_inode_lookup code needs to get moved around. | 124 | * segment inside gfs2_inode_lookup code needs to get moved around. |
127 | * | 125 | * |
128 | * Clean up I_LOCK and I_NEW as well. | 126 | * Clears I_NEW as well. |
129 | **/ | 127 | **/ |
130 | 128 | ||
131 | void gfs2_set_iop(struct inode *inode) | 129 | void gfs2_set_iop(struct inode *inode) |
@@ -801,7 +799,8 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip) | |||
801 | return err; | 799 | return err; |
802 | } | 800 | } |
803 | 801 | ||
804 | err = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SECURITY, name, value, len, 0); | 802 | err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0, |
803 | GFS2_EATYPE_SECURITY); | ||
805 | kfree(value); | 804 | kfree(value); |
806 | kfree(name); | 805 | kfree(name); |
807 | 806 | ||
@@ -871,7 +870,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
871 | if (error) | 870 | if (error) |
872 | goto fail_gunlock2; | 871 | goto fail_gunlock2; |
873 | 872 | ||
874 | error = gfs2_acl_create(dip, GFS2_I(inode)); | 873 | error = gfs2_acl_create(dip, inode); |
875 | if (error) | 874 | if (error) |
876 | goto fail_gunlock2; | 875 | goto fail_gunlock2; |
877 | 876 | ||
@@ -947,9 +946,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) | |||
947 | 946 | ||
948 | str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 947 | str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); |
949 | str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); | 948 | str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); |
950 | str->di_header.__pad0 = 0; | ||
951 | str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); | 949 | str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); |
952 | str->di_header.__pad1 = 0; | ||
953 | str->di_num.no_addr = cpu_to_be64(ip->i_no_addr); | 950 | str->di_num.no_addr = cpu_to_be64(ip->i_no_addr); |
954 | str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); | 951 | str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); |
955 | str->di_mode = cpu_to_be32(ip->i_inode.i_mode); | 952 | str->di_mode = cpu_to_be32(ip->i_inode.i_mode); |
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 46df988323bc..0e0470ed34c2 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/dlm.h> | 11 | #include <linux/dlm.h> |
12 | #include <linux/slab.h> | ||
12 | #include <linux/types.h> | 13 | #include <linux/types.h> |
13 | #include <linux/gfs2_ondisk.h> | 14 | #include <linux/gfs2_ondisk.h> |
14 | 15 | ||
@@ -21,6 +22,7 @@ static void gdlm_ast(void *arg) | |||
21 | { | 22 | { |
22 | struct gfs2_glock *gl = arg; | 23 | struct gfs2_glock *gl = arg; |
23 | unsigned ret = gl->gl_state; | 24 | unsigned ret = gl->gl_state; |
25 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
24 | 26 | ||
25 | BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); | 27 | BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); |
26 | 28 | ||
@@ -29,7 +31,12 @@ static void gdlm_ast(void *arg) | |||
29 | 31 | ||
30 | switch (gl->gl_lksb.sb_status) { | 32 | switch (gl->gl_lksb.sb_status) { |
31 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ | 33 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ |
32 | kmem_cache_free(gfs2_glock_cachep, gl); | 34 | if (gl->gl_ops->go_flags & GLOF_ASPACE) |
35 | kmem_cache_free(gfs2_glock_aspace_cachep, gl); | ||
36 | else | ||
37 | kmem_cache_free(gfs2_glock_cachep, gl); | ||
38 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | ||
39 | wake_up(&sdp->sd_glock_wait); | ||
33 | return; | 40 | return; |
34 | case -DLM_ECANCEL: /* Cancel while getting lock */ | 41 | case -DLM_ECANCEL: /* Cancel while getting lock */ |
35 | ret |= LM_OUT_CANCELED; | 42 | ret |= LM_OUT_CANCELED; |
@@ -164,14 +171,16 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl, | |||
164 | return LM_OUT_ASYNC; | 171 | return LM_OUT_ASYNC; |
165 | } | 172 | } |
166 | 173 | ||
167 | static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr) | 174 | static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl) |
168 | { | 175 | { |
169 | struct gfs2_glock *gl = ptr; | 176 | struct gfs2_sbd *sdp = gl->gl_sbd; |
170 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; | 177 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
171 | int error; | 178 | int error; |
172 | 179 | ||
173 | if (gl->gl_lksb.sb_lkid == 0) { | 180 | if (gl->gl_lksb.sb_lkid == 0) { |
174 | kmem_cache_free(cachep, gl); | 181 | kmem_cache_free(cachep, gl); |
182 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | ||
183 | wake_up(&sdp->sd_glock_wait); | ||
175 | return; | 184 | return; |
176 | } | 185 | } |
177 | 186 | ||
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 13c6237c5f67..e5bf4b59d46e 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -417,7 +417,7 @@ static unsigned int calc_reserved(struct gfs2_sbd *sdp) | |||
417 | databufhdrs_needed = (sdp->sd_log_commited_databuf + | 417 | databufhdrs_needed = (sdp->sd_log_commited_databuf + |
418 | (dbuf_limit - 1)) / dbuf_limit; | 418 | (dbuf_limit - 1)) / dbuf_limit; |
419 | 419 | ||
420 | if (sdp->sd_log_commited_revoke) | 420 | if (sdp->sd_log_commited_revoke > 0) |
421 | revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, | 421 | revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, |
422 | sizeof(u64)); | 422 | sizeof(u64)); |
423 | 423 | ||
@@ -596,7 +596,9 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) | |||
596 | memset(lh, 0, sizeof(struct gfs2_log_header)); | 596 | memset(lh, 0, sizeof(struct gfs2_log_header)); |
597 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 597 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); |
598 | lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); | 598 | lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); |
599 | lh->lh_header.__pad0 = cpu_to_be64(0); | ||
599 | lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); | 600 | lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); |
601 | lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); | ||
600 | lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++); | 602 | lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++); |
601 | lh->lh_flags = cpu_to_be32(flags); | 603 | lh->lh_flags = cpu_to_be32(flags); |
602 | lh->lh_tail = cpu_to_be32(tail); | 604 | lh->lh_tail = cpu_to_be32(tail); |
@@ -788,7 +790,6 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
788 | gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) || | 790 | gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) || |
789 | (((int)sdp->sd_log_commited_databuf) >= 0)); | 791 | (((int)sdp->sd_log_commited_databuf) >= 0)); |
790 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; | 792 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; |
791 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); | ||
792 | reserved = calc_reserved(sdp); | 793 | reserved = calc_reserved(sdp); |
793 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved); | 794 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved); |
794 | unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; | 795 | unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 9969ff062c5b..adc260fbea90 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -132,6 +132,7 @@ static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type) | |||
132 | static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | 132 | static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) |
133 | { | 133 | { |
134 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); | 134 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); |
135 | struct gfs2_meta_header *mh; | ||
135 | struct gfs2_trans *tr; | 136 | struct gfs2_trans *tr; |
136 | 137 | ||
137 | lock_buffer(bd->bd_bh); | 138 | lock_buffer(bd->bd_bh); |
@@ -148,6 +149,9 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
148 | set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); | 149 | set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); |
149 | gfs2_meta_check(sdp, bd->bd_bh); | 150 | gfs2_meta_check(sdp, bd->bd_bh); |
150 | gfs2_pin(sdp, bd->bd_bh); | 151 | gfs2_pin(sdp, bd->bd_bh); |
152 | mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; | ||
153 | mh->__pad0 = cpu_to_be64(0); | ||
154 | mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); | ||
151 | sdp->sd_log_num_buf++; | 155 | sdp->sd_log_num_buf++; |
152 | list_add(&le->le_list, &sdp->sd_log_le_buf); | 156 | list_add(&le->le_list, &sdp->sd_log_le_buf); |
153 | tr->tr_num_buf_new++; | 157 | tr->tr_num_buf_new++; |
@@ -524,9 +528,9 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
524 | gfs2_pin(sdp, bd->bd_bh); | 528 | gfs2_pin(sdp, bd->bd_bh); |
525 | tr->tr_num_databuf_new++; | 529 | tr->tr_num_databuf_new++; |
526 | sdp->sd_log_num_databuf++; | 530 | sdp->sd_log_num_databuf++; |
527 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | 531 | list_add_tail(&le->le_list, &sdp->sd_log_le_databuf); |
528 | } else { | 532 | } else { |
529 | list_add(&le->le_list, &sdp->sd_log_le_ordered); | 533 | list_add_tail(&le->le_list, &sdp->sd_log_le_ordered); |
530 | } | 534 | } |
531 | out: | 535 | out: |
532 | gfs2_log_unlock(sdp); | 536 | gfs2_log_unlock(sdp); |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 5b31f7741a8f..a88fadc704bb 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -52,6 +52,22 @@ static void gfs2_init_glock_once(void *foo) | |||
52 | atomic_set(&gl->gl_ail_count, 0); | 52 | atomic_set(&gl->gl_ail_count, 0); |
53 | } | 53 | } |
54 | 54 | ||
55 | static void gfs2_init_gl_aspace_once(void *foo) | ||
56 | { | ||
57 | struct gfs2_glock *gl = foo; | ||
58 | struct address_space *mapping = (struct address_space *)(gl + 1); | ||
59 | |||
60 | gfs2_init_glock_once(gl); | ||
61 | memset(mapping, 0, sizeof(*mapping)); | ||
62 | INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); | ||
63 | spin_lock_init(&mapping->tree_lock); | ||
64 | spin_lock_init(&mapping->i_mmap_lock); | ||
65 | INIT_LIST_HEAD(&mapping->private_list); | ||
66 | spin_lock_init(&mapping->private_lock); | ||
67 | INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); | ||
68 | INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); | ||
69 | } | ||
70 | |||
55 | /** | 71 | /** |
56 | * init_gfs2_fs - Register GFS2 as a filesystem | 72 | * init_gfs2_fs - Register GFS2 as a filesystem |
57 | * | 73 | * |
@@ -78,6 +94,14 @@ static int __init init_gfs2_fs(void) | |||
78 | if (!gfs2_glock_cachep) | 94 | if (!gfs2_glock_cachep) |
79 | goto fail; | 95 | goto fail; |
80 | 96 | ||
97 | gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock (aspace)", | ||
98 | sizeof(struct gfs2_glock) + | ||
99 | sizeof(struct address_space), | ||
100 | 0, 0, gfs2_init_gl_aspace_once); | ||
101 | |||
102 | if (!gfs2_glock_aspace_cachep) | ||
103 | goto fail; | ||
104 | |||
81 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", | 105 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", |
82 | sizeof(struct gfs2_inode), | 106 | sizeof(struct gfs2_inode), |
83 | 0, SLAB_RECLAIM_ACCOUNT| | 107 | 0, SLAB_RECLAIM_ACCOUNT| |
@@ -144,6 +168,9 @@ fail: | |||
144 | if (gfs2_inode_cachep) | 168 | if (gfs2_inode_cachep) |
145 | kmem_cache_destroy(gfs2_inode_cachep); | 169 | kmem_cache_destroy(gfs2_inode_cachep); |
146 | 170 | ||
171 | if (gfs2_glock_aspace_cachep) | ||
172 | kmem_cache_destroy(gfs2_glock_aspace_cachep); | ||
173 | |||
147 | if (gfs2_glock_cachep) | 174 | if (gfs2_glock_cachep) |
148 | kmem_cache_destroy(gfs2_glock_cachep); | 175 | kmem_cache_destroy(gfs2_glock_cachep); |
149 | 176 | ||
@@ -169,6 +196,7 @@ static void __exit exit_gfs2_fs(void) | |||
169 | kmem_cache_destroy(gfs2_rgrpd_cachep); | 196 | kmem_cache_destroy(gfs2_rgrpd_cachep); |
170 | kmem_cache_destroy(gfs2_bufdata_cachep); | 197 | kmem_cache_destroy(gfs2_bufdata_cachep); |
171 | kmem_cache_destroy(gfs2_inode_cachep); | 198 | kmem_cache_destroy(gfs2_inode_cachep); |
199 | kmem_cache_destroy(gfs2_glock_aspace_cachep); | ||
172 | kmem_cache_destroy(gfs2_glock_cachep); | 200 | kmem_cache_destroy(gfs2_glock_cachep); |
173 | 201 | ||
174 | gfs2_sys_uninit(); | 202 | gfs2_sys_uninit(); |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index cb8d7a93d5ec..0bb12c80937a 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -93,49 +93,13 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb | |||
93 | return err; | 93 | return err; |
94 | } | 94 | } |
95 | 95 | ||
96 | static const struct address_space_operations aspace_aops = { | 96 | const struct address_space_operations gfs2_meta_aops = { |
97 | .writepage = gfs2_aspace_writepage, | 97 | .writepage = gfs2_aspace_writepage, |
98 | .releasepage = gfs2_releasepage, | 98 | .releasepage = gfs2_releasepage, |
99 | .sync_page = block_sync_page, | 99 | .sync_page = block_sync_page, |
100 | }; | 100 | }; |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * gfs2_aspace_get - Create and initialize a struct inode structure | ||
104 | * @sdp: the filesystem the aspace is in | ||
105 | * | ||
106 | * Right now a struct inode is just a struct inode. Maybe Linux | ||
107 | * will supply a more lightweight address space construct (that works) | ||
108 | * in the future. | ||
109 | * | ||
110 | * Make sure pages/buffers in this aspace aren't in high memory. | ||
111 | * | ||
112 | * Returns: the aspace | ||
113 | */ | ||
114 | |||
115 | struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp) | ||
116 | { | ||
117 | struct inode *aspace; | ||
118 | struct gfs2_inode *ip; | ||
119 | |||
120 | aspace = new_inode(sdp->sd_vfs); | ||
121 | if (aspace) { | ||
122 | mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS); | ||
123 | aspace->i_mapping->a_ops = &aspace_aops; | ||
124 | aspace->i_size = ~0ULL; | ||
125 | ip = GFS2_I(aspace); | ||
126 | clear_bit(GIF_USER, &ip->i_flags); | ||
127 | insert_inode_hash(aspace); | ||
128 | } | ||
129 | return aspace; | ||
130 | } | ||
131 | |||
132 | void gfs2_aspace_put(struct inode *aspace) | ||
133 | { | ||
134 | remove_inode_hash(aspace); | ||
135 | iput(aspace); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * gfs2_meta_sync - Sync all buffers associated with a glock | 103 | * gfs2_meta_sync - Sync all buffers associated with a glock |
140 | * @gl: The glock | 104 | * @gl: The glock |
141 | * | 105 | * |
@@ -143,7 +107,7 @@ void gfs2_aspace_put(struct inode *aspace) | |||
143 | 107 | ||
144 | void gfs2_meta_sync(struct gfs2_glock *gl) | 108 | void gfs2_meta_sync(struct gfs2_glock *gl) |
145 | { | 109 | { |
146 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 110 | struct address_space *mapping = gfs2_glock2aspace(gl); |
147 | int error; | 111 | int error; |
148 | 112 | ||
149 | filemap_fdatawrite(mapping); | 113 | filemap_fdatawrite(mapping); |
@@ -164,7 +128,7 @@ void gfs2_meta_sync(struct gfs2_glock *gl) | |||
164 | 128 | ||
165 | struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) | 129 | struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) |
166 | { | 130 | { |
167 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 131 | struct address_space *mapping = gfs2_glock2aspace(gl); |
168 | struct gfs2_sbd *sdp = gl->gl_sbd; | 132 | struct gfs2_sbd *sdp = gl->gl_sbd; |
169 | struct page *page; | 133 | struct page *page; |
170 | struct buffer_head *bh; | 134 | struct buffer_head *bh; |
@@ -344,8 +308,10 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | |||
344 | 308 | ||
345 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) | 309 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) |
346 | { | 310 | { |
347 | struct gfs2_sbd *sdp = GFS2_SB(bh->b_page->mapping->host); | 311 | struct address_space *mapping = bh->b_page->mapping; |
312 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); | ||
348 | struct gfs2_bufdata *bd = bh->b_private; | 313 | struct gfs2_bufdata *bd = bh->b_private; |
314 | |||
349 | if (test_clear_buffer_pinned(bh)) { | 315 | if (test_clear_buffer_pinned(bh)) { |
350 | list_del_init(&bd->bd_le.le_list); | 316 | list_del_init(&bd->bd_le.le_list); |
351 | if (meta) { | 317 | if (meta) { |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index de270c2f9b63..6a1d9ba16411 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
@@ -37,8 +37,16 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh, | |||
37 | 0, from_head - to_head); | 37 | 0, from_head - to_head); |
38 | } | 38 | } |
39 | 39 | ||
40 | struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp); | 40 | extern const struct address_space_operations gfs2_meta_aops; |
41 | void gfs2_aspace_put(struct inode *aspace); | 41 | |
42 | static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping) | ||
43 | { | ||
44 | struct inode *inode = mapping->host; | ||
45 | if (mapping->a_ops == &gfs2_meta_aops) | ||
46 | return (((struct gfs2_glock *)mapping) - 1)->gl_sbd; | ||
47 | else | ||
48 | return inode->i_sb->s_fs_info; | ||
49 | } | ||
42 | 50 | ||
43 | void gfs2_meta_sync(struct gfs2_glock *gl); | 51 | void gfs2_meta_sync(struct gfs2_glock *gl); |
44 | 52 | ||
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 52fb6c048981..c1309ed1c496 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/mount.h> | 18 | #include <linux/mount.h> |
19 | #include <linux/gfs2_ondisk.h> | 19 | #include <linux/gfs2_ondisk.h> |
20 | #include <linux/slow-work.h> | 20 | #include <linux/slow-work.h> |
21 | #include <linux/quotaops.h> | ||
21 | 22 | ||
22 | #include "gfs2.h" | 23 | #include "gfs2.h" |
23 | #include "incore.h" | 24 | #include "incore.h" |
@@ -62,13 +63,9 @@ static void gfs2_tune_init(struct gfs2_tune *gt) | |||
62 | gt->gt_quota_warn_period = 10; | 63 | gt->gt_quota_warn_period = 10; |
63 | gt->gt_quota_scale_num = 1; | 64 | gt->gt_quota_scale_num = 1; |
64 | gt->gt_quota_scale_den = 1; | 65 | gt->gt_quota_scale_den = 1; |
65 | gt->gt_quota_quantum = 60; | ||
66 | gt->gt_new_files_jdata = 0; | 66 | gt->gt_new_files_jdata = 0; |
67 | gt->gt_max_readahead = 1 << 18; | 67 | gt->gt_max_readahead = 1 << 18; |
68 | gt->gt_stall_secs = 600; | ||
69 | gt->gt_complain_secs = 10; | 68 | gt->gt_complain_secs = 10; |
70 | gt->gt_statfs_quantum = 30; | ||
71 | gt->gt_statfs_slow = 0; | ||
72 | } | 69 | } |
73 | 70 | ||
74 | static struct gfs2_sbd *init_sbd(struct super_block *sb) | 71 | static struct gfs2_sbd *init_sbd(struct super_block *sb) |
@@ -84,6 +81,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
84 | 81 | ||
85 | gfs2_tune_init(&sdp->sd_tune); | 82 | gfs2_tune_init(&sdp->sd_tune); |
86 | 83 | ||
84 | init_waitqueue_head(&sdp->sd_glock_wait); | ||
85 | atomic_set(&sdp->sd_glock_disposal, 0); | ||
87 | spin_lock_init(&sdp->sd_statfs_spin); | 86 | spin_lock_init(&sdp->sd_statfs_spin); |
88 | 87 | ||
89 | spin_lock_init(&sdp->sd_rindex_spin); | 88 | spin_lock_init(&sdp->sd_rindex_spin); |
@@ -725,7 +724,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
725 | goto fail; | 724 | goto fail; |
726 | } | 725 | } |
727 | 726 | ||
728 | error = -EINVAL; | 727 | error = -EUSERS; |
729 | if (!gfs2_jindex_size(sdp)) { | 728 | if (!gfs2_jindex_size(sdp)) { |
730 | fs_err(sdp, "no journals!\n"); | 729 | fs_err(sdp, "no journals!\n"); |
731 | goto fail_jindex; | 730 | goto fail_jindex; |
@@ -985,16 +984,24 @@ static const match_table_t nolock_tokens = { | |||
985 | { Opt_err, NULL }, | 984 | { Opt_err, NULL }, |
986 | }; | 985 | }; |
987 | 986 | ||
987 | static void nolock_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl) | ||
988 | { | ||
989 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
990 | kmem_cache_free(cachep, gl); | ||
991 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | ||
992 | wake_up(&sdp->sd_glock_wait); | ||
993 | } | ||
994 | |||
988 | static const struct lm_lockops nolock_ops = { | 995 | static const struct lm_lockops nolock_ops = { |
989 | .lm_proto_name = "lock_nolock", | 996 | .lm_proto_name = "lock_nolock", |
990 | .lm_put_lock = kmem_cache_free, | 997 | .lm_put_lock = nolock_put_lock, |
991 | .lm_tokens = &nolock_tokens, | 998 | .lm_tokens = &nolock_tokens, |
992 | }; | 999 | }; |
993 | 1000 | ||
994 | /** | 1001 | /** |
995 | * gfs2_lm_mount - mount a locking protocol | 1002 | * gfs2_lm_mount - mount a locking protocol |
996 | * @sdp: the filesystem | 1003 | * @sdp: the filesystem |
997 | * @args: mount arguements | 1004 | * @args: mount arguments |
998 | * @silent: if 1, don't complain if the FS isn't a GFS2 fs | 1005 | * @silent: if 1, don't complain if the FS isn't a GFS2 fs |
999 | * | 1006 | * |
1000 | * Returns: errno | 1007 | * Returns: errno |
@@ -1114,7 +1121,7 @@ void gfs2_online_uevent(struct gfs2_sbd *sdp) | |||
1114 | * Returns: errno | 1121 | * Returns: errno |
1115 | */ | 1122 | */ |
1116 | 1123 | ||
1117 | static int fill_super(struct super_block *sb, void *data, int silent) | 1124 | static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent) |
1118 | { | 1125 | { |
1119 | struct gfs2_sbd *sdp; | 1126 | struct gfs2_sbd *sdp; |
1120 | struct gfs2_holder mount_gh; | 1127 | struct gfs2_holder mount_gh; |
@@ -1125,17 +1132,7 @@ static int fill_super(struct super_block *sb, void *data, int silent) | |||
1125 | printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n"); | 1132 | printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n"); |
1126 | return -ENOMEM; | 1133 | return -ENOMEM; |
1127 | } | 1134 | } |
1128 | 1135 | sdp->sd_args = *args; | |
1129 | sdp->sd_args.ar_quota = GFS2_QUOTA_DEFAULT; | ||
1130 | sdp->sd_args.ar_data = GFS2_DATA_DEFAULT; | ||
1131 | sdp->sd_args.ar_commit = 60; | ||
1132 | sdp->sd_args.ar_errors = GFS2_ERRORS_DEFAULT; | ||
1133 | |||
1134 | error = gfs2_mount_args(sdp, &sdp->sd_args, data); | ||
1135 | if (error) { | ||
1136 | printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); | ||
1137 | goto fail; | ||
1138 | } | ||
1139 | 1136 | ||
1140 | if (sdp->sd_args.ar_spectator) { | 1137 | if (sdp->sd_args.ar_spectator) { |
1141 | sb->s_flags |= MS_RDONLY; | 1138 | sb->s_flags |= MS_RDONLY; |
@@ -1143,11 +1140,15 @@ static int fill_super(struct super_block *sb, void *data, int silent) | |||
1143 | } | 1140 | } |
1144 | if (sdp->sd_args.ar_posix_acl) | 1141 | if (sdp->sd_args.ar_posix_acl) |
1145 | sb->s_flags |= MS_POSIXACL; | 1142 | sb->s_flags |= MS_POSIXACL; |
1143 | if (sdp->sd_args.ar_nobarrier) | ||
1144 | set_bit(SDF_NOBARRIERS, &sdp->sd_flags); | ||
1146 | 1145 | ||
1147 | sb->s_magic = GFS2_MAGIC; | 1146 | sb->s_magic = GFS2_MAGIC; |
1148 | sb->s_op = &gfs2_super_ops; | 1147 | sb->s_op = &gfs2_super_ops; |
1149 | sb->s_export_op = &gfs2_export_ops; | 1148 | sb->s_export_op = &gfs2_export_ops; |
1150 | sb->s_xattr = gfs2_xattr_handlers; | 1149 | sb->s_xattr = gfs2_xattr_handlers; |
1150 | sb->s_qcop = &gfs2_quotactl_ops; | ||
1151 | sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; | ||
1151 | sb->s_time_gran = 1; | 1152 | sb->s_time_gran = 1; |
1152 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 1153 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
1153 | 1154 | ||
@@ -1160,6 +1161,15 @@ static int fill_super(struct super_block *sb, void *data, int silent) | |||
1160 | sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; | 1161 | sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; |
1161 | 1162 | ||
1162 | sdp->sd_tune.gt_log_flush_secs = sdp->sd_args.ar_commit; | 1163 | sdp->sd_tune.gt_log_flush_secs = sdp->sd_args.ar_commit; |
1164 | sdp->sd_tune.gt_quota_quantum = sdp->sd_args.ar_quota_quantum; | ||
1165 | if (sdp->sd_args.ar_statfs_quantum) { | ||
1166 | sdp->sd_tune.gt_statfs_slow = 0; | ||
1167 | sdp->sd_tune.gt_statfs_quantum = sdp->sd_args.ar_statfs_quantum; | ||
1168 | } | ||
1169 | else { | ||
1170 | sdp->sd_tune.gt_statfs_slow = 1; | ||
1171 | sdp->sd_tune.gt_statfs_quantum = 30; | ||
1172 | } | ||
1163 | 1173 | ||
1164 | error = init_names(sdp, silent); | 1174 | error = init_names(sdp, silent); |
1165 | if (error) | 1175 | if (error) |
@@ -1230,10 +1240,9 @@ fail_sb: | |||
1230 | fail_locking: | 1240 | fail_locking: |
1231 | init_locking(sdp, &mount_gh, UNDO); | 1241 | init_locking(sdp, &mount_gh, UNDO); |
1232 | fail_lm: | 1242 | fail_lm: |
1243 | invalidate_inodes(sb); | ||
1233 | gfs2_gl_hash_clear(sdp); | 1244 | gfs2_gl_hash_clear(sdp); |
1234 | gfs2_lm_unmount(sdp); | 1245 | gfs2_lm_unmount(sdp); |
1235 | while (invalidate_inodes(sb)) | ||
1236 | yield(); | ||
1237 | fail_sys: | 1246 | fail_sys: |
1238 | gfs2_sys_fs_del(sdp); | 1247 | gfs2_sys_fs_del(sdp); |
1239 | fail: | 1248 | fail: |
@@ -1243,18 +1252,127 @@ fail: | |||
1243 | return error; | 1252 | return error; |
1244 | } | 1253 | } |
1245 | 1254 | ||
1246 | static int gfs2_get_sb(struct file_system_type *fs_type, int flags, | 1255 | static int set_gfs2_super(struct super_block *s, void *data) |
1247 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
1248 | { | 1256 | { |
1249 | return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); | 1257 | s->s_bdev = data; |
1258 | s->s_dev = s->s_bdev->bd_dev; | ||
1259 | |||
1260 | /* | ||
1261 | * We set the bdi here to the queue backing, file systems can | ||
1262 | * overwrite this in ->fill_super() | ||
1263 | */ | ||
1264 | s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info; | ||
1265 | return 0; | ||
1250 | } | 1266 | } |
1251 | 1267 | ||
1252 | static int test_meta_super(struct super_block *s, void *ptr) | 1268 | static int test_gfs2_super(struct super_block *s, void *ptr) |
1253 | { | 1269 | { |
1254 | struct block_device *bdev = ptr; | 1270 | struct block_device *bdev = ptr; |
1255 | return (bdev == s->s_bdev); | 1271 | return (bdev == s->s_bdev); |
1256 | } | 1272 | } |
1257 | 1273 | ||
1274 | /** | ||
1275 | * gfs2_get_sb - Get the GFS2 superblock | ||
1276 | * @fs_type: The GFS2 filesystem type | ||
1277 | * @flags: Mount flags | ||
1278 | * @dev_name: The name of the device | ||
1279 | * @data: The mount arguments | ||
1280 | * @mnt: The vfsmnt for this mount | ||
1281 | * | ||
1282 | * Q. Why not use get_sb_bdev() ? | ||
1283 | * A. We need to select one of two root directories to mount, independent | ||
1284 | * of whether this is the initial, or subsequent, mount of this sb | ||
1285 | * | ||
1286 | * Returns: 0 or -ve on error | ||
1287 | */ | ||
1288 | |||
1289 | static int gfs2_get_sb(struct file_system_type *fs_type, int flags, | ||
1290 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
1291 | { | ||
1292 | struct block_device *bdev; | ||
1293 | struct super_block *s; | ||
1294 | fmode_t mode = FMODE_READ; | ||
1295 | int error; | ||
1296 | struct gfs2_args args; | ||
1297 | struct gfs2_sbd *sdp; | ||
1298 | |||
1299 | if (!(flags & MS_RDONLY)) | ||
1300 | mode |= FMODE_WRITE; | ||
1301 | |||
1302 | bdev = open_bdev_exclusive(dev_name, mode, fs_type); | ||
1303 | if (IS_ERR(bdev)) | ||
1304 | return PTR_ERR(bdev); | ||
1305 | |||
1306 | /* | ||
1307 | * once the super is inserted into the list by sget, s_umount | ||
1308 | * will protect the lockfs code from trying to start a snapshot | ||
1309 | * while we are mounting | ||
1310 | */ | ||
1311 | mutex_lock(&bdev->bd_fsfreeze_mutex); | ||
1312 | if (bdev->bd_fsfreeze_count > 0) { | ||
1313 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
1314 | error = -EBUSY; | ||
1315 | goto error_bdev; | ||
1316 | } | ||
1317 | s = sget(fs_type, test_gfs2_super, set_gfs2_super, bdev); | ||
1318 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
1319 | error = PTR_ERR(s); | ||
1320 | if (IS_ERR(s)) | ||
1321 | goto error_bdev; | ||
1322 | |||
1323 | memset(&args, 0, sizeof(args)); | ||
1324 | args.ar_quota = GFS2_QUOTA_DEFAULT; | ||
1325 | args.ar_data = GFS2_DATA_DEFAULT; | ||
1326 | args.ar_commit = 60; | ||
1327 | args.ar_statfs_quantum = 30; | ||
1328 | args.ar_quota_quantum = 60; | ||
1329 | args.ar_errors = GFS2_ERRORS_DEFAULT; | ||
1330 | |||
1331 | error = gfs2_mount_args(&args, data); | ||
1332 | if (error) { | ||
1333 | printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); | ||
1334 | if (s->s_root) | ||
1335 | goto error_super; | ||
1336 | deactivate_locked_super(s); | ||
1337 | return error; | ||
1338 | } | ||
1339 | |||
1340 | if (s->s_root) { | ||
1341 | error = -EBUSY; | ||
1342 | if ((flags ^ s->s_flags) & MS_RDONLY) | ||
1343 | goto error_super; | ||
1344 | close_bdev_exclusive(bdev, mode); | ||
1345 | } else { | ||
1346 | char b[BDEVNAME_SIZE]; | ||
1347 | |||
1348 | s->s_flags = flags; | ||
1349 | s->s_mode = mode; | ||
1350 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | ||
1351 | sb_set_blocksize(s, block_size(bdev)); | ||
1352 | error = fill_super(s, &args, flags & MS_SILENT ? 1 : 0); | ||
1353 | if (error) { | ||
1354 | deactivate_locked_super(s); | ||
1355 | return error; | ||
1356 | } | ||
1357 | s->s_flags |= MS_ACTIVE; | ||
1358 | bdev->bd_super = s; | ||
1359 | } | ||
1360 | |||
1361 | sdp = s->s_fs_info; | ||
1362 | mnt->mnt_sb = s; | ||
1363 | if (args.ar_meta) | ||
1364 | mnt->mnt_root = dget(sdp->sd_master_dir); | ||
1365 | else | ||
1366 | mnt->mnt_root = dget(sdp->sd_root_dir); | ||
1367 | return 0; | ||
1368 | |||
1369 | error_super: | ||
1370 | deactivate_locked_super(s); | ||
1371 | error_bdev: | ||
1372 | close_bdev_exclusive(bdev, mode); | ||
1373 | return error; | ||
1374 | } | ||
1375 | |||
1258 | static int set_meta_super(struct super_block *s, void *ptr) | 1376 | static int set_meta_super(struct super_block *s, void *ptr) |
1259 | { | 1377 | { |
1260 | return -EINVAL; | 1378 | return -EINVAL; |
@@ -1274,13 +1392,17 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, | |||
1274 | dev_name, error); | 1392 | dev_name, error); |
1275 | return error; | 1393 | return error; |
1276 | } | 1394 | } |
1277 | s = sget(&gfs2_fs_type, test_meta_super, set_meta_super, | 1395 | s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, |
1278 | path.dentry->d_inode->i_sb->s_bdev); | 1396 | path.dentry->d_inode->i_sb->s_bdev); |
1279 | path_put(&path); | 1397 | path_put(&path); |
1280 | if (IS_ERR(s)) { | 1398 | if (IS_ERR(s)) { |
1281 | printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); | 1399 | printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); |
1282 | return PTR_ERR(s); | 1400 | return PTR_ERR(s); |
1283 | } | 1401 | } |
1402 | if ((flags ^ s->s_flags) & MS_RDONLY) { | ||
1403 | deactivate_locked_super(s); | ||
1404 | return -EBUSY; | ||
1405 | } | ||
1284 | sdp = s->s_fs_info; | 1406 | sdp = s->s_fs_info; |
1285 | mnt->mnt_sb = s; | 1407 | mnt->mnt_sb = s; |
1286 | mnt->mnt_root = dget(sdp->sd_master_dir); | 1408 | mnt->mnt_root = dget(sdp->sd_master_dir); |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 247436c10deb..4e64352d49de 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -748,7 +748,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
748 | struct gfs2_rgrpd *nrgd; | 748 | struct gfs2_rgrpd *nrgd; |
749 | unsigned int num_gh; | 749 | unsigned int num_gh; |
750 | int dir_rename = 0; | 750 | int dir_rename = 0; |
751 | int alloc_required; | 751 | int alloc_required = 0; |
752 | unsigned int x; | 752 | unsigned int x; |
753 | int error; | 753 | int error; |
754 | 754 | ||
@@ -867,7 +867,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
867 | goto out_gunlock; | 867 | goto out_gunlock; |
868 | } | 868 | } |
869 | 869 | ||
870 | alloc_required = error = gfs2_diradd_alloc_required(ndir, &ndentry->d_name); | 870 | if (nip == NULL) |
871 | alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name); | ||
872 | error = alloc_required; | ||
871 | if (error < 0) | 873 | if (error < 0) |
872 | goto out_gunlock; | 874 | goto out_gunlock; |
873 | error = 0; | 875 | error = 0; |
@@ -974,121 +976,62 @@ out: | |||
974 | } | 976 | } |
975 | 977 | ||
976 | /** | 978 | /** |
977 | * gfs2_readlinki - return the contents of a symlink | 979 | * gfs2_follow_link - Follow a symbolic link |
978 | * @ip: the symlink's inode | 980 | * @dentry: The dentry of the link |
979 | * @buf: a pointer to the buffer to be filled | 981 | * @nd: Data that we pass to vfs_follow_link() |
980 | * @len: a pointer to the length of @buf | ||
981 | * | 982 | * |
982 | * If @buf is too small, a piece of memory is kmalloc()ed and needs | 983 | * This can handle symlinks of any size. |
983 | * to be freed by the caller. | ||
984 | * | 984 | * |
985 | * Returns: errno | 985 | * Returns: 0 on success or error code |
986 | */ | 986 | */ |
987 | 987 | ||
988 | static int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len) | 988 | static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) |
989 | { | 989 | { |
990 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
990 | struct gfs2_holder i_gh; | 991 | struct gfs2_holder i_gh; |
991 | struct buffer_head *dibh; | 992 | struct buffer_head *dibh; |
992 | unsigned int x; | 993 | unsigned int x; |
994 | char *buf; | ||
993 | int error; | 995 | int error; |
994 | 996 | ||
995 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); | 997 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); |
996 | error = gfs2_glock_nq(&i_gh); | 998 | error = gfs2_glock_nq(&i_gh); |
997 | if (error) { | 999 | if (error) { |
998 | gfs2_holder_uninit(&i_gh); | 1000 | gfs2_holder_uninit(&i_gh); |
999 | return error; | 1001 | nd_set_link(nd, ERR_PTR(error)); |
1002 | return NULL; | ||
1000 | } | 1003 | } |
1001 | 1004 | ||
1002 | if (!ip->i_disksize) { | 1005 | if (!ip->i_disksize) { |
1003 | gfs2_consist_inode(ip); | 1006 | gfs2_consist_inode(ip); |
1004 | error = -EIO; | 1007 | buf = ERR_PTR(-EIO); |
1005 | goto out; | 1008 | goto out; |
1006 | } | 1009 | } |
1007 | 1010 | ||
1008 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1011 | error = gfs2_meta_inode_buffer(ip, &dibh); |
1009 | if (error) | 1012 | if (error) { |
1013 | buf = ERR_PTR(error); | ||
1010 | goto out; | 1014 | goto out; |
1011 | |||
1012 | x = ip->i_disksize + 1; | ||
1013 | if (x > *len) { | ||
1014 | *buf = kmalloc(x, GFP_NOFS); | ||
1015 | if (!*buf) { | ||
1016 | error = -ENOMEM; | ||
1017 | goto out_brelse; | ||
1018 | } | ||
1019 | } | 1015 | } |
1020 | 1016 | ||
1021 | memcpy(*buf, dibh->b_data + sizeof(struct gfs2_dinode), x); | 1017 | x = ip->i_disksize + 1; |
1022 | *len = x; | 1018 | buf = kmalloc(x, GFP_NOFS); |
1023 | 1019 | if (!buf) | |
1024 | out_brelse: | 1020 | buf = ERR_PTR(-ENOMEM); |
1021 | else | ||
1022 | memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), x); | ||
1025 | brelse(dibh); | 1023 | brelse(dibh); |
1026 | out: | 1024 | out: |
1027 | gfs2_glock_dq_uninit(&i_gh); | 1025 | gfs2_glock_dq_uninit(&i_gh); |
1028 | return error; | 1026 | nd_set_link(nd, buf); |
1029 | } | 1027 | return NULL; |
1030 | |||
1031 | /** | ||
1032 | * gfs2_readlink - Read the value of a symlink | ||
1033 | * @dentry: the symlink | ||
1034 | * @buf: the buffer to read the symlink data into | ||
1035 | * @size: the size of the buffer | ||
1036 | * | ||
1037 | * Returns: errno | ||
1038 | */ | ||
1039 | |||
1040 | static int gfs2_readlink(struct dentry *dentry, char __user *user_buf, | ||
1041 | int user_size) | ||
1042 | { | ||
1043 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
1044 | char array[GFS2_FAST_NAME_SIZE], *buf = array; | ||
1045 | unsigned int len = GFS2_FAST_NAME_SIZE; | ||
1046 | int error; | ||
1047 | |||
1048 | error = gfs2_readlinki(ip, &buf, &len); | ||
1049 | if (error) | ||
1050 | return error; | ||
1051 | |||
1052 | if (user_size > len - 1) | ||
1053 | user_size = len - 1; | ||
1054 | |||
1055 | if (copy_to_user(user_buf, buf, user_size)) | ||
1056 | error = -EFAULT; | ||
1057 | else | ||
1058 | error = user_size; | ||
1059 | |||
1060 | if (buf != array) | ||
1061 | kfree(buf); | ||
1062 | |||
1063 | return error; | ||
1064 | } | 1028 | } |
1065 | 1029 | ||
1066 | /** | 1030 | static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p) |
1067 | * gfs2_follow_link - Follow a symbolic link | ||
1068 | * @dentry: The dentry of the link | ||
1069 | * @nd: Data that we pass to vfs_follow_link() | ||
1070 | * | ||
1071 | * This can handle symlinks of any size. It is optimised for symlinks | ||
1072 | * under GFS2_FAST_NAME_SIZE. | ||
1073 | * | ||
1074 | * Returns: 0 on success or error code | ||
1075 | */ | ||
1076 | |||
1077 | static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
1078 | { | 1031 | { |
1079 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 1032 | char *s = nd_get_link(nd); |
1080 | char array[GFS2_FAST_NAME_SIZE], *buf = array; | 1033 | if (!IS_ERR(s)) |
1081 | unsigned int len = GFS2_FAST_NAME_SIZE; | 1034 | kfree(s); |
1082 | int error; | ||
1083 | |||
1084 | error = gfs2_readlinki(ip, &buf, &len); | ||
1085 | if (!error) { | ||
1086 | error = vfs_follow_link(nd, buf); | ||
1087 | if (buf != array) | ||
1088 | kfree(buf); | ||
1089 | } | ||
1090 | |||
1091 | return ERR_PTR(error); | ||
1092 | } | 1035 | } |
1093 | 1036 | ||
1094 | /** | 1037 | /** |
@@ -1423,8 +1366,9 @@ const struct inode_operations gfs2_dir_iops = { | |||
1423 | }; | 1366 | }; |
1424 | 1367 | ||
1425 | const struct inode_operations gfs2_symlink_iops = { | 1368 | const struct inode_operations gfs2_symlink_iops = { |
1426 | .readlink = gfs2_readlink, | 1369 | .readlink = generic_readlink, |
1427 | .follow_link = gfs2_follow_link, | 1370 | .follow_link = gfs2_follow_link, |
1371 | .put_link = gfs2_put_link, | ||
1428 | .permission = gfs2_permission, | 1372 | .permission = gfs2_permission, |
1429 | .setattr = gfs2_setattr, | 1373 | .setattr = gfs2_setattr, |
1430 | .getattr = gfs2_getattr, | 1374 | .getattr = gfs2_getattr, |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 2e9b9326bfc9..6dbcbad6ab17 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * fuzziness in the current usage value of IDs that are being used on different | 15 | * fuzziness in the current usage value of IDs that are being used on different |
16 | * nodes in the cluster simultaneously. So, it is possible for a user on | 16 | * nodes in the cluster simultaneously. So, it is possible for a user on |
17 | * multiple nodes to overrun their quota, but that overrun is controlable. | 17 | * multiple nodes to overrun their quota, but that overrun is controlable. |
18 | * Since quota tags are part of transactions, there is no need to a quota check | 18 | * Since quota tags are part of transactions, there is no need for a quota check |
19 | * program to be run on node crashes or anything like that. | 19 | * program to be run on node crashes or anything like that. |
20 | * | 20 | * |
21 | * There are couple of knobs that let the administrator manage the quota | 21 | * There are couple of knobs that let the administrator manage the quota |
@@ -47,6 +47,8 @@ | |||
47 | #include <linux/gfs2_ondisk.h> | 47 | #include <linux/gfs2_ondisk.h> |
48 | #include <linux/kthread.h> | 48 | #include <linux/kthread.h> |
49 | #include <linux/freezer.h> | 49 | #include <linux/freezer.h> |
50 | #include <linux/quota.h> | ||
51 | #include <linux/dqblk_xfs.h> | ||
50 | 52 | ||
51 | #include "gfs2.h" | 53 | #include "gfs2.h" |
52 | #include "incore.h" | 54 | #include "incore.h" |
@@ -65,13 +67,6 @@ | |||
65 | #define QUOTA_USER 1 | 67 | #define QUOTA_USER 1 |
66 | #define QUOTA_GROUP 0 | 68 | #define QUOTA_GROUP 0 |
67 | 69 | ||
68 | struct gfs2_quota_host { | ||
69 | u64 qu_limit; | ||
70 | u64 qu_warn; | ||
71 | s64 qu_value; | ||
72 | u32 qu_ll_next; | ||
73 | }; | ||
74 | |||
75 | struct gfs2_quota_change_host { | 70 | struct gfs2_quota_change_host { |
76 | u64 qc_change; | 71 | u64 qc_change; |
77 | u32 qc_flags; /* GFS2_QCF_... */ | 72 | u32 qc_flags; /* GFS2_QCF_... */ |
@@ -164,7 +159,7 @@ fail: | |||
164 | return error; | 159 | return error; |
165 | } | 160 | } |
166 | 161 | ||
167 | static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, | 162 | static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, |
168 | struct gfs2_quota_data **qdp) | 163 | struct gfs2_quota_data **qdp) |
169 | { | 164 | { |
170 | struct gfs2_quota_data *qd = NULL, *new_qd = NULL; | 165 | struct gfs2_quota_data *qd = NULL, *new_qd = NULL; |
@@ -202,7 +197,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, | |||
202 | 197 | ||
203 | spin_unlock(&qd_lru_lock); | 198 | spin_unlock(&qd_lru_lock); |
204 | 199 | ||
205 | if (qd || !create) { | 200 | if (qd) { |
206 | if (new_qd) { | 201 | if (new_qd) { |
207 | gfs2_glock_put(new_qd->qd_gl); | 202 | gfs2_glock_put(new_qd->qd_gl); |
208 | kmem_cache_free(gfs2_quotad_cachep, new_qd); | 203 | kmem_cache_free(gfs2_quotad_cachep, new_qd); |
@@ -461,12 +456,12 @@ static void qd_unlock(struct gfs2_quota_data *qd) | |||
461 | qd_put(qd); | 456 | qd_put(qd); |
462 | } | 457 | } |
463 | 458 | ||
464 | static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id, int create, | 459 | static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id, |
465 | struct gfs2_quota_data **qdp) | 460 | struct gfs2_quota_data **qdp) |
466 | { | 461 | { |
467 | int error; | 462 | int error; |
468 | 463 | ||
469 | error = qd_get(sdp, user, id, create, qdp); | 464 | error = qd_get(sdp, user, id, qdp); |
470 | if (error) | 465 | if (error) |
471 | return error; | 466 | return error; |
472 | 467 | ||
@@ -508,20 +503,20 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) | |||
508 | if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) | 503 | if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) |
509 | return 0; | 504 | return 0; |
510 | 505 | ||
511 | error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, CREATE, qd); | 506 | error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd); |
512 | if (error) | 507 | if (error) |
513 | goto out; | 508 | goto out; |
514 | al->al_qd_num++; | 509 | al->al_qd_num++; |
515 | qd++; | 510 | qd++; |
516 | 511 | ||
517 | error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, CREATE, qd); | 512 | error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd); |
518 | if (error) | 513 | if (error) |
519 | goto out; | 514 | goto out; |
520 | al->al_qd_num++; | 515 | al->al_qd_num++; |
521 | qd++; | 516 | qd++; |
522 | 517 | ||
523 | if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { | 518 | if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { |
524 | error = qdsb_get(sdp, QUOTA_USER, uid, CREATE, qd); | 519 | error = qdsb_get(sdp, QUOTA_USER, uid, qd); |
525 | if (error) | 520 | if (error) |
526 | goto out; | 521 | goto out; |
527 | al->al_qd_num++; | 522 | al->al_qd_num++; |
@@ -529,7 +524,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) | |||
529 | } | 524 | } |
530 | 525 | ||
531 | if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { | 526 | if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { |
532 | error = qdsb_get(sdp, QUOTA_GROUP, gid, CREATE, qd); | 527 | error = qdsb_get(sdp, QUOTA_GROUP, gid, qd); |
533 | if (error) | 528 | if (error) |
534 | goto out; | 529 | goto out; |
535 | al->al_qd_num++; | 530 | al->al_qd_num++; |
@@ -617,48 +612,36 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) | |||
617 | mutex_unlock(&sdp->sd_quota_mutex); | 612 | mutex_unlock(&sdp->sd_quota_mutex); |
618 | } | 613 | } |
619 | 614 | ||
620 | static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) | ||
621 | { | ||
622 | const struct gfs2_quota *str = buf; | ||
623 | |||
624 | qu->qu_limit = be64_to_cpu(str->qu_limit); | ||
625 | qu->qu_warn = be64_to_cpu(str->qu_warn); | ||
626 | qu->qu_value = be64_to_cpu(str->qu_value); | ||
627 | qu->qu_ll_next = be32_to_cpu(str->qu_ll_next); | ||
628 | } | ||
629 | |||
630 | static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) | ||
631 | { | ||
632 | struct gfs2_quota *str = buf; | ||
633 | |||
634 | str->qu_limit = cpu_to_be64(qu->qu_limit); | ||
635 | str->qu_warn = cpu_to_be64(qu->qu_warn); | ||
636 | str->qu_value = cpu_to_be64(qu->qu_value); | ||
637 | str->qu_ll_next = cpu_to_be32(qu->qu_ll_next); | ||
638 | memset(&str->qu_reserved, 0, sizeof(str->qu_reserved)); | ||
639 | } | ||
640 | |||
641 | /** | 615 | /** |
642 | * gfs2_adjust_quota | 616 | * gfs2_adjust_quota - adjust record of current block usage |
617 | * @ip: The quota inode | ||
618 | * @loc: Offset of the entry in the quota file | ||
619 | * @change: The amount of usage change to record | ||
620 | * @qd: The quota data | ||
621 | * @fdq: The updated limits to record | ||
643 | * | 622 | * |
644 | * This function was mostly borrowed from gfs2_block_truncate_page which was | 623 | * This function was mostly borrowed from gfs2_block_truncate_page which was |
645 | * in turn mostly borrowed from ext3 | 624 | * in turn mostly borrowed from ext3 |
625 | * | ||
626 | * Returns: 0 or -ve on error | ||
646 | */ | 627 | */ |
628 | |||
647 | static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | 629 | static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, |
648 | s64 change, struct gfs2_quota_data *qd) | 630 | s64 change, struct gfs2_quota_data *qd, |
631 | struct fs_disk_quota *fdq) | ||
649 | { | 632 | { |
650 | struct inode *inode = &ip->i_inode; | 633 | struct inode *inode = &ip->i_inode; |
651 | struct address_space *mapping = inode->i_mapping; | 634 | struct address_space *mapping = inode->i_mapping; |
652 | unsigned long index = loc >> PAGE_CACHE_SHIFT; | 635 | unsigned long index = loc >> PAGE_CACHE_SHIFT; |
653 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); | 636 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); |
654 | unsigned blocksize, iblock, pos; | 637 | unsigned blocksize, iblock, pos; |
655 | struct buffer_head *bh; | 638 | struct buffer_head *bh, *dibh; |
656 | struct page *page; | 639 | struct page *page; |
657 | void *kaddr; | 640 | void *kaddr; |
658 | char *ptr; | 641 | struct gfs2_quota *qp; |
659 | struct gfs2_quota_host qp; | ||
660 | s64 value; | 642 | s64 value; |
661 | int err = -EIO; | 643 | int err = -EIO; |
644 | u64 size; | ||
662 | 645 | ||
663 | if (gfs2_is_stuffed(ip)) | 646 | if (gfs2_is_stuffed(ip)) |
664 | gfs2_unstuff_dinode(ip, NULL); | 647 | gfs2_unstuff_dinode(ip, NULL); |
@@ -700,18 +683,38 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
700 | gfs2_trans_add_bh(ip->i_gl, bh, 0); | 683 | gfs2_trans_add_bh(ip->i_gl, bh, 0); |
701 | 684 | ||
702 | kaddr = kmap_atomic(page, KM_USER0); | 685 | kaddr = kmap_atomic(page, KM_USER0); |
703 | ptr = kaddr + offset; | 686 | qp = kaddr + offset; |
704 | gfs2_quota_in(&qp, ptr); | 687 | value = (s64)be64_to_cpu(qp->qu_value) + change; |
705 | qp.qu_value += change; | 688 | qp->qu_value = cpu_to_be64(value); |
706 | value = qp.qu_value; | 689 | qd->qd_qb.qb_value = qp->qu_value; |
707 | gfs2_quota_out(&qp, ptr); | 690 | if (fdq) { |
691 | if (fdq->d_fieldmask & FS_DQ_BSOFT) { | ||
692 | qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit); | ||
693 | qd->qd_qb.qb_warn = qp->qu_warn; | ||
694 | } | ||
695 | if (fdq->d_fieldmask & FS_DQ_BHARD) { | ||
696 | qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit); | ||
697 | qd->qd_qb.qb_limit = qp->qu_limit; | ||
698 | } | ||
699 | } | ||
708 | flush_dcache_page(page); | 700 | flush_dcache_page(page); |
709 | kunmap_atomic(kaddr, KM_USER0); | 701 | kunmap_atomic(kaddr, KM_USER0); |
710 | err = 0; | 702 | |
711 | qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC); | 703 | err = gfs2_meta_inode_buffer(ip, &dibh); |
712 | qd->qd_qb.qb_value = cpu_to_be64(value); | 704 | if (err) |
713 | ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC); | 705 | goto unlock; |
714 | ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value); | 706 | |
707 | size = loc + sizeof(struct gfs2_quota); | ||
708 | if (size > inode->i_size) { | ||
709 | ip->i_disksize = size; | ||
710 | i_size_write(inode, size); | ||
711 | } | ||
712 | inode->i_mtime = inode->i_atime = CURRENT_TIME; | ||
713 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
714 | gfs2_dinode_out(ip, dibh->b_data); | ||
715 | brelse(dibh); | ||
716 | mark_inode_dirty(inode); | ||
717 | |||
715 | unlock: | 718 | unlock: |
716 | unlock_page(page); | 719 | unlock_page(page); |
717 | page_cache_release(page); | 720 | page_cache_release(page); |
@@ -739,9 +742,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
739 | return -ENOMEM; | 742 | return -ENOMEM; |
740 | 743 | ||
741 | sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL); | 744 | sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL); |
745 | mutex_lock_nested(&ip->i_inode.i_mutex, I_MUTEX_QUOTA); | ||
742 | for (qx = 0; qx < num_qd; qx++) { | 746 | for (qx = 0; qx < num_qd; qx++) { |
743 | error = gfs2_glock_nq_init(qda[qx]->qd_gl, | 747 | error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE, |
744 | LM_ST_EXCLUSIVE, | ||
745 | GL_NOCACHE, &ghs[qx]); | 748 | GL_NOCACHE, &ghs[qx]); |
746 | if (error) | 749 | if (error) |
747 | goto out; | 750 | goto out; |
@@ -795,9 +798,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
795 | for (x = 0; x < num_qd; x++) { | 798 | for (x = 0; x < num_qd; x++) { |
796 | qd = qda[x]; | 799 | qd = qda[x]; |
797 | offset = qd2offset(qd); | 800 | offset = qd2offset(qd); |
798 | error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, | 801 | error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, qd, NULL); |
799 | (struct gfs2_quota_data *) | ||
800 | qd); | ||
801 | if (error) | 802 | if (error) |
802 | goto out_end_trans; | 803 | goto out_end_trans; |
803 | 804 | ||
@@ -817,21 +818,44 @@ out_gunlock: | |||
817 | out: | 818 | out: |
818 | while (qx--) | 819 | while (qx--) |
819 | gfs2_glock_dq_uninit(&ghs[qx]); | 820 | gfs2_glock_dq_uninit(&ghs[qx]); |
821 | mutex_unlock(&ip->i_inode.i_mutex); | ||
820 | kfree(ghs); | 822 | kfree(ghs); |
821 | gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); | 823 | gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); |
822 | return error; | 824 | return error; |
823 | } | 825 | } |
824 | 826 | ||
827 | static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd) | ||
828 | { | ||
829 | struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); | ||
830 | struct gfs2_quota q; | ||
831 | struct gfs2_quota_lvb *qlvb; | ||
832 | loff_t pos; | ||
833 | int error; | ||
834 | |||
835 | memset(&q, 0, sizeof(struct gfs2_quota)); | ||
836 | pos = qd2offset(qd); | ||
837 | error = gfs2_internal_read(ip, NULL, (char *)&q, &pos, sizeof(q)); | ||
838 | if (error < 0) | ||
839 | return error; | ||
840 | |||
841 | qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; | ||
842 | qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC); | ||
843 | qlvb->__pad = 0; | ||
844 | qlvb->qb_limit = q.qu_limit; | ||
845 | qlvb->qb_warn = q.qu_warn; | ||
846 | qlvb->qb_value = q.qu_value; | ||
847 | qd->qd_qb = *qlvb; | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
825 | static int do_glock(struct gfs2_quota_data *qd, int force_refresh, | 852 | static int do_glock(struct gfs2_quota_data *qd, int force_refresh, |
826 | struct gfs2_holder *q_gh) | 853 | struct gfs2_holder *q_gh) |
827 | { | 854 | { |
828 | struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; | 855 | struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; |
829 | struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); | 856 | struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); |
830 | struct gfs2_holder i_gh; | 857 | struct gfs2_holder i_gh; |
831 | struct gfs2_quota_host q; | ||
832 | char buf[sizeof(struct gfs2_quota)]; | ||
833 | int error; | 858 | int error; |
834 | struct gfs2_quota_lvb *qlvb; | ||
835 | 859 | ||
836 | restart: | 860 | restart: |
837 | error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh); | 861 | error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh); |
@@ -841,11 +865,9 @@ restart: | |||
841 | qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; | 865 | qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; |
842 | 866 | ||
843 | if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) { | 867 | if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) { |
844 | loff_t pos; | ||
845 | gfs2_glock_dq_uninit(q_gh); | 868 | gfs2_glock_dq_uninit(q_gh); |
846 | error = gfs2_glock_nq_init(qd->qd_gl, | 869 | error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, |
847 | LM_ST_EXCLUSIVE, GL_NOCACHE, | 870 | GL_NOCACHE, q_gh); |
848 | q_gh); | ||
849 | if (error) | 871 | if (error) |
850 | return error; | 872 | return error; |
851 | 873 | ||
@@ -853,29 +875,14 @@ restart: | |||
853 | if (error) | 875 | if (error) |
854 | goto fail; | 876 | goto fail; |
855 | 877 | ||
856 | memset(buf, 0, sizeof(struct gfs2_quota)); | 878 | error = update_qd(sdp, qd); |
857 | pos = qd2offset(qd); | 879 | if (error) |
858 | error = gfs2_internal_read(ip, NULL, buf, &pos, | ||
859 | sizeof(struct gfs2_quota)); | ||
860 | if (error < 0) | ||
861 | goto fail_gunlock; | 880 | goto fail_gunlock; |
862 | 881 | ||
863 | gfs2_glock_dq_uninit(&i_gh); | 882 | gfs2_glock_dq_uninit(&i_gh); |
864 | 883 | gfs2_glock_dq_uninit(q_gh); | |
865 | gfs2_quota_in(&q, buf); | 884 | force_refresh = 0; |
866 | qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; | 885 | goto restart; |
867 | qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC); | ||
868 | qlvb->__pad = 0; | ||
869 | qlvb->qb_limit = cpu_to_be64(q.qu_limit); | ||
870 | qlvb->qb_warn = cpu_to_be64(q.qu_warn); | ||
871 | qlvb->qb_value = cpu_to_be64(q.qu_value); | ||
872 | qd->qd_qb = *qlvb; | ||
873 | |||
874 | if (gfs2_glock_is_blocking(qd->qd_gl)) { | ||
875 | gfs2_glock_dq_uninit(q_gh); | ||
876 | force_refresh = 0; | ||
877 | goto restart; | ||
878 | } | ||
879 | } | 886 | } |
880 | 887 | ||
881 | return 0; | 888 | return 0; |
@@ -995,7 +1002,7 @@ static int print_message(struct gfs2_quota_data *qd, char *type) | |||
995 | { | 1002 | { |
996 | struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; | 1003 | struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; |
997 | 1004 | ||
998 | printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\r\n", | 1005 | printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\n", |
999 | sdp->sd_fsname, type, | 1006 | sdp->sd_fsname, type, |
1000 | (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group", | 1007 | (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group", |
1001 | qd->qd_id); | 1008 | qd->qd_id); |
@@ -1032,6 +1039,10 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) | |||
1032 | 1039 | ||
1033 | if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) { | 1040 | if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) { |
1034 | print_message(qd, "exceeded"); | 1041 | print_message(qd, "exceeded"); |
1042 | quota_send_warning(test_bit(QDF_USER, &qd->qd_flags) ? | ||
1043 | USRQUOTA : GRPQUOTA, qd->qd_id, | ||
1044 | sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN); | ||
1045 | |||
1035 | error = -EDQUOT; | 1046 | error = -EDQUOT; |
1036 | break; | 1047 | break; |
1037 | } else if (be64_to_cpu(qd->qd_qb.qb_warn) && | 1048 | } else if (be64_to_cpu(qd->qd_qb.qb_warn) && |
@@ -1039,6 +1050,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) | |||
1039 | time_after_eq(jiffies, qd->qd_last_warn + | 1050 | time_after_eq(jiffies, qd->qd_last_warn + |
1040 | gfs2_tune_get(sdp, | 1051 | gfs2_tune_get(sdp, |
1041 | gt_quota_warn_period) * HZ)) { | 1052 | gt_quota_warn_period) * HZ)) { |
1053 | quota_send_warning(test_bit(QDF_USER, &qd->qd_flags) ? | ||
1054 | USRQUOTA : GRPQUOTA, qd->qd_id, | ||
1055 | sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN); | ||
1042 | error = print_message(qd, "warning"); | 1056 | error = print_message(qd, "warning"); |
1043 | qd->qd_last_warn = jiffies; | 1057 | qd->qd_last_warn = jiffies; |
1044 | } | 1058 | } |
@@ -1069,8 +1083,9 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change, | |||
1069 | } | 1083 | } |
1070 | } | 1084 | } |
1071 | 1085 | ||
1072 | int gfs2_quota_sync(struct gfs2_sbd *sdp) | 1086 | int gfs2_quota_sync(struct super_block *sb, int type, int wait) |
1073 | { | 1087 | { |
1088 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
1074 | struct gfs2_quota_data **qda; | 1089 | struct gfs2_quota_data **qda; |
1075 | unsigned int max_qd = gfs2_tune_get(sdp, gt_quota_simul_sync); | 1090 | unsigned int max_qd = gfs2_tune_get(sdp, gt_quota_simul_sync); |
1076 | unsigned int num_qd; | 1091 | unsigned int num_qd; |
@@ -1112,13 +1127,18 @@ int gfs2_quota_sync(struct gfs2_sbd *sdp) | |||
1112 | return error; | 1127 | return error; |
1113 | } | 1128 | } |
1114 | 1129 | ||
1130 | static int gfs2_quota_sync_timeo(struct super_block *sb, int type) | ||
1131 | { | ||
1132 | return gfs2_quota_sync(sb, type, 0); | ||
1133 | } | ||
1134 | |||
1115 | int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) | 1135 | int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) |
1116 | { | 1136 | { |
1117 | struct gfs2_quota_data *qd; | 1137 | struct gfs2_quota_data *qd; |
1118 | struct gfs2_holder q_gh; | 1138 | struct gfs2_holder q_gh; |
1119 | int error; | 1139 | int error; |
1120 | 1140 | ||
1121 | error = qd_get(sdp, user, id, CREATE, &qd); | 1141 | error = qd_get(sdp, user, id, &qd); |
1122 | if (error) | 1142 | if (error) |
1123 | return error; | 1143 | return error; |
1124 | 1144 | ||
@@ -1127,7 +1147,6 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) | |||
1127 | gfs2_glock_dq_uninit(&q_gh); | 1147 | gfs2_glock_dq_uninit(&q_gh); |
1128 | 1148 | ||
1129 | qd_put(qd); | 1149 | qd_put(qd); |
1130 | |||
1131 | return error; | 1150 | return error; |
1132 | } | 1151 | } |
1133 | 1152 | ||
@@ -1298,12 +1317,12 @@ static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error) | |||
1298 | } | 1317 | } |
1299 | 1318 | ||
1300 | static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg, | 1319 | static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg, |
1301 | int (*fxn)(struct gfs2_sbd *sdp), | 1320 | int (*fxn)(struct super_block *sb, int type), |
1302 | unsigned long t, unsigned long *timeo, | 1321 | unsigned long t, unsigned long *timeo, |
1303 | unsigned int *new_timeo) | 1322 | unsigned int *new_timeo) |
1304 | { | 1323 | { |
1305 | if (t >= *timeo) { | 1324 | if (t >= *timeo) { |
1306 | int error = fxn(sdp); | 1325 | int error = fxn(sdp->sd_vfs, 0); |
1307 | quotad_error(sdp, msg, error); | 1326 | quotad_error(sdp, msg, error); |
1308 | *timeo = gfs2_tune_get_i(&sdp->sd_tune, new_timeo) * HZ; | 1327 | *timeo = gfs2_tune_get_i(&sdp->sd_tune, new_timeo) * HZ; |
1309 | } else { | 1328 | } else { |
@@ -1330,6 +1349,14 @@ static void quotad_check_trunc_list(struct gfs2_sbd *sdp) | |||
1330 | } | 1349 | } |
1331 | } | 1350 | } |
1332 | 1351 | ||
1352 | void gfs2_wake_up_statfs(struct gfs2_sbd *sdp) { | ||
1353 | if (!sdp->sd_statfs_force_sync) { | ||
1354 | sdp->sd_statfs_force_sync = 1; | ||
1355 | wake_up(&sdp->sd_quota_wait); | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1359 | |||
1333 | /** | 1360 | /** |
1334 | * gfs2_quotad - Write cached quota changes into the quota file | 1361 | * gfs2_quotad - Write cached quota changes into the quota file |
1335 | * @sdp: Pointer to GFS2 superblock | 1362 | * @sdp: Pointer to GFS2 superblock |
@@ -1349,11 +1376,18 @@ int gfs2_quotad(void *data) | |||
1349 | while (!kthread_should_stop()) { | 1376 | while (!kthread_should_stop()) { |
1350 | 1377 | ||
1351 | /* Update the master statfs file */ | 1378 | /* Update the master statfs file */ |
1352 | quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t, | 1379 | if (sdp->sd_statfs_force_sync) { |
1353 | &statfs_timeo, &tune->gt_statfs_quantum); | 1380 | int error = gfs2_statfs_sync(sdp->sd_vfs, 0); |
1381 | quotad_error(sdp, "statfs", error); | ||
1382 | statfs_timeo = gfs2_tune_get(sdp, gt_statfs_quantum) * HZ; | ||
1383 | } | ||
1384 | else | ||
1385 | quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t, | ||
1386 | &statfs_timeo, | ||
1387 | &tune->gt_statfs_quantum); | ||
1354 | 1388 | ||
1355 | /* Update quota file */ | 1389 | /* Update quota file */ |
1356 | quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t, | 1390 | quotad_check_timeo(sdp, "sync", gfs2_quota_sync_timeo, t, |
1357 | "ad_timeo, &tune->gt_quota_quantum); | 1391 | "ad_timeo, &tune->gt_quota_quantum); |
1358 | 1392 | ||
1359 | /* Check for & recover partially truncated inodes */ | 1393 | /* Check for & recover partially truncated inodes */ |
@@ -1367,7 +1401,7 @@ int gfs2_quotad(void *data) | |||
1367 | spin_lock(&sdp->sd_trunc_lock); | 1401 | spin_lock(&sdp->sd_trunc_lock); |
1368 | empty = list_empty(&sdp->sd_trunc_list); | 1402 | empty = list_empty(&sdp->sd_trunc_list); |
1369 | spin_unlock(&sdp->sd_trunc_lock); | 1403 | spin_unlock(&sdp->sd_trunc_lock); |
1370 | if (empty) | 1404 | if (empty && !sdp->sd_statfs_force_sync) |
1371 | t -= schedule_timeout(t); | 1405 | t -= schedule_timeout(t); |
1372 | else | 1406 | else |
1373 | t = 0; | 1407 | t = 0; |
@@ -1377,3 +1411,181 @@ int gfs2_quotad(void *data) | |||
1377 | return 0; | 1411 | return 0; |
1378 | } | 1412 | } |
1379 | 1413 | ||
1414 | static int gfs2_quota_get_xstate(struct super_block *sb, | ||
1415 | struct fs_quota_stat *fqs) | ||
1416 | { | ||
1417 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
1418 | |||
1419 | memset(fqs, 0, sizeof(struct fs_quota_stat)); | ||
1420 | fqs->qs_version = FS_QSTAT_VERSION; | ||
1421 | if (sdp->sd_args.ar_quota == GFS2_QUOTA_ON) | ||
1422 | fqs->qs_flags = (XFS_QUOTA_UDQ_ENFD | XFS_QUOTA_GDQ_ENFD); | ||
1423 | else if (sdp->sd_args.ar_quota == GFS2_QUOTA_ACCOUNT) | ||
1424 | fqs->qs_flags = (XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_GDQ_ACCT); | ||
1425 | if (sdp->sd_quota_inode) { | ||
1426 | fqs->qs_uquota.qfs_ino = GFS2_I(sdp->sd_quota_inode)->i_no_addr; | ||
1427 | fqs->qs_uquota.qfs_nblks = sdp->sd_quota_inode->i_blocks; | ||
1428 | } | ||
1429 | fqs->qs_uquota.qfs_nextents = 1; /* unsupported */ | ||
1430 | fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */ | ||
1431 | fqs->qs_incoredqs = atomic_read(&qd_lru_count); | ||
1432 | return 0; | ||
1433 | } | ||
1434 | |||
1435 | static int gfs2_xquota_get(struct super_block *sb, int type, qid_t id, | ||
1436 | struct fs_disk_quota *fdq) | ||
1437 | { | ||
1438 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
1439 | struct gfs2_quota_lvb *qlvb; | ||
1440 | struct gfs2_quota_data *qd; | ||
1441 | struct gfs2_holder q_gh; | ||
1442 | int error; | ||
1443 | |||
1444 | memset(fdq, 0, sizeof(struct fs_disk_quota)); | ||
1445 | |||
1446 | if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) | ||
1447 | return -ESRCH; /* Crazy XFS error code */ | ||
1448 | |||
1449 | if (type == USRQUOTA) | ||
1450 | type = QUOTA_USER; | ||
1451 | else if (type == GRPQUOTA) | ||
1452 | type = QUOTA_GROUP; | ||
1453 | else | ||
1454 | return -EINVAL; | ||
1455 | |||
1456 | error = qd_get(sdp, type, id, &qd); | ||
1457 | if (error) | ||
1458 | return error; | ||
1459 | error = do_glock(qd, FORCE, &q_gh); | ||
1460 | if (error) | ||
1461 | goto out; | ||
1462 | |||
1463 | qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; | ||
1464 | fdq->d_version = FS_DQUOT_VERSION; | ||
1465 | fdq->d_flags = (type == QUOTA_USER) ? XFS_USER_QUOTA : XFS_GROUP_QUOTA; | ||
1466 | fdq->d_id = id; | ||
1467 | fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit); | ||
1468 | fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn); | ||
1469 | fdq->d_bcount = be64_to_cpu(qlvb->qb_value); | ||
1470 | |||
1471 | gfs2_glock_dq_uninit(&q_gh); | ||
1472 | out: | ||
1473 | qd_put(qd); | ||
1474 | return error; | ||
1475 | } | ||
1476 | |||
1477 | /* GFS2 only supports a subset of the XFS fields */ | ||
1478 | #define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD) | ||
1479 | |||
1480 | static int gfs2_xquota_set(struct super_block *sb, int type, qid_t id, | ||
1481 | struct fs_disk_quota *fdq) | ||
1482 | { | ||
1483 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
1484 | struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); | ||
1485 | struct gfs2_quota_data *qd; | ||
1486 | struct gfs2_holder q_gh, i_gh; | ||
1487 | unsigned int data_blocks, ind_blocks; | ||
1488 | unsigned int blocks = 0; | ||
1489 | int alloc_required; | ||
1490 | struct gfs2_alloc *al; | ||
1491 | loff_t offset; | ||
1492 | int error; | ||
1493 | |||
1494 | if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) | ||
1495 | return -ESRCH; /* Crazy XFS error code */ | ||
1496 | |||
1497 | switch(type) { | ||
1498 | case USRQUOTA: | ||
1499 | type = QUOTA_USER; | ||
1500 | if (fdq->d_flags != XFS_USER_QUOTA) | ||
1501 | return -EINVAL; | ||
1502 | break; | ||
1503 | case GRPQUOTA: | ||
1504 | type = QUOTA_GROUP; | ||
1505 | if (fdq->d_flags != XFS_GROUP_QUOTA) | ||
1506 | return -EINVAL; | ||
1507 | break; | ||
1508 | default: | ||
1509 | return -EINVAL; | ||
1510 | } | ||
1511 | |||
1512 | if (fdq->d_fieldmask & ~GFS2_FIELDMASK) | ||
1513 | return -EINVAL; | ||
1514 | if (fdq->d_id != id) | ||
1515 | return -EINVAL; | ||
1516 | |||
1517 | error = qd_get(sdp, type, id, &qd); | ||
1518 | if (error) | ||
1519 | return error; | ||
1520 | |||
1521 | mutex_lock(&ip->i_inode.i_mutex); | ||
1522 | error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh); | ||
1523 | if (error) | ||
1524 | goto out_put; | ||
1525 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); | ||
1526 | if (error) | ||
1527 | goto out_q; | ||
1528 | |||
1529 | /* Check for existing entry, if none then alloc new blocks */ | ||
1530 | error = update_qd(sdp, qd); | ||
1531 | if (error) | ||
1532 | goto out_i; | ||
1533 | |||
1534 | /* If nothing has changed, this is a no-op */ | ||
1535 | if ((fdq->d_fieldmask & FS_DQ_BSOFT) && | ||
1536 | (fdq->d_blk_softlimit == be64_to_cpu(qd->qd_qb.qb_warn))) | ||
1537 | fdq->d_fieldmask ^= FS_DQ_BSOFT; | ||
1538 | if ((fdq->d_fieldmask & FS_DQ_BHARD) && | ||
1539 | (fdq->d_blk_hardlimit == be64_to_cpu(qd->qd_qb.qb_limit))) | ||
1540 | fdq->d_fieldmask ^= FS_DQ_BHARD; | ||
1541 | if (fdq->d_fieldmask == 0) | ||
1542 | goto out_i; | ||
1543 | |||
1544 | offset = qd2offset(qd); | ||
1545 | error = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota), | ||
1546 | &alloc_required); | ||
1547 | if (error) | ||
1548 | goto out_i; | ||
1549 | if (alloc_required) { | ||
1550 | al = gfs2_alloc_get(ip); | ||
1551 | if (al == NULL) | ||
1552 | goto out_i; | ||
1553 | gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), | ||
1554 | &data_blocks, &ind_blocks); | ||
1555 | blocks = al->al_requested = 1 + data_blocks + ind_blocks; | ||
1556 | error = gfs2_inplace_reserve(ip); | ||
1557 | if (error) | ||
1558 | goto out_alloc; | ||
1559 | } | ||
1560 | |||
1561 | error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0); | ||
1562 | if (error) | ||
1563 | goto out_release; | ||
1564 | |||
1565 | /* Apply changes */ | ||
1566 | error = gfs2_adjust_quota(ip, offset, 0, qd, fdq); | ||
1567 | |||
1568 | gfs2_trans_end(sdp); | ||
1569 | out_release: | ||
1570 | if (alloc_required) { | ||
1571 | gfs2_inplace_release(ip); | ||
1572 | out_alloc: | ||
1573 | gfs2_alloc_put(ip); | ||
1574 | } | ||
1575 | out_i: | ||
1576 | gfs2_glock_dq_uninit(&i_gh); | ||
1577 | out_q: | ||
1578 | gfs2_glock_dq_uninit(&q_gh); | ||
1579 | out_put: | ||
1580 | mutex_unlock(&ip->i_inode.i_mutex); | ||
1581 | qd_put(qd); | ||
1582 | return error; | ||
1583 | } | ||
1584 | |||
1585 | const struct quotactl_ops gfs2_quotactl_ops = { | ||
1586 | .quota_sync = gfs2_quota_sync, | ||
1587 | .get_xstate = gfs2_quota_get_xstate, | ||
1588 | .get_xquota = gfs2_xquota_get, | ||
1589 | .set_xquota = gfs2_xquota_set, | ||
1590 | }; | ||
1591 | |||
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index 0fa5fa63d0e8..195f60c8bd14 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h | |||
@@ -25,13 +25,15 @@ extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid); | |||
25 | extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, | 25 | extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, |
26 | u32 uid, u32 gid); | 26 | u32 uid, u32 gid); |
27 | 27 | ||
28 | extern int gfs2_quota_sync(struct gfs2_sbd *sdp); | 28 | extern int gfs2_quota_sync(struct super_block *sb, int type, int wait); |
29 | extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id); | 29 | extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id); |
30 | 30 | ||
31 | extern int gfs2_quota_init(struct gfs2_sbd *sdp); | 31 | extern int gfs2_quota_init(struct gfs2_sbd *sdp); |
32 | extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp); | 32 | extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp); |
33 | extern int gfs2_quotad(void *data); | 33 | extern int gfs2_quotad(void *data); |
34 | 34 | ||
35 | extern void gfs2_wake_up_statfs(struct gfs2_sbd *sdp); | ||
36 | |||
35 | static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) | 37 | static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) |
36 | { | 38 | { |
37 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 39 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
@@ -50,5 +52,6 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) | |||
50 | } | 52 | } |
51 | 53 | ||
52 | extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask); | 54 | extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask); |
55 | extern const struct quotactl_ops gfs2_quotactl_ops; | ||
53 | 56 | ||
54 | #endif /* __QUOTA_DOT_H__ */ | 57 | #endif /* __QUOTA_DOT_H__ */ |
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 09fa31965576..4b9bece3d437 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
@@ -410,7 +410,9 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea | |||
410 | memset(lh, 0, sizeof(struct gfs2_log_header)); | 410 | memset(lh, 0, sizeof(struct gfs2_log_header)); |
411 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 411 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); |
412 | lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); | 412 | lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); |
413 | lh->lh_header.__pad0 = cpu_to_be64(0); | ||
413 | lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); | 414 | lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); |
415 | lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); | ||
414 | lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1); | 416 | lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1); |
415 | lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT); | 417 | lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT); |
416 | lh->lh_blkno = cpu_to_be32(lblock); | 418 | lh->lh_blkno = cpu_to_be32(lblock); |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 8f1cfb02a6cb..503b842f3ba2 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -591,11 +591,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
591 | u64 rgrp_count = ip->i_disksize; | 591 | u64 rgrp_count = ip->i_disksize; |
592 | int error; | 592 | int error; |
593 | 593 | ||
594 | if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) { | 594 | do_div(rgrp_count, sizeof(struct gfs2_rindex)); |
595 | gfs2_consist_inode(ip); | ||
596 | return -EIO; | ||
597 | } | ||
598 | |||
599 | clear_rgrpdi(sdp); | 595 | clear_rgrpdi(sdp); |
600 | 596 | ||
601 | file_ra_state_init(&ra_state, inode->i_mapping); | 597 | file_ra_state_init(&ra_state, inode->i_mapping); |
@@ -915,7 +911,7 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) | |||
915 | struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) | 911 | struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) |
916 | { | 912 | { |
917 | BUG_ON(ip->i_alloc != NULL); | 913 | BUG_ON(ip->i_alloc != NULL); |
918 | ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_KERNEL); | 914 | ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_NOFS); |
919 | return ip->i_alloc; | 915 | return ip->i_alloc; |
920 | } | 916 | } |
921 | 917 | ||
@@ -1710,11 +1706,16 @@ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type) | |||
1710 | { | 1706 | { |
1711 | struct gfs2_rgrpd *rgd; | 1707 | struct gfs2_rgrpd *rgd; |
1712 | struct gfs2_holder ri_gh, rgd_gh; | 1708 | struct gfs2_holder ri_gh, rgd_gh; |
1709 | struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex); | ||
1710 | int ri_locked = 0; | ||
1713 | int error; | 1711 | int error; |
1714 | 1712 | ||
1715 | error = gfs2_rindex_hold(sdp, &ri_gh); | 1713 | if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { |
1716 | if (error) | 1714 | error = gfs2_rindex_hold(sdp, &ri_gh); |
1717 | goto fail; | 1715 | if (error) |
1716 | goto fail; | ||
1717 | ri_locked = 1; | ||
1718 | } | ||
1718 | 1719 | ||
1719 | error = -EINVAL; | 1720 | error = -EINVAL; |
1720 | rgd = gfs2_blk2rgrpd(sdp, no_addr); | 1721 | rgd = gfs2_blk2rgrpd(sdp, no_addr); |
@@ -1730,7 +1731,8 @@ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type) | |||
1730 | 1731 | ||
1731 | gfs2_glock_dq_uninit(&rgd_gh); | 1732 | gfs2_glock_dq_uninit(&rgd_gh); |
1732 | fail_rindex: | 1733 | fail_rindex: |
1733 | gfs2_glock_dq_uninit(&ri_gh); | 1734 | if (ri_locked) |
1735 | gfs2_glock_dq_uninit(&ri_gh); | ||
1734 | fail: | 1736 | fail: |
1735 | return error; | 1737 | return error; |
1736 | } | 1738 | } |
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index b4106ddaaa98..f07119d89557 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h | |||
@@ -10,6 +10,8 @@ | |||
10 | #ifndef __RGRP_DOT_H__ | 10 | #ifndef __RGRP_DOT_H__ |
11 | #define __RGRP_DOT_H__ | 11 | #define __RGRP_DOT_H__ |
12 | 12 | ||
13 | #include <linux/slab.h> | ||
14 | |||
13 | struct gfs2_rgrpd; | 15 | struct gfs2_rgrpd; |
14 | struct gfs2_sbd; | 16 | struct gfs2_sbd; |
15 | struct gfs2_holder; | 17 | struct gfs2_holder; |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0ec3ec672de1..50aac606b990 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/gfs2_ondisk.h> | 21 | #include <linux/gfs2_ondisk.h> |
22 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
23 | #include <linux/time.h> | 23 | #include <linux/time.h> |
24 | #include <linux/wait.h> | ||
25 | #include <linux/writeback.h> | ||
24 | 26 | ||
25 | #include "gfs2.h" | 27 | #include "gfs2.h" |
26 | #include "incore.h" | 28 | #include "incore.h" |
@@ -70,6 +72,11 @@ enum { | |||
70 | Opt_commit, | 72 | Opt_commit, |
71 | Opt_err_withdraw, | 73 | Opt_err_withdraw, |
72 | Opt_err_panic, | 74 | Opt_err_panic, |
75 | Opt_statfs_quantum, | ||
76 | Opt_statfs_percent, | ||
77 | Opt_quota_quantum, | ||
78 | Opt_barrier, | ||
79 | Opt_nobarrier, | ||
73 | Opt_error, | 80 | Opt_error, |
74 | }; | 81 | }; |
75 | 82 | ||
@@ -101,18 +108,23 @@ static const match_table_t tokens = { | |||
101 | {Opt_commit, "commit=%d"}, | 108 | {Opt_commit, "commit=%d"}, |
102 | {Opt_err_withdraw, "errors=withdraw"}, | 109 | {Opt_err_withdraw, "errors=withdraw"}, |
103 | {Opt_err_panic, "errors=panic"}, | 110 | {Opt_err_panic, "errors=panic"}, |
111 | {Opt_statfs_quantum, "statfs_quantum=%d"}, | ||
112 | {Opt_statfs_percent, "statfs_percent=%d"}, | ||
113 | {Opt_quota_quantum, "quota_quantum=%d"}, | ||
114 | {Opt_barrier, "barrier"}, | ||
115 | {Opt_nobarrier, "nobarrier"}, | ||
104 | {Opt_error, NULL} | 116 | {Opt_error, NULL} |
105 | }; | 117 | }; |
106 | 118 | ||
107 | /** | 119 | /** |
108 | * gfs2_mount_args - Parse mount options | 120 | * gfs2_mount_args - Parse mount options |
109 | * @sdp: | 121 | * @args: The structure into which the parsed options will be written |
110 | * @data: | 122 | * @options: The options to parse |
111 | * | 123 | * |
112 | * Return: errno | 124 | * Return: errno |
113 | */ | 125 | */ |
114 | 126 | ||
115 | int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | 127 | int gfs2_mount_args(struct gfs2_args *args, char *options) |
116 | { | 128 | { |
117 | char *o; | 129 | char *o; |
118 | int token; | 130 | int token; |
@@ -157,7 +169,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
157 | break; | 169 | break; |
158 | case Opt_debug: | 170 | case Opt_debug: |
159 | if (args->ar_errors == GFS2_ERRORS_PANIC) { | 171 | if (args->ar_errors == GFS2_ERRORS_PANIC) { |
160 | fs_info(sdp, "-o debug and -o errors=panic " | 172 | printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " |
161 | "are mutually exclusive.\n"); | 173 | "are mutually exclusive.\n"); |
162 | return -EINVAL; | 174 | return -EINVAL; |
163 | } | 175 | } |
@@ -210,7 +222,29 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
210 | case Opt_commit: | 222 | case Opt_commit: |
211 | rv = match_int(&tmp[0], &args->ar_commit); | 223 | rv = match_int(&tmp[0], &args->ar_commit); |
212 | if (rv || args->ar_commit <= 0) { | 224 | if (rv || args->ar_commit <= 0) { |
213 | fs_info(sdp, "commit mount option requires a positive numeric argument\n"); | 225 | printk(KERN_WARNING "GFS2: commit mount option requires a positive numeric argument\n"); |
226 | return rv ? rv : -EINVAL; | ||
227 | } | ||
228 | break; | ||
229 | case Opt_statfs_quantum: | ||
230 | rv = match_int(&tmp[0], &args->ar_statfs_quantum); | ||
231 | if (rv || args->ar_statfs_quantum < 0) { | ||
232 | printk(KERN_WARNING "GFS2: statfs_quantum mount option requires a non-negative numeric argument\n"); | ||
233 | return rv ? rv : -EINVAL; | ||
234 | } | ||
235 | break; | ||
236 | case Opt_quota_quantum: | ||
237 | rv = match_int(&tmp[0], &args->ar_quota_quantum); | ||
238 | if (rv || args->ar_quota_quantum <= 0) { | ||
239 | printk(KERN_WARNING "GFS2: quota_quantum mount option requires a positive numeric argument\n"); | ||
240 | return rv ? rv : -EINVAL; | ||
241 | } | ||
242 | break; | ||
243 | case Opt_statfs_percent: | ||
244 | rv = match_int(&tmp[0], &args->ar_statfs_percent); | ||
245 | if (rv || args->ar_statfs_percent < 0 || | ||
246 | args->ar_statfs_percent > 100) { | ||
247 | printk(KERN_WARNING "statfs_percent mount option requires a numeric argument between 0 and 100\n"); | ||
214 | return rv ? rv : -EINVAL; | 248 | return rv ? rv : -EINVAL; |
215 | } | 249 | } |
216 | break; | 250 | break; |
@@ -219,15 +253,21 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
219 | break; | 253 | break; |
220 | case Opt_err_panic: | 254 | case Opt_err_panic: |
221 | if (args->ar_debug) { | 255 | if (args->ar_debug) { |
222 | fs_info(sdp, "-o debug and -o errors=panic " | 256 | printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " |
223 | "are mutually exclusive.\n"); | 257 | "are mutually exclusive.\n"); |
224 | return -EINVAL; | 258 | return -EINVAL; |
225 | } | 259 | } |
226 | args->ar_errors = GFS2_ERRORS_PANIC; | 260 | args->ar_errors = GFS2_ERRORS_PANIC; |
227 | break; | 261 | break; |
262 | case Opt_barrier: | ||
263 | args->ar_nobarrier = 0; | ||
264 | break; | ||
265 | case Opt_nobarrier: | ||
266 | args->ar_nobarrier = 1; | ||
267 | break; | ||
228 | case Opt_error: | 268 | case Opt_error: |
229 | default: | 269 | default: |
230 | fs_info(sdp, "invalid mount option: %s\n", o); | 270 | printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o); |
231 | return -EINVAL; | 271 | return -EINVAL; |
232 | } | 272 | } |
233 | } | 273 | } |
@@ -442,7 +482,10 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
442 | { | 482 | { |
443 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | 483 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); |
444 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | 484 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; |
485 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
445 | struct buffer_head *l_bh; | 486 | struct buffer_head *l_bh; |
487 | s64 x, y; | ||
488 | int need_sync = 0; | ||
446 | int error; | 489 | int error; |
447 | 490 | ||
448 | error = gfs2_meta_inode_buffer(l_ip, &l_bh); | 491 | error = gfs2_meta_inode_buffer(l_ip, &l_bh); |
@@ -456,9 +499,17 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
456 | l_sc->sc_free += free; | 499 | l_sc->sc_free += free; |
457 | l_sc->sc_dinodes += dinodes; | 500 | l_sc->sc_dinodes += dinodes; |
458 | gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode)); | 501 | gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode)); |
502 | if (sdp->sd_args.ar_statfs_percent) { | ||
503 | x = 100 * l_sc->sc_free; | ||
504 | y = m_sc->sc_free * sdp->sd_args.ar_statfs_percent; | ||
505 | if (x >= y || x <= -y) | ||
506 | need_sync = 1; | ||
507 | } | ||
459 | spin_unlock(&sdp->sd_statfs_spin); | 508 | spin_unlock(&sdp->sd_statfs_spin); |
460 | 509 | ||
461 | brelse(l_bh); | 510 | brelse(l_bh); |
511 | if (need_sync) | ||
512 | gfs2_wake_up_statfs(sdp); | ||
462 | } | 513 | } |
463 | 514 | ||
464 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | 515 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, |
@@ -484,8 +535,9 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | |||
484 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | 535 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); |
485 | } | 536 | } |
486 | 537 | ||
487 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) | 538 | int gfs2_statfs_sync(struct super_block *sb, int type) |
488 | { | 539 | { |
540 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
489 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | 541 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); |
490 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | 542 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); |
491 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | 543 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; |
@@ -521,6 +573,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) | |||
521 | goto out_bh2; | 573 | goto out_bh2; |
522 | 574 | ||
523 | update_statfs(sdp, m_bh, l_bh); | 575 | update_statfs(sdp, m_bh, l_bh); |
576 | sdp->sd_statfs_force_sync = 0; | ||
524 | 577 | ||
525 | gfs2_trans_end(sdp); | 578 | gfs2_trans_end(sdp); |
526 | 579 | ||
@@ -659,7 +712,7 @@ void gfs2_unfreeze_fs(struct gfs2_sbd *sdp) | |||
659 | * Returns: errno | 712 | * Returns: errno |
660 | */ | 713 | */ |
661 | 714 | ||
662 | static int gfs2_write_inode(struct inode *inode, int sync) | 715 | static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) |
663 | { | 716 | { |
664 | struct gfs2_inode *ip = GFS2_I(inode); | 717 | struct gfs2_inode *ip = GFS2_I(inode); |
665 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 718 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
@@ -670,8 +723,7 @@ static int gfs2_write_inode(struct inode *inode, int sync) | |||
670 | int ret = 0; | 723 | int ret = 0; |
671 | 724 | ||
672 | /* Check this is a "normal" inode, etc */ | 725 | /* Check this is a "normal" inode, etc */ |
673 | if (!test_bit(GIF_USER, &ip->i_flags) || | 726 | if (current->flags & PF_MEMALLOC) |
674 | (current->flags & PF_MEMALLOC)) | ||
675 | return 0; | 727 | return 0; |
676 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 728 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
677 | if (ret) | 729 | if (ret) |
@@ -694,7 +746,7 @@ static int gfs2_write_inode(struct inode *inode, int sync) | |||
694 | do_unlock: | 746 | do_unlock: |
695 | gfs2_glock_dq_uninit(&gh); | 747 | gfs2_glock_dq_uninit(&gh); |
696 | do_flush: | 748 | do_flush: |
697 | if (sync != 0) | 749 | if (wbc->sync_mode == WB_SYNC_ALL) |
698 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | 750 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); |
699 | return ret; | 751 | return ret; |
700 | } | 752 | } |
@@ -712,8 +764,8 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
712 | int error; | 764 | int error; |
713 | 765 | ||
714 | flush_workqueue(gfs2_delete_workqueue); | 766 | flush_workqueue(gfs2_delete_workqueue); |
715 | gfs2_quota_sync(sdp); | 767 | gfs2_quota_sync(sdp->sd_vfs, 0, 1); |
716 | gfs2_statfs_sync(sdp); | 768 | gfs2_statfs_sync(sdp->sd_vfs, 0); |
717 | 769 | ||
718 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, | 770 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, |
719 | &t_gh); | 771 | &t_gh); |
@@ -808,6 +860,7 @@ restart: | |||
808 | gfs2_clear_rgrpd(sdp); | 860 | gfs2_clear_rgrpd(sdp); |
809 | gfs2_jindex_free(sdp); | 861 | gfs2_jindex_free(sdp); |
810 | /* Take apart glock structures and buffer lists */ | 862 | /* Take apart glock structures and buffer lists */ |
863 | invalidate_inodes(sdp->sd_vfs); | ||
811 | gfs2_gl_hash_clear(sdp); | 864 | gfs2_gl_hash_clear(sdp); |
812 | /* Unmount the locking protocol */ | 865 | /* Unmount the locking protocol */ |
813 | gfs2_lm_unmount(sdp); | 866 | gfs2_lm_unmount(sdp); |
@@ -1061,8 +1114,13 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1061 | 1114 | ||
1062 | spin_lock(>->gt_spin); | 1115 | spin_lock(>->gt_spin); |
1063 | args.ar_commit = gt->gt_log_flush_secs; | 1116 | args.ar_commit = gt->gt_log_flush_secs; |
1117 | args.ar_quota_quantum = gt->gt_quota_quantum; | ||
1118 | if (gt->gt_statfs_slow) | ||
1119 | args.ar_statfs_quantum = 0; | ||
1120 | else | ||
1121 | args.ar_statfs_quantum = gt->gt_statfs_quantum; | ||
1064 | spin_unlock(>->gt_spin); | 1122 | spin_unlock(>->gt_spin); |
1065 | error = gfs2_mount_args(sdp, &args, data); | 1123 | error = gfs2_mount_args(&args, data); |
1066 | if (error) | 1124 | if (error) |
1067 | return error; | 1125 | return error; |
1068 | 1126 | ||
@@ -1097,8 +1155,21 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1097 | sb->s_flags |= MS_POSIXACL; | 1155 | sb->s_flags |= MS_POSIXACL; |
1098 | else | 1156 | else |
1099 | sb->s_flags &= ~MS_POSIXACL; | 1157 | sb->s_flags &= ~MS_POSIXACL; |
1158 | if (sdp->sd_args.ar_nobarrier) | ||
1159 | set_bit(SDF_NOBARRIERS, &sdp->sd_flags); | ||
1160 | else | ||
1161 | clear_bit(SDF_NOBARRIERS, &sdp->sd_flags); | ||
1100 | spin_lock(>->gt_spin); | 1162 | spin_lock(>->gt_spin); |
1101 | gt->gt_log_flush_secs = args.ar_commit; | 1163 | gt->gt_log_flush_secs = args.ar_commit; |
1164 | gt->gt_quota_quantum = args.ar_quota_quantum; | ||
1165 | if (args.ar_statfs_quantum) { | ||
1166 | gt->gt_statfs_slow = 0; | ||
1167 | gt->gt_statfs_quantum = args.ar_statfs_quantum; | ||
1168 | } | ||
1169 | else { | ||
1170 | gt->gt_statfs_slow = 1; | ||
1171 | gt->gt_statfs_quantum = 30; | ||
1172 | } | ||
1102 | spin_unlock(>->gt_spin); | 1173 | spin_unlock(>->gt_spin); |
1103 | 1174 | ||
1104 | gfs2_online_uevent(sdp); | 1175 | gfs2_online_uevent(sdp); |
@@ -1124,7 +1195,7 @@ static void gfs2_drop_inode(struct inode *inode) | |||
1124 | { | 1195 | { |
1125 | struct gfs2_inode *ip = GFS2_I(inode); | 1196 | struct gfs2_inode *ip = GFS2_I(inode); |
1126 | 1197 | ||
1127 | if (test_bit(GIF_USER, &ip->i_flags) && inode->i_nlink) { | 1198 | if (inode->i_nlink) { |
1128 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; | 1199 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; |
1129 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1200 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) |
1130 | clear_nlink(inode); | 1201 | clear_nlink(inode); |
@@ -1142,18 +1213,12 @@ static void gfs2_clear_inode(struct inode *inode) | |||
1142 | { | 1213 | { |
1143 | struct gfs2_inode *ip = GFS2_I(inode); | 1214 | struct gfs2_inode *ip = GFS2_I(inode); |
1144 | 1215 | ||
1145 | /* This tells us its a "real" inode and not one which only | 1216 | ip->i_gl->gl_object = NULL; |
1146 | * serves to contain an address space (see rgrp.c, meta_io.c) | 1217 | gfs2_glock_put(ip->i_gl); |
1147 | * which therefore doesn't have its own glocks. | 1218 | ip->i_gl = NULL; |
1148 | */ | 1219 | if (ip->i_iopen_gh.gh_gl) { |
1149 | if (test_bit(GIF_USER, &ip->i_flags)) { | 1220 | ip->i_iopen_gh.gh_gl->gl_object = NULL; |
1150 | ip->i_gl->gl_object = NULL; | 1221 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1151 | gfs2_glock_put(ip->i_gl); | ||
1152 | ip->i_gl = NULL; | ||
1153 | if (ip->i_iopen_gh.gh_gl) { | ||
1154 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | ||
1155 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | ||
1156 | } | ||
1157 | } | 1222 | } |
1158 | } | 1223 | } |
1159 | 1224 | ||
@@ -1179,7 +1244,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1179 | { | 1244 | { |
1180 | struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; | 1245 | struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; |
1181 | struct gfs2_args *args = &sdp->sd_args; | 1246 | struct gfs2_args *args = &sdp->sd_args; |
1182 | int lfsecs; | 1247 | int val; |
1183 | 1248 | ||
1184 | if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir)) | 1249 | if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir)) |
1185 | seq_printf(s, ",meta"); | 1250 | seq_printf(s, ",meta"); |
@@ -1240,9 +1305,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1240 | } | 1305 | } |
1241 | if (args->ar_discard) | 1306 | if (args->ar_discard) |
1242 | seq_printf(s, ",discard"); | 1307 | seq_printf(s, ",discard"); |
1243 | lfsecs = sdp->sd_tune.gt_log_flush_secs; | 1308 | val = sdp->sd_tune.gt_log_flush_secs; |
1244 | if (lfsecs != 60) | 1309 | if (val != 60) |
1245 | seq_printf(s, ",commit=%d", lfsecs); | 1310 | seq_printf(s, ",commit=%d", val); |
1311 | val = sdp->sd_tune.gt_statfs_quantum; | ||
1312 | if (val != 30) | ||
1313 | seq_printf(s, ",statfs_quantum=%d", val); | ||
1314 | val = sdp->sd_tune.gt_quota_quantum; | ||
1315 | if (val != 60) | ||
1316 | seq_printf(s, ",quota_quantum=%d", val); | ||
1317 | if (args->ar_statfs_percent) | ||
1318 | seq_printf(s, ",statfs_percent=%d", args->ar_statfs_percent); | ||
1246 | if (args->ar_errors != GFS2_ERRORS_DEFAULT) { | 1319 | if (args->ar_errors != GFS2_ERRORS_DEFAULT) { |
1247 | const char *state; | 1320 | const char *state; |
1248 | 1321 | ||
@@ -1259,6 +1332,9 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1259 | } | 1332 | } |
1260 | seq_printf(s, ",errors=%s", state); | 1333 | seq_printf(s, ",errors=%s", state); |
1261 | } | 1334 | } |
1335 | if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) | ||
1336 | seq_printf(s, ",nobarrier"); | ||
1337 | |||
1262 | return 0; | 1338 | return 0; |
1263 | } | 1339 | } |
1264 | 1340 | ||
@@ -1277,9 +1353,6 @@ static void gfs2_delete_inode(struct inode *inode) | |||
1277 | struct gfs2_holder gh; | 1353 | struct gfs2_holder gh; |
1278 | int error; | 1354 | int error; |
1279 | 1355 | ||
1280 | if (!test_bit(GIF_USER, &ip->i_flags)) | ||
1281 | goto out; | ||
1282 | |||
1283 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1356 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
1284 | if (unlikely(error)) { | 1357 | if (unlikely(error)) { |
1285 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1358 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 235db3682885..3df60f2d84e3 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
@@ -27,7 +27,7 @@ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) | |||
27 | 27 | ||
28 | extern void gfs2_jindex_free(struct gfs2_sbd *sdp); | 28 | extern void gfs2_jindex_free(struct gfs2_sbd *sdp); |
29 | 29 | ||
30 | extern int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *data); | 30 | extern int gfs2_mount_args(struct gfs2_args *args, char *data); |
31 | 31 | ||
32 | extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid); | 32 | extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid); |
33 | extern int gfs2_jdesc_check(struct gfs2_jdesc *jd); | 33 | extern int gfs2_jdesc_check(struct gfs2_jdesc *jd); |
@@ -44,7 +44,7 @@ extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, | |||
44 | const void *buf); | 44 | const void *buf); |
45 | extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | 45 | extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, |
46 | struct buffer_head *l_bh); | 46 | struct buffer_head *l_bh); |
47 | extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); | 47 | extern int gfs2_statfs_sync(struct super_block *sb, int type); |
48 | 48 | ||
49 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); | 49 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); |
50 | extern void gfs2_unfreeze_fs(struct gfs2_sbd *sdp); | 50 | extern void gfs2_unfreeze_fs(struct gfs2_sbd *sdp); |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 446329728d52..54fd98425991 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -8,7 +8,6 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
11 | #include <linux/slab.h> | ||
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
14 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
@@ -49,7 +48,7 @@ static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr, | |||
49 | return a->store ? a->store(sdp, buf, len) : len; | 48 | return a->store ? a->store(sdp, buf, len) : len; |
50 | } | 49 | } |
51 | 50 | ||
52 | static struct sysfs_ops gfs2_attr_ops = { | 51 | static const struct sysfs_ops gfs2_attr_ops = { |
53 | .show = gfs2_attr_show, | 52 | .show = gfs2_attr_show, |
54 | .store = gfs2_attr_store, | 53 | .store = gfs2_attr_store, |
55 | }; | 54 | }; |
@@ -85,11 +84,7 @@ static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf) | |||
85 | buf[0] = '\0'; | 84 | buf[0] = '\0'; |
86 | if (!gfs2_uuid_valid(uuid)) | 85 | if (!gfs2_uuid_valid(uuid)) |
87 | return 0; | 86 | return 0; |
88 | return snprintf(buf, PAGE_SIZE, "%02X%02X%02X%02X-%02X%02X-" | 87 | return snprintf(buf, PAGE_SIZE, "%pUB\n", uuid); |
89 | "%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", | ||
90 | uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], | ||
91 | uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], | ||
92 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
93 | } | 88 | } |
94 | 89 | ||
95 | static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf) | 90 | static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf) |
@@ -158,7 +153,7 @@ static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf, | |||
158 | if (simple_strtol(buf, NULL, 0) != 1) | 153 | if (simple_strtol(buf, NULL, 0) != 1) |
159 | return -EINVAL; | 154 | return -EINVAL; |
160 | 155 | ||
161 | gfs2_statfs_sync(sdp); | 156 | gfs2_statfs_sync(sdp->sd_vfs, 0); |
162 | return len; | 157 | return len; |
163 | } | 158 | } |
164 | 159 | ||
@@ -171,13 +166,14 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf, | |||
171 | if (simple_strtol(buf, NULL, 0) != 1) | 166 | if (simple_strtol(buf, NULL, 0) != 1) |
172 | return -EINVAL; | 167 | return -EINVAL; |
173 | 168 | ||
174 | gfs2_quota_sync(sdp); | 169 | gfs2_quota_sync(sdp->sd_vfs, 0, 1); |
175 | return len; | 170 | return len; |
176 | } | 171 | } |
177 | 172 | ||
178 | static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, | 173 | static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, |
179 | size_t len) | 174 | size_t len) |
180 | { | 175 | { |
176 | int error; | ||
181 | u32 id; | 177 | u32 id; |
182 | 178 | ||
183 | if (!capable(CAP_SYS_ADMIN)) | 179 | if (!capable(CAP_SYS_ADMIN)) |
@@ -185,13 +181,14 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, | |||
185 | 181 | ||
186 | id = simple_strtoul(buf, NULL, 0); | 182 | id = simple_strtoul(buf, NULL, 0); |
187 | 183 | ||
188 | gfs2_quota_refresh(sdp, 1, id); | 184 | error = gfs2_quota_refresh(sdp, 1, id); |
189 | return len; | 185 | return error ? error : len; |
190 | } | 186 | } |
191 | 187 | ||
192 | static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, | 188 | static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, |
193 | size_t len) | 189 | size_t len) |
194 | { | 190 | { |
191 | int error; | ||
195 | u32 id; | 192 | u32 id; |
196 | 193 | ||
197 | if (!capable(CAP_SYS_ADMIN)) | 194 | if (!capable(CAP_SYS_ADMIN)) |
@@ -199,8 +196,8 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, | |||
199 | 196 | ||
200 | id = simple_strtoul(buf, NULL, 0); | 197 | id = simple_strtoul(buf, NULL, 0); |
201 | 198 | ||
202 | gfs2_quota_refresh(sdp, 0, id); | 199 | error = gfs2_quota_refresh(sdp, 0, id); |
203 | return len; | 200 | return error ? error : len; |
204 | } | 201 | } |
205 | 202 | ||
206 | static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | 203 | static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len) |
@@ -480,7 +477,6 @@ TUNE_ATTR(complain_secs, 0); | |||
480 | TUNE_ATTR(statfs_slow, 0); | 477 | TUNE_ATTR(statfs_slow, 0); |
481 | TUNE_ATTR(new_files_jdata, 0); | 478 | TUNE_ATTR(new_files_jdata, 0); |
482 | TUNE_ATTR(quota_simul_sync, 1); | 479 | TUNE_ATTR(quota_simul_sync, 1); |
483 | TUNE_ATTR(stall_secs, 1); | ||
484 | TUNE_ATTR(statfs_quantum, 1); | 480 | TUNE_ATTR(statfs_quantum, 1); |
485 | TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store); | 481 | TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store); |
486 | 482 | ||
@@ -493,7 +489,6 @@ static struct attribute *tune_attrs[] = { | |||
493 | &tune_attr_complain_secs.attr, | 489 | &tune_attr_complain_secs.attr, |
494 | &tune_attr_statfs_slow.attr, | 490 | &tune_attr_statfs_slow.attr, |
495 | &tune_attr_quota_simul_sync.attr, | 491 | &tune_attr_quota_simul_sync.attr, |
496 | &tune_attr_stall_secs.attr, | ||
497 | &tune_attr_statfs_quantum.attr, | 492 | &tune_attr_statfs_quantum.attr, |
498 | &tune_attr_quota_scale.attr, | 493 | &tune_attr_quota_scale.attr, |
499 | &tune_attr_new_files_jdata.attr, | 494 | &tune_attr_new_files_jdata.attr, |
@@ -573,18 +568,12 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, | |||
573 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); | 568 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); |
574 | if (!sdp->sd_args.ar_spectator) | 569 | if (!sdp->sd_args.ar_spectator) |
575 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); | 570 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); |
576 | if (gfs2_uuid_valid(uuid)) { | 571 | if (gfs2_uuid_valid(uuid)) |
577 | add_uevent_var(env, "UUID=%02X%02X%02X%02X-%02X%02X-%02X%02X-" | 572 | add_uevent_var(env, "UUID=%pUB", uuid); |
578 | "%02X%02X-%02X%02X%02X%02X%02X%02X", | ||
579 | uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], | ||
580 | uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], | ||
581 | uuid[10], uuid[11], uuid[12], uuid[13], | ||
582 | uuid[14], uuid[15]); | ||
583 | } | ||
584 | return 0; | 573 | return 0; |
585 | } | 574 | } |
586 | 575 | ||
587 | static struct kset_uevent_ops gfs2_uevent_ops = { | 576 | static const struct kset_uevent_ops gfs2_uevent_ops = { |
588 | .uevent = gfs2_uevent, | 577 | .uevent = gfs2_uevent, |
589 | }; | 578 | }; |
590 | 579 | ||
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index f6a7efa34eb9..53511291fe36 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
12 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
13 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
@@ -21,6 +20,7 @@ | |||
21 | #include "util.h" | 20 | #include "util.h" |
22 | 21 | ||
23 | struct kmem_cache *gfs2_glock_cachep __read_mostly; | 22 | struct kmem_cache *gfs2_glock_cachep __read_mostly; |
23 | struct kmem_cache *gfs2_glock_aspace_cachep __read_mostly; | ||
24 | struct kmem_cache *gfs2_inode_cachep __read_mostly; | 24 | struct kmem_cache *gfs2_inode_cachep __read_mostly; |
25 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; | 25 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; |
26 | struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; | 26 | struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; |
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 33e96b0ce9ab..b432e04600de 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h | |||
@@ -145,6 +145,7 @@ gfs2_io_error_bh_i((sdp), (bh), __func__, __FILE__, __LINE__); | |||
145 | 145 | ||
146 | 146 | ||
147 | extern struct kmem_cache *gfs2_glock_cachep; | 147 | extern struct kmem_cache *gfs2_glock_cachep; |
148 | extern struct kmem_cache *gfs2_glock_aspace_cachep; | ||
148 | extern struct kmem_cache *gfs2_inode_cachep; | 149 | extern struct kmem_cache *gfs2_inode_cachep; |
149 | extern struct kmem_cache *gfs2_bufdata_cachep; | 150 | extern struct kmem_cache *gfs2_bufdata_cachep; |
150 | extern struct kmem_cache *gfs2_rgrpd_cachep; | 151 | extern struct kmem_cache *gfs2_rgrpd_cachep; |
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 8a0f8ef6ee27..c2ebdf2c01d4 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c | |||
@@ -186,8 +186,8 @@ static int ea_find_i(struct gfs2_inode *ip, struct buffer_head *bh, | |||
186 | return 0; | 186 | return 0; |
187 | } | 187 | } |
188 | 188 | ||
189 | int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, | 189 | static int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, |
190 | struct gfs2_ea_location *el) | 190 | struct gfs2_ea_location *el) |
191 | { | 191 | { |
192 | struct ea_find ef; | 192 | struct ea_find ef; |
193 | int error; | 193 | int error; |
@@ -516,8 +516,8 @@ out: | |||
516 | return error; | 516 | return error; |
517 | } | 517 | } |
518 | 518 | ||
519 | int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, | 519 | static int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, |
520 | char *data, size_t size) | 520 | char *data, size_t size) |
521 | { | 521 | { |
522 | int ret; | 522 | int ret; |
523 | size_t len = GFS2_EA_DATA_LEN(el->el_ea); | 523 | size_t len = GFS2_EA_DATA_LEN(el->el_ea); |
@@ -534,21 +534,50 @@ int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, | |||
534 | return len; | 534 | return len; |
535 | } | 535 | } |
536 | 536 | ||
537 | int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **ppdata) | ||
538 | { | ||
539 | struct gfs2_ea_location el; | ||
540 | int error; | ||
541 | int len; | ||
542 | char *data; | ||
543 | |||
544 | error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, &el); | ||
545 | if (error) | ||
546 | return error; | ||
547 | if (!el.el_ea) | ||
548 | goto out; | ||
549 | if (!GFS2_EA_DATA_LEN(el.el_ea)) | ||
550 | goto out; | ||
551 | |||
552 | len = GFS2_EA_DATA_LEN(el.el_ea); | ||
553 | data = kmalloc(len, GFP_NOFS); | ||
554 | error = -ENOMEM; | ||
555 | if (data == NULL) | ||
556 | goto out; | ||
557 | |||
558 | error = gfs2_ea_get_copy(ip, &el, data, len); | ||
559 | if (error == 0) | ||
560 | error = len; | ||
561 | *ppdata = data; | ||
562 | out: | ||
563 | brelse(el.el_bh); | ||
564 | return error; | ||
565 | } | ||
566 | |||
537 | /** | 567 | /** |
538 | * gfs2_xattr_get - Get a GFS2 extended attribute | 568 | * gfs2_xattr_get - Get a GFS2 extended attribute |
539 | * @inode: The inode | 569 | * @inode: The inode |
540 | * @type: The type of extended attribute | ||
541 | * @name: The name of the extended attribute | 570 | * @name: The name of the extended attribute |
542 | * @buffer: The buffer to write the result into | 571 | * @buffer: The buffer to write the result into |
543 | * @size: The size of the buffer | 572 | * @size: The size of the buffer |
573 | * @type: The type of extended attribute | ||
544 | * | 574 | * |
545 | * Returns: actual size of data on success, -errno on error | 575 | * Returns: actual size of data on success, -errno on error |
546 | */ | 576 | */ |
547 | 577 | static int gfs2_xattr_get(struct dentry *dentry, const char *name, | |
548 | int gfs2_xattr_get(struct inode *inode, int type, const char *name, | 578 | void *buffer, size_t size, int type) |
549 | void *buffer, size_t size) | ||
550 | { | 579 | { |
551 | struct gfs2_inode *ip = GFS2_I(inode); | 580 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); |
552 | struct gfs2_ea_location el; | 581 | struct gfs2_ea_location el; |
553 | int error; | 582 | int error; |
554 | 583 | ||
@@ -1089,7 +1118,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) | |||
1089 | 1118 | ||
1090 | /** | 1119 | /** |
1091 | * gfs2_xattr_remove - Remove a GFS2 extended attribute | 1120 | * gfs2_xattr_remove - Remove a GFS2 extended attribute |
1092 | * @inode: The inode | 1121 | * @ip: The inode |
1093 | * @type: The type of the extended attribute | 1122 | * @type: The type of the extended attribute |
1094 | * @name: The name of the extended attribute | 1123 | * @name: The name of the extended attribute |
1095 | * | 1124 | * |
@@ -1100,9 +1129,8 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) | |||
1100 | * Returns: 0, or errno on failure | 1129 | * Returns: 0, or errno on failure |
1101 | */ | 1130 | */ |
1102 | 1131 | ||
1103 | static int gfs2_xattr_remove(struct inode *inode, int type, const char *name) | 1132 | static int gfs2_xattr_remove(struct gfs2_inode *ip, int type, const char *name) |
1104 | { | 1133 | { |
1105 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1106 | struct gfs2_ea_location el; | 1134 | struct gfs2_ea_location el; |
1107 | int error; | 1135 | int error; |
1108 | 1136 | ||
@@ -1126,24 +1154,24 @@ static int gfs2_xattr_remove(struct inode *inode, int type, const char *name) | |||
1126 | } | 1154 | } |
1127 | 1155 | ||
1128 | /** | 1156 | /** |
1129 | * gfs2_xattr_set - Set (or remove) a GFS2 extended attribute | 1157 | * __gfs2_xattr_set - Set (or remove) a GFS2 extended attribute |
1130 | * @inode: The inode | 1158 | * @ip: The inode |
1131 | * @type: The type of the extended attribute | ||
1132 | * @name: The name of the extended attribute | 1159 | * @name: The name of the extended attribute |
1133 | * @value: The value of the extended attribute (NULL for remove) | 1160 | * @value: The value of the extended attribute (NULL for remove) |
1134 | * @size: The size of the @value argument | 1161 | * @size: The size of the @value argument |
1135 | * @flags: Create or Replace | 1162 | * @flags: Create or Replace |
1163 | * @type: The type of the extended attribute | ||
1136 | * | 1164 | * |
1137 | * See gfs2_xattr_remove() for details of the removal of xattrs. | 1165 | * See gfs2_xattr_remove() for details of the removal of xattrs. |
1138 | * | 1166 | * |
1139 | * Returns: 0 or errno on failure | 1167 | * Returns: 0 or errno on failure |
1140 | */ | 1168 | */ |
1141 | 1169 | ||
1142 | int gfs2_xattr_set(struct inode *inode, int type, const char *name, | 1170 | int __gfs2_xattr_set(struct inode *inode, const char *name, |
1143 | const void *value, size_t size, int flags) | 1171 | const void *value, size_t size, int flags, int type) |
1144 | { | 1172 | { |
1145 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1146 | struct gfs2_inode *ip = GFS2_I(inode); | 1173 | struct gfs2_inode *ip = GFS2_I(inode); |
1174 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1147 | struct gfs2_ea_location el; | 1175 | struct gfs2_ea_location el; |
1148 | unsigned int namel = strlen(name); | 1176 | unsigned int namel = strlen(name); |
1149 | int error; | 1177 | int error; |
@@ -1154,7 +1182,7 @@ int gfs2_xattr_set(struct inode *inode, int type, const char *name, | |||
1154 | return -ERANGE; | 1182 | return -ERANGE; |
1155 | 1183 | ||
1156 | if (value == NULL) | 1184 | if (value == NULL) |
1157 | return gfs2_xattr_remove(inode, type, name); | 1185 | return gfs2_xattr_remove(ip, type, name); |
1158 | 1186 | ||
1159 | if (ea_check_size(sdp, namel, size)) | 1187 | if (ea_check_size(sdp, namel, size)) |
1160 | return -ERANGE; | 1188 | return -ERANGE; |
@@ -1194,6 +1222,13 @@ int gfs2_xattr_set(struct inode *inode, int type, const char *name, | |||
1194 | return error; | 1222 | return error; |
1195 | } | 1223 | } |
1196 | 1224 | ||
1225 | static int gfs2_xattr_set(struct dentry *dentry, const char *name, | ||
1226 | const void *value, size_t size, int flags, int type) | ||
1227 | { | ||
1228 | return __gfs2_xattr_set(dentry->d_inode, name, value, | ||
1229 | size, flags, type); | ||
1230 | } | ||
1231 | |||
1197 | static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, | 1232 | static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, |
1198 | struct gfs2_ea_header *ea, char *data) | 1233 | struct gfs2_ea_header *ea, char *data) |
1199 | { | 1234 | { |
@@ -1259,23 +1294,29 @@ fail: | |||
1259 | return error; | 1294 | return error; |
1260 | } | 1295 | } |
1261 | 1296 | ||
1262 | int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, | 1297 | int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) |
1263 | struct iattr *attr, char *data) | ||
1264 | { | 1298 | { |
1299 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1300 | struct gfs2_ea_location el; | ||
1265 | struct buffer_head *dibh; | 1301 | struct buffer_head *dibh; |
1266 | int error; | 1302 | int error; |
1267 | 1303 | ||
1268 | if (GFS2_EA_IS_STUFFED(el->el_ea)) { | 1304 | error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el); |
1269 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0); | 1305 | if (error) |
1270 | if (error) | 1306 | return error; |
1271 | return error; | ||
1272 | 1307 | ||
1273 | gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1); | 1308 | if (GFS2_EA_IS_STUFFED(el.el_ea)) { |
1274 | memcpy(GFS2_EA2DATA(el->el_ea), data, | 1309 | error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0); |
1275 | GFS2_EA_DATA_LEN(el->el_ea)); | 1310 | if (error == 0) { |
1276 | } else | 1311 | gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1); |
1277 | error = ea_acl_chmod_unstuffed(ip, el->el_ea, data); | 1312 | memcpy(GFS2_EA2DATA(el.el_ea), data, |
1313 | GFS2_EA_DATA_LEN(el.el_ea)); | ||
1314 | } | ||
1315 | } else { | ||
1316 | error = ea_acl_chmod_unstuffed(ip, el.el_ea, data); | ||
1317 | } | ||
1278 | 1318 | ||
1319 | brelse(el.el_bh); | ||
1279 | if (error) | 1320 | if (error) |
1280 | return error; | 1321 | return error; |
1281 | 1322 | ||
@@ -1288,8 +1329,7 @@ int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, | |||
1288 | brelse(dibh); | 1329 | brelse(dibh); |
1289 | } | 1330 | } |
1290 | 1331 | ||
1291 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); | 1332 | gfs2_trans_end(sdp); |
1292 | |||
1293 | return error; | 1333 | return error; |
1294 | } | 1334 | } |
1295 | 1335 | ||
@@ -1495,58 +1535,18 @@ out_alloc: | |||
1495 | return error; | 1535 | return error; |
1496 | } | 1536 | } |
1497 | 1537 | ||
1498 | static int gfs2_xattr_user_get(struct inode *inode, const char *name, | ||
1499 | void *buffer, size_t size) | ||
1500 | { | ||
1501 | return gfs2_xattr_get(inode, GFS2_EATYPE_USR, name, buffer, size); | ||
1502 | } | ||
1503 | |||
1504 | static int gfs2_xattr_user_set(struct inode *inode, const char *name, | ||
1505 | const void *value, size_t size, int flags) | ||
1506 | { | ||
1507 | return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags); | ||
1508 | } | ||
1509 | |||
1510 | static int gfs2_xattr_system_get(struct inode *inode, const char *name, | ||
1511 | void *buffer, size_t size) | ||
1512 | { | ||
1513 | return gfs2_xattr_get(inode, GFS2_EATYPE_SYS, name, buffer, size); | ||
1514 | } | ||
1515 | |||
1516 | static int gfs2_xattr_system_set(struct inode *inode, const char *name, | ||
1517 | const void *value, size_t size, int flags) | ||
1518 | { | ||
1519 | return gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, flags); | ||
1520 | } | ||
1521 | |||
1522 | static int gfs2_xattr_security_get(struct inode *inode, const char *name, | ||
1523 | void *buffer, size_t size) | ||
1524 | { | ||
1525 | return gfs2_xattr_get(inode, GFS2_EATYPE_SECURITY, name, buffer, size); | ||
1526 | } | ||
1527 | |||
1528 | static int gfs2_xattr_security_set(struct inode *inode, const char *name, | ||
1529 | const void *value, size_t size, int flags) | ||
1530 | { | ||
1531 | return gfs2_xattr_set(inode, GFS2_EATYPE_SECURITY, name, value, size, flags); | ||
1532 | } | ||
1533 | |||
1534 | static struct xattr_handler gfs2_xattr_user_handler = { | 1538 | static struct xattr_handler gfs2_xattr_user_handler = { |
1535 | .prefix = XATTR_USER_PREFIX, | 1539 | .prefix = XATTR_USER_PREFIX, |
1536 | .get = gfs2_xattr_user_get, | 1540 | .flags = GFS2_EATYPE_USR, |
1537 | .set = gfs2_xattr_user_set, | 1541 | .get = gfs2_xattr_get, |
1542 | .set = gfs2_xattr_set, | ||
1538 | }; | 1543 | }; |
1539 | 1544 | ||
1540 | static struct xattr_handler gfs2_xattr_security_handler = { | 1545 | static struct xattr_handler gfs2_xattr_security_handler = { |
1541 | .prefix = XATTR_SECURITY_PREFIX, | 1546 | .prefix = XATTR_SECURITY_PREFIX, |
1542 | .get = gfs2_xattr_security_get, | 1547 | .flags = GFS2_EATYPE_SECURITY, |
1543 | .set = gfs2_xattr_security_set, | 1548 | .get = gfs2_xattr_get, |
1544 | }; | 1549 | .set = gfs2_xattr_set, |
1545 | |||
1546 | static struct xattr_handler gfs2_xattr_system_handler = { | ||
1547 | .prefix = XATTR_SYSTEM_PREFIX, | ||
1548 | .get = gfs2_xattr_system_get, | ||
1549 | .set = gfs2_xattr_system_set, | ||
1550 | }; | 1550 | }; |
1551 | 1551 | ||
1552 | struct xattr_handler *gfs2_xattr_handlers[] = { | 1552 | struct xattr_handler *gfs2_xattr_handlers[] = { |
diff --git a/fs/gfs2/xattr.h b/fs/gfs2/xattr.h index cbdfd7743733..d392f8358f2f 100644 --- a/fs/gfs2/xattr.h +++ b/fs/gfs2/xattr.h | |||
@@ -53,20 +53,15 @@ struct gfs2_ea_location { | |||
53 | struct gfs2_ea_header *el_prev; | 53 | struct gfs2_ea_header *el_prev; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | extern int gfs2_xattr_get(struct inode *inode, int type, const char *name, | 56 | extern int __gfs2_xattr_set(struct inode *inode, const char *name, |
57 | void *buffer, size_t size); | 57 | const void *value, size_t size, |
58 | extern int gfs2_xattr_set(struct inode *inode, int type, const char *name, | 58 | int flags, int type); |
59 | const void *value, size_t size, int flags); | ||
60 | extern ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size); | 59 | extern ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size); |
61 | extern int gfs2_ea_dealloc(struct gfs2_inode *ip); | 60 | extern int gfs2_ea_dealloc(struct gfs2_inode *ip); |
62 | 61 | ||
63 | /* Exported to acl.c */ | 62 | /* Exported to acl.c */ |
64 | 63 | ||
65 | extern int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, | 64 | extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data); |
66 | struct gfs2_ea_location *el); | 65 | extern int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data); |
67 | extern int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, | ||
68 | char *data, size_t size); | ||
69 | extern int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, | ||
70 | struct iattr *attr, char *data); | ||
71 | 66 | ||
72 | #endif /* __EATTR_DOT_H__ */ | 67 | #endif /* __EATTR_DOT_H__ */ |