diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_super.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 293 |
1 files changed, 128 insertions, 165 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 9731898083ae..b38e58d02299 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -173,6 +173,15 @@ xfs_parseargs( | |||
173 | __uint8_t iosizelog = 0; | 173 | __uint8_t iosizelog = 0; |
174 | 174 | ||
175 | /* | 175 | /* |
176 | * set up the mount name first so all the errors will refer to the | ||
177 | * correct device. | ||
178 | */ | ||
179 | mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); | ||
180 | if (!mp->m_fsname) | ||
181 | return ENOMEM; | ||
182 | mp->m_fsname_len = strlen(mp->m_fsname) + 1; | ||
183 | |||
184 | /* | ||
176 | * Copy binary VFS mount flags we are interested in. | 185 | * Copy binary VFS mount flags we are interested in. |
177 | */ | 186 | */ |
178 | if (sb->s_flags & MS_RDONLY) | 187 | if (sb->s_flags & MS_RDONLY) |
@@ -189,6 +198,7 @@ xfs_parseargs( | |||
189 | mp->m_flags |= XFS_MOUNT_BARRIER; | 198 | mp->m_flags |= XFS_MOUNT_BARRIER; |
190 | mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; | 199 | mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; |
191 | mp->m_flags |= XFS_MOUNT_SMALL_INUMS; | 200 | mp->m_flags |= XFS_MOUNT_SMALL_INUMS; |
201 | mp->m_flags |= XFS_MOUNT_DELAYLOG; | ||
192 | 202 | ||
193 | /* | 203 | /* |
194 | * These can be overridden by the mount option parsing. | 204 | * These can be overridden by the mount option parsing. |
@@ -207,24 +217,21 @@ xfs_parseargs( | |||
207 | 217 | ||
208 | if (!strcmp(this_char, MNTOPT_LOGBUFS)) { | 218 | if (!strcmp(this_char, MNTOPT_LOGBUFS)) { |
209 | if (!value || !*value) { | 219 | if (!value || !*value) { |
210 | cmn_err(CE_WARN, | 220 | xfs_warn(mp, "%s option requires an argument", |
211 | "XFS: %s option requires an argument", | ||
212 | this_char); | 221 | this_char); |
213 | return EINVAL; | 222 | return EINVAL; |
214 | } | 223 | } |
215 | mp->m_logbufs = simple_strtoul(value, &eov, 10); | 224 | mp->m_logbufs = simple_strtoul(value, &eov, 10); |
216 | } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { | 225 | } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { |
217 | if (!value || !*value) { | 226 | if (!value || !*value) { |
218 | cmn_err(CE_WARN, | 227 | xfs_warn(mp, "%s option requires an argument", |
219 | "XFS: %s option requires an argument", | ||
220 | this_char); | 228 | this_char); |
221 | return EINVAL; | 229 | return EINVAL; |
222 | } | 230 | } |
223 | mp->m_logbsize = suffix_strtoul(value, &eov, 10); | 231 | mp->m_logbsize = suffix_strtoul(value, &eov, 10); |
224 | } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { | 232 | } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { |
225 | if (!value || !*value) { | 233 | if (!value || !*value) { |
226 | cmn_err(CE_WARN, | 234 | xfs_warn(mp, "%s option requires an argument", |
227 | "XFS: %s option requires an argument", | ||
228 | this_char); | 235 | this_char); |
229 | return EINVAL; | 236 | return EINVAL; |
230 | } | 237 | } |
@@ -232,14 +239,12 @@ xfs_parseargs( | |||
232 | if (!mp->m_logname) | 239 | if (!mp->m_logname) |
233 | return ENOMEM; | 240 | return ENOMEM; |
234 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { | 241 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { |
235 | cmn_err(CE_WARN, | 242 | xfs_warn(mp, "%s option not allowed on this system", |
236 | "XFS: %s option not allowed on this system", | ||
237 | this_char); | 243 | this_char); |
238 | return EINVAL; | 244 | return EINVAL; |
239 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { | 245 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { |
240 | if (!value || !*value) { | 246 | if (!value || !*value) { |
241 | cmn_err(CE_WARN, | 247 | xfs_warn(mp, "%s option requires an argument", |
242 | "XFS: %s option requires an argument", | ||
243 | this_char); | 248 | this_char); |
244 | return EINVAL; | 249 | return EINVAL; |
245 | } | 250 | } |
@@ -248,8 +253,7 @@ xfs_parseargs( | |||
248 | return ENOMEM; | 253 | return ENOMEM; |
249 | } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { | 254 | } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { |
250 | if (!value || !*value) { | 255 | if (!value || !*value) { |
251 | cmn_err(CE_WARN, | 256 | xfs_warn(mp, "%s option requires an argument", |
252 | "XFS: %s option requires an argument", | ||
253 | this_char); | 257 | this_char); |
254 | return EINVAL; | 258 | return EINVAL; |
255 | } | 259 | } |
@@ -257,8 +261,7 @@ xfs_parseargs( | |||
257 | iosizelog = ffs(iosize) - 1; | 261 | iosizelog = ffs(iosize) - 1; |
258 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { | 262 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { |
259 | if (!value || !*value) { | 263 | if (!value || !*value) { |
260 | cmn_err(CE_WARN, | 264 | xfs_warn(mp, "%s option requires an argument", |
261 | "XFS: %s option requires an argument", | ||
262 | this_char); | 265 | this_char); |
263 | return EINVAL; | 266 | return EINVAL; |
264 | } | 267 | } |
@@ -280,16 +283,14 @@ xfs_parseargs( | |||
280 | mp->m_flags |= XFS_MOUNT_SWALLOC; | 283 | mp->m_flags |= XFS_MOUNT_SWALLOC; |
281 | } else if (!strcmp(this_char, MNTOPT_SUNIT)) { | 284 | } else if (!strcmp(this_char, MNTOPT_SUNIT)) { |
282 | if (!value || !*value) { | 285 | if (!value || !*value) { |
283 | cmn_err(CE_WARN, | 286 | xfs_warn(mp, "%s option requires an argument", |
284 | "XFS: %s option requires an argument", | ||
285 | this_char); | 287 | this_char); |
286 | return EINVAL; | 288 | return EINVAL; |
287 | } | 289 | } |
288 | dsunit = simple_strtoul(value, &eov, 10); | 290 | dsunit = simple_strtoul(value, &eov, 10); |
289 | } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { | 291 | } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { |
290 | if (!value || !*value) { | 292 | if (!value || !*value) { |
291 | cmn_err(CE_WARN, | 293 | xfs_warn(mp, "%s option requires an argument", |
292 | "XFS: %s option requires an argument", | ||
293 | this_char); | 294 | this_char); |
294 | return EINVAL; | 295 | return EINVAL; |
295 | } | 296 | } |
@@ -297,8 +298,7 @@ xfs_parseargs( | |||
297 | } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { | 298 | } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { |
298 | mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS; | 299 | mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS; |
299 | #if !XFS_BIG_INUMS | 300 | #if !XFS_BIG_INUMS |
300 | cmn_err(CE_WARN, | 301 | xfs_warn(mp, "%s option not allowed on this system", |
301 | "XFS: %s option not allowed on this system", | ||
302 | this_char); | 302 | this_char); |
303 | return EINVAL; | 303 | return EINVAL; |
304 | #endif | 304 | #endif |
@@ -356,20 +356,19 @@ xfs_parseargs( | |||
356 | } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) { | 356 | } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) { |
357 | mp->m_flags &= ~XFS_MOUNT_DELAYLOG; | 357 | mp->m_flags &= ~XFS_MOUNT_DELAYLOG; |
358 | } else if (!strcmp(this_char, "ihashsize")) { | 358 | } else if (!strcmp(this_char, "ihashsize")) { |
359 | cmn_err(CE_WARN, | 359 | xfs_warn(mp, |
360 | "XFS: ihashsize no longer used, option is deprecated."); | 360 | "ihashsize no longer used, option is deprecated."); |
361 | } else if (!strcmp(this_char, "osyncisdsync")) { | 361 | } else if (!strcmp(this_char, "osyncisdsync")) { |
362 | cmn_err(CE_WARN, | 362 | xfs_warn(mp, |
363 | "XFS: osyncisdsync has no effect, option is deprecated."); | 363 | "osyncisdsync has no effect, option is deprecated."); |
364 | } else if (!strcmp(this_char, "osyncisosync")) { | 364 | } else if (!strcmp(this_char, "osyncisosync")) { |
365 | cmn_err(CE_WARN, | 365 | xfs_warn(mp, |
366 | "XFS: osyncisosync has no effect, option is deprecated."); | 366 | "osyncisosync has no effect, option is deprecated."); |
367 | } else if (!strcmp(this_char, "irixsgid")) { | 367 | } else if (!strcmp(this_char, "irixsgid")) { |
368 | cmn_err(CE_WARN, | 368 | xfs_warn(mp, |
369 | "XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); | 369 | "irixsgid is now a sysctl(2) variable, option is deprecated."); |
370 | } else { | 370 | } else { |
371 | cmn_err(CE_WARN, | 371 | xfs_warn(mp, "unknown mount option [%s].", this_char); |
372 | "XFS: unknown mount option [%s].", this_char); | ||
373 | return EINVAL; | 372 | return EINVAL; |
374 | } | 373 | } |
375 | } | 374 | } |
@@ -379,40 +378,37 @@ xfs_parseargs( | |||
379 | */ | 378 | */ |
380 | if ((mp->m_flags & XFS_MOUNT_NORECOVERY) && | 379 | if ((mp->m_flags & XFS_MOUNT_NORECOVERY) && |
381 | !(mp->m_flags & XFS_MOUNT_RDONLY)) { | 380 | !(mp->m_flags & XFS_MOUNT_RDONLY)) { |
382 | cmn_err(CE_WARN, "XFS: no-recovery mounts must be read-only."); | 381 | xfs_warn(mp, "no-recovery mounts must be read-only."); |
383 | return EINVAL; | 382 | return EINVAL; |
384 | } | 383 | } |
385 | 384 | ||
386 | if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) { | 385 | if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) { |
387 | cmn_err(CE_WARN, | 386 | xfs_warn(mp, |
388 | "XFS: sunit and swidth options incompatible with the noalign option"); | 387 | "sunit and swidth options incompatible with the noalign option"); |
389 | return EINVAL; | 388 | return EINVAL; |
390 | } | 389 | } |
391 | 390 | ||
392 | #ifndef CONFIG_XFS_QUOTA | 391 | #ifndef CONFIG_XFS_QUOTA |
393 | if (XFS_IS_QUOTA_RUNNING(mp)) { | 392 | if (XFS_IS_QUOTA_RUNNING(mp)) { |
394 | cmn_err(CE_WARN, | 393 | xfs_warn(mp, "quota support not available in this kernel."); |
395 | "XFS: quota support not available in this kernel."); | ||
396 | return EINVAL; | 394 | return EINVAL; |
397 | } | 395 | } |
398 | #endif | 396 | #endif |
399 | 397 | ||
400 | if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) && | 398 | if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) && |
401 | (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) { | 399 | (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) { |
402 | cmn_err(CE_WARN, | 400 | xfs_warn(mp, "cannot mount with both project and group quota"); |
403 | "XFS: cannot mount with both project and group quota"); | ||
404 | return EINVAL; | 401 | return EINVAL; |
405 | } | 402 | } |
406 | 403 | ||
407 | if ((dsunit && !dswidth) || (!dsunit && dswidth)) { | 404 | if ((dsunit && !dswidth) || (!dsunit && dswidth)) { |
408 | cmn_err(CE_WARN, | 405 | xfs_warn(mp, "sunit and swidth must be specified together"); |
409 | "XFS: sunit and swidth must be specified together"); | ||
410 | return EINVAL; | 406 | return EINVAL; |
411 | } | 407 | } |
412 | 408 | ||
413 | if (dsunit && (dswidth % dsunit != 0)) { | 409 | if (dsunit && (dswidth % dsunit != 0)) { |
414 | cmn_err(CE_WARN, | 410 | xfs_warn(mp, |
415 | "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)", | 411 | "stripe width (%d) must be a multiple of the stripe unit (%d)", |
416 | dswidth, dsunit); | 412 | dswidth, dsunit); |
417 | return EINVAL; | 413 | return EINVAL; |
418 | } | 414 | } |
@@ -438,8 +434,7 @@ done: | |||
438 | mp->m_logbufs != 0 && | 434 | mp->m_logbufs != 0 && |
439 | (mp->m_logbufs < XLOG_MIN_ICLOGS || | 435 | (mp->m_logbufs < XLOG_MIN_ICLOGS || |
440 | mp->m_logbufs > XLOG_MAX_ICLOGS)) { | 436 | mp->m_logbufs > XLOG_MAX_ICLOGS)) { |
441 | cmn_err(CE_WARN, | 437 | xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]", |
442 | "XFS: invalid logbufs value: %d [not %d-%d]", | ||
443 | mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS); | 438 | mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS); |
444 | return XFS_ERROR(EINVAL); | 439 | return XFS_ERROR(EINVAL); |
445 | } | 440 | } |
@@ -448,22 +443,16 @@ done: | |||
448 | (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE || | 443 | (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE || |
449 | mp->m_logbsize > XLOG_MAX_RECORD_BSIZE || | 444 | mp->m_logbsize > XLOG_MAX_RECORD_BSIZE || |
450 | !is_power_of_2(mp->m_logbsize))) { | 445 | !is_power_of_2(mp->m_logbsize))) { |
451 | cmn_err(CE_WARN, | 446 | xfs_warn(mp, |
452 | "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", | 447 | "invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", |
453 | mp->m_logbsize); | 448 | mp->m_logbsize); |
454 | return XFS_ERROR(EINVAL); | 449 | return XFS_ERROR(EINVAL); |
455 | } | 450 | } |
456 | 451 | ||
457 | mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); | ||
458 | if (!mp->m_fsname) | ||
459 | return ENOMEM; | ||
460 | mp->m_fsname_len = strlen(mp->m_fsname) + 1; | ||
461 | |||
462 | if (iosizelog) { | 452 | if (iosizelog) { |
463 | if (iosizelog > XFS_MAX_IO_LOG || | 453 | if (iosizelog > XFS_MAX_IO_LOG || |
464 | iosizelog < XFS_MIN_IO_LOG) { | 454 | iosizelog < XFS_MIN_IO_LOG) { |
465 | cmn_err(CE_WARN, | 455 | xfs_warn(mp, "invalid log iosize: %d [not %d-%d]", |
466 | "XFS: invalid log iosize: %d [not %d-%d]", | ||
467 | iosizelog, XFS_MIN_IO_LOG, | 456 | iosizelog, XFS_MIN_IO_LOG, |
468 | XFS_MAX_IO_LOG); | 457 | XFS_MAX_IO_LOG); |
469 | return XFS_ERROR(EINVAL); | 458 | return XFS_ERROR(EINVAL); |
@@ -610,7 +599,7 @@ xfs_blkdev_get( | |||
610 | mp); | 599 | mp); |
611 | if (IS_ERR(*bdevp)) { | 600 | if (IS_ERR(*bdevp)) { |
612 | error = PTR_ERR(*bdevp); | 601 | error = PTR_ERR(*bdevp); |
613 | printk("XFS: Invalid device [%s], error=%d\n", name, error); | 602 | xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error); |
614 | } | 603 | } |
615 | 604 | ||
616 | return -error; | 605 | return -error; |
@@ -664,23 +653,23 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp) | |||
664 | int error; | 653 | int error; |
665 | 654 | ||
666 | if (mp->m_logdev_targp != mp->m_ddev_targp) { | 655 | if (mp->m_logdev_targp != mp->m_ddev_targp) { |
667 | xfs_fs_cmn_err(CE_NOTE, mp, | 656 | xfs_notice(mp, |
668 | "Disabling barriers, not supported with external log device"); | 657 | "Disabling barriers, not supported with external log device"); |
669 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 658 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
670 | return; | 659 | return; |
671 | } | 660 | } |
672 | 661 | ||
673 | if (xfs_readonly_buftarg(mp->m_ddev_targp)) { | 662 | if (xfs_readonly_buftarg(mp->m_ddev_targp)) { |
674 | xfs_fs_cmn_err(CE_NOTE, mp, | 663 | xfs_notice(mp, |
675 | "Disabling barriers, underlying device is readonly"); | 664 | "Disabling barriers, underlying device is readonly"); |
676 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 665 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
677 | return; | 666 | return; |
678 | } | 667 | } |
679 | 668 | ||
680 | error = xfs_barrier_test(mp); | 669 | error = xfs_barrier_test(mp); |
681 | if (error) { | 670 | if (error) { |
682 | xfs_fs_cmn_err(CE_NOTE, mp, | 671 | xfs_notice(mp, |
683 | "Disabling barriers, trial barrier write failed"); | 672 | "Disabling barriers, trial barrier write failed"); |
684 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 673 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
685 | return; | 674 | return; |
686 | } | 675 | } |
@@ -743,8 +732,8 @@ xfs_open_devices( | |||
743 | goto out_close_logdev; | 732 | goto out_close_logdev; |
744 | 733 | ||
745 | if (rtdev == ddev || rtdev == logdev) { | 734 | if (rtdev == ddev || rtdev == logdev) { |
746 | cmn_err(CE_WARN, | 735 | xfs_warn(mp, |
747 | "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); | 736 | "Cannot mount filesystem with identical rtdev and ddev/logdev."); |
748 | error = EINVAL; | 737 | error = EINVAL; |
749 | goto out_close_rtdev; | 738 | goto out_close_rtdev; |
750 | } | 739 | } |
@@ -827,75 +816,6 @@ xfs_setup_devices( | |||
827 | return 0; | 816 | return 0; |
828 | } | 817 | } |
829 | 818 | ||
830 | /* | ||
831 | * XFS AIL push thread support | ||
832 | */ | ||
833 | void | ||
834 | xfsaild_wakeup( | ||
835 | struct xfs_ail *ailp, | ||
836 | xfs_lsn_t threshold_lsn) | ||
837 | { | ||
838 | /* only ever move the target forwards */ | ||
839 | if (XFS_LSN_CMP(threshold_lsn, ailp->xa_target) > 0) { | ||
840 | ailp->xa_target = threshold_lsn; | ||
841 | wake_up_process(ailp->xa_task); | ||
842 | } | ||
843 | } | ||
844 | |||
845 | STATIC int | ||
846 | xfsaild( | ||
847 | void *data) | ||
848 | { | ||
849 | struct xfs_ail *ailp = data; | ||
850 | xfs_lsn_t last_pushed_lsn = 0; | ||
851 | long tout = 0; /* milliseconds */ | ||
852 | |||
853 | while (!kthread_should_stop()) { | ||
854 | /* | ||
855 | * for short sleeps indicating congestion, don't allow us to | ||
856 | * get woken early. Otherwise all we do is bang on the AIL lock | ||
857 | * without making progress. | ||
858 | */ | ||
859 | if (tout && tout <= 20) | ||
860 | __set_current_state(TASK_KILLABLE); | ||
861 | else | ||
862 | __set_current_state(TASK_INTERRUPTIBLE); | ||
863 | schedule_timeout(tout ? | ||
864 | msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT); | ||
865 | |||
866 | /* swsusp */ | ||
867 | try_to_freeze(); | ||
868 | |||
869 | ASSERT(ailp->xa_mount->m_log); | ||
870 | if (XFS_FORCED_SHUTDOWN(ailp->xa_mount)) | ||
871 | continue; | ||
872 | |||
873 | tout = xfsaild_push(ailp, &last_pushed_lsn); | ||
874 | } | ||
875 | |||
876 | return 0; | ||
877 | } /* xfsaild */ | ||
878 | |||
879 | int | ||
880 | xfsaild_start( | ||
881 | struct xfs_ail *ailp) | ||
882 | { | ||
883 | ailp->xa_target = 0; | ||
884 | ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s", | ||
885 | ailp->xa_mount->m_fsname); | ||
886 | if (IS_ERR(ailp->xa_task)) | ||
887 | return -PTR_ERR(ailp->xa_task); | ||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | void | ||
892 | xfsaild_stop( | ||
893 | struct xfs_ail *ailp) | ||
894 | { | ||
895 | kthread_stop(ailp->xa_task); | ||
896 | } | ||
897 | |||
898 | |||
899 | /* Catch misguided souls that try to use this interface on XFS */ | 819 | /* Catch misguided souls that try to use this interface on XFS */ |
900 | STATIC struct inode * | 820 | STATIC struct inode * |
901 | xfs_fs_alloc_inode( | 821 | xfs_fs_alloc_inode( |
@@ -1089,7 +1009,7 @@ xfs_fs_write_inode( | |||
1089 | error = 0; | 1009 | error = 0; |
1090 | goto out_unlock; | 1010 | goto out_unlock; |
1091 | } | 1011 | } |
1092 | error = xfs_iflush(ip, 0); | 1012 | error = xfs_iflush(ip, SYNC_TRYLOCK); |
1093 | } | 1013 | } |
1094 | 1014 | ||
1095 | out_unlock: | 1015 | out_unlock: |
@@ -1202,22 +1122,12 @@ xfs_fs_sync_fs( | |||
1202 | return -error; | 1122 | return -error; |
1203 | 1123 | ||
1204 | if (laptop_mode) { | 1124 | if (laptop_mode) { |
1205 | int prev_sync_seq = mp->m_sync_seq; | ||
1206 | |||
1207 | /* | 1125 | /* |
1208 | * The disk must be active because we're syncing. | 1126 | * The disk must be active because we're syncing. |
1209 | * We schedule xfssyncd now (now that the disk is | 1127 | * We schedule xfssyncd now (now that the disk is |
1210 | * active) instead of later (when it might not be). | 1128 | * active) instead of later (when it might not be). |
1211 | */ | 1129 | */ |
1212 | wake_up_process(mp->m_sync_task); | 1130 | flush_delayed_work_sync(&mp->m_sync_work); |
1213 | /* | ||
1214 | * We have to wait for the sync iteration to complete. | ||
1215 | * If we don't, the disk activity caused by the sync | ||
1216 | * will come after the sync is completed, and that | ||
1217 | * triggers another sync from laptop mode. | ||
1218 | */ | ||
1219 | wait_event(mp->m_wait_single_sync_task, | ||
1220 | mp->m_sync_seq != prev_sync_seq); | ||
1221 | } | 1131 | } |
1222 | 1132 | ||
1223 | return 0; | 1133 | return 0; |
@@ -1345,8 +1255,8 @@ xfs_fs_remount( | |||
1345 | * options that we can't actually change. | 1255 | * options that we can't actually change. |
1346 | */ | 1256 | */ |
1347 | #if 0 | 1257 | #if 0 |
1348 | printk(KERN_INFO | 1258 | xfs_info(mp, |
1349 | "XFS: mount option \"%s\" not supported for remount\n", p); | 1259 | "mount option \"%s\" not supported for remount\n", p); |
1350 | return -EINVAL; | 1260 | return -EINVAL; |
1351 | #else | 1261 | #else |
1352 | break; | 1262 | break; |
@@ -1367,8 +1277,7 @@ xfs_fs_remount( | |||
1367 | if (mp->m_update_flags) { | 1277 | if (mp->m_update_flags) { |
1368 | error = xfs_mount_log_sb(mp, mp->m_update_flags); | 1278 | error = xfs_mount_log_sb(mp, mp->m_update_flags); |
1369 | if (error) { | 1279 | if (error) { |
1370 | cmn_err(CE_WARN, | 1280 | xfs_warn(mp, "failed to write sb changes"); |
1371 | "XFS: failed to write sb changes"); | ||
1372 | return error; | 1281 | return error; |
1373 | } | 1282 | } |
1374 | mp->m_update_flags = 0; | 1283 | mp->m_update_flags = 0; |
@@ -1452,15 +1361,15 @@ xfs_finish_flags( | |||
1452 | mp->m_logbsize = mp->m_sb.sb_logsunit; | 1361 | mp->m_logbsize = mp->m_sb.sb_logsunit; |
1453 | } else if (mp->m_logbsize > 0 && | 1362 | } else if (mp->m_logbsize > 0 && |
1454 | mp->m_logbsize < mp->m_sb.sb_logsunit) { | 1363 | mp->m_logbsize < mp->m_sb.sb_logsunit) { |
1455 | cmn_err(CE_WARN, | 1364 | xfs_warn(mp, |
1456 | "XFS: logbuf size must be greater than or equal to log stripe size"); | 1365 | "logbuf size must be greater than or equal to log stripe size"); |
1457 | return XFS_ERROR(EINVAL); | 1366 | return XFS_ERROR(EINVAL); |
1458 | } | 1367 | } |
1459 | } else { | 1368 | } else { |
1460 | /* Fail a mount if the logbuf is larger than 32K */ | 1369 | /* Fail a mount if the logbuf is larger than 32K */ |
1461 | if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) { | 1370 | if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) { |
1462 | cmn_err(CE_WARN, | 1371 | xfs_warn(mp, |
1463 | "XFS: logbuf size for version 1 logs must be 16K or 32K"); | 1372 | "logbuf size for version 1 logs must be 16K or 32K"); |
1464 | return XFS_ERROR(EINVAL); | 1373 | return XFS_ERROR(EINVAL); |
1465 | } | 1374 | } |
1466 | } | 1375 | } |
@@ -1477,8 +1386,8 @@ xfs_finish_flags( | |||
1477 | * prohibit r/w mounts of read-only filesystems | 1386 | * prohibit r/w mounts of read-only filesystems |
1478 | */ | 1387 | */ |
1479 | if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) { | 1388 | if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) { |
1480 | cmn_err(CE_WARN, | 1389 | xfs_warn(mp, |
1481 | "XFS: cannot mount a read-only filesystem as read-write"); | 1390 | "cannot mount a read-only filesystem as read-write"); |
1482 | return XFS_ERROR(EROFS); | 1391 | return XFS_ERROR(EROFS); |
1483 | } | 1392 | } |
1484 | 1393 | ||
@@ -1502,9 +1411,6 @@ xfs_fs_fill_super( | |||
1502 | spin_lock_init(&mp->m_sb_lock); | 1411 | spin_lock_init(&mp->m_sb_lock); |
1503 | mutex_init(&mp->m_growlock); | 1412 | mutex_init(&mp->m_growlock); |
1504 | atomic_set(&mp->m_active_trans, 0); | 1413 | atomic_set(&mp->m_active_trans, 0); |
1505 | INIT_LIST_HEAD(&mp->m_sync_list); | ||
1506 | spin_lock_init(&mp->m_sync_lock); | ||
1507 | init_waitqueue_head(&mp->m_wait_single_sync_task); | ||
1508 | 1414 | ||
1509 | mp->m_super = sb; | 1415 | mp->m_super = sb; |
1510 | sb->s_fs_info = mp; | 1416 | sb->s_fs_info = mp; |
@@ -1551,10 +1457,14 @@ xfs_fs_fill_super( | |||
1551 | if (error) | 1457 | if (error) |
1552 | goto out_free_sb; | 1458 | goto out_free_sb; |
1553 | 1459 | ||
1554 | error = xfs_mountfs(mp); | 1460 | /* |
1555 | if (error) | 1461 | * we must configure the block size in the superblock before we run the |
1556 | goto out_filestream_unmount; | 1462 | * full mount process as the mount process can lookup and cache inodes. |
1557 | 1463 | * For the same reason we must also initialise the syncd and register | |
1464 | * the inode cache shrinker so that inodes can be reclaimed during | ||
1465 | * operations like a quotacheck that iterate all inodes in the | ||
1466 | * filesystem. | ||
1467 | */ | ||
1558 | sb->s_magic = XFS_SB_MAGIC; | 1468 | sb->s_magic = XFS_SB_MAGIC; |
1559 | sb->s_blocksize = mp->m_sb.sb_blocksize; | 1469 | sb->s_blocksize = mp->m_sb.sb_blocksize; |
1560 | sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1; | 1470 | sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1; |
@@ -1562,6 +1472,16 @@ xfs_fs_fill_super( | |||
1562 | sb->s_time_gran = 1; | 1472 | sb->s_time_gran = 1; |
1563 | set_posix_acl_flag(sb); | 1473 | set_posix_acl_flag(sb); |
1564 | 1474 | ||
1475 | error = xfs_syncd_init(mp); | ||
1476 | if (error) | ||
1477 | goto out_filestream_unmount; | ||
1478 | |||
1479 | xfs_inode_shrinker_register(mp); | ||
1480 | |||
1481 | error = xfs_mountfs(mp); | ||
1482 | if (error) | ||
1483 | goto out_syncd_stop; | ||
1484 | |||
1565 | root = igrab(VFS_I(mp->m_rootip)); | 1485 | root = igrab(VFS_I(mp->m_rootip)); |
1566 | if (!root) { | 1486 | if (!root) { |
1567 | error = ENOENT; | 1487 | error = ENOENT; |
@@ -1577,14 +1497,11 @@ xfs_fs_fill_super( | |||
1577 | goto fail_vnrele; | 1497 | goto fail_vnrele; |
1578 | } | 1498 | } |
1579 | 1499 | ||
1580 | error = xfs_syncd_init(mp); | ||
1581 | if (error) | ||
1582 | goto fail_vnrele; | ||
1583 | |||
1584 | xfs_inode_shrinker_register(mp); | ||
1585 | |||
1586 | return 0; | 1500 | return 0; |
1587 | 1501 | ||
1502 | out_syncd_stop: | ||
1503 | xfs_inode_shrinker_unregister(mp); | ||
1504 | xfs_syncd_stop(mp); | ||
1588 | out_filestream_unmount: | 1505 | out_filestream_unmount: |
1589 | xfs_filestream_unmount(mp); | 1506 | xfs_filestream_unmount(mp); |
1590 | out_free_sb: | 1507 | out_free_sb: |
@@ -1608,6 +1525,9 @@ xfs_fs_fill_super( | |||
1608 | } | 1525 | } |
1609 | 1526 | ||
1610 | fail_unmount: | 1527 | fail_unmount: |
1528 | xfs_inode_shrinker_unregister(mp); | ||
1529 | xfs_syncd_stop(mp); | ||
1530 | |||
1611 | /* | 1531 | /* |
1612 | * Blow away any referenced inode in the filestreams cache. | 1532 | * Blow away any referenced inode in the filestreams cache. |
1613 | * This can and will cause log traffic as inodes go inactive | 1533 | * This can and will cause log traffic as inodes go inactive |
@@ -1797,6 +1717,38 @@ xfs_destroy_zones(void) | |||
1797 | } | 1717 | } |
1798 | 1718 | ||
1799 | STATIC int __init | 1719 | STATIC int __init |
1720 | xfs_init_workqueues(void) | ||
1721 | { | ||
1722 | /* | ||
1723 | * max_active is set to 8 to give enough concurency to allow | ||
1724 | * multiple work operations on each CPU to run. This allows multiple | ||
1725 | * filesystems to be running sync work concurrently, and scales with | ||
1726 | * the number of CPUs in the system. | ||
1727 | */ | ||
1728 | xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8); | ||
1729 | if (!xfs_syncd_wq) | ||
1730 | goto out; | ||
1731 | |||
1732 | xfs_ail_wq = alloc_workqueue("xfsail", WQ_CPU_INTENSIVE, 8); | ||
1733 | if (!xfs_ail_wq) | ||
1734 | goto out_destroy_syncd; | ||
1735 | |||
1736 | return 0; | ||
1737 | |||
1738 | out_destroy_syncd: | ||
1739 | destroy_workqueue(xfs_syncd_wq); | ||
1740 | out: | ||
1741 | return -ENOMEM; | ||
1742 | } | ||
1743 | |||
1744 | STATIC void | ||
1745 | xfs_destroy_workqueues(void) | ||
1746 | { | ||
1747 | destroy_workqueue(xfs_ail_wq); | ||
1748 | destroy_workqueue(xfs_syncd_wq); | ||
1749 | } | ||
1750 | |||
1751 | STATIC int __init | ||
1800 | init_xfs_fs(void) | 1752 | init_xfs_fs(void) |
1801 | { | 1753 | { |
1802 | int error; | 1754 | int error; |
@@ -1811,10 +1763,14 @@ init_xfs_fs(void) | |||
1811 | if (error) | 1763 | if (error) |
1812 | goto out; | 1764 | goto out; |
1813 | 1765 | ||
1814 | error = xfs_mru_cache_init(); | 1766 | error = xfs_init_workqueues(); |
1815 | if (error) | 1767 | if (error) |
1816 | goto out_destroy_zones; | 1768 | goto out_destroy_zones; |
1817 | 1769 | ||
1770 | error = xfs_mru_cache_init(); | ||
1771 | if (error) | ||
1772 | goto out_destroy_wq; | ||
1773 | |||
1818 | error = xfs_filestream_init(); | 1774 | error = xfs_filestream_init(); |
1819 | if (error) | 1775 | if (error) |
1820 | goto out_mru_cache_uninit; | 1776 | goto out_mru_cache_uninit; |
@@ -1831,6 +1787,10 @@ init_xfs_fs(void) | |||
1831 | if (error) | 1787 | if (error) |
1832 | goto out_cleanup_procfs; | 1788 | goto out_cleanup_procfs; |
1833 | 1789 | ||
1790 | error = xfs_init_workqueues(); | ||
1791 | if (error) | ||
1792 | goto out_sysctl_unregister; | ||
1793 | |||
1834 | vfs_initquota(); | 1794 | vfs_initquota(); |
1835 | 1795 | ||
1836 | error = register_filesystem(&xfs_fs_type); | 1796 | error = register_filesystem(&xfs_fs_type); |
@@ -1848,6 +1808,8 @@ init_xfs_fs(void) | |||
1848 | xfs_filestream_uninit(); | 1808 | xfs_filestream_uninit(); |
1849 | out_mru_cache_uninit: | 1809 | out_mru_cache_uninit: |
1850 | xfs_mru_cache_uninit(); | 1810 | xfs_mru_cache_uninit(); |
1811 | out_destroy_wq: | ||
1812 | xfs_destroy_workqueues(); | ||
1851 | out_destroy_zones: | 1813 | out_destroy_zones: |
1852 | xfs_destroy_zones(); | 1814 | xfs_destroy_zones(); |
1853 | out: | 1815 | out: |
@@ -1864,6 +1826,7 @@ exit_xfs_fs(void) | |||
1864 | xfs_buf_terminate(); | 1826 | xfs_buf_terminate(); |
1865 | xfs_filestream_uninit(); | 1827 | xfs_filestream_uninit(); |
1866 | xfs_mru_cache_uninit(); | 1828 | xfs_mru_cache_uninit(); |
1829 | xfs_destroy_workqueues(); | ||
1867 | xfs_destroy_zones(); | 1830 | xfs_destroy_zones(); |
1868 | } | 1831 | } |
1869 | 1832 | ||