📄 inode.c
字号:
*/ if (inodes_stat.nr_inodes > max_inodes) { struct list_head *tmp; try_to_free_inodes(inodes_stat.nr_inodes >> 2); tmp = inode_unused.next; if (tmp != &inode_unused) { inodes_stat.nr_free_inodes--; list_del(tmp); inode = list_entry(tmp, struct inode, i_list); return inode; } } spin_unlock(&inode_lock); inode = (struct inode *)__get_free_pages(GFP_KERNEL,INODE_PAGE_ORDER); if (inode) { int size; struct inode * tmp; size = INODE_ALLOCATION_SIZE - 2*sizeof(struct inode); tmp = inode; spin_lock(&inode_lock); do { tmp++; init_once(tmp); list_add(&tmp->i_list, &inode_unused); size -= sizeof(struct inode); } while (size >= 0); init_once(inode); /* * Update the inode statistics */ inodes_stat.nr_inodes += INODES_PER_ALLOCATION; inodes_stat.nr_free_inodes += INODES_PER_ALLOCATION - 1; return inode; } /* * If the allocation failed, do an extensive pruning of * the dcache and then try again to free some inodes. */ prune_dcache(inodes_stat.nr_inodes >> 2); spin_lock(&inode_lock); free_inodes(); { struct list_head *tmp = inode_unused.next; if (tmp != &inode_unused) { inodes_stat.nr_free_inodes--; list_del(tmp); inode = list_entry(tmp, struct inode, i_list); return inode; } } spin_unlock(&inode_lock); printk("grow_inodes: allocation failed\n"); return NULL;}/* * Called with the inode lock held. */static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head){ struct list_head *tmp; struct inode * inode; tmp = head; for (;;) { tmp = tmp->next; inode = NULL; if (tmp == head) break; inode = list_entry(tmp, struct inode, i_hash); if (inode->i_sb != sb) continue; if (inode->i_ino != ino) continue; inode->i_count++; break; } return inode;}/* * This just initializes the inode fields * to known values before returning the inode.. * * i_sb, i_ino, i_count, i_state and the lists have * been initialized elsewhere.. */void clean_inode(struct inode *inode){ memset(&inode->u, 0, sizeof(inode->u)); inode->i_sock = 0; inode->i_op = NULL; inode->i_nlink = 1; inode->i_writecount = 0; inode->i_size = 0; inode->i_generation = 0; memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); sema_init(&inode->i_sem, 1);}/* * This is called by things like the networking layer * etc that want to get an inode without any inode * number, or filesystems that allocate new inodes with * no pre-existing information. */struct inode * get_empty_inode(void){ static unsigned long last_ino = 0; struct inode * inode; struct list_head * tmp; spin_lock(&inode_lock); tmp = inode_unused.next; if (tmp != &inode_unused) { list_del(tmp); inodes_stat.nr_free_inodes--; inode = list_entry(tmp, struct inode, i_list);add_new_inode: list_add(&inode->i_list, &inode_in_use); inode->i_sb = NULL; inode->i_dev = 0; inode->i_ino = ++last_ino; inode->i_flags = 0; inode->i_count = 1; inode->i_state = 0; spin_unlock(&inode_lock); clean_inode(inode); return inode; } /* * Warning: if this succeeded, we will now * return with the inode lock. */ inode = grow_inodes(); if (inode) goto add_new_inode; return inode;}/* * This is called with the inode lock held.. Be careful. * * 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){ struct inode * inode; struct list_head * tmp = inode_unused.next; if (tmp != &inode_unused) { list_del(tmp); inodes_stat.nr_free_inodes--; inode = list_entry(tmp, struct inode, i_list);add_new_inode: 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_ino = ino; inode->i_flags = 0; inode->i_count = 1; inode->i_state = I_LOCK; spin_unlock(&inode_lock); clean_inode(inode); 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; } /* * We need to expand. Note that "grow_inodes()" will * release the spinlock, but will return with the lock * held again if the allocation succeeded. */ inode = grow_inodes(); if (inode) { /* We released the lock, so.. */ struct inode * old = find_inode(sb, ino, head); if (!old) goto add_new_inode; list_add(&inode->i_list, &inode_unused); inodes_stat.nr_free_inodes++; spin_unlock(&inode_lock); wait_on_inode(old); return old; } return inode;}static inline unsigned long hash(struct super_block *sb, unsigned long i_ino){ unsigned long tmp = i_ino | (unsigned long) sb; tmp = tmp + (tmp >> HASH_BITS) + (tmp >> HASH_BITS*2); return tmp & HASH_MASK;}/* Yeah, I know about quadratic hash. Maybe, later. */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); if (!inode) { spin_unlock(&inode_lock); return res; } inode->i_count--; /* compensate find_inode() */ } else { counter = max_reserved + 1; } goto retry; }struct inode *igrab(struct inode *inode){ spin_lock(&inode_lock); if (inode->i_state & I_FREEING) inode = NULL; else inode->i_count++; spin_unlock(&inode_lock); if (inode) wait_on_inode(inode); return inode;}struct inode *iget(struct super_block *sb, unsigned long ino){ struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; spin_lock(&inode_lock); inode = find_inode(sb, ino, head); if (inode) { spin_unlock(&inode_lock); wait_on_inode(inode); return inode; } /* * get_new_inode() will do the right thing, releasing * the inode lock and re-trying the search in case it * had to block at any point. */ return get_new_inode(sb, ino, head);}void insert_inode_hash(struct inode *inode){ struct list_head *head = inode_hashtable + hash(inode->i_sb, inode->i_ino); spin_lock(&inode_lock); list_add(&inode->i_hash, head); spin_unlock(&inode_lock);}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);}void iput(struct inode *inode){ if (inode) { struct super_operations *op = NULL; if (inode->i_sb && inode->i_sb->s_op) op = inode->i_sb->s_op; if (op && op->put_inode) op->put_inode(inode); spin_lock(&inode_lock); if (!--inode->i_count) { 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; if (op && op->delete_inode) { void (*delete)(struct inode *) = op->delete_inode; spin_unlock(&inode_lock); delete(inode); spin_lock(&inode_lock); } } if (list_empty(&inode->i_hash)) { list_del(&inode->i_list); INIT_LIST_HEAD(&inode->i_list); inode->i_state|=I_FREEING; spin_unlock(&inode_lock); clear_inode(inode); spin_lock(&inode_lock); list_add(&inode->i_list, &inode_unused); inodes_stat.nr_free_inodes++; } else if (!(inode->i_state & I_DIRTY)) { list_del(&inode->i_list); list_add(&inode->i_list, &inode_in_use); }#ifdef INODE_PARANOIAif (inode->i_flock)printk(KERN_ERR "iput: inode %s/%ld still has locks!\n",kdevname(inode->i_dev), inode->i_ino);if (!list_empty(&inode->i_dentry))printk(KERN_ERR "iput: device %s inode %ld still has aliases!\n",kdevname(inode->i_dev), inode->i_ino);if (inode->i_count)printk(KERN_ERR "iput: device %s inode %ld count changed, count=%d\n",kdevname(inode->i_dev), inode->i_ino, inode->i_count);if (atomic_read(&inode->i_sem.count) != 1)printk(KERN_ERR "iput: Aieee, semaphore in use inode %s/%ld, count=%d\n",kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count));if (atomic_read(&inode->i_atomic_write.count) != 1)printk(KERN_ERR "iput: Aieee, atomic write semaphore in use inode %s/%ld, count=%d\n",kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count));#endif } if (inode->i_count > (1<<31)) { printk(KERN_ERR "iput: inode %s/%ld count wrapped\n", kdevname(inode->i_dev), inode->i_ino); } spin_unlock(&inode_lock); }}int bmap(struct inode * inode, int block){ if (inode->i_op && inode->i_op->bmap) return inode->i_op->bmap(inode, block); return 0;}/* * Initialize the hash tables and default * value for max inodes */#define MAX_INODE (16384)void __init inode_init(void){ int i, max; struct list_head *head = inode_hashtable; i = HASH_SIZE; do { INIT_LIST_HEAD(head); head++; i--; } while (i); /* Initial guess at reasonable inode number */#ifndef OSKIT max = num_physpages >> 1; if (max > MAX_INODE) max = MAX_INODE; max_inodes = max;#else max_inodes = 4096;#endif}#ifndef OSKIT/* This belongs in file_table.c, not here... */int fs_may_remount_ro(struct super_block *sb){ struct file *file; /* Check that no files are currently opened for writing. */ for (file = inuse_filps; file; file = file->f_next) { struct inode *inode; if (!file->f_dentry) continue; inode = file->f_dentry->d_inode; if (!inode || inode->i_sb != sb) continue; /* File with pending delete? */ if (inode->i_nlink == 0) return 0; /* Writable file? */ if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)) return 0; } return 1; /* Tis' cool bro. */}#endif /* OSKIT */void update_atime (struct inode *inode){ 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 (inode);} /* End Function update_atime */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -