diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/gfs2/glops.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/gfs2/glops.c')
-rw-r--r-- | fs/gfs2/glops.c | 214 |
1 files changed, 178 insertions, 36 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 49f97d3bb690..2cca29316bd6 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -28,18 +28,45 @@ | |||
28 | #include "trans.h" | 28 | #include "trans.h" |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * ail_empty_gl - remove all buffers for a given lock from the AIL | 31 | * __gfs2_ail_flush - remove all buffers for a given lock from the AIL |
32 | * @gl: the glock | 32 | * @gl: the glock |
33 | * | 33 | * |
34 | * None of the buffers should be dirty, locked, or pinned. | 34 | * None of the buffers should be dirty, locked, or pinned. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | 37 | static void __gfs2_ail_flush(struct gfs2_glock *gl) |
38 | { | 38 | { |
39 | struct gfs2_sbd *sdp = gl->gl_sbd; | 39 | struct gfs2_sbd *sdp = gl->gl_sbd; |
40 | struct list_head *head = &gl->gl_ail_list; | 40 | struct list_head *head = &gl->gl_ail_list; |
41 | struct gfs2_bufdata *bd; | 41 | struct gfs2_bufdata *bd; |
42 | struct buffer_head *bh; | 42 | struct buffer_head *bh; |
43 | |||
44 | spin_lock(&sdp->sd_ail_lock); | ||
45 | while (!list_empty(head)) { | ||
46 | bd = list_entry(head->next, struct gfs2_bufdata, | ||
47 | bd_ail_gl_list); | ||
48 | bh = bd->bd_bh; | ||
49 | gfs2_remove_from_ail(bd); | ||
50 | bd->bd_bh = NULL; | ||
51 | bh->b_private = NULL; | ||
52 | spin_unlock(&sdp->sd_ail_lock); | ||
53 | |||
54 | bd->bd_blkno = bh->b_blocknr; | ||
55 | gfs2_log_lock(sdp); | ||
56 | gfs2_assert_withdraw(sdp, !buffer_busy(bh)); | ||
57 | gfs2_trans_add_revoke(sdp, bd); | ||
58 | gfs2_log_unlock(sdp); | ||
59 | |||
60 | spin_lock(&sdp->sd_ail_lock); | ||
61 | } | ||
62 | gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); | ||
63 | spin_unlock(&sdp->sd_ail_lock); | ||
64 | } | ||
65 | |||
66 | |||
67 | static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | ||
68 | { | ||
69 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
43 | struct gfs2_trans tr; | 70 | struct gfs2_trans tr; |
44 | 71 | ||
45 | memset(&tr, 0, sizeof(tr)); | 72 | memset(&tr, 0, sizeof(tr)); |
@@ -56,25 +83,29 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
56 | BUG_ON(current->journal_info); | 83 | BUG_ON(current->journal_info); |
57 | current->journal_info = &tr; | 84 | current->journal_info = &tr; |
58 | 85 | ||
59 | gfs2_log_lock(sdp); | 86 | __gfs2_ail_flush(gl); |
60 | while (!list_empty(head)) { | ||
61 | bd = list_entry(head->next, struct gfs2_bufdata, | ||
62 | bd_ail_gl_list); | ||
63 | bh = bd->bd_bh; | ||
64 | gfs2_remove_from_ail(bd); | ||
65 | bd->bd_bh = NULL; | ||
66 | bh->b_private = NULL; | ||
67 | bd->bd_blkno = bh->b_blocknr; | ||
68 | gfs2_assert_withdraw(sdp, !buffer_busy(bh)); | ||
69 | gfs2_trans_add_revoke(sdp, bd); | ||
70 | } | ||
71 | gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); | ||
72 | gfs2_log_unlock(sdp); | ||
73 | 87 | ||
74 | gfs2_trans_end(sdp); | 88 | gfs2_trans_end(sdp); |
75 | gfs2_log_flush(sdp, NULL); | 89 | gfs2_log_flush(sdp, NULL); |
76 | } | 90 | } |
77 | 91 | ||
92 | void gfs2_ail_flush(struct gfs2_glock *gl) | ||
93 | { | ||
94 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
95 | unsigned int revokes = atomic_read(&gl->gl_ail_count); | ||
96 | int ret; | ||
97 | |||
98 | if (!revokes) | ||
99 | return; | ||
100 | |||
101 | ret = gfs2_trans_begin(sdp, 0, revokes); | ||
102 | if (ret) | ||
103 | return; | ||
104 | __gfs2_ail_flush(gl); | ||
105 | gfs2_trans_end(sdp); | ||
106 | gfs2_log_flush(sdp, NULL); | ||
107 | } | ||
108 | |||
78 | /** | 109 | /** |
79 | * rgrp_go_sync - sync out the metadata for this glock | 110 | * rgrp_go_sync - sync out the metadata for this glock |
80 | * @gl: the glock | 111 | * @gl: the glock |
@@ -190,8 +221,10 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
190 | } | 221 | } |
191 | } | 222 | } |
192 | 223 | ||
193 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) | 224 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) { |
225 | gfs2_log_flush(gl->gl_sbd, NULL); | ||
194 | gl->gl_sbd->sd_rindex_uptodate = 0; | 226 | gl->gl_sbd->sd_rindex_uptodate = 0; |
227 | } | ||
195 | if (ip && S_ISREG(ip->i_inode.i_mode)) | 228 | if (ip && S_ISREG(ip->i_inode.i_mode)) |
196 | truncate_inode_pages(ip->i_inode.i_mapping, 0); | 229 | truncate_inode_pages(ip->i_inode.i_mapping, 0); |
197 | } | 230 | } |
@@ -206,12 +239,134 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
206 | static int inode_go_demote_ok(const struct gfs2_glock *gl) | 239 | static int inode_go_demote_ok(const struct gfs2_glock *gl) |
207 | { | 240 | { |
208 | struct gfs2_sbd *sdp = gl->gl_sbd; | 241 | struct gfs2_sbd *sdp = gl->gl_sbd; |
242 | struct gfs2_holder *gh; | ||
243 | |||
209 | if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) | 244 | if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) |
210 | return 0; | 245 | return 0; |
246 | |||
247 | if (!list_empty(&gl->gl_holders)) { | ||
248 | gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); | ||
249 | if (gh->gh_list.next != &gl->gl_holders) | ||
250 | return 0; | ||
251 | } | ||
252 | |||
211 | return 1; | 253 | return 1; |
212 | } | 254 | } |
213 | 255 | ||
214 | /** | 256 | /** |
257 | * gfs2_set_nlink - Set the inode's link count based on on-disk info | ||
258 | * @inode: The inode in question | ||
259 | * @nlink: The link count | ||
260 | * | ||
261 | * If the link count has hit zero, it must never be raised, whatever the | ||
262 | * on-disk inode might say. When new struct inodes are created the link | ||
263 | * count is set to 1, so that we can safely use this test even when reading | ||
264 | * in on disk information for the first time. | ||
265 | */ | ||
266 | |||
267 | static void gfs2_set_nlink(struct inode *inode, u32 nlink) | ||
268 | { | ||
269 | /* | ||
270 | * We will need to review setting the nlink count here in the | ||
271 | * light of the forthcoming ro bind mount work. This is a reminder | ||
272 | * to do that. | ||
273 | */ | ||
274 | if ((inode->i_nlink != nlink) && (inode->i_nlink != 0)) { | ||
275 | if (nlink == 0) | ||
276 | clear_nlink(inode); | ||
277 | else | ||
278 | inode->i_nlink = nlink; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | ||
283 | { | ||
284 | const struct gfs2_dinode *str = buf; | ||
285 | struct timespec atime; | ||
286 | u16 height, depth; | ||
287 | |||
288 | if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) | ||
289 | goto corrupt; | ||
290 | ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); | ||
291 | ip->i_inode.i_mode = be32_to_cpu(str->di_mode); | ||
292 | ip->i_inode.i_rdev = 0; | ||
293 | switch (ip->i_inode.i_mode & S_IFMT) { | ||
294 | case S_IFBLK: | ||
295 | case S_IFCHR: | ||
296 | ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major), | ||
297 | be32_to_cpu(str->di_minor)); | ||
298 | break; | ||
299 | }; | ||
300 | |||
301 | ip->i_inode.i_uid = be32_to_cpu(str->di_uid); | ||
302 | ip->i_inode.i_gid = be32_to_cpu(str->di_gid); | ||
303 | gfs2_set_nlink(&ip->i_inode, be32_to_cpu(str->di_nlink)); | ||
304 | i_size_write(&ip->i_inode, be64_to_cpu(str->di_size)); | ||
305 | gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); | ||
306 | atime.tv_sec = be64_to_cpu(str->di_atime); | ||
307 | atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); | ||
308 | if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0) | ||
309 | ip->i_inode.i_atime = atime; | ||
310 | ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); | ||
311 | ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); | ||
312 | ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); | ||
313 | ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); | ||
314 | |||
315 | ip->i_goal = be64_to_cpu(str->di_goal_meta); | ||
316 | ip->i_generation = be64_to_cpu(str->di_generation); | ||
317 | |||
318 | ip->i_diskflags = be32_to_cpu(str->di_flags); | ||
319 | gfs2_set_inode_flags(&ip->i_inode); | ||
320 | height = be16_to_cpu(str->di_height); | ||
321 | if (unlikely(height > GFS2_MAX_META_HEIGHT)) | ||
322 | goto corrupt; | ||
323 | ip->i_height = (u8)height; | ||
324 | |||
325 | depth = be16_to_cpu(str->di_depth); | ||
326 | if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) | ||
327 | goto corrupt; | ||
328 | ip->i_depth = (u8)depth; | ||
329 | ip->i_entries = be32_to_cpu(str->di_entries); | ||
330 | |||
331 | ip->i_eattr = be64_to_cpu(str->di_eattr); | ||
332 | if (S_ISREG(ip->i_inode.i_mode)) | ||
333 | gfs2_set_aops(&ip->i_inode); | ||
334 | |||
335 | return 0; | ||
336 | corrupt: | ||
337 | gfs2_consist_inode(ip); | ||
338 | return -EIO; | ||
339 | } | ||
340 | |||
341 | /** | ||
342 | * gfs2_inode_refresh - Refresh the incore copy of the dinode | ||
343 | * @ip: The GFS2 inode | ||
344 | * | ||
345 | * Returns: errno | ||
346 | */ | ||
347 | |||
348 | int gfs2_inode_refresh(struct gfs2_inode *ip) | ||
349 | { | ||
350 | struct buffer_head *dibh; | ||
351 | int error; | ||
352 | |||
353 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
354 | if (error) | ||
355 | return error; | ||
356 | |||
357 | if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), dibh, GFS2_METATYPE_DI)) { | ||
358 | brelse(dibh); | ||
359 | return -EIO; | ||
360 | } | ||
361 | |||
362 | error = gfs2_dinode_in(ip, dibh->b_data); | ||
363 | brelse(dibh); | ||
364 | clear_bit(GIF_INVALID, &ip->i_flags); | ||
365 | |||
366 | return error; | ||
367 | } | ||
368 | |||
369 | /** | ||
215 | * inode_go_lock - operation done after an inode lock is locked by a process | 370 | * inode_go_lock - operation done after an inode lock is locked by a process |
216 | * @gl: the glock | 371 | * @gl: the glock |
217 | * @flags: | 372 | * @flags: |
@@ -262,30 +417,16 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
262 | const struct gfs2_inode *ip = gl->gl_object; | 417 | const struct gfs2_inode *ip = gl->gl_object; |
263 | if (ip == NULL) | 418 | if (ip == NULL) |
264 | return 0; | 419 | return 0; |
265 | gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu/%llu\n", | 420 | gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu\n", |
266 | (unsigned long long)ip->i_no_formal_ino, | 421 | (unsigned long long)ip->i_no_formal_ino, |
267 | (unsigned long long)ip->i_no_addr, | 422 | (unsigned long long)ip->i_no_addr, |
268 | IF2DT(ip->i_inode.i_mode), ip->i_flags, | 423 | IF2DT(ip->i_inode.i_mode), ip->i_flags, |
269 | (unsigned int)ip->i_diskflags, | 424 | (unsigned int)ip->i_diskflags, |
270 | (unsigned long long)ip->i_inode.i_size, | 425 | (unsigned long long)i_size_read(&ip->i_inode)); |
271 | (unsigned long long)ip->i_disksize); | ||
272 | return 0; | 426 | return 0; |
273 | } | 427 | } |
274 | 428 | ||
275 | /** | 429 | /** |
276 | * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock | ||
277 | * @gl: the glock | ||
278 | * | ||
279 | * Returns: 1 if it's ok | ||
280 | */ | ||
281 | |||
282 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) | ||
283 | { | ||
284 | const struct address_space *mapping = (const struct address_space *)(gl + 1); | ||
285 | return !mapping->nrpages; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * rgrp_go_lock - operation done after an rgrp lock is locked by | 430 | * rgrp_go_lock - operation done after an rgrp lock is locked by |
290 | * a first holder on this node. | 431 | * a first holder on this node. |
291 | * @gl: the glock | 432 | * @gl: the glock |
@@ -326,7 +467,6 @@ static void trans_go_sync(struct gfs2_glock *gl) | |||
326 | 467 | ||
327 | if (gl->gl_state != LM_ST_UNLOCKED && | 468 | if (gl->gl_state != LM_ST_UNLOCKED && |
328 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { | 469 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { |
329 | flush_workqueue(gfs2_delete_workqueue); | ||
330 | gfs2_meta_syncfs(sdp); | 470 | gfs2_meta_syncfs(sdp); |
331 | gfs2_log_shutdown(sdp); | 471 | gfs2_log_shutdown(sdp); |
332 | } | 472 | } |
@@ -385,6 +525,10 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl) | |||
385 | static void iopen_go_callback(struct gfs2_glock *gl) | 525 | static void iopen_go_callback(struct gfs2_glock *gl) |
386 | { | 526 | { |
387 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | 527 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; |
528 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
529 | |||
530 | if (sdp->sd_vfs->s_flags & MS_RDONLY) | ||
531 | return; | ||
388 | 532 | ||
389 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | 533 | if (gl->gl_demote_state == LM_ST_UNLOCKED && |
390 | gl->gl_state == LM_ST_SHARED && ip) { | 534 | gl->gl_state == LM_ST_SHARED && ip) { |
@@ -412,7 +556,6 @@ const struct gfs2_glock_operations gfs2_inode_glops = { | |||
412 | const struct gfs2_glock_operations gfs2_rgrp_glops = { | 556 | const struct gfs2_glock_operations gfs2_rgrp_glops = { |
413 | .go_xmote_th = rgrp_go_sync, | 557 | .go_xmote_th = rgrp_go_sync, |
414 | .go_inval = rgrp_go_inval, | 558 | .go_inval = rgrp_go_inval, |
415 | .go_demote_ok = rgrp_go_demote_ok, | ||
416 | .go_lock = rgrp_go_lock, | 559 | .go_lock = rgrp_go_lock, |
417 | .go_unlock = rgrp_go_unlock, | 560 | .go_unlock = rgrp_go_unlock, |
418 | .go_dump = gfs2_rgrp_dump, | 561 | .go_dump = gfs2_rgrp_dump, |
@@ -453,7 +596,6 @@ const struct gfs2_glock_operations *gfs2_glops_list[] = { | |||
453 | [LM_TYPE_META] = &gfs2_meta_glops, | 596 | [LM_TYPE_META] = &gfs2_meta_glops, |
454 | [LM_TYPE_INODE] = &gfs2_inode_glops, | 597 | [LM_TYPE_INODE] = &gfs2_inode_glops, |
455 | [LM_TYPE_RGRP] = &gfs2_rgrp_glops, | 598 | [LM_TYPE_RGRP] = &gfs2_rgrp_glops, |
456 | [LM_TYPE_NONDISK] = &gfs2_trans_glops, | ||
457 | [LM_TYPE_IOPEN] = &gfs2_iopen_glops, | 599 | [LM_TYPE_IOPEN] = &gfs2_iopen_glops, |
458 | [LM_TYPE_FLOCK] = &gfs2_flock_glops, | 600 | [LM_TYPE_FLOCK] = &gfs2_flock_glops, |
459 | [LM_TYPE_NONDISK] = &gfs2_nondisk_glops, | 601 | [LM_TYPE_NONDISK] = &gfs2_nondisk_glops, |