📄 inode.c
字号:
* * We no longer cache the sb_flags in i_flags - see fs.h * -- rmk@arm.uk.linux.org */static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque){ struct inode * inode; inode = alloc_inode(); if (inode) { struct inode * old; spin_lock(&inode_lock); /* We released the lock, so.. */ old = find_inode(sb, ino, head, find_actor, opaque); if (!old) { inodes_stat.nr_inodes++; list_add(&inode->i_list, &inode_in_use); list_add(&inode->i_hash, head); inode->i_sb = sb; inode->i_dev = sb->s_dev; inode->i_blkbits = sb->s_blocksize_bits; inode->i_ino = ino; inode->i_flags = 0; atomic_set(&inode->i_count, 1); inode->i_state = I_LOCK; spin_unlock(&inode_lock); clean_inode(inode); /* reiserfs specific hack right here. We don't ** want this to last, and are looking for VFS changes ** that will allow us to get rid of it. ** -- mason@suse.com */ if (sb->s_op->read_inode2) { sb->s_op->read_inode2(inode, opaque) ; } else { sb->s_op->read_inode(inode); } /* * This is special! We do not need the spinlock * when clearing I_LOCK, because we're guaranteed * that nobody else tries to do anything about the * state of the inode when it is locked, as we * just created it (so there can be no old holders * that haven't tested I_LOCK). */ inode->i_state &= ~I_LOCK; wake_up(&inode->i_wait); return inode; } /* * Uhhuh, somebody else created the same inode under * us. Use the old inode instead of the one we just * allocated. */ __iget(old); spin_unlock(&inode_lock); destroy_inode(inode); inode = old; wait_on_inode(inode); } return inode;}static inline unsigned long hash(struct super_block *sb, unsigned long i_ino){ unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES); tmp = tmp + (tmp >> I_HASHBITS); return tmp & I_HASHMASK;}/* Yeah, I know about quadratic hash. Maybe, later. *//** * iunique - get a unique inode number * @sb: superblock * @max_reserved: highest reserved inode number * * Obtain an inode number that is unique on the system for a given * superblock. This is used by file systems that have no natural * permanent inode numbering system. An inode number is returned that * is higher than the reserved limit but unique. * * BUGS: * With a large number of inodes live on the file system this function * currently becomes quite slow. */ ino_t iunique(struct super_block *sb, ino_t max_reserved){ static ino_t counter = 0; struct inode *inode; struct list_head * head; ino_t res; spin_lock(&inode_lock);retry: if (counter > max_reserved) { head = inode_hashtable + hash(sb,counter); inode = find_inode(sb, res = counter++, head, NULL, NULL); if (!inode) { spin_unlock(&inode_lock); return res; } } else { counter = max_reserved + 1; } goto retry; }struct inode *igrab(struct inode *inode){ spin_lock(&inode_lock); if (!(inode->i_state & I_FREEING)) __iget(inode); else /* * Handle the case where s_op->clear_inode is not been * called yet, and somebody is calling igrab * while the inode is getting freed. */ inode = NULL; spin_unlock(&inode_lock); return inode;}struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque){ struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; spin_lock(&inode_lock); inode = find_inode(sb, ino, head, find_actor, opaque); if (inode) { __iget(inode); spin_unlock(&inode_lock); wait_on_inode(inode); return inode; } spin_unlock(&inode_lock); /* * get_new_inode() will do the right thing, re-trying the search * in case it had to block at any point. */ return get_new_inode(sb, ino, head, find_actor, opaque);}/** * insert_inode_hash - hash an inode * @inode: unhashed inode * * Add an inode to the inode hash for this superblock. If the inode * has no superblock it is added to a separate anonymous chain. */ void insert_inode_hash(struct inode *inode){ struct list_head *head = &anon_hash_chain; if (inode->i_sb) head = inode_hashtable + hash(inode->i_sb, inode->i_ino); spin_lock(&inode_lock); list_add(&inode->i_hash, head); spin_unlock(&inode_lock);}/** * remove_inode_hash - remove an inode from the hash * @inode: inode to unhash * * Remove an inode from the superblock or anonymous hash. */ void remove_inode_hash(struct inode *inode){ spin_lock(&inode_lock); list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); spin_unlock(&inode_lock);}/** * iput - put an inode * @inode: inode to put * * Puts an inode, dropping its usage count. If the inode use count hits * zero the inode is also then freed and may be destroyed. */ void iput(struct inode *inode){ if (inode) { struct super_block *sb = inode->i_sb; struct super_operations *op = NULL; if (inode->i_state == I_CLEAR) BUG(); if (sb && sb->s_op) op = sb->s_op; if (op && op->put_inode) op->put_inode(inode); if (!atomic_dec_and_lock(&inode->i_count, &inode_lock)) return; if (!inode->i_nlink) { list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); list_del(&inode->i_list); INIT_LIST_HEAD(&inode->i_list); inode->i_state|=I_FREEING; inodes_stat.nr_inodes--; spin_unlock(&inode_lock); if (inode->i_data.nrpages) truncate_inode_pages(&inode->i_data, 0); if (op && op->delete_inode) { void (*delete)(struct inode *) = op->delete_inode; if (!is_bad_inode(inode)) DQUOT_INIT(inode); /* s_op->delete_inode internally recalls clear_inode() */ delete(inode); } else clear_inode(inode); if (inode->i_state != I_CLEAR) BUG(); } else { if (!list_empty(&inode->i_hash)) { if (!(inode->i_state & (I_DIRTY|I_LOCK))) { list_del(&inode->i_list); list_add(&inode->i_list, &inode_unused); } inodes_stat.nr_unused++; spin_unlock(&inode_lock); if (!sb || (sb->s_flags & MS_ACTIVE)) return; write_inode_now(inode, 1); spin_lock(&inode_lock); inodes_stat.nr_unused--; list_del_init(&inode->i_hash); } list_del_init(&inode->i_list); inode->i_state|=I_FREEING; inodes_stat.nr_inodes--; spin_unlock(&inode_lock); if (inode->i_data.nrpages) truncate_inode_pages(&inode->i_data, 0); clear_inode(inode); } destroy_inode(inode); }}void force_delete(struct inode *inode){ /* * Kill off unused inodes ... iput() will unhash and * delete the inode if we set i_nlink to zero. */ if (atomic_read(&inode->i_count) == 1) inode->i_nlink = 0;}/** * bmap - find a block number in a file * @inode: inode of file * @block: block to find * * Returns the block number on the device holding the inode that * is the disk block number for the block of the file requested. * That is, asked for block 4 of inode 1 the function will return the * disk block relative to the disk start that holds that block of the * file. */ int bmap(struct inode * inode, int block){ int res = 0; if (inode->i_mapping->a_ops->bmap) res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block); return res;}/* * Initialize the hash tables. */void __init inode_init(unsigned long mempages){ struct list_head *head; unsigned long order; unsigned int nr_hash; int i; mempages >>= (14 - PAGE_SHIFT); mempages *= sizeof(struct list_head); for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) ; do { unsigned long tmp; nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct list_head); i_hash_mask = (nr_hash - 1); tmp = nr_hash; i_hash_shift = 0; while ((tmp >>= 1UL) != 0UL) i_hash_shift++; inode_hashtable = (struct list_head *) __get_free_pages(GFP_ATOMIC, order); } while (inode_hashtable == NULL && --order >= 0); printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n", nr_hash, order, (PAGE_SIZE << order)); if (!inode_hashtable) panic("Failed to allocate inode hash table\n"); head = inode_hashtable; i = nr_hash; do { INIT_LIST_HEAD(head); head++; i--; } while (i); /* inode slab cache */ inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), 0, SLAB_HWCACHE_ALIGN, init_once, NULL); if (!inode_cachep) panic("cannot create inode slab cache"); unused_inodes_flush_task.routine = try_to_sync_unused_inodes;}/** * update_atime - update the access time * @inode: inode accessed * * Update the accessed time on an inode and mark it for writeback. * This function automatically handles read only file systems and media, * as well as the "noatime" flag and inode specific "noatime" markers. */ void update_atime (struct inode *inode){ if (inode->i_atime == CURRENT_TIME) return; if ( IS_NOATIME (inode) ) return; if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return; if ( IS_RDONLY (inode) ) return; inode->i_atime = CURRENT_TIME; mark_inode_dirty_sync (inode);} /* End Function update_atime *//* * Quota functions that want to walk the inode lists.. */#ifdef CONFIG_QUOTA/* Functions back in dquot.c */void put_dquot_list(struct list_head *);int remove_inode_dquot_ref(struct inode *, short, struct list_head *);void remove_dquot_ref(struct super_block *sb, short type){ struct inode *inode; struct list_head *act_head; LIST_HEAD(tofree_head); if (!sb->dq_op) return; /* nothing to do */ /* We have to be protected against other CPUs */ lock_kernel(); /* This lock is for quota code */ spin_lock(&inode_lock); /* This lock is for inodes code */ list_for_each(act_head, &inode_in_use) { inode = list_entry(act_head, struct inode, i_list); if (inode->i_sb == sb && IS_QUOTAINIT(inode)) remove_inode_dquot_ref(inode, type, &tofree_head); } list_for_each(act_head, &inode_unused) { inode = list_entry(act_head, struct inode, i_list); if (inode->i_sb == sb && IS_QUOTAINIT(inode)) remove_inode_dquot_ref(inode, type, &tofree_head); } list_for_each(act_head, &sb->s_dirty) { inode = list_entry(act_head, struct inode, i_list); if (IS_QUOTAINIT(inode)) remove_inode_dquot_ref(inode, type, &tofree_head); } list_for_each(act_head, &sb->s_locked_inodes) { inode = list_entry(act_head, struct inode, i_list); if (IS_QUOTAINIT(inode)) remove_inode_dquot_ref(inode, type, &tofree_head); } spin_unlock(&inode_lock); unlock_kernel(); put_dquot_list(&tofree_head);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -