inode.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,950 行 · 第 1/5 页

C
1,950
字号
    if (old_format_only (sb)) {	make_le_item_head (ih, NULL, KEY_FORMAT_3_5, DOT_OFFSET, TYPE_DIRENTRY, EMPTY_DIR_SIZE_V1, 2);		make_empty_dir_item_v1 (body, ih->ih_key.k_dir_id, ih->ih_key.k_objectid,				INODE_PKEY (dir)->k_dir_id, 				INODE_PKEY (dir)->k_objectid );    } else {	make_le_item_head (ih, NULL, KEY_FORMAT_3_5, DOT_OFFSET, TYPE_DIRENTRY, EMPTY_DIR_SIZE, 2);		make_empty_dir_item (body, ih->ih_key.k_dir_id, ih->ih_key.k_objectid,		   		INODE_PKEY (dir)->k_dir_id, 		   		INODE_PKEY (dir)->k_objectid );    }        /* look for place in the tree for new item */    retval = search_item (sb, &key, path);    if (retval == IO_ERROR) {	reiserfs_warning (sb, "vs-13080: reiserfs_new_directory: "			  "i/o failure occurred creating new directory");	return -EIO;    }    if (retval == ITEM_FOUND) {	pathrelse (path);	reiserfs_warning (sb, "vs-13070: reiserfs_new_directory: "			  "object with this key exists (%k)", &(ih->ih_key));	return -EEXIST;    }    /* insert item, that is empty directory item */    return reiserfs_insert_item (th, path, &key, ih, inode, body);}/* stat data of object has been inserted, this inserts the item   containing the body of symlink */static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th, 				 struct inode *inode,	/* Inode of symlink */				 struct item_head * ih,				 struct path * path, const char * symname, int item_len){    struct super_block * sb = th->t_super;    struct cpu_key key;    int retval;    _make_cpu_key (&key, KEY_FORMAT_3_5, 		   le32_to_cpu (ih->ih_key.k_dir_id), 		   le32_to_cpu (ih->ih_key.k_objectid),		   1, TYPE_DIRECT, 3/*key length*/);    make_le_item_head (ih, NULL, KEY_FORMAT_3_5, 1, TYPE_DIRECT, item_len, 0/*free_space*/);    /* look for place in the tree for new item */    retval = search_item (sb, &key, path);    if (retval == IO_ERROR) {	reiserfs_warning (sb, "vs-13080: reiserfs_new_symlinik: "			  "i/o failure occurred creating new symlink");	return -EIO;    }    if (retval == ITEM_FOUND) {	pathrelse (path);	reiserfs_warning (sb, "vs-13080: reiserfs_new_symlink: "			  "object with this key exists (%k)", &(ih->ih_key));	return -EEXIST;    }    /* insert item, that is body of symlink */    return reiserfs_insert_item (th, path, &key, ih, inode, symname);}/* inserts the stat data into the tree, and then calls   reiserfs_new_directory (to insert ".", ".." item if new object is   directory) or reiserfs_new_symlink (to insert symlink body if new   object is symlink) or nothing (if new object is regular file)    NOTE! uid and gid must already be set in the inode.  If we return   non-zero due to an error, we have to drop the quota previously allocated   for the fresh inode.  This can only be done outside a transaction, so   if we return non-zero, we also end the transaction.  */int reiserfs_new_inode (struct reiserfs_transaction_handle *th,			struct inode * dir, int mode, 			const char * symname,                         /* 0 for regular, EMTRY_DIR_SIZE for dirs, 			   strlen (symname) for symlinks)*/		         loff_t i_size, struct dentry *dentry, 			 struct inode *inode){    struct super_block * sb;    INITIALIZE_PATH (path_to_key);    struct cpu_key key;    struct item_head ih;    struct stat_data sd;    int retval;    int err;      if (!dir || !dir->i_nlink) {	err = -EPERM;	goto out_bad_inode;    }    sb = dir->i_sb;    /* item head of new item */    ih.ih_key.k_dir_id = reiserfs_choose_packing(dir);    ih.ih_key.k_objectid = cpu_to_le32 (reiserfs_get_unused_objectid (th));    if (!ih.ih_key.k_objectid) {	err = -ENOMEM;	goto out_bad_inode ;    }    if (old_format_only (sb))	/* not a perfect generation count, as object ids can be reused, but 	** this is as good as reiserfs can do right now.	** note that the private part of inode isn't filled in yet, we have	** to use the directory.	*/	inode->i_generation = le32_to_cpu (INODE_PKEY (dir)->k_objectid);    else#if defined( USE_INODE_GENERATION_COUNTER )	inode->i_generation = le32_to_cpu(REISERFS_SB(sb)->s_rs->s_inode_generation);#else	inode->i_generation = ++event;#endif    /* fill stat data */    inode->i_nlink = (S_ISDIR (mode) ? 2 : 1);    /* uid and gid must already be set by the caller for quota init */    /* symlink cannot be immutable or append only, right? */    if( S_ISLNK( inode -> i_mode ) )	    inode -> i_flags &= ~ ( S_IMMUTABLE | S_APPEND );    inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;    inode->i_size = i_size;    inode->i_blocks = 0;    inode->i_bytes = 0;    REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 :       U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/;    INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list ));    REISERFS_I(inode)->i_flags = 0;    REISERFS_I(inode)->i_prealloc_block = 0;    REISERFS_I(inode)->i_prealloc_count = 0;    REISERFS_I(inode)->i_trans_id = 0;    REISERFS_I(inode)->i_jl = NULL;    REISERFS_I(inode)->i_attrs =	REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;    sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode );    REISERFS_I(inode)->i_acl_access = NULL;    REISERFS_I(inode)->i_acl_default = NULL;    init_rwsem (&REISERFS_I(inode)->xattr_sem);    if (old_format_only (sb))	make_le_item_head (&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);    else	make_le_item_head (&ih, NULL, KEY_FORMAT_3_6, SD_OFFSET, TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);    /* key to search for correct place for new stat data */    _make_cpu_key (&key, KEY_FORMAT_3_6, le32_to_cpu (ih.ih_key.k_dir_id),		   le32_to_cpu (ih.ih_key.k_objectid), SD_OFFSET, TYPE_STAT_DATA, 3/*key length*/);    /* find proper place for inserting of stat data */    retval = search_item (sb, &key, &path_to_key);    if (retval == IO_ERROR) {	err = -EIO;	goto out_bad_inode;    }    if (retval == ITEM_FOUND) {	pathrelse (&path_to_key);	err = -EEXIST;	goto out_bad_inode;    }    if (old_format_only (sb)) {	if (inode->i_uid & ~0xffff || inode->i_gid & ~0xffff) {	    pathrelse (&path_to_key);	    /* i_uid or i_gid is too big to be stored in stat data v3.5 */	    err = -EINVAL;	    goto out_bad_inode;	}	inode2sd_v1 (&sd, inode, inode->i_size);    } else {	inode2sd (&sd, inode, inode->i_size);    }    // these do not go to on-disk stat data    inode->i_ino = le32_to_cpu (ih.ih_key.k_objectid);    inode->i_blksize = reiserfs_default_io_size;      // store in in-core inode the key of stat data and version all    // object items will have (directory items will have old offset    // format, other new objects will consist of new items)    memcpy (INODE_PKEY (inode), &(ih.ih_key), KEY_SIZE);    if (old_format_only (sb) || S_ISDIR(mode) || S_ISLNK(mode))        set_inode_item_key_version (inode, KEY_FORMAT_3_5);    else        set_inode_item_key_version (inode, KEY_FORMAT_3_6);    if (old_format_only (sb))	set_inode_sd_version (inode, STAT_DATA_V1);    else	set_inode_sd_version (inode, STAT_DATA_V2);        /* insert the stat data into the tree */#ifdef DISPLACE_NEW_PACKING_LOCALITIES    if (REISERFS_I(dir)->new_packing_locality)	th->displace_new_blocks = 1;#endif    retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, inode, (char *)(&sd));    if (retval) {	err = retval;	reiserfs_check_path(&path_to_key) ;	goto out_bad_inode;    }#ifdef DISPLACE_NEW_PACKING_LOCALITIES    if (!th->displace_new_blocks)	REISERFS_I(dir)->new_packing_locality = 0;#endif    if (S_ISDIR(mode)) {	/* insert item with "." and ".." */	retval = reiserfs_new_directory (th, inode, &ih, &path_to_key, dir);    }    if (S_ISLNK(mode)) {	/* insert body of symlink */	if (!old_format_only (sb))	    i_size = ROUND_UP(i_size);	retval = reiserfs_new_symlink (th, inode, &ih, &path_to_key, symname, i_size);    }    if (retval) {	err = retval;	reiserfs_check_path(&path_to_key) ;	journal_end(th, th->t_super, th->t_blocks_allocated);	goto out_inserted_sd;    }    /* XXX CHECK THIS */    if (reiserfs_posixacl (inode->i_sb)) {        retval = reiserfs_inherit_default_acl (dir, dentry, inode);        if (retval) {            err = retval;            reiserfs_check_path(&path_to_key) ;            journal_end(th, th->t_super, th->t_blocks_allocated);            goto out_inserted_sd;        }    } else if (inode->i_sb->s_flags & MS_POSIXACL) {	reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, "			  "but vfs thinks they are!");    }    insert_inode_hash (inode);    reiserfs_update_sd(th, inode);    reiserfs_check_path(&path_to_key) ;    return 0;/* it looks like you can easily compress these two goto targets into * one.  Keeping it like this doesn't actually hurt anything, and they * are place holders for what the quota code actually needs. */out_bad_inode:    /* Invalidate the object, nothing was inserted yet */    INODE_PKEY(inode)->k_objectid = 0;    /* dquot_drop must be done outside a transaction */    journal_end(th, th->t_super, th->t_blocks_allocated) ;    DQUOT_FREE_INODE(inode);    DQUOT_DROP(inode);    inode->i_flags |= S_NOQUOTA;    make_bad_inode(inode);out_inserted_sd:    inode->i_nlink = 0;    th->t_trans_id = 0; /* so the caller can't use this handle later */    iput(inode);    return err;}/*** finds the tail page in the page cache,** reads the last block in.**** On success, page_result is set to a locked, pinned page, and bh_result** is set to an up to date buffer for the last block in the file.  returns 0.**** tail conversion is not done, so bh_result might not be valid for writing** check buffer_mapped(bh_result) and bh_result->b_blocknr != 0 before** trying to write the block.**** on failure, nonzero is returned, page_result and bh_result are untouched.*/static int grab_tail_page(struct inode *p_s_inode, 			  struct page **page_result, 			  struct buffer_head **bh_result) {    /* we want the page with the last byte in the file,    ** not the page that will hold the next byte for appending    */    unsigned long index = (p_s_inode->i_size-1) >> PAGE_CACHE_SHIFT ;    unsigned long pos = 0 ;    unsigned long start = 0 ;    unsigned long blocksize = p_s_inode->i_sb->s_blocksize ;    unsigned long offset = (p_s_inode->i_size) & (PAGE_CACHE_SIZE - 1) ;    struct buffer_head *bh ;    struct buffer_head *head ;    struct page * page ;    int error ;        /* we know that we are only called with inode->i_size > 0.    ** we also know that a file tail can never be as big as a block    ** If i_size % blocksize == 0, our file is currently block aligned    ** and it won't need converting or zeroing after a truncate.    */    if ((offset & (blocksize - 1)) == 0) {        return -ENOENT ;    }    page = grab_cache_page(p_s_inode->i_mapping, index) ;    error = -ENOMEM ;    if (!page) {        goto out ;    }    /* start within the page of the last block in the file */    start = (offset / blocksize) * blocksize ;    error = block_prepare_write(page, start, offset, 				reiserfs_get_block_create_0) ;    if (error)	goto unlock ;    head = page_buffers(page) ;          bh = head;    do {	if (pos >= start) {	    break ;	}	bh = bh->b_this_page ;	pos += blocksize ;    } while(bh != head) ;    if (!buffer_uptodate(bh)) {	/* note, this should never happen, prepare_write should	** be taking care of this for us.  If the buffer isn't up to date,	** I've screwed up the code to find the buffer, or the code to	** call prepare_write	*/	reiserfs_warning (p_s_inode->i_sb,			  "clm-6000: error reading block %lu on dev %s",			  bh->b_blocknr,			  reiserfs_bdevname (p_s_inode->i_sb)) ;	error = -EIO ;	goto unlock ;    }    *bh_result = bh ;    *page_result = page ;out:    return error ;unlock:    unlock_page(page) ;    page_cache_release(page) ;    return error ;}/*** vfs version of truncate file.  Must NOT be called with** a transaction already started.**** some code taken from block_truncate_page*/void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {    struct reiserfs_transaction_handle th ;    /* we want the offset for the first byte after the end of the file */    unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1) ;    unsigned blocksize = p_s_inode->i_sb->s_blocksize ;    unsigned length ;    struct page *page = NULL ;    int error ;    struct buffer_head *bh = NULL ;    reiserfs_write_lock(p_s_inode->i_sb);    if (p_s_inode->i_size > 0) {        if ((error = grab_tail_page(p_s_inode, &page, &bh))) {	    // -ENOENT means we truncated past the end of the file, 	    // and get_block_create_0 could not find a block to read in,	    // which is ok.	    if (error != -ENOENT)	        reiserfs_warning (p_s_inode->i_sb,				  "clm-6001: grab_tail_page failed %d",				  error);	    page = NULL ;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?