📄 inode.c
字号:
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 treepath *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; BUG_ON(!th->t_trans_id); 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.k_offset = 0; key.on_disk_key.k_type = 0; /* 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;}static struct dentry *reiserfs_get_dentry(struct super_block *sb, u32 objectid, u32 dir_id, u32 generation){ struct cpu_key key; struct dentry *result; struct inode *inode; key.on_disk_key.k_objectid = objectid; key.on_disk_key.k_dir_id = dir_id; reiserfs_write_lock(sb); inode = reiserfs_iget(sb, &key); if (inode && !IS_ERR(inode) && generation != 0 && generation != inode->i_generation) { iput(inode); inode = NULL; } reiserfs_write_unlock(sb); 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_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type){ /* 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 (fh_type > fh_len) { if (fh_type != 6 || fh_len != 5) reiserfs_warning(sb, "nfsd/reiserfs, fhtype=%d, len=%d - odd", fh_type, fh_len); fh_type = 5; } return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0);}struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fh_type){ if (fh_type < 4) return NULL; return reiserfs_get_dentry(sb, (fh_type >= 5) ? fid->raw[3] : fid->raw[2], (fh_type >= 5) ? fid->raw[4] : fid->raw[3], (fh_type == 6) ? fid->raw[5] : 0);}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) 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); if (!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;}/* 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 treepath *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; BUG_ON(!th->t_trans_id); _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 */ 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -