diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-03 17:40:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-03 17:40:10 -0400 |
commit | 3a09b1be53d23df780a0cd0e4087a05e2ca4a00c (patch) | |
tree | 16c4ee5593847cc96e44e95f94e3ca0e315dfb1d | |
parent | 7046e668d7973c470146fbe6635967a1b4a31bca (diff) | |
parent | 0809f6ec18bbce54c996f5c36f4b9d371075c98b (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw:
GFS2: Fix recovery stuck bug (try #2)
GFS2: Fix typo in stuffed file data copy handling
Revert "GFS2: recovery stuck on transaction lock"
GFS2: Make "try" lock not try quite so hard
GFS2: remove dependency on __GFP_NOFAIL
GFS2: Simplify gfs2_write_alloc_required
GFS2: Wait for journal id on mount if not specified on mount command line
GFS2: Use nobh_writepage
-rw-r--r-- | fs/gfs2/aops.c | 9 | ||||
-rw-r--r-- | fs/gfs2/bmap.c | 17 | ||||
-rw-r--r-- | fs/gfs2/bmap.h | 2 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 11 | ||||
-rw-r--r-- | fs/gfs2/file.c | 4 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 105 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 1 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 27 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 15 | ||||
-rw-r--r-- | fs/gfs2/super.c | 9 | ||||
-rw-r--r-- | fs/gfs2/sys.c | 57 |
11 files changed, 169 insertions, 88 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 9f8b52500d63..5e96cbd8a454 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -136,10 +136,7 @@ static int gfs2_writeback_writepage(struct page *page, | |||
136 | if (ret <= 0) | 136 | if (ret <= 0) |
137 | return ret; | 137 | return ret; |
138 | 138 | ||
139 | ret = mpage_writepage(page, gfs2_get_block_noalloc, wbc); | 139 | return nobh_writepage(page, gfs2_get_block_noalloc, wbc); |
140 | if (ret == -EAGAIN) | ||
141 | ret = block_write_full_page(page, gfs2_get_block_noalloc, wbc); | ||
142 | return ret; | ||
143 | } | 140 | } |
144 | 141 | ||
145 | /** | 142 | /** |
@@ -637,9 +634,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
637 | } | 634 | } |
638 | } | 635 | } |
639 | 636 | ||
640 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); | 637 | alloc_required = gfs2_write_alloc_required(ip, pos, len); |
641 | if (error) | ||
642 | goto out_unlock; | ||
643 | 638 | ||
644 | if (alloc_required || gfs2_is_jdata(ip)) | 639 | if (alloc_required || gfs2_is_jdata(ip)) |
645 | gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); | 640 | gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); |
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 84da64b551b2..6f482809d1a3 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -1040,7 +1040,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) | |||
1040 | goto out; | 1040 | goto out; |
1041 | 1041 | ||
1042 | if (gfs2_is_stuffed(ip)) { | 1042 | if (gfs2_is_stuffed(ip)) { |
1043 | u64 dsize = size + sizeof(struct gfs2_inode); | 1043 | u64 dsize = size + sizeof(struct gfs2_dinode); |
1044 | ip->i_disksize = size; | 1044 | ip->i_disksize = size; |
1045 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 1045 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
1046 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1046 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
@@ -1244,13 +1244,12 @@ int gfs2_file_dealloc(struct gfs2_inode *ip) | |||
1244 | * @ip: the file being written to | 1244 | * @ip: the file being written to |
1245 | * @offset: the offset to write to | 1245 | * @offset: the offset to write to |
1246 | * @len: the number of bytes being written | 1246 | * @len: the number of bytes being written |
1247 | * @alloc_required: set to 1 if an alloc is required, 0 otherwise | ||
1248 | * | 1247 | * |
1249 | * Returns: errno | 1248 | * Returns: 1 if an alloc is required, 0 otherwise |
1250 | */ | 1249 | */ |
1251 | 1250 | ||
1252 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | 1251 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, |
1253 | unsigned int len, int *alloc_required) | 1252 | unsigned int len) |
1254 | { | 1253 | { |
1255 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1254 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1256 | struct buffer_head bh; | 1255 | struct buffer_head bh; |
@@ -1258,26 +1257,23 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1258 | u64 lblock, lblock_stop, size; | 1257 | u64 lblock, lblock_stop, size; |
1259 | u64 end_of_file; | 1258 | u64 end_of_file; |
1260 | 1259 | ||
1261 | *alloc_required = 0; | ||
1262 | |||
1263 | if (!len) | 1260 | if (!len) |
1264 | return 0; | 1261 | return 0; |
1265 | 1262 | ||
1266 | if (gfs2_is_stuffed(ip)) { | 1263 | if (gfs2_is_stuffed(ip)) { |
1267 | if (offset + len > | 1264 | if (offset + len > |
1268 | sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) | 1265 | sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) |
1269 | *alloc_required = 1; | 1266 | return 1; |
1270 | return 0; | 1267 | return 0; |
1271 | } | 1268 | } |
1272 | 1269 | ||
1273 | *alloc_required = 1; | ||
1274 | shift = sdp->sd_sb.sb_bsize_shift; | 1270 | shift = sdp->sd_sb.sb_bsize_shift; |
1275 | BUG_ON(gfs2_is_dir(ip)); | 1271 | BUG_ON(gfs2_is_dir(ip)); |
1276 | end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; | 1272 | end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; |
1277 | lblock = offset >> shift; | 1273 | lblock = offset >> shift; |
1278 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; | 1274 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; |
1279 | if (lblock_stop > end_of_file) | 1275 | if (lblock_stop > end_of_file) |
1280 | return 0; | 1276 | return 1; |
1281 | 1277 | ||
1282 | size = (lblock_stop - lblock) << shift; | 1278 | size = (lblock_stop - lblock) << shift; |
1283 | do { | 1279 | do { |
@@ -1285,12 +1281,11 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1285 | bh.b_size = size; | 1281 | bh.b_size = size; |
1286 | gfs2_block_map(&ip->i_inode, lblock, &bh, 0); | 1282 | gfs2_block_map(&ip->i_inode, lblock, &bh, 0); |
1287 | if (!buffer_mapped(&bh)) | 1283 | if (!buffer_mapped(&bh)) |
1288 | return 0; | 1284 | return 1; |
1289 | size -= bh.b_size; | 1285 | size -= bh.b_size; |
1290 | lblock += (bh.b_size >> ip->i_inode.i_blkbits); | 1286 | lblock += (bh.b_size >> ip->i_inode.i_blkbits); |
1291 | } while(size > 0); | 1287 | } while(size > 0); |
1292 | 1288 | ||
1293 | *alloc_required = 0; | ||
1294 | return 0; | 1289 | return 0; |
1295 | } | 1290 | } |
1296 | 1291 | ||
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h index c983177e05ac..a20a5213135a 100644 --- a/fs/gfs2/bmap.h +++ b/fs/gfs2/bmap.h | |||
@@ -52,6 +52,6 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size); | |||
52 | int gfs2_truncatei_resume(struct gfs2_inode *ip); | 52 | int gfs2_truncatei_resume(struct gfs2_inode *ip); |
53 | int gfs2_file_dealloc(struct gfs2_inode *ip); | 53 | int gfs2_file_dealloc(struct gfs2_inode *ip); |
54 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | 54 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, |
55 | unsigned int len, int *alloc_required); | 55 | unsigned int len); |
56 | 56 | ||
57 | #endif /* __BMAP_DOT_H__ */ | 57 | #endif /* __BMAP_DOT_H__ */ |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 6b48d7c268b2..b9dd88a78dd4 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -955,7 +955,12 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
955 | /* Change the pointers. | 955 | /* Change the pointers. |
956 | Don't bother distinguishing stuffed from non-stuffed. | 956 | Don't bother distinguishing stuffed from non-stuffed. |
957 | This code is complicated enough already. */ | 957 | This code is complicated enough already. */ |
958 | lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS | __GFP_NOFAIL); | 958 | lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS); |
959 | if (!lp) { | ||
960 | error = -ENOMEM; | ||
961 | goto fail_brelse; | ||
962 | } | ||
963 | |||
959 | /* Change the pointers */ | 964 | /* Change the pointers */ |
960 | for (x = 0; x < half_len; x++) | 965 | for (x = 0; x < half_len; x++) |
961 | lp[x] = cpu_to_be64(bn); | 966 | lp[x] = cpu_to_be64(bn); |
@@ -1063,7 +1068,9 @@ static int dir_double_exhash(struct gfs2_inode *dip) | |||
1063 | 1068 | ||
1064 | /* Allocate both the "from" and "to" buffers in one big chunk */ | 1069 | /* Allocate both the "from" and "to" buffers in one big chunk */ |
1065 | 1070 | ||
1066 | buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL); | 1071 | buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS); |
1072 | if (!buf) | ||
1073 | return -ENOMEM; | ||
1067 | 1074 | ||
1068 | for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) { | 1075 | for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) { |
1069 | error = gfs2_dir_read_data(dip, (char *)buf, | 1076 | error = gfs2_dir_read_data(dip, (char *)buf, |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index ed9a94f0ef15..4edd662c8232 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -351,7 +351,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
351 | unsigned long last_index; | 351 | unsigned long last_index; |
352 | u64 pos = page->index << PAGE_CACHE_SHIFT; | 352 | u64 pos = page->index << PAGE_CACHE_SHIFT; |
353 | unsigned int data_blocks, ind_blocks, rblocks; | 353 | unsigned int data_blocks, ind_blocks, rblocks; |
354 | int alloc_required = 0; | ||
355 | struct gfs2_holder gh; | 354 | struct gfs2_holder gh; |
356 | struct gfs2_alloc *al; | 355 | struct gfs2_alloc *al; |
357 | int ret; | 356 | int ret; |
@@ -364,8 +363,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
364 | set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); | 363 | set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); |
365 | set_bit(GIF_SW_PAGED, &ip->i_flags); | 364 | set_bit(GIF_SW_PAGED, &ip->i_flags); |
366 | 365 | ||
367 | ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required); | 366 | if (!gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE)) |
368 | if (ret || !alloc_required) | ||
369 | goto out_unlock; | 367 | goto out_unlock; |
370 | ret = -ENOMEM; | 368 | ret = -ENOMEM; |
371 | al = gfs2_alloc_get(ip); | 369 | al = gfs2_alloc_get(ip); |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 0898f3ec8212..9adf8f924e08 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -328,6 +328,30 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) | |||
328 | } | 328 | } |
329 | 329 | ||
330 | /** | 330 | /** |
331 | * do_error - Something unexpected has happened during a lock request | ||
332 | * | ||
333 | */ | ||
334 | |||
335 | static inline void do_error(struct gfs2_glock *gl, const int ret) | ||
336 | { | ||
337 | struct gfs2_holder *gh, *tmp; | ||
338 | |||
339 | list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { | ||
340 | if (test_bit(HIF_HOLDER, &gh->gh_iflags)) | ||
341 | continue; | ||
342 | if (ret & LM_OUT_ERROR) | ||
343 | gh->gh_error = -EIO; | ||
344 | else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) | ||
345 | gh->gh_error = GLR_TRYFAILED; | ||
346 | else | ||
347 | continue; | ||
348 | list_del_init(&gh->gh_list); | ||
349 | trace_gfs2_glock_queue(gh, 0); | ||
350 | gfs2_holder_wake(gh); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | /** | ||
331 | * do_promote - promote as many requests as possible on the current queue | 355 | * do_promote - promote as many requests as possible on the current queue |
332 | * @gl: The glock | 356 | * @gl: The glock |
333 | * | 357 | * |
@@ -375,36 +399,13 @@ restart: | |||
375 | } | 399 | } |
376 | if (gh->gh_list.prev == &gl->gl_holders) | 400 | if (gh->gh_list.prev == &gl->gl_holders) |
377 | return 1; | 401 | return 1; |
402 | do_error(gl, 0); | ||
378 | break; | 403 | break; |
379 | } | 404 | } |
380 | return 0; | 405 | return 0; |
381 | } | 406 | } |
382 | 407 | ||
383 | /** | 408 | /** |
384 | * do_error - Something unexpected has happened during a lock request | ||
385 | * | ||
386 | */ | ||
387 | |||
388 | static inline void do_error(struct gfs2_glock *gl, const int ret) | ||
389 | { | ||
390 | struct gfs2_holder *gh, *tmp; | ||
391 | |||
392 | list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { | ||
393 | if (test_bit(HIF_HOLDER, &gh->gh_iflags)) | ||
394 | continue; | ||
395 | if (ret & LM_OUT_ERROR) | ||
396 | gh->gh_error = -EIO; | ||
397 | else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) | ||
398 | gh->gh_error = GLR_TRYFAILED; | ||
399 | else | ||
400 | continue; | ||
401 | list_del_init(&gh->gh_list); | ||
402 | trace_gfs2_glock_queue(gh, 0); | ||
403 | gfs2_holder_wake(gh); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | /** | ||
408 | * find_first_waiter - find the first gh that's waiting for the glock | 409 | * find_first_waiter - find the first gh that's waiting for the glock |
409 | * @gl: the glock | 410 | * @gl: the glock |
410 | */ | 411 | */ |
@@ -706,18 +707,8 @@ static void glock_work_func(struct work_struct *work) | |||
706 | { | 707 | { |
707 | unsigned long delay = 0; | 708 | unsigned long delay = 0; |
708 | struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); | 709 | struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); |
709 | struct gfs2_holder *gh; | ||
710 | int drop_ref = 0; | 710 | int drop_ref = 0; |
711 | 711 | ||
712 | if (unlikely(test_bit(GLF_FROZEN, &gl->gl_flags))) { | ||
713 | spin_lock(&gl->gl_spin); | ||
714 | gh = find_first_waiter(gl); | ||
715 | if (gh && (gh->gh_flags & LM_FLAG_NOEXP) && | ||
716 | test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) | ||
717 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); | ||
718 | spin_unlock(&gl->gl_spin); | ||
719 | } | ||
720 | |||
721 | if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) { | 712 | if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) { |
722 | finish_xmote(gl, gl->gl_reply); | 713 | finish_xmote(gl, gl->gl_reply); |
723 | drop_ref = 1; | 714 | drop_ref = 1; |
@@ -1072,6 +1063,9 @@ int gfs2_glock_nq(struct gfs2_holder *gh) | |||
1072 | 1063 | ||
1073 | spin_lock(&gl->gl_spin); | 1064 | spin_lock(&gl->gl_spin); |
1074 | add_to_queue(gh); | 1065 | add_to_queue(gh); |
1066 | if ((LM_FLAG_NOEXP & gh->gh_flags) && | ||
1067 | test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) | ||
1068 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); | ||
1075 | run_queue(gl, 1); | 1069 | run_queue(gl, 1); |
1076 | spin_unlock(&gl->gl_spin); | 1070 | spin_unlock(&gl->gl_spin); |
1077 | 1071 | ||
@@ -1329,6 +1323,36 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) | |||
1329 | } | 1323 | } |
1330 | 1324 | ||
1331 | /** | 1325 | /** |
1326 | * gfs2_should_freeze - Figure out if glock should be frozen | ||
1327 | * @gl: The glock in question | ||
1328 | * | ||
1329 | * Glocks are not frozen if (a) the result of the dlm operation is | ||
1330 | * an error, (b) the locking operation was an unlock operation or | ||
1331 | * (c) if there is a "noexp" flagged request anywhere in the queue | ||
1332 | * | ||
1333 | * Returns: 1 if freezing should occur, 0 otherwise | ||
1334 | */ | ||
1335 | |||
1336 | static int gfs2_should_freeze(const struct gfs2_glock *gl) | ||
1337 | { | ||
1338 | const struct gfs2_holder *gh; | ||
1339 | |||
1340 | if (gl->gl_reply & ~LM_OUT_ST_MASK) | ||
1341 | return 0; | ||
1342 | if (gl->gl_target == LM_ST_UNLOCKED) | ||
1343 | return 0; | ||
1344 | |||
1345 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { | ||
1346 | if (test_bit(HIF_HOLDER, &gh->gh_iflags)) | ||
1347 | continue; | ||
1348 | if (LM_FLAG_NOEXP & gh->gh_flags) | ||
1349 | return 0; | ||
1350 | } | ||
1351 | |||
1352 | return 1; | ||
1353 | } | ||
1354 | |||
1355 | /** | ||
1332 | * gfs2_glock_complete - Callback used by locking | 1356 | * gfs2_glock_complete - Callback used by locking |
1333 | * @gl: Pointer to the glock | 1357 | * @gl: Pointer to the glock |
1334 | * @ret: The return value from the dlm | 1358 | * @ret: The return value from the dlm |
@@ -1338,18 +1362,17 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) | |||
1338 | void gfs2_glock_complete(struct gfs2_glock *gl, int ret) | 1362 | void gfs2_glock_complete(struct gfs2_glock *gl, int ret) |
1339 | { | 1363 | { |
1340 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; | 1364 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; |
1365 | |||
1341 | gl->gl_reply = ret; | 1366 | gl->gl_reply = ret; |
1367 | |||
1342 | if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { | 1368 | if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { |
1343 | struct gfs2_holder *gh; | ||
1344 | spin_lock(&gl->gl_spin); | 1369 | spin_lock(&gl->gl_spin); |
1345 | gh = find_first_waiter(gl); | 1370 | if (gfs2_should_freeze(gl)) { |
1346 | if ((!(gh && (gh->gh_flags & LM_FLAG_NOEXP)) && | ||
1347 | (gl->gl_target != LM_ST_UNLOCKED)) || | ||
1348 | ((ret & ~LM_OUT_ST_MASK) != 0)) | ||
1349 | set_bit(GLF_FROZEN, &gl->gl_flags); | 1371 | set_bit(GLF_FROZEN, &gl->gl_flags); |
1350 | spin_unlock(&gl->gl_spin); | 1372 | spin_unlock(&gl->gl_spin); |
1351 | if (test_bit(GLF_FROZEN, &gl->gl_flags)) | ||
1352 | return; | 1373 | return; |
1374 | } | ||
1375 | spin_unlock(&gl->gl_spin); | ||
1353 | } | 1376 | } |
1354 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); | 1377 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); |
1355 | gfs2_glock_hold(gl); | 1378 | gfs2_glock_hold(gl); |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index b5d7363b22da..8fcbce48a128 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -460,6 +460,7 @@ enum { | |||
460 | SDF_NOBARRIERS = 3, | 460 | SDF_NOBARRIERS = 3, |
461 | SDF_NORECOVERY = 4, | 461 | SDF_NORECOVERY = 4, |
462 | SDF_DEMOTE = 5, | 462 | SDF_DEMOTE = 5, |
463 | SDF_NOJOURNALID = 6, | ||
463 | }; | 464 | }; |
464 | 465 | ||
465 | #define GFS2_FSNAME_LEN 256 | 466 | #define GFS2_FSNAME_LEN 256 |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 3593b3a7290e..45a4a36195d8 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -76,7 +76,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
76 | 76 | ||
77 | sb->s_fs_info = sdp; | 77 | sb->s_fs_info = sdp; |
78 | sdp->sd_vfs = sb; | 78 | sdp->sd_vfs = sb; |
79 | 79 | set_bit(SDF_NOJOURNALID, &sdp->sd_flags); | |
80 | gfs2_tune_init(&sdp->sd_tune); | 80 | gfs2_tune_init(&sdp->sd_tune); |
81 | 81 | ||
82 | init_waitqueue_head(&sdp->sd_glock_wait); | 82 | init_waitqueue_head(&sdp->sd_glock_wait); |
@@ -1050,7 +1050,8 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) | |||
1050 | ret = match_int(&tmp[0], &option); | 1050 | ret = match_int(&tmp[0], &option); |
1051 | if (ret || option < 0) | 1051 | if (ret || option < 0) |
1052 | goto hostdata_error; | 1052 | goto hostdata_error; |
1053 | ls->ls_jid = option; | 1053 | if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags)) |
1054 | ls->ls_jid = option; | ||
1054 | break; | 1055 | break; |
1055 | case Opt_id: | 1056 | case Opt_id: |
1056 | /* Obsolete, but left for backward compat purposes */ | 1057 | /* Obsolete, but left for backward compat purposes */ |
@@ -1102,6 +1103,24 @@ void gfs2_lm_unmount(struct gfs2_sbd *sdp) | |||
1102 | lm->lm_unmount(sdp); | 1103 | lm->lm_unmount(sdp); |
1103 | } | 1104 | } |
1104 | 1105 | ||
1106 | static int gfs2_journalid_wait(void *word) | ||
1107 | { | ||
1108 | if (signal_pending(current)) | ||
1109 | return -EINTR; | ||
1110 | schedule(); | ||
1111 | return 0; | ||
1112 | } | ||
1113 | |||
1114 | static int wait_on_journal(struct gfs2_sbd *sdp) | ||
1115 | { | ||
1116 | if (sdp->sd_args.ar_spectator) | ||
1117 | return 0; | ||
1118 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) | ||
1119 | return 0; | ||
1120 | |||
1121 | return wait_on_bit(&sdp->sd_flags, SDF_NOJOURNALID, gfs2_journalid_wait, TASK_INTERRUPTIBLE); | ||
1122 | } | ||
1123 | |||
1105 | void gfs2_online_uevent(struct gfs2_sbd *sdp) | 1124 | void gfs2_online_uevent(struct gfs2_sbd *sdp) |
1106 | { | 1125 | { |
1107 | struct super_block *sb = sdp->sd_vfs; | 1126 | struct super_block *sb = sdp->sd_vfs; |
@@ -1194,6 +1213,10 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent | |||
1194 | if (error) | 1213 | if (error) |
1195 | goto fail_locking; | 1214 | goto fail_locking; |
1196 | 1215 | ||
1216 | error = wait_on_journal(sdp); | ||
1217 | if (error) | ||
1218 | goto fail_sb; | ||
1219 | |||
1197 | error = init_inodes(sdp, DO); | 1220 | error = init_inodes(sdp, DO); |
1198 | if (error) | 1221 | if (error) |
1199 | goto fail_sb; | 1222 | goto fail_sb; |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 8f02d3db8f42..8bb643cb2658 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -787,15 +787,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
787 | goto out; | 787 | goto out; |
788 | 788 | ||
789 | for (x = 0; x < num_qd; x++) { | 789 | for (x = 0; x < num_qd; x++) { |
790 | int alloc_required; | ||
791 | |||
792 | offset = qd2offset(qda[x]); | 790 | offset = qd2offset(qda[x]); |
793 | error = gfs2_write_alloc_required(ip, offset, | 791 | if (gfs2_write_alloc_required(ip, offset, |
794 | sizeof(struct gfs2_quota), | 792 | sizeof(struct gfs2_quota))) |
795 | &alloc_required); | ||
796 | if (error) | ||
797 | goto out_gunlock; | ||
798 | if (alloc_required) | ||
799 | nalloc++; | 793 | nalloc++; |
800 | } | 794 | } |
801 | 795 | ||
@@ -1584,10 +1578,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, | |||
1584 | goto out_i; | 1578 | goto out_i; |
1585 | 1579 | ||
1586 | offset = qd2offset(qd); | 1580 | offset = qd2offset(qd); |
1587 | error = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota), | 1581 | alloc_required = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota)); |
1588 | &alloc_required); | ||
1589 | if (error) | ||
1590 | goto out_i; | ||
1591 | if (alloc_required) { | 1582 | if (alloc_required) { |
1592 | al = gfs2_alloc_get(ip); | 1583 | al = gfs2_alloc_get(ip); |
1593 | if (al == NULL) | 1584 | if (al == NULL) |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 4d1aad38f1b1..4140811a921c 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -342,8 +342,6 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) | |||
342 | { | 342 | { |
343 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); | 343 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); |
344 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); | 344 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); |
345 | int ar; | ||
346 | int error; | ||
347 | 345 | ||
348 | if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) || | 346 | if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) || |
349 | (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) { | 347 | (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) { |
@@ -352,13 +350,12 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) | |||
352 | } | 350 | } |
353 | jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; | 351 | jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; |
354 | 352 | ||
355 | error = gfs2_write_alloc_required(ip, 0, ip->i_disksize, &ar); | 353 | if (gfs2_write_alloc_required(ip, 0, ip->i_disksize)) { |
356 | if (!error && ar) { | ||
357 | gfs2_consist_inode(ip); | 354 | gfs2_consist_inode(ip); |
358 | error = -EIO; | 355 | return -EIO; |
359 | } | 356 | } |
360 | 357 | ||
361 | return error; | 358 | return 0; |
362 | } | 359 | } |
363 | 360 | ||
364 | /** | 361 | /** |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 37f5393e68e6..d019d0d55e00 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -325,6 +325,30 @@ static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf) | |||
325 | return sprintf(buf, "%d\n", ls->ls_first); | 325 | return sprintf(buf, "%d\n", ls->ls_first); |
326 | } | 326 | } |
327 | 327 | ||
328 | static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | ||
329 | { | ||
330 | unsigned first; | ||
331 | int rv; | ||
332 | |||
333 | rv = sscanf(buf, "%u", &first); | ||
334 | if (rv != 1 || first > 1) | ||
335 | return -EINVAL; | ||
336 | spin_lock(&sdp->sd_jindex_spin); | ||
337 | rv = -EBUSY; | ||
338 | if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) | ||
339 | goto out; | ||
340 | rv = -EINVAL; | ||
341 | if (sdp->sd_args.ar_spectator) | ||
342 | goto out; | ||
343 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) | ||
344 | goto out; | ||
345 | sdp->sd_lockstruct.ls_first = first; | ||
346 | rv = 0; | ||
347 | out: | ||
348 | spin_unlock(&sdp->sd_jindex_spin); | ||
349 | return rv ? rv : len; | ||
350 | } | ||
351 | |||
328 | static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf) | 352 | static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf) |
329 | { | 353 | { |
330 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; | 354 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
@@ -377,14 +401,41 @@ static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf) | |||
377 | return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid); | 401 | return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid); |
378 | } | 402 | } |
379 | 403 | ||
404 | static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | ||
405 | { | ||
406 | unsigned jid; | ||
407 | int rv; | ||
408 | |||
409 | rv = sscanf(buf, "%u", &jid); | ||
410 | if (rv != 1) | ||
411 | return -EINVAL; | ||
412 | |||
413 | spin_lock(&sdp->sd_jindex_spin); | ||
414 | rv = -EINVAL; | ||
415 | if (sdp->sd_args.ar_spectator) | ||
416 | goto out; | ||
417 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) | ||
418 | goto out; | ||
419 | rv = -EBUSY; | ||
420 | if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) | ||
421 | goto out; | ||
422 | sdp->sd_lockstruct.ls_jid = jid; | ||
423 | smp_mb__after_clear_bit(); | ||
424 | wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID); | ||
425 | rv = 0; | ||
426 | out: | ||
427 | spin_unlock(&sdp->sd_jindex_spin); | ||
428 | return rv ? rv : len; | ||
429 | } | ||
430 | |||
380 | #define GDLM_ATTR(_name,_mode,_show,_store) \ | 431 | #define GDLM_ATTR(_name,_mode,_show,_store) \ |
381 | static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) | 432 | static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) |
382 | 433 | ||
383 | GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); | 434 | GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); |
384 | GDLM_ATTR(block, 0644, block_show, block_store); | 435 | GDLM_ATTR(block, 0644, block_show, block_store); |
385 | GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); | 436 | GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); |
386 | GDLM_ATTR(jid, 0444, jid_show, NULL); | 437 | GDLM_ATTR(jid, 0644, jid_show, jid_store); |
387 | GDLM_ATTR(first, 0444, lkfirst_show, NULL); | 438 | GDLM_ATTR(first, 0644, lkfirst_show, lkfirst_store); |
388 | GDLM_ATTR(first_done, 0444, first_done_show, NULL); | 439 | GDLM_ATTR(first_done, 0444, first_done_show, NULL); |
389 | GDLM_ATTR(recover, 0600, NULL, recover_store); | 440 | GDLM_ATTR(recover, 0600, NULL, recover_store); |
390 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); | 441 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); |
@@ -564,7 +615,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, | |||
564 | 615 | ||
565 | add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); | 616 | add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); |
566 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); | 617 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); |
567 | if (!sdp->sd_args.ar_spectator) | 618 | if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags)) |
568 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); | 619 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); |
569 | if (gfs2_uuid_valid(uuid)) | 620 | if (gfs2_uuid_valid(uuid)) |
570 | add_uevent_var(env, "UUID=%pUB", uuid); | 621 | add_uevent_var(env, "UUID=%pUB", uuid); |