diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_super.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 166 |
1 files changed, 99 insertions, 67 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index f6dd7de25927..0da87bfc9999 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -70,11 +70,15 @@ | |||
70 | #include <linux/namei.h> | 70 | #include <linux/namei.h> |
71 | #include <linux/init.h> | 71 | #include <linux/init.h> |
72 | #include <linux/mount.h> | 72 | #include <linux/mount.h> |
73 | #include <linux/mempool.h> | ||
73 | #include <linux/writeback.h> | 74 | #include <linux/writeback.h> |
75 | #include <linux/kthread.h> | ||
74 | 76 | ||
75 | STATIC struct quotactl_ops linvfs_qops; | 77 | STATIC struct quotactl_ops linvfs_qops; |
76 | STATIC struct super_operations linvfs_sops; | 78 | STATIC struct super_operations linvfs_sops; |
77 | STATIC kmem_zone_t *linvfs_inode_zone; | 79 | STATIC kmem_zone_t *xfs_vnode_zone; |
80 | STATIC kmem_zone_t *xfs_ioend_zone; | ||
81 | mempool_t *xfs_ioend_pool; | ||
78 | 82 | ||
79 | STATIC struct xfs_mount_args * | 83 | STATIC struct xfs_mount_args * |
80 | xfs_args_allocate( | 84 | xfs_args_allocate( |
@@ -138,24 +142,25 @@ STATIC __inline__ void | |||
138 | xfs_set_inodeops( | 142 | xfs_set_inodeops( |
139 | struct inode *inode) | 143 | struct inode *inode) |
140 | { | 144 | { |
141 | vnode_t *vp = LINVFS_GET_VP(inode); | 145 | switch (inode->i_mode & S_IFMT) { |
142 | 146 | case S_IFREG: | |
143 | if (vp->v_type == VNON) { | ||
144 | vn_mark_bad(vp); | ||
145 | } else if (S_ISREG(inode->i_mode)) { | ||
146 | inode->i_op = &linvfs_file_inode_operations; | 147 | inode->i_op = &linvfs_file_inode_operations; |
147 | inode->i_fop = &linvfs_file_operations; | 148 | inode->i_fop = &linvfs_file_operations; |
148 | inode->i_mapping->a_ops = &linvfs_aops; | 149 | inode->i_mapping->a_ops = &linvfs_aops; |
149 | } else if (S_ISDIR(inode->i_mode)) { | 150 | break; |
151 | case S_IFDIR: | ||
150 | inode->i_op = &linvfs_dir_inode_operations; | 152 | inode->i_op = &linvfs_dir_inode_operations; |
151 | inode->i_fop = &linvfs_dir_operations; | 153 | inode->i_fop = &linvfs_dir_operations; |
152 | } else if (S_ISLNK(inode->i_mode)) { | 154 | break; |
155 | case S_IFLNK: | ||
153 | inode->i_op = &linvfs_symlink_inode_operations; | 156 | inode->i_op = &linvfs_symlink_inode_operations; |
154 | if (inode->i_blocks) | 157 | if (inode->i_blocks) |
155 | inode->i_mapping->a_ops = &linvfs_aops; | 158 | inode->i_mapping->a_ops = &linvfs_aops; |
156 | } else { | 159 | break; |
160 | default: | ||
157 | inode->i_op = &linvfs_file_inode_operations; | 161 | inode->i_op = &linvfs_file_inode_operations; |
158 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | 162 | init_special_inode(inode, inode->i_mode, inode->i_rdev); |
163 | break; | ||
159 | } | 164 | } |
160 | } | 165 | } |
161 | 166 | ||
@@ -167,16 +172,23 @@ xfs_revalidate_inode( | |||
167 | { | 172 | { |
168 | struct inode *inode = LINVFS_GET_IP(vp); | 173 | struct inode *inode = LINVFS_GET_IP(vp); |
169 | 174 | ||
170 | inode->i_mode = (ip->i_d.di_mode & MODEMASK) | VTTOIF(vp->v_type); | 175 | inode->i_mode = ip->i_d.di_mode; |
171 | inode->i_nlink = ip->i_d.di_nlink; | 176 | inode->i_nlink = ip->i_d.di_nlink; |
172 | inode->i_uid = ip->i_d.di_uid; | 177 | inode->i_uid = ip->i_d.di_uid; |
173 | inode->i_gid = ip->i_d.di_gid; | 178 | inode->i_gid = ip->i_d.di_gid; |
174 | if (((1 << vp->v_type) & ((1<<VBLK) | (1<<VCHR))) == 0) { | 179 | |
180 | switch (inode->i_mode & S_IFMT) { | ||
181 | case S_IFBLK: | ||
182 | case S_IFCHR: | ||
183 | inode->i_rdev = | ||
184 | MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff, | ||
185 | sysv_minor(ip->i_df.if_u2.if_rdev)); | ||
186 | break; | ||
187 | default: | ||
175 | inode->i_rdev = 0; | 188 | inode->i_rdev = 0; |
176 | } else { | 189 | break; |
177 | xfs_dev_t dev = ip->i_df.if_u2.if_rdev; | ||
178 | inode->i_rdev = MKDEV(sysv_major(dev) & 0x1ff, sysv_minor(dev)); | ||
179 | } | 190 | } |
191 | |||
180 | inode->i_blksize = PAGE_CACHE_SIZE; | 192 | inode->i_blksize = PAGE_CACHE_SIZE; |
181 | inode->i_generation = ip->i_d.di_gen; | 193 | inode->i_generation = ip->i_d.di_gen; |
182 | i_size_write(inode, ip->i_d.di_size); | 194 | i_size_write(inode, ip->i_d.di_size); |
@@ -231,7 +243,6 @@ xfs_initialize_vnode( | |||
231 | * finish our work. | 243 | * finish our work. |
232 | */ | 244 | */ |
233 | if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) { | 245 | if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) { |
234 | vp->v_type = IFTOVT(ip->i_d.di_mode); | ||
235 | xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); | 246 | xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); |
236 | xfs_set_inodeops(inode); | 247 | xfs_set_inodeops(inode); |
237 | 248 | ||
@@ -274,8 +285,7 @@ linvfs_alloc_inode( | |||
274 | { | 285 | { |
275 | vnode_t *vp; | 286 | vnode_t *vp; |
276 | 287 | ||
277 | vp = (vnode_t *)kmem_cache_alloc(linvfs_inode_zone, | 288 | vp = kmem_cache_alloc(xfs_vnode_zone, kmem_flags_convert(KM_SLEEP)); |
278 | kmem_flags_convert(KM_SLEEP)); | ||
279 | if (!vp) | 289 | if (!vp) |
280 | return NULL; | 290 | return NULL; |
281 | return LINVFS_GET_IP(vp); | 291 | return LINVFS_GET_IP(vp); |
@@ -285,11 +295,11 @@ STATIC void | |||
285 | linvfs_destroy_inode( | 295 | linvfs_destroy_inode( |
286 | struct inode *inode) | 296 | struct inode *inode) |
287 | { | 297 | { |
288 | kmem_cache_free(linvfs_inode_zone, LINVFS_GET_VP(inode)); | 298 | kmem_zone_free(xfs_vnode_zone, LINVFS_GET_VP(inode)); |
289 | } | 299 | } |
290 | 300 | ||
291 | STATIC void | 301 | STATIC void |
292 | init_once( | 302 | linvfs_inode_init_once( |
293 | void *data, | 303 | void *data, |
294 | kmem_cache_t *cachep, | 304 | kmem_cache_t *cachep, |
295 | unsigned long flags) | 305 | unsigned long flags) |
@@ -302,21 +312,41 @@ init_once( | |||
302 | } | 312 | } |
303 | 313 | ||
304 | STATIC int | 314 | STATIC int |
305 | init_inodecache( void ) | 315 | linvfs_init_zones(void) |
306 | { | 316 | { |
307 | linvfs_inode_zone = kmem_cache_create("linvfs_icache", | 317 | xfs_vnode_zone = kmem_cache_create("xfs_vnode", |
308 | sizeof(vnode_t), 0, SLAB_RECLAIM_ACCOUNT, | 318 | sizeof(vnode_t), 0, SLAB_RECLAIM_ACCOUNT, |
309 | init_once, NULL); | 319 | linvfs_inode_init_once, NULL); |
310 | if (linvfs_inode_zone == NULL) | 320 | if (!xfs_vnode_zone) |
311 | return -ENOMEM; | 321 | goto out; |
322 | |||
323 | xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend"); | ||
324 | if (!xfs_ioend_zone) | ||
325 | goto out_destroy_vnode_zone; | ||
326 | |||
327 | xfs_ioend_pool = mempool_create(4 * MAX_BUF_PER_PAGE, | ||
328 | mempool_alloc_slab, mempool_free_slab, | ||
329 | xfs_ioend_zone); | ||
330 | if (!xfs_ioend_pool) | ||
331 | goto out_free_ioend_zone; | ||
332 | |||
312 | return 0; | 333 | return 0; |
334 | |||
335 | |||
336 | out_free_ioend_zone: | ||
337 | kmem_zone_destroy(xfs_ioend_zone); | ||
338 | out_destroy_vnode_zone: | ||
339 | kmem_zone_destroy(xfs_vnode_zone); | ||
340 | out: | ||
341 | return -ENOMEM; | ||
313 | } | 342 | } |
314 | 343 | ||
315 | STATIC void | 344 | STATIC void |
316 | destroy_inodecache( void ) | 345 | linvfs_destroy_zones(void) |
317 | { | 346 | { |
318 | if (kmem_cache_destroy(linvfs_inode_zone)) | 347 | mempool_destroy(xfs_ioend_pool); |
319 | printk(KERN_WARNING "%s: cache still in use!\n", __FUNCTION__); | 348 | kmem_zone_destroy(xfs_vnode_zone); |
349 | kmem_zone_destroy(xfs_ioend_zone); | ||
320 | } | 350 | } |
321 | 351 | ||
322 | /* | 352 | /* |
@@ -354,17 +384,38 @@ linvfs_clear_inode( | |||
354 | struct inode *inode) | 384 | struct inode *inode) |
355 | { | 385 | { |
356 | vnode_t *vp = LINVFS_GET_VP(inode); | 386 | vnode_t *vp = LINVFS_GET_VP(inode); |
387 | int error, cache; | ||
357 | 388 | ||
358 | if (vp) { | 389 | vn_trace_entry(vp, "clear_inode", (inst_t *)__return_address); |
359 | vn_rele(vp); | 390 | |
360 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | 391 | XFS_STATS_INC(vn_rele); |
361 | /* | 392 | XFS_STATS_INC(vn_remove); |
362 | * Do all our cleanup, and remove this vnode. | 393 | XFS_STATS_INC(vn_reclaim); |
363 | */ | 394 | XFS_STATS_DEC(vn_active); |
364 | vn_remove(vp); | 395 | |
396 | /* | ||
397 | * This can happen because xfs_iget_core calls xfs_idestroy if we | ||
398 | * find an inode with di_mode == 0 but without IGET_CREATE set. | ||
399 | */ | ||
400 | if (vp->v_fbhv) | ||
401 | VOP_INACTIVE(vp, NULL, cache); | ||
402 | |||
403 | VN_LOCK(vp); | ||
404 | vp->v_flag &= ~VMODIFIED; | ||
405 | VN_UNLOCK(vp, 0); | ||
406 | |||
407 | if (vp->v_fbhv) { | ||
408 | VOP_RECLAIM(vp, error); | ||
409 | if (error) | ||
410 | panic("vn_purge: cannot reclaim"); | ||
365 | } | 411 | } |
366 | } | ||
367 | 412 | ||
413 | ASSERT(vp->v_fbhv == NULL); | ||
414 | |||
415 | #ifdef XFS_VNODE_TRACE | ||
416 | ktrace_free(vp->v_trace); | ||
417 | #endif | ||
418 | } | ||
368 | 419 | ||
369 | /* | 420 | /* |
370 | * Enqueue a work item to be picked up by the vfs xfssyncd thread. | 421 | * Enqueue a work item to be picked up by the vfs xfssyncd thread. |
@@ -466,25 +517,16 @@ xfssyncd( | |||
466 | { | 517 | { |
467 | long timeleft; | 518 | long timeleft; |
468 | vfs_t *vfsp = (vfs_t *) arg; | 519 | vfs_t *vfsp = (vfs_t *) arg; |
469 | struct list_head tmp; | ||
470 | struct vfs_sync_work *work, *n; | 520 | struct vfs_sync_work *work, *n; |
521 | LIST_HEAD (tmp); | ||
471 | 522 | ||
472 | daemonize("xfssyncd"); | ||
473 | |||
474 | vfsp->vfs_sync_work.w_vfs = vfsp; | ||
475 | vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; | ||
476 | vfsp->vfs_sync_task = current; | ||
477 | wmb(); | ||
478 | wake_up(&vfsp->vfs_wait_sync_task); | ||
479 | |||
480 | INIT_LIST_HEAD(&tmp); | ||
481 | timeleft = (xfs_syncd_centisecs * HZ) / 100; | 523 | timeleft = (xfs_syncd_centisecs * HZ) / 100; |
482 | for (;;) { | 524 | for (;;) { |
483 | set_current_state(TASK_INTERRUPTIBLE); | 525 | set_current_state(TASK_INTERRUPTIBLE); |
484 | timeleft = schedule_timeout(timeleft); | 526 | timeleft = schedule_timeout(timeleft); |
485 | /* swsusp */ | 527 | /* swsusp */ |
486 | try_to_freeze(); | 528 | try_to_freeze(); |
487 | if (vfsp->vfs_flag & VFS_UMOUNT) | 529 | if (kthread_should_stop()) |
488 | break; | 530 | break; |
489 | 531 | ||
490 | spin_lock(&vfsp->vfs_sync_lock); | 532 | spin_lock(&vfsp->vfs_sync_lock); |
@@ -513,10 +555,6 @@ xfssyncd( | |||
513 | } | 555 | } |
514 | } | 556 | } |
515 | 557 | ||
516 | vfsp->vfs_sync_task = NULL; | ||
517 | wmb(); | ||
518 | wake_up(&vfsp->vfs_wait_sync_task); | ||
519 | |||
520 | return 0; | 558 | return 0; |
521 | } | 559 | } |
522 | 560 | ||
@@ -524,13 +562,11 @@ STATIC int | |||
524 | linvfs_start_syncd( | 562 | linvfs_start_syncd( |
525 | vfs_t *vfsp) | 563 | vfs_t *vfsp) |
526 | { | 564 | { |
527 | int pid; | 565 | vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; |
528 | 566 | vfsp->vfs_sync_work.w_vfs = vfsp; | |
529 | pid = kernel_thread(xfssyncd, (void *) vfsp, | 567 | vfsp->vfs_sync_task = kthread_run(xfssyncd, vfsp, "xfssyncd"); |
530 | CLONE_VM | CLONE_FS | CLONE_FILES); | 568 | if (IS_ERR(vfsp->vfs_sync_task)) |
531 | if (pid < 0) | 569 | return -PTR_ERR(vfsp->vfs_sync_task); |
532 | return -pid; | ||
533 | wait_event(vfsp->vfs_wait_sync_task, vfsp->vfs_sync_task); | ||
534 | return 0; | 570 | return 0; |
535 | } | 571 | } |
536 | 572 | ||
@@ -538,11 +574,7 @@ STATIC void | |||
538 | linvfs_stop_syncd( | 574 | linvfs_stop_syncd( |
539 | vfs_t *vfsp) | 575 | vfs_t *vfsp) |
540 | { | 576 | { |
541 | vfsp->vfs_flag |= VFS_UMOUNT; | 577 | kthread_stop(vfsp->vfs_sync_task); |
542 | wmb(); | ||
543 | |||
544 | wake_up_process(vfsp->vfs_sync_task); | ||
545 | wait_event(vfsp->vfs_wait_sync_task, !vfsp->vfs_sync_task); | ||
546 | } | 578 | } |
547 | 579 | ||
548 | STATIC void | 580 | STATIC void |
@@ -866,9 +898,9 @@ init_xfs_fs( void ) | |||
866 | 898 | ||
867 | ktrace_init(64); | 899 | ktrace_init(64); |
868 | 900 | ||
869 | error = init_inodecache(); | 901 | error = linvfs_init_zones(); |
870 | if (error < 0) | 902 | if (error < 0) |
871 | goto undo_inodecache; | 903 | goto undo_zones; |
872 | 904 | ||
873 | error = pagebuf_init(); | 905 | error = pagebuf_init(); |
874 | if (error < 0) | 906 | if (error < 0) |
@@ -889,9 +921,9 @@ undo_register: | |||
889 | pagebuf_terminate(); | 921 | pagebuf_terminate(); |
890 | 922 | ||
891 | undo_pagebuf: | 923 | undo_pagebuf: |
892 | destroy_inodecache(); | 924 | linvfs_destroy_zones(); |
893 | 925 | ||
894 | undo_inodecache: | 926 | undo_zones: |
895 | return error; | 927 | return error; |
896 | } | 928 | } |
897 | 929 | ||
@@ -903,7 +935,7 @@ exit_xfs_fs( void ) | |||
903 | unregister_filesystem(&xfs_fs_type); | 935 | unregister_filesystem(&xfs_fs_type); |
904 | xfs_cleanup(); | 936 | xfs_cleanup(); |
905 | pagebuf_terminate(); | 937 | pagebuf_terminate(); |
906 | destroy_inodecache(); | 938 | linvfs_destroy_zones(); |
907 | ktrace_uninit(); | 939 | ktrace_uninit(); |
908 | } | 940 | } |
909 | 941 | ||