struct inode * ext_new_inode(const struct inode * dir) { struct super_block * sb; struct inode * inode; struct ext_free_inode * efi; unsigned long block; int j; if (!dir || !(inode=get_empty_inode())) return NULL; sb = dir->i_sb; inode->i_sb = sb; inode->i_flags = sb->s_flags; if (!sb->u.ext_sb.s_firstfreeinodeblock) return 0; lock_super (sb); efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) + (sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK; if (efi->count) { j = efi->free[--efi->count]; mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1); } else { #ifdef EXTFS_DEBUG printk("ext_free_inode: inode empty, skipping to %d\n", efi->next); #endif j = sb->u.ext_sb.s_firstfreeinodenumber; if (efi->next > sb->u.ext_sb.s_ninodes) { printk ("efi->next = %ld\n", efi->next); panic ("ext_new_inode: bad inode number in free list\n"); } sb->u.ext_sb.s_firstfreeinodenumber = efi->next; block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK; brelse (sb->u.ext_sb.s_firstfreeinodeblock); if (!sb->u.ext_sb.s_firstfreeinodenumber) { sb->u.ext_sb.s_firstfreeinodeblock = NULL; } else { if (!(sb->u.ext_sb.s_firstfreeinodeblock = bread(sb->s_dev, block, sb->s_blocksize))) panic ("ext_new_inode: unable to read next free inode block\n"); } } sb->u.ext_sb.s_freeinodescount --; sb->s_dirt = 1; inode->i_count = 1; inode->i_nlink = 1; inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; inode->i_dirt = 1; inode->i_ino = j; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_op = NULL; inode->i_blocks = inode->i_blksize = 0; insert_inode_hash(inode); #ifdef EXTFS_DEBUG printk("ext_new_inode : allocating inode %d\n", inode->i_ino); #endif unlock_super (sb); return inode; }
struct inode *new_inode(register struct inode *dir, __u16 mode) { register struct inode *inode; if (!(inode = get_empty_inode())) return inode; inode->i_gid =(__u8) current->egid; if (dir) { inode->i_sb = dir->i_sb; inode->i_dev = inode->i_sb->s_dev; inode->i_flags = inode->i_sb->s_flags; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) mode |= S_ISGID; } } if (S_ISLNK(mode)) mode |= 0777; else mode &= ~(current->fs.umask & 0777); inode->i_mode = mode; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; #ifdef BLOAT_FS inode->i_blocks = inode->i_blksize = 0; #endif set_ops(inode); return inode; }
static struct inode * get_pipe_inode(void) { extern struct inode_operations pipe_inode_operations; struct inode *inode = get_empty_inode(); if (inode) { unsigned long page = __get_free_page(GFP_USER); if (!page) { iput(inode); inode = NULL; } else { PIPE_BASE(*inode) = (char *) page; inode->i_op = &pipe_inode_operations; PIPE_WAIT(*inode) = NULL; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; PIPE_LOCK(*inode) = 0; /* * Mark the inode dirty from the very beginning, * that way it will never be moved to the dirty * list because "mark_inode_dirty()" will think * that it already _is_ on the dirty list. */ inode->i_state = I_DIRTY; inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_blksize = PAGE_SIZE; } } return inode; }
static int umount_dev(kdev_t dev, int flags) { int retval; struct inode * inode = get_empty_inode(); retval = -ENOMEM; if (!inode) goto out; inode->i_rdev = dev; retval = -ENXIO; if (MAJOR(dev) >= MAX_BLKDEV) goto out_iput; fsync_dev(dev); down(&mount_sem); retval = do_umount(dev, 0, flags); if (!retval) { fsync_dev(dev); if (dev != ROOT_DEV) { blkdev_release(inode); put_unnamed_dev(dev); } } up(&mount_sem); out_iput: iput(inode); out: return retval; }
struct inode *__iget(register struct super_block *sb, ino_t inr /*,int crossmntp */ ) { int i; register struct inode *inode; register struct inode *empty = NULL; debug3("iget called(%x, %d, %d)\n", sb, inr, 0 /* crossmntp */ ); if (!sb) panic("VFS: iget with sb==NULL"); repeat: inode = inode_block; for (i = NR_INODE; i; i--, inode++) { if (inode->i_dev == sb->s_dev && inode->i_ino == inr) { goto found_it; } } if (!empty) { debug("iget: getting an empty inode...\n"); empty = get_empty_inode(); debug1("iget: got one... (%x)!\n", empty); if (empty) goto repeat; return NULL; } inode = empty; inode->i_sb = sb; inode->i_dev = sb->s_dev; inode->i_ino = inr; inode->i_flags = ((unsigned short int) sb->s_flags); put_last_free(inode); debug("iget: Reading inode\n"); read_inode(inode); debug("iget: Read it\n"); goto return_it; found_it: if (!inode->i_count) nr_free_inodes--; inode->i_count++; wait_on_inode(inode); if (inode->i_dev != sb->s_dev || inode->i_ino != inr) { printk("Whee.. inode changed from under us. Tell _.\n"); iput(inode); goto repeat; } if ( /* crossmntp && */ inode->i_mount) { struct inode *tmp = inode->i_mount; tmp->i_count++; iput(inode); inode = tmp; wait_on_inode(inode); } if (empty) iput(empty); return_it: return inode; }
struct inode *get_pipe_inode(void) { register struct inode *inode; extern struct inode_operations pipe_inode_operations; if ((inode = get_empty_inode())) { if (!(PIPE_BASE(*inode) = get_pipe_mem())) { iput(inode); return NULL; } inode->i_op = &pipe_inode_operations; inode->i_count = 2; /* sum of readers/writers */ PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; PIPE_LOCK(*inode) = 0; inode->i_pipe = 1; inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR; inode->i_uid = current->euid; inode->i_gid = (__u8) current->egid; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; #if 0 inode->i_blksize = PAGE_SIZE; #endif } return inode; }
static int _linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode) { int error; struct inode *r = 0; ntfs_volume *vol; ntfs_inode *ino; ntfs_attribute *si; ntfs_debug (DEBUG_DIR1, "mkdir %s in %x\n",d->d_name.name, dir->i_ino); error = ENAMETOOLONG; if (d->d_name.len > /* FIXME */255) goto out; error = EIO; r = get_empty_inode(); if (!r) goto out; vol = NTFS_INO2VOL(dir); #ifdef NTFS_IN_LINUX_KERNEL ino = NTFS_LINO2NINO(r); #else ino = ntfs_malloc(sizeof(ntfs_inode)); error = ENOMEM; if(!ino) goto out; r->u.generic_ip = ino; #endif error = ntfs_mkdir(NTFS_LINO2NINO(dir), d->d_name.name, d->d_name.len, ino); if(error) goto out; r->i_uid = vol->uid; r->i_gid = vol->gid; r->i_nlink = 1; r->i_sb = dir->i_sb; si = ntfs_find_attr(ino,vol->at_standard_information,NULL); if(si){ char *attr = si->d.data; r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18)); r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr)); r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+8)); } /* It's a directory */ r->i_op = &ntfs_dir_inode_operations; r->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; #ifdef CONFIG_NTFS_RW r->i_mode|=S_IWUGO; #endif r->i_mode &= ~vol->umask; insert_inode_hash(r); d_instantiate(d, r); error = 0; out: ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", -error); return -error; }
/* 查找一个空闲的struct socket结构,并初始化相应的关系 * 如sock中有inode节点指针,inode中有struct socket指针 * wait表示在获取socket结构的时候,该函数是不是阻塞的, * wait>0表示阻塞,=0表示非阻塞 */ static struct socket *sock_alloc(int wait) { struct socket *sock; while (1) { cli(); for (sock = sockets; sock <= last_socket; ++sock) { if (sock->state == SS_FREE) { /* 注意在socket系统调用完成后struct socket的状态为SS_UNCONNECTED */ sock->state = SS_UNCONNECTED; sti(); sock->flags = 0; sock->ops = NULL; sock->data = NULL; sock->conn = NULL; sock->iconn = NULL; /* * This really shouldn't be necessary, but everything * else depends on inodes, so we grab it. * Sleeps are also done on the i_wait member of this * inode. The close system call will iput this inode * for us. */ /* 此处给socket分配了一个inode,但是inode是空的, * 并没有包含有效数据的 */ if (!(SOCK_INODE(sock) = get_empty_inode())) { printk("NET: sock_alloc: no more inodes\n"); sock->state = SS_FREE; return(NULL); } /* 此时设置inode和socket之间的关系, * S_IFSOCK指明inode指向的时socket文件 */ SOCK_INODE(sock)->i_mode = S_IFSOCK; SOCK_INODE(sock)->i_uid = current->euid; SOCK_INODE(sock)->i_gid = current->egid; SOCK_INODE(sock)->i_socket = sock; sock->wait = &SOCK_INODE(sock)->i_wait; DPRINTF((net_debug, "NET: sock_alloc: sk 0x%x, ino 0x%x\n", sock, SOCK_INODE(sock))); return(sock); } } sti(); if (!wait) return(NULL); DPRINTF((net_debug, "NET: sock_alloc: no free sockets, sleeping...\n")); /* 如果没找到,则在socket_wait_free队列中睡眠,当有释放时,则唤醒该进程 */ interruptible_sleep_on(&socket_wait_free); if (current->signal & ~current->blocked) { DPRINTF((net_debug, "NET: sock_alloc: sleep was interrupted\n")); return(NULL); } DPRINTF((net_debug, "NET: sock_alloc: wakeup... trying again...\n")); } }
struct inode *__iget(register struct super_block *sb, ino_t inr /*,int crossmntp */ ) { register struct inode *inode; debug3("iget called(%x, %d, %d)\n", sb, inr, 0 /* crossmntp */ ); if (!sb) panic("VFS: iget with sb==NULL"); repeat: do { inode = first_inode; do { if (inode->i_dev == sb->s_dev && inode->i_ino == inr) goto found_it; } while ((inode = inode->i_prev) != first_inode); debug("iget: getting an empty inode...\n"); } while (!(inode = get_empty_inode())); debug1("iget: got one... (%x)!\n", empty); inode->i_sb = sb; inode->i_dev = sb->s_dev; inode->i_flags = ((unsigned short int) sb->s_flags); inode->i_ino = inr; put_last_lru(inode); debug("iget: Reading inode\n"); read_inode(inode); debug("iget: Read it\n"); goto return_it; found_it: if (!inode->i_count) nr_free_inodes--; inode->i_count++; wait_on_inode(inode); if (inode->i_dev != sb->s_dev || inode->i_ino != inr) { printk("Whee.. inode changed from under us. Tell _.\n"); iput(inode); goto repeat; } if ( /* crossmntp && */ inode->i_mount) { struct inode *tmp = inode->i_mount; tmp->i_count++; iput(inode); inode = tmp; wait_on_inode(inode); } return_it: return inode; }
static struct socket * sock_alloc(int wait) { struct socket *sock; while (1) { cli(); for (sock = sockets; sock <= last_socket; ++sock) if (sock->state == SS_FREE) { sock->state = SS_UNCONNECTED; sti(); sock->flags = 0; sock->ops = NULL; sock->data = NULL; sock->conn = NULL; sock->iconn = NULL; /* * this really shouldn't be necessary, but * everything else depends on inodes, so we * grab it. * sleeps are also done on the i_wait member * of this inode. * the close system call will iput this inode * for us. */ if (!(SOCK_INODE(sock) = get_empty_inode())) { printk("sock_alloc: no more inodes\n"); sock->state = SS_FREE; return NULL; } SOCK_INODE(sock)->i_mode = S_IFSOCK; sock->wait = &SOCK_INODE(sock)->i_wait; PRINTK("sock_alloc: socket 0x%x, inode 0x%x\n", sock, SOCK_INODE(sock)); return sock; } sti(); if (!wait) return NULL; PRINTK("sock_alloc: no free sockets, sleeping...\n"); interruptible_sleep_on(&socket_wait_free); if (current->signal & ~current->blocked) { PRINTK("sock_alloc: sleep was interrupted\n"); return NULL; } PRINTK("sock_alloc: wakeup... trying again...\n"); } }
struct inode * affs_new_inode(const struct inode *dir) { struct inode *inode; struct super_block *sb; s32 block; if (!dir || !(inode = get_empty_inode())) return NULL; sb = dir->i_sb; inode->i_sb = sb; inode->i_flags = 0; if (!(block = affs_new_header((struct inode *)dir))) { iput(inode); return NULL; } inode->i_count = 1; inode->i_nlink = 1; inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; inode->i_ino = block; inode->i_op = NULL; inode->i_blocks = 0; inode->i_size = 0; inode->i_mode = 0; inode->i_blksize = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->u.affs_i.i_original = 0; inode->u.affs_i.i_parent = dir->i_ino; inode->u.affs_i.i_zone = 0; inode->u.affs_i.i_hlink = 0; inode->u.affs_i.i_pa_cnt = 0; inode->u.affs_i.i_pa_next = 0; inode->u.affs_i.i_pa_last = 0; inode->u.affs_i.i_ec = NULL; inode->u.affs_i.i_lastblock = -1; insert_inode_hash(inode); mark_inode_dirty(inode); return inode; }
int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode) { int error; struct inode * inode; struct reiserfs_dir_entry de; int windex ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ; struct reiserfs_transaction_handle th ; int err; if (!dir) return -ENOENT; inode = get_empty_inode() ; if (!inode) { return -ENOSPC ; } journal_begin(&th, dir->i_sb, jbegin_count) ; th.t_caller = "create" ; windex = push_journal_writer("reiserfs_create") ; inode = reiserfs_new_inode (&th, dir, mode, 0, dentry, inode, &err); if (!inode) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return err; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; inode->i_op = &reiserfs_file_inode_operations; inode->i_mode = mode; error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1); if (error) { inode->i_nlink--; if_in_ram_update_sd (&th, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return error; } if_in_ram_update_sd (&th, dir); d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0; }
struct inode* ftp_iget(struct super_block* sb, struct ftp_fattr *fattr){ struct inode *res; // DEBUG(" Hangin' in here!\n"); res = get_empty_inode(); res->i_sb = sb; res->i_dev = sb->s_dev; res->i_ino = fattr->f_ino; res->u.generic_ip = NULL; ftp_set_inode_attr(res,fattr); if(S_ISDIR(res->i_mode)){ // DEBUG(" yup, it's a dir!\n"); res->i_op = &ftp_dir_inode_operations; }else res->i_op = &ftp_file_inode_operations; insert_inode_hash(res); return res; }
/* * This is our own version of iget that looks up inodes by file handle * instead of inode number. We use this technique instead of using * the vfs read_inode function because there is no way to pass the * file handle or current attributes into the read_inode function. * * We provide a special check for NetApp .snapshot directories to avoid * inode aliasing problems. All snapshot inodes are anonymous (unhashed). */ struct inode * nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct super_block *sb = dentry->d_sb; dprintk("NFS: nfs_fhget(%s/%s fileid=%d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, fattr->fileid); /* Install the file handle in the dentry */ *((struct nfs_fh *) dentry->d_fsdata) = *fhandle; #ifdef CONFIG_NFS_SNAPSHOT /* * Check for NetApp snapshot dentries, and get an * unhashed inode to avoid aliasing problems. */ if ((dentry->d_parent->d_inode->u.nfs_i.flags & NFS_IS_SNAPSHOT) || (dentry->d_name.len == 9 && memcmp(dentry->d_name.name, ".snapshot", 9) == 0)) { struct inode *inode = get_empty_inode(); if (!inode) goto out; inode->i_sb = sb; inode->i_dev = sb->s_dev; inode->i_flags = 0; inode->i_ino = fattr->fileid; nfs_read_inode(inode); nfs_fill_inode(inode, fattr); inode->u.nfs_i.flags |= NFS_IS_SNAPSHOT; dprintk("NFS: nfs_fhget(snapshot ino=%ld)\n", inode->i_ino); out: return inode; } #endif return __nfs_fhget(sb, fattr); }
int reiserfs_symlink (struct inode * dir, struct dentry * dentry, const char * symname) { struct inode * inode; struct path path_to_entry; struct reiserfs_dir_entry de; int error; int windex ; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int err; init_path (&path_to_entry); if (strlen (symname) + 1 + SD_SIZE > MAX_ITEM_LEN (dir->i_sb->s_blocksize)) { return -ENAMETOOLONG; } inode = get_empty_inode() ; if (!inode) { return -ENOSPC ; } journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_symlink") ; inode = reiserfs_new_inode (&th, dir, S_IFLNK, symname, dentry, inode, &err); if (inode == 0) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return err; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; inode->i_op = &reiserfs_symlink_inode_operations; inode->i_size = strlen (symname); inode->i_mode = S_IFLNK | 0777; if_in_ram_update_sd (&th, inode); de.de_gen_number_bit_string = 0; if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de) == POSITION_FOUND) { pathrelse (&path_to_entry); inode->i_nlink--; if_in_ram_update_sd (&th, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return -EEXIST; } pathrelse (&path_to_entry); error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1); if (error) { inode->i_nlink--; if_in_ram_update_sd (&th, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return error; } if_in_ram_update_sd (&th, dir); d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0; }
int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode) { int error; struct inode * inode; struct path path_to_entry; struct reiserfs_dir_entry de; int windex ; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int err; init_path (&path_to_entry); if (!dir || !dir->i_sb) { return -EINVAL; } inode = get_empty_inode() ; if (!inode) { return -ENOSPC ; } journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_mkdir") ; de.de_gen_number_bit_string = 0; if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de) == POSITION_FOUND) { pathrelse (&path_to_entry); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput(inode) ; return -EEXIST; } pathrelse (&path_to_entry); if (dir->i_nlink >= REISERFS_LINK_MAX) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput(inode) ; return -EMLINK; } mode = S_IFDIR | (mode & 0777 & ~current->fs->umask); if (dir->i_mode & S_ISGID) mode |= S_ISGID; inode = reiserfs_new_inode (&th, dir, mode, 0, dentry, inode, &err); if (!inode) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return err; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; inode->i_op = &reiserfs_dir_inode_operations; /* new inode and stat data are uptodate. Inode is clean. */ error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1); if (error) { inode->i_nlink = 0; if_in_ram_update_sd (&th, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return error; } /* update dir inode, reiserfs_add_entry does not do that */ dir->i_nlink ++; if_in_ram_update_sd (&th, dir); d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0; }
int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) { int error; struct inode * inode; struct path path_to_entry; struct reiserfs_dir_entry de; int windex ; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int err; if (!dir) return -ENOENT; init_path (&path_to_entry); inode = get_empty_inode() ; if (!inode) { return -ENOSPC ; } journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_mknod") ; de.de_gen_number_bit_string = 0; if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de) == POSITION_FOUND) { pathrelse ( &path_to_entry); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput(inode) ; return -EEXIST; } pathrelse ( &path_to_entry); inode = reiserfs_new_inode (&th, dir, mode, 0, dentry, inode, &err); if (!inode) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return err; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; inode->i_uid = current->fsuid; inode->i_mode = mode; inode->i_op = NULL; if (S_ISREG(inode->i_mode)) inode->i_op = &reiserfs_file_inode_operations; else if (S_ISDIR(inode->i_mode)) { inode->i_op = &reiserfs_dir_inode_operations; if (dir->i_mode & S_ISGID) inode->i_mode |= S_ISGID; } else if (S_ISLNK(inode->i_mode)) inode->i_op = &reiserfs_symlink_inode_operations; else if (S_ISCHR(inode->i_mode)) inode->i_op = &chrdev_inode_operations; else if (S_ISBLK(inode->i_mode)) inode->i_op = &blkdev_inode_operations; else if (S_ISFIFO(inode->i_mode)) init_fifo(inode); if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = to_kdev_t(rdev); if_in_ram_update_sd (&th, inode); error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1); if (error) { inode->i_nlink--; if_in_ram_update_sd (&th, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return error; } if_in_ram_update_sd (&th, dir); d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0; }
void __init mount_root(void) { struct file_system_type * fs_type; struct super_block * sb; struct vfsmount *vfsmnt; struct inode * d_inode = NULL; struct file filp; int retval; #ifdef CONFIG_ROOT_NFS if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { ROOT_DEV = 0; if ((fs_type = get_fs_type("nfs"))) { sb = get_empty_super(); /* "can't fail" */ sb->s_dev = get_unnamed_dev(); sb->s_flags = root_mountflags; sema_init(&sb->s_vfs_rename_sem,1); vfsmnt = add_vfsmnt(sb, "/dev/root", "/"); if (vfsmnt) { if (nfs_root_mount(sb) >= 0) { sb->s_dirt = 0; sb->s_type = fs_type; current->fs->root = dget(sb->s_root); current->fs->pwd = dget(sb->s_root); ROOT_DEV = sb->s_dev; printk (KERN_NOTICE "VFS: Mounted root (NFS filesystem)%s.\n", (sb->s_flags & MS_RDONLY) ? " readonly" : ""); return; } remove_vfsmnt(sb->s_dev); } put_unnamed_dev(sb->s_dev); sb->s_dev = 0; } if (!ROOT_DEV) { printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); } } #endif #ifdef CONFIG_BLK_DEV_FD if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { #ifdef CONFIG_BLK_DEV_RAM extern int rd_doload; #endif floppy_eject(); #ifndef CONFIG_BLK_DEV_RAM printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n"); #else /* rd_doload is 2 for a dual initrd/ramload setup */ if(rd_doload==2) rd_load_secondary(); else #endif { printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n"); wait_for_keypress(); } } #endif memset(&filp, 0, sizeof(filp)); d_inode = get_empty_inode(); d_inode->i_rdev = ROOT_DEV; filp.f_dentry = NULL; if ( root_mountflags & MS_RDONLY) filp.f_mode = 1; /* read only */ else filp.f_mode = 3; /* read write */ retval = blkdev_open(d_inode, &filp); if (retval == -EROFS) { root_mountflags |= MS_RDONLY; filp.f_mode = 1; retval = blkdev_open(d_inode, &filp); } iput(d_inode); if (retval) /* * Allow the user to distinguish between failed open * and bad superblock on root device. */ printk("VFS: Cannot open root device %s\n", kdevname(ROOT_DEV)); else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) { if (!(fs_type->fs_flags & FS_REQUIRES_DEV)) continue; sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,root_mount_data,1); if (sb) { sb->s_flags = root_mountflags; current->fs->root = dget(sb->s_root); current->fs->pwd = dget(sb->s_root); printk ("VFS: Mounted root (%s filesystem)%s.\n", fs_type->name, (sb->s_flags & MS_RDONLY) ? " readonly" : ""); vfsmnt = add_vfsmnt(sb, "/dev/root", "/"); if (vfsmnt) return; panic("VFS: add_vfsmnt failed for root fs"); } } #ifdef CONFIG_EMPEG_DISPLAY display_bootfail(); #endif panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV)); }
/* * There are two policies for allocating an inode. If the new inode is * a directory, then a forward search is made for a block group with both * free space and a low directory-to-inode ratio; if that fails, then of * the groups with above-average free space, that group with the fewest * directories already is chosen. * * For other inodes, search forward from the parent directory\'s block * group to find a free inode. */ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err) { struct super_block * sb; struct buffer_head * bh; struct buffer_head * bh2; int i, j, avefreei; struct inode * inode; int bitmap_nr; struct ext2_group_desc * gdp; struct ext2_group_desc * tmp; struct ext2_super_block * es; /* Cannot create files in a deleted directory */ if (!dir || !dir->i_nlink) { *err = -EPERM; return NULL; } inode = get_empty_inode (); if (!inode) { *err = -ENOMEM; return NULL; } sb = dir->i_sb; inode->i_sb = sb; inode->i_flags = 0; lock_super (sb); es = sb->u.ext2_sb.s_es; repeat: gdp = NULL; i=0; *err = -ENOSPC; if (S_ISDIR(mode)) { avefreei = le32_to_cpu(es->s_free_inodes_count) / sb->u.ext2_sb.s_groups_count; /* I am not yet convinced that this next bit is necessary. i = dir->u.ext2_i.i_block_group; for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) { tmp = ext2_get_group_desc (sb, i, &bh2); if (tmp && (le16_to_cpu(tmp->bg_used_dirs_count) << 8) < le16_to_cpu(tmp->bg_free_inodes_count)) { gdp = tmp; break; } else i = ++i % sb->u.ext2_sb.s_groups_count; } */ if (!gdp) { for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) { tmp = ext2_get_group_desc (sb, j, &bh2); if (tmp && le16_to_cpu(tmp->bg_free_inodes_count) && le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) { if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) > le16_to_cpu(gdp->bg_free_blocks_count))) { i = j; gdp = tmp; } } } } } else { /* * Try to place the inode in its parent directory */ i = dir->u.ext2_i.i_block_group; tmp = ext2_get_group_desc (sb, i, &bh2); if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) gdp = tmp; else { /* * Use a quadratic hash to find a group with a * free inode */ for (j = 1; j < sb->u.ext2_sb.s_groups_count; j <<= 1) { i += j; if (i >= sb->u.ext2_sb.s_groups_count) i -= sb->u.ext2_sb.s_groups_count; tmp = ext2_get_group_desc (sb, i, &bh2); if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) { gdp = tmp; break; } } } if (!gdp) { /* * That failed: try linear search for a free inode */ i = dir->u.ext2_i.i_block_group + 1; for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) { if (++i >= sb->u.ext2_sb.s_groups_count) i = 0; tmp = ext2_get_group_desc (sb, i, &bh2); if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) { gdp = tmp; break; } } } } if (!gdp) { unlock_super (sb); iput(inode); return NULL; } bitmap_nr = load_inode_bitmap (sb, i); if (bitmap_nr < 0) { unlock_super (sb); iput(inode); *err = -EIO; return NULL; } bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr]; if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data, EXT2_INODES_PER_GROUP(sb))) < EXT2_INODES_PER_GROUP(sb)) { if (ext2_set_bit (j, bh->b_data)) { ext2_warning (sb, "ext2_new_inode", "bit already set for inode %d", j); goto repeat; } mark_buffer_dirty(bh, 1); if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } } else { if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) { ext2_error (sb, "ext2_new_inode", "Free inodes count corrupted in group %d", i); unlock_super (sb); iput (inode); return NULL; } goto repeat; } j += i * EXT2_INODES_PER_GROUP(sb) + 1; if (j < EXT2_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) { ext2_error (sb, "ext2_new_inode", "reserved inode or inode > inodes count - " "block_group = %d,inode=%d", i, j); unlock_super (sb); iput (inode); return NULL; } gdp->bg_free_inodes_count = cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1); if (S_ISDIR(mode)) gdp->bg_used_dirs_count = cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1); mark_buffer_dirty(bh2, 1); es->s_free_inodes_count = cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1); mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); sb->s_dirt = 1; inode->i_mode = mode; inode->i_sb = sb; inode->i_nlink = 1; inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; if (test_opt (sb, GRPID)) inode->i_gid = dir->i_gid; else if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) mode |= S_ISGID; } else inode->i_gid = current->fsgid; inode->i_ino = j; inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */ inode->i_blocks = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->u.ext2_i.i_new_inode = 1; inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags; if (S_ISLNK(mode)) inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL); inode->u.ext2_i.i_faddr = 0; inode->u.ext2_i.i_frag_no = 0; inode->u.ext2_i.i_frag_size = 0; inode->u.ext2_i.i_file_acl = 0; inode->u.ext2_i.i_dir_acl = 0; inode->u.ext2_i.i_dtime = 0; inode->u.ext2_i.i_block_group = i; inode->i_op = NULL; if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) inode->i_flags |= MS_SYNCHRONOUS; insert_inode_hash(inode); mark_inode_dirty(inode); inc_inode_version (inode, gdp, mode); unlock_super (sb); if(DQUOT_ALLOC_INODE(sb, inode)) { sb->dq_op->drop(inode); inode->i_nlink = 0; iput(inode); *err = -EDQUOT; return NULL; } ext2_debug ("allocating inode %lu\n", inode->i_ino); *err = 0; return inode; }
static int ntfs_create(struct inode* dir,struct dentry *d,int mode) { struct inode *r=0; ntfs_inode *ino=0; ntfs_volume *vol; int error=0; ntfs_attribute *si; r=get_empty_inode(); if(!r){ error=ENOMEM; goto fail; } ntfs_debug(DEBUG_OTHER, "ntfs_create %s\n",d->d_name.name); vol=NTFS_INO2VOL(dir); #ifdef NTFS_IN_LINUX_KERNEL ino=NTFS_LINO2NINO(r); #else ino=ntfs_malloc(sizeof(ntfs_inode)); if(!ino){ error=ENOMEM; goto fail; } r->u.generic_ip=ino; #endif error=ntfs_alloc_file(NTFS_LINO2NINO(dir),ino,(char*)d->d_name.name, d->d_name.len); if(error)goto fail; error=ntfs_update_inode(ino); if(error)goto fail; error=ntfs_update_inode(NTFS_LINO2NINO(dir)); if(error)goto fail; r->i_uid=vol->uid; r->i_gid=vol->gid; r->i_nlink=1; r->i_sb=dir->i_sb; /* FIXME: dirty? dev? */ /* get the file modification times from the standard information */ si=ntfs_find_attr(ino,vol->at_standard_information,NULL); if(si){ char *attr=si->d.data; r->i_atime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18)); r->i_ctime=ntfs_ntutc2unixutc(NTFS_GETU64(attr)); r->i_mtime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+8)); } /* It's not a directory */ r->i_op=&ntfs_inode_operations_nobmap; r->i_mode=S_IFREG|S_IRUGO; #ifdef CONFIG_NTFS_RW r->i_mode|=S_IWUGO; #endif r->i_mode &= ~vol->umask; insert_inode_hash(r); d_instantiate(d,r); return 0; fail: #ifndef NTFS_IN_LINUX_KERNEL if(ino)ntfs_free(ino); #endif if(r)iput(r); return -error; }