diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 11:17:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 11:17:51 -0400 |
commit | f16a5e347835c6a0ba958535cf6e6c89d50463b8 (patch) | |
tree | 41d2e7784f57212a3f910690e00dcd1707a7e47f /fs | |
parent | 110b93842e36b17598cf24874e90d0401431cda2 (diff) | |
parent | 7df0e0397b9a18358573274db9fdab991941062f (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
GFS2: Fix permissions checking for setflags ioctl()
GFS2: Don't "get" xattrs for ACLs when ACLs are turned off
GFS2: Rework reclaiming unlinked dinodes
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/acl.c | 4 | ||||
-rw-r--r-- | fs/gfs2/file.c | 7 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 54 | ||||
-rw-r--r-- | fs/gfs2/inode.h | 3 | ||||
-rw-r--r-- | fs/gfs2/log.c | 2 | ||||
-rw-r--r-- | fs/gfs2/log.h | 29 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 20 |
7 files changed, 65 insertions, 54 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 9fb76b0a0485..48171f4c943d 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c | |||
@@ -236,10 +236,14 @@ static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, | |||
236 | void *buffer, size_t size, int xtype) | 236 | void *buffer, size_t size, int xtype) |
237 | { | 237 | { |
238 | struct inode *inode = dentry->d_inode; | 238 | struct inode *inode = dentry->d_inode; |
239 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
239 | struct posix_acl *acl; | 240 | struct posix_acl *acl; |
240 | int type; | 241 | int type; |
241 | int error; | 242 | int error; |
242 | 243 | ||
244 | if (!sdp->sd_args.ar_posix_acl) | ||
245 | return -EOPNOTSUPP; | ||
246 | |||
243 | type = gfs2_acl_type(name); | 247 | type = gfs2_acl_type(name); |
244 | if (type < 0) | 248 | if (type < 0) |
245 | return type; | 249 | return type; |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index e6dd2aec6f82..b20bfcc9fa2d 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -218,6 +218,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) | |||
218 | if (error) | 218 | if (error) |
219 | goto out_drop_write; | 219 | goto out_drop_write; |
220 | 220 | ||
221 | error = -EACCES; | ||
222 | if (!is_owner_or_cap(inode)) | ||
223 | goto out; | ||
224 | |||
225 | error = 0; | ||
221 | flags = ip->i_diskflags; | 226 | flags = ip->i_diskflags; |
222 | new_flags = (flags & ~mask) | (reqflags & mask); | 227 | new_flags = (flags & ~mask) | (reqflags & mask); |
223 | if ((new_flags ^ flags) == 0) | 228 | if ((new_flags ^ flags) == 0) |
@@ -275,8 +280,10 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr) | |||
275 | { | 280 | { |
276 | struct inode *inode = filp->f_path.dentry->d_inode; | 281 | struct inode *inode = filp->f_path.dentry->d_inode; |
277 | u32 fsflags, gfsflags; | 282 | u32 fsflags, gfsflags; |
283 | |||
278 | if (get_user(fsflags, ptr)) | 284 | if (get_user(fsflags, ptr)) |
279 | return -EFAULT; | 285 | return -EFAULT; |
286 | |||
280 | gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags); | 287 | gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags); |
281 | if (!S_ISDIR(inode->i_mode)) { | 288 | if (!S_ISDIR(inode->i_mode)) { |
282 | if (gfsflags & GFS2_DIF_INHERIT_JDATA) | 289 | if (gfsflags & GFS2_DIF_INHERIT_JDATA) |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 51d8061fa07a..b5612cbb62a5 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -242,34 +242,38 @@ fail: | |||
242 | } | 242 | } |
243 | 243 | ||
244 | /** | 244 | /** |
245 | * gfs2_unlinked_inode_lookup - Lookup an unlinked inode for reclamation | 245 | * gfs2_process_unlinked_inode - Lookup an unlinked inode for reclamation |
246 | * and try to reclaim it by doing iput. | ||
247 | * | ||
248 | * This function assumes no rgrp locks are currently held. | ||
249 | * | ||
246 | * @sb: The super block | 250 | * @sb: The super block |
247 | * no_addr: The inode number | 251 | * no_addr: The inode number |
248 | * @@inode: A pointer to the inode found, if any | ||
249 | * | 252 | * |
250 | * Returns: 0 and *inode if no errors occurred. If an error occurs, | ||
251 | * the resulting *inode may or may not be NULL. | ||
252 | */ | 253 | */ |
253 | 254 | ||
254 | int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr, | 255 | void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) |
255 | struct inode **inode) | ||
256 | { | 256 | { |
257 | struct gfs2_sbd *sdp; | 257 | struct gfs2_sbd *sdp; |
258 | struct gfs2_inode *ip; | 258 | struct gfs2_inode *ip; |
259 | struct gfs2_glock *io_gl; | 259 | struct gfs2_glock *io_gl; |
260 | int error; | 260 | int error; |
261 | struct gfs2_holder gh; | 261 | struct gfs2_holder gh; |
262 | struct inode *inode; | ||
262 | 263 | ||
263 | *inode = gfs2_iget_skip(sb, no_addr); | 264 | inode = gfs2_iget_skip(sb, no_addr); |
264 | 265 | ||
265 | if (!(*inode)) | 266 | if (!inode) |
266 | return -ENOBUFS; | 267 | return; |
267 | 268 | ||
268 | if (!((*inode)->i_state & I_NEW)) | 269 | /* If it's not a new inode, someone's using it, so leave it alone. */ |
269 | return -ENOBUFS; | 270 | if (!(inode->i_state & I_NEW)) { |
271 | iput(inode); | ||
272 | return; | ||
273 | } | ||
270 | 274 | ||
271 | ip = GFS2_I(*inode); | 275 | ip = GFS2_I(inode); |
272 | sdp = GFS2_SB(*inode); | 276 | sdp = GFS2_SB(inode); |
273 | ip->i_no_formal_ino = -1; | 277 | ip->i_no_formal_ino = -1; |
274 | 278 | ||
275 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); | 279 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); |
@@ -284,15 +288,13 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr, | |||
284 | set_bit(GIF_INVALID, &ip->i_flags); | 288 | set_bit(GIF_INVALID, &ip->i_flags); |
285 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT, | 289 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT, |
286 | &ip->i_iopen_gh); | 290 | &ip->i_iopen_gh); |
287 | if (unlikely(error)) { | 291 | if (unlikely(error)) |
288 | if (error == GLR_TRYFAILED) | ||
289 | error = 0; | ||
290 | goto fail_iopen; | 292 | goto fail_iopen; |
291 | } | 293 | |
292 | ip->i_iopen_gh.gh_gl->gl_object = ip; | 294 | ip->i_iopen_gh.gh_gl->gl_object = ip; |
293 | gfs2_glock_put(io_gl); | 295 | gfs2_glock_put(io_gl); |
294 | 296 | ||
295 | (*inode)->i_mode = DT2IF(DT_UNKNOWN); | 297 | inode->i_mode = DT2IF(DT_UNKNOWN); |
296 | 298 | ||
297 | /* | 299 | /* |
298 | * We must read the inode in order to work out its type in | 300 | * We must read the inode in order to work out its type in |
@@ -303,16 +305,17 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr, | |||
303 | */ | 305 | */ |
304 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY, | 306 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY, |
305 | &gh); | 307 | &gh); |
306 | if (unlikely(error)) { | 308 | if (unlikely(error)) |
307 | if (error == GLR_TRYFAILED) | ||
308 | error = 0; | ||
309 | goto fail_glock; | 309 | goto fail_glock; |
310 | } | 310 | |
311 | /* Inode is now uptodate */ | 311 | /* Inode is now uptodate */ |
312 | gfs2_glock_dq_uninit(&gh); | 312 | gfs2_glock_dq_uninit(&gh); |
313 | gfs2_set_iop(*inode); | 313 | gfs2_set_iop(inode); |
314 | |||
315 | /* The iput will cause it to be deleted. */ | ||
316 | iput(inode); | ||
317 | return; | ||
314 | 318 | ||
315 | return 0; | ||
316 | fail_glock: | 319 | fail_glock: |
317 | gfs2_glock_dq(&ip->i_iopen_gh); | 320 | gfs2_glock_dq(&ip->i_iopen_gh); |
318 | fail_iopen: | 321 | fail_iopen: |
@@ -321,7 +324,8 @@ fail_put: | |||
321 | ip->i_gl->gl_object = NULL; | 324 | ip->i_gl->gl_object = NULL; |
322 | gfs2_glock_put(ip->i_gl); | 325 | gfs2_glock_put(ip->i_gl); |
323 | fail: | 326 | fail: |
324 | return error; | 327 | iget_failed(inode); |
328 | return; | ||
325 | } | 329 | } |
326 | 330 | ||
327 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | 331 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) |
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index e161461d4c57..300ada3f21de 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -84,8 +84,7 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip, | |||
84 | extern void gfs2_set_iop(struct inode *inode); | 84 | extern void gfs2_set_iop(struct inode *inode); |
85 | extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, | 85 | extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, |
86 | u64 no_addr, u64 no_formal_ino); | 86 | u64 no_addr, u64 no_formal_ino); |
87 | extern int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr, | 87 | extern void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr); |
88 | struct inode **inode); | ||
89 | extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); | 88 | extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); |
90 | 89 | ||
91 | extern int gfs2_inode_refresh(struct gfs2_inode *ip); | 90 | extern int gfs2_inode_refresh(struct gfs2_inode *ip); |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index b593f0e28f25..6a857e24f947 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -696,7 +696,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp) | |||
696 | * | 696 | * |
697 | */ | 697 | */ |
698 | 698 | ||
699 | void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | 699 | void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) |
700 | { | 700 | { |
701 | struct gfs2_ail *ai; | 701 | struct gfs2_ail *ai; |
702 | 702 | ||
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index eb570b4ad443..0d007f920234 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h | |||
@@ -47,28 +47,21 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp, | |||
47 | sdp->sd_log_head = sdp->sd_log_tail = value; | 47 | sdp->sd_log_head = sdp->sd_log_tail = value; |
48 | } | 48 | } |
49 | 49 | ||
50 | unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, | 50 | extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, |
51 | unsigned int ssize); | 51 | unsigned int ssize); |
52 | 52 | ||
53 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); | 53 | extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); |
54 | void gfs2_log_incr_head(struct gfs2_sbd *sdp); | 54 | extern void gfs2_log_incr_head(struct gfs2_sbd *sdp); |
55 | 55 | ||
56 | struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp); | 56 | extern struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp); |
57 | struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, | 57 | extern struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, |
58 | struct buffer_head *real); | 58 | struct buffer_head *real); |
59 | void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); | 59 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); |
60 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); | ||
61 | extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); | ||
60 | 62 | ||
61 | static inline void gfs2_log_flush(struct gfs2_sbd *sbd, struct gfs2_glock *gl) | 63 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); |
62 | { | 64 | extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp); |
63 | if (!gl || test_bit(GLF_LFLUSH, &gl->gl_flags)) | 65 | extern int gfs2_logd(void *data); |
64 | __gfs2_log_flush(sbd, gl); | ||
65 | } | ||
66 | |||
67 | void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); | ||
68 | void gfs2_remove_from_ail(struct gfs2_bufdata *bd); | ||
69 | |||
70 | void gfs2_log_shutdown(struct gfs2_sbd *sdp); | ||
71 | void gfs2_meta_syncfs(struct gfs2_sbd *sdp); | ||
72 | int gfs2_logd(void *data); | ||
73 | 66 | ||
74 | #endif /* __LOG_DOT_H__ */ | 67 | #endif /* __LOG_DOT_H__ */ |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 117fa4171f62..171a744f8e45 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1192,7 +1192,6 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
1192 | { | 1192 | { |
1193 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1193 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1194 | struct gfs2_alloc *al = ip->i_alloc; | 1194 | struct gfs2_alloc *al = ip->i_alloc; |
1195 | struct inode *inode; | ||
1196 | int error = 0; | 1195 | int error = 0; |
1197 | u64 last_unlinked = NO_BLOCK, unlinked; | 1196 | u64 last_unlinked = NO_BLOCK, unlinked; |
1198 | 1197 | ||
@@ -1210,22 +1209,27 @@ try_again: | |||
1210 | if (error) | 1209 | if (error) |
1211 | return error; | 1210 | return error; |
1212 | 1211 | ||
1212 | /* Find an rgrp suitable for allocation. If it encounters any unlinked | ||
1213 | dinodes along the way, error will equal -EAGAIN and unlinked will | ||
1214 | contains it block address. We then need to look up that inode and | ||
1215 | try to free it, and try the allocation again. */ | ||
1213 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); | 1216 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); |
1214 | if (error) { | 1217 | if (error) { |
1215 | if (ip != GFS2_I(sdp->sd_rindex)) | 1218 | if (ip != GFS2_I(sdp->sd_rindex)) |
1216 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1219 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1217 | if (error != -EAGAIN) | 1220 | if (error != -EAGAIN) |
1218 | return error; | 1221 | return error; |
1219 | error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb, | 1222 | |
1220 | unlinked, &inode); | 1223 | gfs2_process_unlinked_inode(ip->i_inode.i_sb, unlinked); |
1221 | if (inode) | 1224 | /* regardless of whether or not gfs2_process_unlinked_inode |
1222 | iput(inode); | 1225 | was successful, we don't want to repeat it again. */ |
1226 | last_unlinked = unlinked; | ||
1223 | gfs2_log_flush(sdp, NULL); | 1227 | gfs2_log_flush(sdp, NULL); |
1224 | if (error == GLR_TRYFAILED) | 1228 | error = 0; |
1225 | error = 0; | 1229 | |
1226 | goto try_again; | 1230 | goto try_again; |
1227 | } | 1231 | } |
1228 | 1232 | /* no error, so we have the rgrp set in the inode's allocation. */ | |
1229 | al->al_file = file; | 1233 | al->al_file = file; |
1230 | al->al_line = line; | 1234 | al->al_line = line; |
1231 | 1235 | ||