diff options
author | David Chinner <david@fromorbit.com> | 2008-10-30 02:35:24 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-10-30 02:35:24 -0400 |
commit | 8290c35f87304a6b73d4fd17b03580b4f7425de8 (patch) | |
tree | cf7fb08de3fd7a6a1ccb079d2d5d53837aca16fe | |
parent | 2cb1599f9b2ecdd7a9e59feeee647eb258966839 (diff) |
Inode: Allow external list initialisation
To allow XFS to combine the XFS and linux inodes into a single
structure, we need to drive inode lookup from the XFS inode cache,
not the generic inode cache. This means that we need initialise a
struct inode from a context outside alloc_inode() as it is no longer
used by XFS.
After inode allocation and initialisation, we need to add the inode
to the superblock list, the in-use list, hash it and do some
accounting. This all needs to be done with the inode_lock held and
there are already several places in fs/inode.c that do this list
manipulation. Factor out the common code, add a locking wrapper and
export the function so ti can be called from XFS.
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r-- | fs/inode.c | 67 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
2 files changed, 47 insertions, 21 deletions
diff --git a/fs/inode.c b/fs/inode.c index e7ee99907d60..fbcf6c5e7605 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -550,6 +550,49 @@ repeat: | |||
550 | return node ? inode : NULL; | 550 | return node ? inode : NULL; |
551 | } | 551 | } |
552 | 552 | ||
553 | static unsigned long hash(struct super_block *sb, unsigned long hashval) | ||
554 | { | ||
555 | unsigned long tmp; | ||
556 | |||
557 | tmp = (hashval * (unsigned long)sb) ^ (GOLDEN_RATIO_PRIME + hashval) / | ||
558 | L1_CACHE_BYTES; | ||
559 | tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> I_HASHBITS); | ||
560 | return tmp & I_HASHMASK; | ||
561 | } | ||
562 | |||
563 | static inline void | ||
564 | __inode_add_to_lists(struct super_block *sb, struct hlist_head *head, | ||
565 | struct inode *inode) | ||
566 | { | ||
567 | inodes_stat.nr_inodes++; | ||
568 | list_add(&inode->i_list, &inode_in_use); | ||
569 | list_add(&inode->i_sb_list, &sb->s_inodes); | ||
570 | if (head) | ||
571 | hlist_add_head(&inode->i_hash, head); | ||
572 | } | ||
573 | |||
574 | /** | ||
575 | * inode_add_to_lists - add a new inode to relevant lists | ||
576 | * @sb - superblock inode belongs to. | ||
577 | * @inode - inode to mark in use | ||
578 | * | ||
579 | * When an inode is allocated it needs to be accounted for, added to the in use | ||
580 | * list, the owning superblock and the inode hash. This needs to be done under | ||
581 | * the inode_lock, so export a function to do this rather than the inode lock | ||
582 | * itself. We calculate the hash list to add to here so it is all internal | ||
583 | * which requires the caller to have already set up the inode number in the | ||
584 | * inode to add. | ||
585 | */ | ||
586 | void inode_add_to_lists(struct super_block *sb, struct inode *inode) | ||
587 | { | ||
588 | struct hlist_head *head = inode_hashtable + hash(sb, inode->i_ino); | ||
589 | |||
590 | spin_lock(&inode_lock); | ||
591 | __inode_add_to_lists(sb, head, inode); | ||
592 | spin_unlock(&inode_lock); | ||
593 | } | ||
594 | EXPORT_SYMBOL_GPL(inode_add_to_lists); | ||
595 | |||
553 | /** | 596 | /** |
554 | * new_inode - obtain an inode | 597 | * new_inode - obtain an inode |
555 | * @sb: superblock | 598 | * @sb: superblock |
@@ -577,9 +620,7 @@ struct inode *new_inode(struct super_block *sb) | |||
577 | inode = alloc_inode(sb); | 620 | inode = alloc_inode(sb); |
578 | if (inode) { | 621 | if (inode) { |
579 | spin_lock(&inode_lock); | 622 | spin_lock(&inode_lock); |
580 | inodes_stat.nr_inodes++; | 623 | __inode_add_to_lists(sb, NULL, inode); |
581 | list_add(&inode->i_list, &inode_in_use); | ||
582 | list_add(&inode->i_sb_list, &sb->s_inodes); | ||
583 | inode->i_ino = ++last_ino; | 624 | inode->i_ino = ++last_ino; |
584 | inode->i_state = 0; | 625 | inode->i_state = 0; |
585 | spin_unlock(&inode_lock); | 626 | spin_unlock(&inode_lock); |
@@ -638,10 +679,7 @@ static struct inode * get_new_inode(struct super_block *sb, struct hlist_head *h | |||
638 | if (set(inode, data)) | 679 | if (set(inode, data)) |
639 | goto set_failed; | 680 | goto set_failed; |
640 | 681 | ||
641 | inodes_stat.nr_inodes++; | 682 | __inode_add_to_lists(sb, head, inode); |
642 | list_add(&inode->i_list, &inode_in_use); | ||
643 | list_add(&inode->i_sb_list, &sb->s_inodes); | ||
644 | hlist_add_head(&inode->i_hash, head); | ||
645 | inode->i_state = I_LOCK|I_NEW; | 683 | inode->i_state = I_LOCK|I_NEW; |
646 | spin_unlock(&inode_lock); | 684 | spin_unlock(&inode_lock); |
647 | 685 | ||
@@ -687,10 +725,7 @@ static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_he | |||
687 | old = find_inode_fast(sb, head, ino); | 725 | old = find_inode_fast(sb, head, ino); |
688 | if (!old) { | 726 | if (!old) { |
689 | inode->i_ino = ino; | 727 | inode->i_ino = ino; |
690 | inodes_stat.nr_inodes++; | 728 | __inode_add_to_lists(sb, head, inode); |
691 | list_add(&inode->i_list, &inode_in_use); | ||
692 | list_add(&inode->i_sb_list, &sb->s_inodes); | ||
693 | hlist_add_head(&inode->i_hash, head); | ||
694 | inode->i_state = I_LOCK|I_NEW; | 729 | inode->i_state = I_LOCK|I_NEW; |
695 | spin_unlock(&inode_lock); | 730 | spin_unlock(&inode_lock); |
696 | 731 | ||
@@ -714,16 +749,6 @@ static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_he | |||
714 | return inode; | 749 | return inode; |
715 | } | 750 | } |
716 | 751 | ||
717 | static unsigned long hash(struct super_block *sb, unsigned long hashval) | ||
718 | { | ||
719 | unsigned long tmp; | ||
720 | |||
721 | tmp = (hashval * (unsigned long)sb) ^ (GOLDEN_RATIO_PRIME + hashval) / | ||
722 | L1_CACHE_BYTES; | ||
723 | tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> I_HASHBITS); | ||
724 | return tmp & I_HASHMASK; | ||
725 | } | ||
726 | |||
727 | /** | 752 | /** |
728 | * iunique - get a unique inode number | 753 | * iunique - get a unique inode number |
729 | * @sb: superblock | 754 | * @sb: superblock |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 04abead4b021..1deedf235d55 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1883,6 +1883,7 @@ extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); | |||
1883 | 1883 | ||
1884 | extern struct inode * inode_init_always(struct super_block *, struct inode *); | 1884 | extern struct inode * inode_init_always(struct super_block *, struct inode *); |
1885 | extern void inode_init_once(struct inode *); | 1885 | extern void inode_init_once(struct inode *); |
1886 | extern void inode_add_to_lists(struct super_block *, struct inode *); | ||
1886 | extern void iput(struct inode *); | 1887 | extern void iput(struct inode *); |
1887 | extern struct inode * igrab(struct inode *); | 1888 | extern struct inode * igrab(struct inode *); |
1888 | extern ino_t iunique(struct super_block *, ino_t); | 1889 | extern ino_t iunique(struct super_block *, ino_t); |