📄 inode.c
字号:
/* either due to i/o error or a stale NFS handle */ iput (inode); inode = 0; } return inode;}struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, __u32 *data, int len, int fhtype, int parent) { struct cpu_key key ; struct inode *inode = NULL ; struct list_head *lp; struct dentry *result; /* 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) printk(KERN_WARNING "nfsd/reiserfs, fhtype=%d, len=%d - odd\n", fhtype, len); fhtype = 5; } if (fhtype < 2 || (parent && fhtype < 4)) goto out ; if (! parent) { /* this works for handles from old kernels because the default ** reiserfs generation number is the packing locality. */ 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) && (fhtype == 3 || fhtype >= 5) && data[2] != inode->i_generation) { iput(inode) ; inode = NULL ; } } else { key.on_disk_key.k_objectid = data[fhtype>=5?3:2] ; key.on_disk_key.k_dir_id = data[fhtype>=5?4:3] ; inode = reiserfs_iget(sb, &key) ; if (inode && !IS_ERR(inode) && fhtype == 6 && data[5] != inode->i_generation) { iput(inode) ; inode = NULL ; } }out: if (IS_ERR(inode)) return ERR_PTR(PTR_ERR(inode)); if (!inode) return ERR_PTR(-ESTALE) ; /* now to find a dentry. * If possible, get a well-connected one */ spin_lock(&dcache_lock); for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { result = list_entry(lp,struct dentry, d_alias); if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) { dget_locked(result); result->d_vfs_flags |= DCACHE_REFERENCED; spin_unlock(&dcache_lock); iput(inode); return result; } } spin_unlock(&dcache_lock); result = d_alloc_root(inode); if (result == NULL) { iput(inode); return ERR_PTR(-ENOMEM); } result->d_flags |= DCACHE_NFSD_DISCONNECTED; return result;}int reiserfs_dentry_to_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 ; 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) return 5 ; data[5] = inode->i_generation ; *lenp = 6 ; return 6 ;}//// initially this function was derived from minix or ext2's analog and// evolved as the prototype did///* 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.*/void 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("clm-6005: writing inode %lu on readonly FS\n", inode->i_ino) ; return ; } /* 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)) { lock_kernel() ; journal_begin(&th, inode->i_sb, jbegin_count) ; reiserfs_update_sd (&th, inode); journal_end_sync(&th, inode->i_sb, jbegin_count) ; unlock_kernel() ; }}/* 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 item_head * ih, struct path * path, const 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 */ if (old_format_only (sb)) { make_le_item_head (ih, 0, 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, 0, 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 ("vs-13080: reiserfs_new_directory: " "i/o failure occurred creating new directory\n"); return -EIO; } if (retval == ITEM_FOUND) { pathrelse (path); reiserfs_warning ("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, 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 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, 0, 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 ("vs-13080: reiserfs_new_symlinik: " "i/o failure occurred creating new symlink\n"); return -EIO; } if (retval == ITEM_FOUND) { pathrelse (path); reiserfs_warning ("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, 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) */struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th, const struct inode * dir, int mode, const char * symname, int i_size, /* 0 for regular, EMTRY_DIR_SIZE for dirs, strlen (symname) for symlinks)*/ struct dentry *dentry, struct inode *inode, int * err){ struct super_block * sb; INITIALIZE_PATH (path_to_key); struct cpu_key key; struct item_head ih; struct stat_data sd; int retval; if (!dir || !dir->i_nlink) { *err = -EPERM; iput(inode) ; return NULL; } sb = dir->i_sb; inode->i_flags = 0;//inode->i_sb->s_flags; /* item head of new item */ ih.ih_key.k_dir_id = INODE_PKEY (dir)->k_objectid; ih.ih_key.k_objectid = cpu_to_le32 (reiserfs_get_unused_objectid (th)); if (!ih.ih_key.k_objectid) { iput(inode) ; *err = -ENOMEM; return NULL; } 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( sb -> u.reiserfs_sb.s_rs -> s_inode_generation );#else inode->i_generation = ++event;#endif if (old_format_only (sb)) make_le_item_head (&ih, 0, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT); else make_le_item_head (&ih, 0, 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) { iput (inode); *err = -EIO; return NULL; } if (retval == ITEM_FOUND) { pathrelse (&path_to_key); iput (inode); *err = -EEXIST; return NULL; } /* fill stat data */ inode->i_mode = mode; inode->i_nlink = (S_ISDIR (mode) ? 2 : 1); inode->i_uid = current->fsuid; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) inode->i_mode |= S_ISGID; } else inode->i_gid = current->fsgid; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_size = i_size; inode->i_blocks = (inode->i_size + 511) >> 9; inode->u.reiserfs_i.i_first_direct_byte = S_ISLNK(mode) ? 1 : U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/; INIT_LIST_HEAD(&inode->u.reiserfs_i.i_prealloc_list) ; 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 */ iput (inode); *err = -EINVAL; return NULL; } inode2sd_v1 (&sd, inode); } else inode2sd (&sd, inode); // these do not go to on-disk stat data inode->i_ino = le32_to_cpu (ih.ih_key.k_objectid); inode->i_blksize = PAGE_SIZE; inode->i_dev = sb->s_dev; // 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 */ retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, (char *)(&sd)); if (retval) { iput (inode); *err = retval; reiserfs_check_path(&path_to_key) ; return NULL; } if (S_ISDIR(mode)) { /* insert item with "." and ".." */ retval = reiserfs_new_directory (th, &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, &ih, &path_to_key, symname, i_size); } if (retval) { inode->i_nlink = 0; iput (inode); *err = retval; reiserfs_check_path(&path_to_key) ; return NULL; } insert_inode_hash (inode); // we do not mark inode dirty: on disk content matches to the // in-core one reiserfs_check_path(&path_to_key) ; return inode;}/*** finds the tail page in the page cache,** reads the last block in.**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -