diff options
author | Dave Chinner <david@fromorbit.com> | 2014-03-13 04:12:13 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-03-13 04:12:13 -0400 |
commit | 730357a5cb72d9754a396a350653ff98a9e44783 (patch) | |
tree | 8d97cc0f756e803c8c2f991cab8f1ba00d6dbbe4 /fs/xfs | |
parent | b6db0551fddfc8826bc07fc99d64d830530b2d77 (diff) | |
parent | 93a8614e3a4dccd526aca34e892ac0b27f64b506 (diff) |
Merge branch 'xfs-stack-fixes' into for-next
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_dir2.c | 342 | ||||
-rw-r--r-- | fs/xfs/xfs_iops.c | 14 | ||||
-rw-r--r-- | fs/xfs/xfs_log_cil.c | 52 |
3 files changed, 265 insertions, 143 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index ce16ef02997a..fda46253966a 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -180,16 +180,23 @@ xfs_dir_init( | |||
180 | xfs_inode_t *dp, | 180 | xfs_inode_t *dp, |
181 | xfs_inode_t *pdp) | 181 | xfs_inode_t *pdp) |
182 | { | 182 | { |
183 | xfs_da_args_t args; | 183 | struct xfs_da_args *args; |
184 | int error; | 184 | int error; |
185 | 185 | ||
186 | memset((char *)&args, 0, sizeof(args)); | ||
187 | args.dp = dp; | ||
188 | args.trans = tp; | ||
189 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 186 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
190 | if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) | 187 | error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino); |
188 | if (error) | ||
191 | return error; | 189 | return error; |
192 | return xfs_dir2_sf_create(&args, pdp->i_ino); | 190 | |
191 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); | ||
192 | if (!args) | ||
193 | return ENOMEM; | ||
194 | |||
195 | args->dp = dp; | ||
196 | args->trans = tp; | ||
197 | error = xfs_dir2_sf_create(args, pdp->i_ino); | ||
198 | kmem_free(args); | ||
199 | return error; | ||
193 | } | 200 | } |
194 | 201 | ||
195 | /* | 202 | /* |
@@ -205,41 +212,56 @@ xfs_dir_createname( | |||
205 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ | 212 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ |
206 | xfs_extlen_t total) /* bmap's total block count */ | 213 | xfs_extlen_t total) /* bmap's total block count */ |
207 | { | 214 | { |
208 | xfs_da_args_t args; | 215 | struct xfs_da_args *args; |
209 | int rval; | 216 | int rval; |
210 | int v; /* type-checking value */ | 217 | int v; /* type-checking value */ |
211 | 218 | ||
212 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 219 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
213 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) | 220 | rval = xfs_dir_ino_validate(tp->t_mountp, inum); |
221 | if (rval) | ||
214 | return rval; | 222 | return rval; |
215 | XFS_STATS_INC(xs_dir_create); | 223 | XFS_STATS_INC(xs_dir_create); |
216 | 224 | ||
217 | memset(&args, 0, sizeof(xfs_da_args_t)); | 225 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); |
218 | args.name = name->name; | 226 | if (!args) |
219 | args.namelen = name->len; | 227 | return ENOMEM; |
220 | args.filetype = name->type; | 228 | |
221 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); | 229 | args->name = name->name; |
222 | args.inumber = inum; | 230 | args->namelen = name->len; |
223 | args.dp = dp; | 231 | args->filetype = name->type; |
224 | args.firstblock = first; | 232 | args->hashval = dp->i_mount->m_dirnameops->hashname(name); |
225 | args.flist = flist; | 233 | args->inumber = inum; |
226 | args.total = total; | 234 | args->dp = dp; |
227 | args.whichfork = XFS_DATA_FORK; | 235 | args->firstblock = first; |
228 | args.trans = tp; | 236 | args->flist = flist; |
229 | args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; | 237 | args->total = total; |
230 | 238 | args->whichfork = XFS_DATA_FORK; | |
231 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 239 | args->trans = tp; |
232 | rval = xfs_dir2_sf_addname(&args); | 240 | args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; |
233 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) | 241 | |
234 | return rval; | 242 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
235 | else if (v) | 243 | rval = xfs_dir2_sf_addname(args); |
236 | rval = xfs_dir2_block_addname(&args); | 244 | goto out_free; |
237 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) | 245 | } |
238 | return rval; | 246 | |
239 | else if (v) | 247 | rval = xfs_dir2_isblock(tp, dp, &v); |
240 | rval = xfs_dir2_leaf_addname(&args); | 248 | if (rval) |
249 | goto out_free; | ||
250 | if (v) { | ||
251 | rval = xfs_dir2_block_addname(args); | ||
252 | goto out_free; | ||
253 | } | ||
254 | |||
255 | rval = xfs_dir2_isleaf(tp, dp, &v); | ||
256 | if (rval) | ||
257 | goto out_free; | ||
258 | if (v) | ||
259 | rval = xfs_dir2_leaf_addname(args); | ||
241 | else | 260 | else |
242 | rval = xfs_dir2_node_addname(&args); | 261 | rval = xfs_dir2_node_addname(args); |
262 | |||
263 | out_free: | ||
264 | kmem_free(args); | ||
243 | return rval; | 265 | return rval; |
244 | } | 266 | } |
245 | 267 | ||
@@ -282,46 +304,66 @@ xfs_dir_lookup( | |||
282 | xfs_ino_t *inum, /* out: inode number */ | 304 | xfs_ino_t *inum, /* out: inode number */ |
283 | struct xfs_name *ci_name) /* out: actual name if CI match */ | 305 | struct xfs_name *ci_name) /* out: actual name if CI match */ |
284 | { | 306 | { |
285 | xfs_da_args_t args; | 307 | struct xfs_da_args *args; |
286 | int rval; | 308 | int rval; |
287 | int v; /* type-checking value */ | 309 | int v; /* type-checking value */ |
288 | 310 | ||
289 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 311 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
290 | XFS_STATS_INC(xs_dir_lookup); | 312 | XFS_STATS_INC(xs_dir_lookup); |
291 | 313 | ||
292 | memset(&args, 0, sizeof(xfs_da_args_t)); | 314 | /* |
293 | args.name = name->name; | 315 | * We need to use KM_NOFS here so that lockdep will not throw false |
294 | args.namelen = name->len; | 316 | * positive deadlock warnings on a non-transactional lookup path. It is |
295 | args.filetype = name->type; | 317 | * safe to recurse into inode recalim in that case, but lockdep can't |
296 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); | 318 | * easily be taught about it. Hence KM_NOFS avoids having to add more |
297 | args.dp = dp; | 319 | * lockdep Doing this avoids having to add a bunch of lockdep class |
298 | args.whichfork = XFS_DATA_FORK; | 320 | * annotations into the reclaim path for the ilock. |
299 | args.trans = tp; | 321 | */ |
300 | args.op_flags = XFS_DA_OP_OKNOENT; | 322 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); |
323 | args->name = name->name; | ||
324 | args->namelen = name->len; | ||
325 | args->filetype = name->type; | ||
326 | args->hashval = dp->i_mount->m_dirnameops->hashname(name); | ||
327 | args->dp = dp; | ||
328 | args->whichfork = XFS_DATA_FORK; | ||
329 | args->trans = tp; | ||
330 | args->op_flags = XFS_DA_OP_OKNOENT; | ||
301 | if (ci_name) | 331 | if (ci_name) |
302 | args.op_flags |= XFS_DA_OP_CILOOKUP; | 332 | args->op_flags |= XFS_DA_OP_CILOOKUP; |
303 | 333 | ||
304 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 334 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
305 | rval = xfs_dir2_sf_lookup(&args); | 335 | rval = xfs_dir2_sf_lookup(args); |
306 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) | 336 | goto out_check_rval; |
307 | return rval; | 337 | } |
308 | else if (v) | 338 | |
309 | rval = xfs_dir2_block_lookup(&args); | 339 | rval = xfs_dir2_isblock(tp, dp, &v); |
310 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) | 340 | if (rval) |
311 | return rval; | 341 | goto out_free; |
312 | else if (v) | 342 | if (v) { |
313 | rval = xfs_dir2_leaf_lookup(&args); | 343 | rval = xfs_dir2_block_lookup(args); |
344 | goto out_check_rval; | ||
345 | } | ||
346 | |||
347 | rval = xfs_dir2_isleaf(tp, dp, &v); | ||
348 | if (rval) | ||
349 | goto out_free; | ||
350 | if (v) | ||
351 | rval = xfs_dir2_leaf_lookup(args); | ||
314 | else | 352 | else |
315 | rval = xfs_dir2_node_lookup(&args); | 353 | rval = xfs_dir2_node_lookup(args); |
354 | |||
355 | out_check_rval: | ||
316 | if (rval == EEXIST) | 356 | if (rval == EEXIST) |
317 | rval = 0; | 357 | rval = 0; |
318 | if (!rval) { | 358 | if (!rval) { |
319 | *inum = args.inumber; | 359 | *inum = args->inumber; |
320 | if (ci_name) { | 360 | if (ci_name) { |
321 | ci_name->name = args.value; | 361 | ci_name->name = args->value; |
322 | ci_name->len = args.valuelen; | 362 | ci_name->len = args->valuelen; |
323 | } | 363 | } |
324 | } | 364 | } |
365 | out_free: | ||
366 | kmem_free(args); | ||
325 | return rval; | 367 | return rval; |
326 | } | 368 | } |
327 | 369 | ||
@@ -338,38 +380,51 @@ xfs_dir_removename( | |||
338 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ | 380 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ |
339 | xfs_extlen_t total) /* bmap's total block count */ | 381 | xfs_extlen_t total) /* bmap's total block count */ |
340 | { | 382 | { |
341 | xfs_da_args_t args; | 383 | struct xfs_da_args *args; |
342 | int rval; | 384 | int rval; |
343 | int v; /* type-checking value */ | 385 | int v; /* type-checking value */ |
344 | 386 | ||
345 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 387 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
346 | XFS_STATS_INC(xs_dir_remove); | 388 | XFS_STATS_INC(xs_dir_remove); |
347 | 389 | ||
348 | memset(&args, 0, sizeof(xfs_da_args_t)); | 390 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); |
349 | args.name = name->name; | 391 | if (!args) |
350 | args.namelen = name->len; | 392 | return ENOMEM; |
351 | args.filetype = name->type; | 393 | |
352 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); | 394 | args->name = name->name; |
353 | args.inumber = ino; | 395 | args->namelen = name->len; |
354 | args.dp = dp; | 396 | args->filetype = name->type; |
355 | args.firstblock = first; | 397 | args->hashval = dp->i_mount->m_dirnameops->hashname(name); |
356 | args.flist = flist; | 398 | args->inumber = ino; |
357 | args.total = total; | 399 | args->dp = dp; |
358 | args.whichfork = XFS_DATA_FORK; | 400 | args->firstblock = first; |
359 | args.trans = tp; | 401 | args->flist = flist; |
360 | 402 | args->total = total; | |
361 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 403 | args->whichfork = XFS_DATA_FORK; |
362 | rval = xfs_dir2_sf_removename(&args); | 404 | args->trans = tp; |
363 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) | 405 | |
364 | return rval; | 406 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
365 | else if (v) | 407 | rval = xfs_dir2_sf_removename(args); |
366 | rval = xfs_dir2_block_removename(&args); | 408 | goto out_free; |
367 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) | 409 | } |
368 | return rval; | 410 | |
369 | else if (v) | 411 | rval = xfs_dir2_isblock(tp, dp, &v); |
370 | rval = xfs_dir2_leaf_removename(&args); | 412 | if (rval) |
413 | goto out_free; | ||
414 | if (v) { | ||
415 | rval = xfs_dir2_block_removename(args); | ||
416 | goto out_free; | ||
417 | } | ||
418 | |||
419 | rval = xfs_dir2_isleaf(tp, dp, &v); | ||
420 | if (rval) | ||
421 | goto out_free; | ||
422 | if (v) | ||
423 | rval = xfs_dir2_leaf_removename(args); | ||
371 | else | 424 | else |
372 | rval = xfs_dir2_node_removename(&args); | 425 | rval = xfs_dir2_node_removename(args); |
426 | out_free: | ||
427 | kmem_free(args); | ||
373 | return rval; | 428 | return rval; |
374 | } | 429 | } |
375 | 430 | ||
@@ -386,40 +441,54 @@ xfs_dir_replace( | |||
386 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ | 441 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ |
387 | xfs_extlen_t total) /* bmap's total block count */ | 442 | xfs_extlen_t total) /* bmap's total block count */ |
388 | { | 443 | { |
389 | xfs_da_args_t args; | 444 | struct xfs_da_args *args; |
390 | int rval; | 445 | int rval; |
391 | int v; /* type-checking value */ | 446 | int v; /* type-checking value */ |
392 | 447 | ||
393 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 448 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
394 | 449 | ||
395 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) | 450 | rval = xfs_dir_ino_validate(tp->t_mountp, inum); |
451 | if (rval) | ||
396 | return rval; | 452 | return rval; |
397 | 453 | ||
398 | memset(&args, 0, sizeof(xfs_da_args_t)); | 454 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); |
399 | args.name = name->name; | 455 | if (!args) |
400 | args.namelen = name->len; | 456 | return ENOMEM; |
401 | args.filetype = name->type; | 457 | |
402 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); | 458 | args->name = name->name; |
403 | args.inumber = inum; | 459 | args->namelen = name->len; |
404 | args.dp = dp; | 460 | args->filetype = name->type; |
405 | args.firstblock = first; | 461 | args->hashval = dp->i_mount->m_dirnameops->hashname(name); |
406 | args.flist = flist; | 462 | args->inumber = inum; |
407 | args.total = total; | 463 | args->dp = dp; |
408 | args.whichfork = XFS_DATA_FORK; | 464 | args->firstblock = first; |
409 | args.trans = tp; | 465 | args->flist = flist; |
410 | 466 | args->total = total; | |
411 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 467 | args->whichfork = XFS_DATA_FORK; |
412 | rval = xfs_dir2_sf_replace(&args); | 468 | args->trans = tp; |
413 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) | 469 | |
414 | return rval; | 470 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
415 | else if (v) | 471 | rval = xfs_dir2_sf_replace(args); |
416 | rval = xfs_dir2_block_replace(&args); | 472 | goto out_free; |
417 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) | 473 | } |
418 | return rval; | 474 | |
419 | else if (v) | 475 | rval = xfs_dir2_isblock(tp, dp, &v); |
420 | rval = xfs_dir2_leaf_replace(&args); | 476 | if (rval) |
477 | goto out_free; | ||
478 | if (v) { | ||
479 | rval = xfs_dir2_block_replace(args); | ||
480 | goto out_free; | ||
481 | } | ||
482 | |||
483 | rval = xfs_dir2_isleaf(tp, dp, &v); | ||
484 | if (rval) | ||
485 | goto out_free; | ||
486 | if (v) | ||
487 | rval = xfs_dir2_leaf_replace(args); | ||
421 | else | 488 | else |
422 | rval = xfs_dir2_node_replace(&args); | 489 | rval = xfs_dir2_node_replace(args); |
490 | out_free: | ||
491 | kmem_free(args); | ||
423 | return rval; | 492 | return rval; |
424 | } | 493 | } |
425 | 494 | ||
@@ -434,7 +503,7 @@ xfs_dir_canenter( | |||
434 | struct xfs_name *name, /* name of entry to add */ | 503 | struct xfs_name *name, /* name of entry to add */ |
435 | uint resblks) | 504 | uint resblks) |
436 | { | 505 | { |
437 | xfs_da_args_t args; | 506 | struct xfs_da_args *args; |
438 | int rval; | 507 | int rval; |
439 | int v; /* type-checking value */ | 508 | int v; /* type-checking value */ |
440 | 509 | ||
@@ -443,29 +512,42 @@ xfs_dir_canenter( | |||
443 | 512 | ||
444 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 513 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
445 | 514 | ||
446 | memset(&args, 0, sizeof(xfs_da_args_t)); | 515 | args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); |
447 | args.name = name->name; | 516 | if (!args) |
448 | args.namelen = name->len; | 517 | return ENOMEM; |
449 | args.filetype = name->type; | 518 | |
450 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); | 519 | args->name = name->name; |
451 | args.dp = dp; | 520 | args->namelen = name->len; |
452 | args.whichfork = XFS_DATA_FORK; | 521 | args->filetype = name->type; |
453 | args.trans = tp; | 522 | args->hashval = dp->i_mount->m_dirnameops->hashname(name); |
454 | args.op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME | | 523 | args->dp = dp; |
524 | args->whichfork = XFS_DATA_FORK; | ||
525 | args->trans = tp; | ||
526 | args->op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME | | ||
455 | XFS_DA_OP_OKNOENT; | 527 | XFS_DA_OP_OKNOENT; |
456 | 528 | ||
457 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 529 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
458 | rval = xfs_dir2_sf_addname(&args); | 530 | rval = xfs_dir2_sf_addname(args); |
459 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) | 531 | goto out_free; |
460 | return rval; | 532 | } |
461 | else if (v) | 533 | |
462 | rval = xfs_dir2_block_addname(&args); | 534 | rval = xfs_dir2_isblock(tp, dp, &v); |
463 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) | 535 | if (rval) |
464 | return rval; | 536 | goto out_free; |
465 | else if (v) | 537 | if (v) { |
466 | rval = xfs_dir2_leaf_addname(&args); | 538 | rval = xfs_dir2_block_addname(args); |
539 | goto out_free; | ||
540 | } | ||
541 | |||
542 | rval = xfs_dir2_isleaf(tp, dp, &v); | ||
543 | if (rval) | ||
544 | goto out_free; | ||
545 | if (v) | ||
546 | rval = xfs_dir2_leaf_addname(args); | ||
467 | else | 547 | else |
468 | rval = xfs_dir2_node_addname(&args); | 548 | rval = xfs_dir2_node_addname(args); |
549 | out_free: | ||
550 | kmem_free(args); | ||
469 | return rval; | 551 | return rval; |
470 | } | 552 | } |
471 | 553 | ||
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 9ddfb8190ca1..bb3bb658e39c 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -48,6 +48,18 @@ | |||
48 | #include <linux/fiemap.h> | 48 | #include <linux/fiemap.h> |
49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | 50 | ||
51 | /* | ||
52 | * Directories have different lock order w.r.t. mmap_sem compared to regular | ||
53 | * files. This is due to readdir potentially triggering page faults on a user | ||
54 | * buffer inside filldir(), and this happens with the ilock on the directory | ||
55 | * held. For regular files, the lock order is the other way around - the | ||
56 | * mmap_sem is taken during the page fault, and then we lock the ilock to do | ||
57 | * block mapping. Hence we need a different class for the directory ilock so | ||
58 | * that lockdep can tell them apart. | ||
59 | */ | ||
60 | static struct lock_class_key xfs_nondir_ilock_class; | ||
61 | static struct lock_class_key xfs_dir_ilock_class; | ||
62 | |||
51 | static int | 63 | static int |
52 | xfs_initxattrs( | 64 | xfs_initxattrs( |
53 | struct inode *inode, | 65 | struct inode *inode, |
@@ -1191,6 +1203,7 @@ xfs_setup_inode( | |||
1191 | xfs_diflags_to_iflags(inode, ip); | 1203 | xfs_diflags_to_iflags(inode, ip); |
1192 | 1204 | ||
1193 | ip->d_ops = ip->i_mount->m_nondir_inode_ops; | 1205 | ip->d_ops = ip->i_mount->m_nondir_inode_ops; |
1206 | lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class); | ||
1194 | switch (inode->i_mode & S_IFMT) { | 1207 | switch (inode->i_mode & S_IFMT) { |
1195 | case S_IFREG: | 1208 | case S_IFREG: |
1196 | inode->i_op = &xfs_inode_operations; | 1209 | inode->i_op = &xfs_inode_operations; |
@@ -1198,6 +1211,7 @@ xfs_setup_inode( | |||
1198 | inode->i_mapping->a_ops = &xfs_address_space_operations; | 1211 | inode->i_mapping->a_ops = &xfs_address_space_operations; |
1199 | break; | 1212 | break; |
1200 | case S_IFDIR: | 1213 | case S_IFDIR: |
1214 | lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class); | ||
1201 | if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) | 1215 | if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) |
1202 | inode->i_op = &xfs_dir_ci_inode_operations; | 1216 | inode->i_op = &xfs_dir_ci_inode_operations; |
1203 | else | 1217 | else |
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index b57a8e08b3d1..7e5455391176 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -499,13 +499,6 @@ xlog_cil_push( | |||
499 | cil->xc_ctx = new_ctx; | 499 | cil->xc_ctx = new_ctx; |
500 | 500 | ||
501 | /* | 501 | /* |
502 | * mirror the new sequence into the cil structure so that we can do | ||
503 | * unlocked checks against the current sequence in log forces without | ||
504 | * risking deferencing a freed context pointer. | ||
505 | */ | ||
506 | cil->xc_current_sequence = new_ctx->sequence; | ||
507 | |||
508 | /* | ||
509 | * The switch is now done, so we can drop the context lock and move out | 502 | * The switch is now done, so we can drop the context lock and move out |
510 | * of a shared context. We can't just go straight to the commit record, | 503 | * of a shared context. We can't just go straight to the commit record, |
511 | * though - we need to synchronise with previous and future commits so | 504 | * though - we need to synchronise with previous and future commits so |
@@ -523,8 +516,15 @@ xlog_cil_push( | |||
523 | * Hence we need to add this context to the committing context list so | 516 | * Hence we need to add this context to the committing context list so |
524 | * that higher sequences will wait for us to write out a commit record | 517 | * that higher sequences will wait for us to write out a commit record |
525 | * before they do. | 518 | * before they do. |
519 | * | ||
520 | * xfs_log_force_lsn requires us to mirror the new sequence into the cil | ||
521 | * structure atomically with the addition of this sequence to the | ||
522 | * committing list. This also ensures that we can do unlocked checks | ||
523 | * against the current sequence in log forces without risking | ||
524 | * deferencing a freed context pointer. | ||
526 | */ | 525 | */ |
527 | spin_lock(&cil->xc_push_lock); | 526 | spin_lock(&cil->xc_push_lock); |
527 | cil->xc_current_sequence = new_ctx->sequence; | ||
528 | list_add(&ctx->committing, &cil->xc_committing); | 528 | list_add(&ctx->committing, &cil->xc_committing); |
529 | spin_unlock(&cil->xc_push_lock); | 529 | spin_unlock(&cil->xc_push_lock); |
530 | up_write(&cil->xc_ctx_lock); | 530 | up_write(&cil->xc_ctx_lock); |
@@ -662,8 +662,14 @@ xlog_cil_push_background( | |||
662 | 662 | ||
663 | } | 663 | } |
664 | 664 | ||
665 | /* | ||
666 | * xlog_cil_push_now() is used to trigger an immediate CIL push to the sequence | ||
667 | * number that is passed. When it returns, the work will be queued for | ||
668 | * @push_seq, but it won't be completed. The caller is expected to do any | ||
669 | * waiting for push_seq to complete if it is required. | ||
670 | */ | ||
665 | static void | 671 | static void |
666 | xlog_cil_push_foreground( | 672 | xlog_cil_push_now( |
667 | struct xlog *log, | 673 | struct xlog *log, |
668 | xfs_lsn_t push_seq) | 674 | xfs_lsn_t push_seq) |
669 | { | 675 | { |
@@ -688,10 +694,8 @@ xlog_cil_push_foreground( | |||
688 | } | 694 | } |
689 | 695 | ||
690 | cil->xc_push_seq = push_seq; | 696 | cil->xc_push_seq = push_seq; |
697 | queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work); | ||
691 | spin_unlock(&cil->xc_push_lock); | 698 | spin_unlock(&cil->xc_push_lock); |
692 | |||
693 | /* do the push now */ | ||
694 | xlog_cil_push(log); | ||
695 | } | 699 | } |
696 | 700 | ||
697 | bool | 701 | bool |
@@ -795,7 +799,8 @@ xlog_cil_force_lsn( | |||
795 | * xlog_cil_push() handles racing pushes for the same sequence, | 799 | * xlog_cil_push() handles racing pushes for the same sequence, |
796 | * so no need to deal with it here. | 800 | * so no need to deal with it here. |
797 | */ | 801 | */ |
798 | xlog_cil_push_foreground(log, sequence); | 802 | restart: |
803 | xlog_cil_push_now(log, sequence); | ||
799 | 804 | ||
800 | /* | 805 | /* |
801 | * See if we can find a previous sequence still committing. | 806 | * See if we can find a previous sequence still committing. |
@@ -803,7 +808,6 @@ xlog_cil_force_lsn( | |||
803 | * before allowing the force of push_seq to go ahead. Hence block | 808 | * before allowing the force of push_seq to go ahead. Hence block |
804 | * on commits for those as well. | 809 | * on commits for those as well. |
805 | */ | 810 | */ |
806 | restart: | ||
807 | spin_lock(&cil->xc_push_lock); | 811 | spin_lock(&cil->xc_push_lock); |
808 | list_for_each_entry(ctx, &cil->xc_committing, committing) { | 812 | list_for_each_entry(ctx, &cil->xc_committing, committing) { |
809 | if (ctx->sequence > sequence) | 813 | if (ctx->sequence > sequence) |
@@ -821,6 +825,28 @@ restart: | |||
821 | /* found it! */ | 825 | /* found it! */ |
822 | commit_lsn = ctx->commit_lsn; | 826 | commit_lsn = ctx->commit_lsn; |
823 | } | 827 | } |
828 | |||
829 | /* | ||
830 | * The call to xlog_cil_push_now() executes the push in the background. | ||
831 | * Hence by the time we have got here it our sequence may not have been | ||
832 | * pushed yet. This is true if the current sequence still matches the | ||
833 | * push sequence after the above wait loop and the CIL still contains | ||
834 | * dirty objects. | ||
835 | * | ||
836 | * When the push occurs, it will empty the CIL and | ||
837 | * atomically increment the currect sequence past the push sequence and | ||
838 | * move it into the committing list. Of course, if the CIL is clean at | ||
839 | * the time of the push, it won't have pushed the CIL at all, so in that | ||
840 | * case we should try the push for this sequence again from the start | ||
841 | * just in case. | ||
842 | */ | ||
843 | |||
844 | if (sequence == cil->xc_current_sequence && | ||
845 | !list_empty(&cil->xc_cil)) { | ||
846 | spin_unlock(&cil->xc_push_lock); | ||
847 | goto restart; | ||
848 | } | ||
849 | |||
824 | spin_unlock(&cil->xc_push_lock); | 850 | spin_unlock(&cil->xc_push_lock); |
825 | return commit_lsn; | 851 | return commit_lsn; |
826 | } | 852 | } |