inode.c

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

C
1,950
字号
    if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))        set_sd_v1_rdev(sd_v1, new_encode_dev(inode->i_rdev));    else        set_sd_v1_blocks(sd_v1, to_fake_used_blocks(inode, SD_V1_SIZE));    // Sigh. i_first_direct_byte is back    set_sd_v1_first_direct_byte(sd_v1, REISERFS_I(inode)->i_first_direct_byte);}/* NOTE, you must prepare the buffer head before sending it here,** and then log it after the call*/static void update_stat_data (struct path * path, struct inode * inode,                              loff_t size){    struct buffer_head * bh;    struct item_head * ih;      bh = PATH_PLAST_BUFFER (path);    ih = PATH_PITEM_HEAD (path);    if (!is_statdata_le_ih (ih))	reiserfs_panic (inode->i_sb, "vs-13065: update_stat_data: key %k, found item %h",			INODE_PKEY (inode), ih);      if (stat_data_v1 (ih)) {	// path points to old stat data	inode2sd_v1 (B_I_PITEM (bh, ih), inode, size);    } else {	inode2sd (B_I_PITEM (bh, ih), inode, size);    }    return;}void reiserfs_update_sd_size (struct reiserfs_transaction_handle *th,			      struct inode * inode, loff_t size){    struct cpu_key key;    INITIALIZE_PATH(path);    struct buffer_head *bh ;    int fs_gen ;    struct item_head *ih, tmp_ih ;    int retval;    make_cpu_key (&key, inode, SD_OFFSET, TYPE_STAT_DATA, 3);//key type is unimportant        for(;;) {	int pos;	/* look for the object's stat data */	retval = search_item (inode->i_sb, &key, &path);	if (retval == IO_ERROR) {	    reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: "			      "i/o failure occurred trying to update %K stat data",			      &key);	    return;	}	if (retval == ITEM_NOT_FOUND) {	    pos = PATH_LAST_POSITION (&path);	    pathrelse(&path) ;	    if (inode->i_nlink == 0) {		/*reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found");*/		return;	    }	    reiserfs_warning (inode->i_sb, "vs-13060: reiserfs_update_sd: "			      "stat data of object %k (nlink == %d) not found (pos %d)",			      INODE_PKEY (inode), inode->i_nlink, pos);	    reiserfs_check_path(&path) ;	    return;	}		/* sigh, prepare_for_journal might schedule.  When it schedules the	** FS might change.  We have to detect that, and loop back to the	** search if the stat data item has moved	*/	bh = get_last_bh(&path) ;	ih = get_ih(&path) ;	copy_item_head (&tmp_ih, ih);	fs_gen = get_generation (inode->i_sb);	reiserfs_prepare_for_journal(inode->i_sb, bh, 1) ;	if (fs_changed (fs_gen, inode->i_sb) && item_moved(&tmp_ih, &path)) {	    reiserfs_restore_prepared_buffer(inode->i_sb, bh) ;	    continue ;	/* Stat_data item has been moved after scheduling. */	}	break;    }    update_stat_data (&path, inode, size);    journal_mark_dirty(th, th->t_super, bh) ;     pathrelse (&path);    return;}/* reiserfs_read_locked_inode is called to read the inode off disk, and it** does a make_bad_inode when things go wrong.  But, we need to make sure** and clear the key in the private portion of the inode, otherwise a** corresponding iput might try to delete whatever object the inode last** represented.*/static void reiserfs_make_bad_inode(struct inode *inode) {    memset(INODE_PKEY(inode), 0, KEY_SIZE);    make_bad_inode(inode);}//// initially this function was derived from minix or ext2's analog and// evolved as the prototype did//int reiserfs_init_locked_inode (struct inode * inode, void *p){    struct reiserfs_iget_args *args = (struct reiserfs_iget_args *)p ;    inode->i_ino = args->objectid;    INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->dirid);    return 0;}/* looks for stat data in the tree, and fills up the fields of in-core   inode stat data fields */void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args *args){    INITIALIZE_PATH (path_to_sd);    struct cpu_key key;    unsigned long dirino;    int retval;    dirino = args->dirid ;    /* set version 1, version 2 could be used too, because stat data       key is the same in both versions */    key.version = KEY_FORMAT_3_5;    key.on_disk_key.k_dir_id = dirino;    key.on_disk_key.k_objectid = inode->i_ino;    key.on_disk_key.u.k_offset_v1.k_offset = SD_OFFSET;    key.on_disk_key.u.k_offset_v1.k_uniqueness = SD_UNIQUENESS;    /* look for the object's stat data */    retval = search_item (inode->i_sb, &key, &path_to_sd);    if (retval == IO_ERROR) {	reiserfs_warning (inode->i_sb, "vs-13070: reiserfs_read_locked_inode: "			  "i/o failure occurred trying to find stat data of %K",			  &key);	reiserfs_make_bad_inode(inode) ;	return;    }    if (retval != ITEM_FOUND) {	/* a stale NFS handle can trigger this without it being an error */	pathrelse (&path_to_sd);	reiserfs_make_bad_inode(inode) ;	inode->i_nlink = 0;	return;    }    init_inode (inode, &path_to_sd);       /* It is possible that knfsd is trying to access inode of a file       that is being removed from the disk by some other thread. As we       update sd on unlink all that is required is to check for nlink       here. This bug was first found by Sizif when debugging       SquidNG/Butterfly, forgotten, and found again after Philippe       Gramoulle <philippe.gramoulle@mmania.com> reproduced it.        More logical fix would require changes in fs/inode.c:iput() to       remove inode from hash-table _after_ fs cleaned disk stuff up and       in iget() to return NULL if I_FREEING inode is found in       hash-table. */    /* Currently there is one place where it's ok to meet inode with       nlink==0: processing of open-unlinked and half-truncated files       during mount (fs/reiserfs/super.c:finish_unfinished()). */    if( ( inode -> i_nlink == 0 ) && 	! REISERFS_SB(inode -> i_sb) -> s_is_unlinked_ok ) {	    reiserfs_warning (inode->i_sb,			      "vs-13075: reiserfs_read_locked_inode: "			      "dead inode read from disk %K. "			      "This is likely to be race with knfsd. Ignore",			      &key );	    reiserfs_make_bad_inode( inode );    }    reiserfs_check_path(&path_to_sd) ; /* init inode should be relsing */}/** * reiserfs_find_actor() - "find actor" reiserfs supplies to iget5_locked(). * * @inode:    inode from hash table to check * @opaque:   "cookie" passed to iget5_locked(). This is &reiserfs_iget_args. * * This function is called by iget5_locked() to distinguish reiserfs inodes * having the same inode numbers. Such inodes can only exist due to some * error condition. One of them should be bad. Inodes with identical * inode numbers (objectids) are distinguished by parent directory ids. * */int reiserfs_find_actor( struct inode *inode, void *opaque ){    struct reiserfs_iget_args *args;    args = opaque;    /* args is already in CPU order */    return (inode->i_ino == args->objectid) &&	(le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args->dirid);}struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key){    struct inode * inode;    struct reiserfs_iget_args args ;    args.objectid = key->on_disk_key.k_objectid ;    args.dirid = key->on_disk_key.k_dir_id ;    inode = iget5_locked (s, key->on_disk_key.k_objectid, 		   reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));    if (!inode) 	return ERR_PTR(-ENOMEM) ;    if (inode->i_state & I_NEW) {	reiserfs_read_locked_inode(inode, &args);	unlock_new_inode(inode);    }    if (comp_short_keys (INODE_PKEY (inode), key) || is_bad_inode (inode)) {	/* either due to i/o error or a stale NFS handle */	iput (inode);	inode = NULL;    }    return inode;}struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp){    __u32 *data = vobjp;    struct cpu_key key ;    struct dentry *result;    struct inode *inode;        key.on_disk_key.k_objectid = data[0] ;    key.on_disk_key.k_dir_id = data[1] ;    inode = reiserfs_iget(sb, &key) ;    if (inode && !IS_ERR(inode) && data[2] != 0 &&	data[2] != inode->i_generation) {	    iput(inode) ;	    inode = NULL ;    }    if (!inode)	    inode = ERR_PTR(-ESTALE);    if (IS_ERR(inode))	    return ERR_PTR(PTR_ERR(inode));    result = d_alloc_anon(inode);    if (!result) {	    iput(inode);	    return ERR_PTR(-ENOMEM);    }    return result;}struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 *data,                                     int len, int fhtype,				  int (*acceptable)(void *contect, struct dentry *de),				  void *context) {    __u32 obj[3], parent[3];    /* fhtype happens to reflect the number of u32s encoded.     * due to a bug in earlier code, fhtype might indicate there     * are more u32s then actually fitted.     * so if fhtype seems to be more than len, reduce fhtype.     * Valid types are:     *   2 - objectid + dir_id - legacy support     *   3 - objectid + dir_id + generation     *   4 - objectid + dir_id + objectid and dirid of parent - legacy     *   5 - objectid + dir_id + generation + objectid and dirid of parent     *   6 - as above plus generation of directory     * 6 does not fit in NFSv2 handles     */    if (fhtype > len) {	    if (fhtype != 6 || len != 5)		    reiserfs_warning (sb, "nfsd/reiserfs, fhtype=%d, len=%d - odd",			   fhtype, len);	    fhtype = 5;    }    obj[0] = data[0];    obj[1] = data[1];    if (fhtype == 3 || fhtype >= 5)	    obj[2] = data[2];    else    obj[2] = 0; /* generation number */    if (fhtype >= 4) {	    parent[0] = data[fhtype>=5?3:2] ;	    parent[1] = data[fhtype>=5?4:3] ;	    if (fhtype == 6)		    parent[2] = data[5];	    else    parent[2] = 0;    }    return sb->s_export_op->find_exported_dentry(sb, obj, fhtype < 4 ? NULL : parent,			       acceptable, context);}int reiserfs_encode_fh(struct dentry *dentry, __u32 *data, int *lenp, int need_parent) {    struct inode *inode = dentry->d_inode ;    int maxlen = *lenp;        if (maxlen < 3)        return 255 ;    data[0] = inode->i_ino ;    data[1] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ;    data[2] = inode->i_generation ;    *lenp = 3 ;    /* no room for directory info? return what we've stored so far */    if (maxlen < 5 || ! need_parent)        return 3 ;    spin_lock(&dentry->d_lock);    inode = dentry->d_parent->d_inode ;    data[3] = inode->i_ino ;    data[4] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ;    *lenp = 5 ;    if (maxlen >= 6) {	    data[5] = inode->i_generation ;	    *lenp = 6 ;    }    spin_unlock(&dentry->d_lock);    return *lenp ;}/* looks for stat data, then copies fields to it, marks the buffer   containing stat data as dirty *//* reiserfs inodes are never really dirty, since the dirty inode call** always logs them.  This call allows the VFS inode marking routines** to properly mark inodes for datasync and such, but only actually** does something when called for a synchronous update.*/int reiserfs_write_inode (struct inode * inode, int do_sync) {    struct reiserfs_transaction_handle th ;    int jbegin_count = 1 ;    if (inode->i_sb->s_flags & MS_RDONLY) {        reiserfs_warning (inode->i_sb,			  "clm-6005: writing inode %lu on readonly FS",			  inode->i_ino) ;        return -EROFS;    }    /* memory pressure can sometimes initiate write_inode calls with sync == 1,    ** these cases are just when the system needs ram, not when the     ** inode needs to reach disk for safety, and they can safely be    ** ignored because the altered inode has already been logged.    */    if (do_sync && !(current->flags & PF_MEMALLOC)) {	reiserfs_write_lock(inode->i_sb);	journal_begin(&th, inode->i_sb, jbegin_count) ;	reiserfs_update_sd (&th, inode);	journal_end_sync(&th, inode->i_sb, jbegin_count) ;	reiserfs_write_unlock(inode->i_sb);    }    return 0;}/* FIXME: no need any more. right? */int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * inode){  int err = 0;  reiserfs_update_sd (th, inode);  return err;}/* stat data of new object is inserted already, this inserts the item   containing "." and ".." entries */static int reiserfs_new_directory (struct reiserfs_transaction_handle *th, 				   struct inode *inode,				   struct item_head * ih, struct path * path,				   struct inode * dir){    struct super_block * sb = th->t_super;    char empty_dir [EMPTY_DIR_SIZE];    char * body = empty_dir;    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), DOT_OFFSET, TYPE_DIRENTRY, 3/*key length*/);        /* compose item head for new item. Directories consist of items of       old type (ITEM_VERSION_1). Do not set key (second arg is 0), it       is done by reiserfs_new_inode */

⌨️ 快捷键说明

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