/* ** looks up the dentry of the parent directory for child. ** taken from ext2_get_parent */ struct dentry *reiserfs_get_parent(struct dentry *child) { int retval; struct inode *inode = NULL; struct reiserfs_dir_entry de; INITIALIZE_PATH(path_to_entry); struct inode *dir = child->d_inode; if (dir->i_nlink == 0) { return ERR_PTR(-ENOENT); } de.de_gen_number_bit_string = NULL; reiserfs_write_lock(dir->i_sb); retval = reiserfs_find_entry(dir, "..", 2, &path_to_entry, &de); pathrelse(&path_to_entry); if (retval != NAME_FOUND) { reiserfs_write_unlock(dir->i_sb); return ERR_PTR(-ENOENT); } inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); reiserfs_write_unlock(dir->i_sb); return d_obtain_alias(inode); }
/* ** looks up the dentry of the parent directory for child. ** taken from ext2_get_parent */ struct dentry *reiserfs_get_parent(struct dentry *child) { int retval; struct inode * inode = NULL; struct reiserfs_dir_entry de; INITIALIZE_PATH (path_to_entry); struct dentry *parent; struct inode *dir = child->d_inode ; if (dir->i_nlink == 0) { return ERR_PTR(-ENOENT); } de.de_gen_number_bit_string = NULL; reiserfs_write_lock(dir->i_sb); retval = reiserfs_find_entry (dir, "..", 2, &path_to_entry, &de); pathrelse (&path_to_entry); if (retval != NAME_FOUND) { reiserfs_write_unlock(dir->i_sb); return ERR_PTR(-ENOENT); } inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); reiserfs_write_unlock(dir->i_sb); if (!inode || IS_ERR(inode)) { return ERR_PTR(-EACCES); } parent = d_alloc_anon(inode); if (!parent) { iput(inode); parent = ERR_PTR(-ENOMEM); } return parent; }
static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { int retval; struct inode *inode = NULL; struct reiserfs_dir_entry de; INITIALIZE_PATH(path_to_entry); if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) return ERR_PTR(-ENAMETOOLONG); reiserfs_write_lock(dir->i_sb); de.de_gen_number_bit_string = NULL; retval = reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de); pathrelse(&path_to_entry); if (retval == NAME_FOUND) { /* Hide the .reiserfs_priv directory */ if (reiserfs_xattrs(dir->i_sb) && !old_format_only(dir->i_sb) && REISERFS_SB(dir->i_sb)->priv_root && REISERFS_SB(dir->i_sb)->priv_root->d_inode && de.de_objectid == le32_to_cpu(INODE_PKEY (REISERFS_SB(dir->i_sb)->priv_root->d_inode)-> k_objectid)) { reiserfs_write_unlock(dir->i_sb); return ERR_PTR(-EACCES); } inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); if (!inode || IS_ERR(inode)) { reiserfs_write_unlock(dir->i_sb); return ERR_PTR(-EACCES); } /* Propogate the priv_object flag so we know we're in the priv tree */ if (is_reiserfs_priv_object(dir)) reiserfs_mark_inode_private(inode); } reiserfs_write_unlock(dir->i_sb); if (retval == IO_ERROR) { return ERR_PTR(-EIO); } return d_splice_alias(inode, dentry); }
/* * Return the root of a filesystem. */ static int reiserfs_root(struct mount *mp, int flags, struct vnode **vpp) { int error; struct vnode *vp; struct cpu_key rootkey; rootkey.on_disk_key.k_dir_id = REISERFS_ROOT_PARENT_OBJECTID; rootkey.on_disk_key.k_objectid = REISERFS_ROOT_OBJECTID; error = reiserfs_iget(mp, &rootkey, &vp, curthread); if (error == 0) *vpp = vp; return (error); }
/* * File handle to vnode * * Have to be really careful about stale file handles: * - check that the inode key is valid * - call ffs_vget() to get the locked inode * - check for an unallocated inode (i_mode == 0) * - check that the given client host has export rights and return * those rights via. exflagsp and credanonp */ static int reiserfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) { int error; struct rfid *rfhp; struct vnode *nvp; struct cpu_key key; struct reiserfs_node *ip; struct reiserfs_sb_info *sbi; struct thread *td = curthread; rfhp = (struct rfid *)fhp; sbi = VFSTOREISERFS(mp)->rm_reiserfs; /* Check that the key is valid */ if (rfhp->rfid_dirid < REISERFS_ROOT_PARENT_OBJECTID && rfhp->rfid_objectid < REISERFS_ROOT_OBJECTID) return (ESTALE); reiserfs_log(LOG_DEBUG, "file handle key is (dirid=%d, objectid=%d)\n", rfhp->rfid_dirid, rfhp->rfid_objectid); key.on_disk_key.k_dir_id = rfhp->rfid_dirid; key.on_disk_key.k_objectid = rfhp->rfid_objectid; reiserfs_log(LOG_DEBUG, "read this inode\n"); error = reiserfs_iget(mp, &key, &nvp, td); if (error) { *vpp = NULLVP; return (error); } reiserfs_log(LOG_DEBUG, "check validity\n"); ip = VTOI(nvp); if (ip->i_mode == 0 || ip->i_generation != rfhp->rfid_gen) { vput(nvp); *vpp = NULLVP; return (ESTALE); } reiserfs_log(LOG_DEBUG, "return it\n"); *vpp = nvp; return (0); }
static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { int retval; int lock_depth; struct inode *inode = NULL; struct reiserfs_dir_entry de; INITIALIZE_PATH(path_to_entry); if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) return ERR_PTR(-ENAMETOOLONG); /* * Might be called with or without the write lock, must be careful * to not recursively hold it in case we want to release the lock * before rescheduling. */ lock_depth = reiserfs_write_lock_once(dir->i_sb); de.de_gen_number_bit_string = NULL; retval = reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de); pathrelse(&path_to_entry); if (retval == NAME_FOUND) { inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); if (!inode || IS_ERR(inode)) { reiserfs_write_unlock_once(dir->i_sb, lock_depth); return ERR_PTR(-EACCES); } /* Propagate the private flag so we know we're * in the priv tree */ if (IS_PRIVATE(dir)) inode->i_flags |= S_PRIVATE; } reiserfs_write_unlock_once(dir->i_sb, lock_depth); if (retval == IO_ERROR) { return ERR_PTR(-EIO); } return d_splice_alias(inode, dentry); }
struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry) { struct inode * inode = 0; struct reiserfs_dir_entry de; struct path path_to_entry; int error; init_path (&path_to_entry); de.de_gen_number_bit_string = 0; error = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de); pathrelse (&path_to_entry); if (error == POSITION_FOUND) { inode = reiserfs_iget (dir->i_sb, (struct key *)&(de.de_dir_id)); if (!inode) return ERR_PTR(-EACCES); } d_add(dentry, inode); return NULL; }
static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { int retval; struct inode *inode = NULL; struct reiserfs_dir_entry de; INITIALIZE_PATH(path_to_entry); if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) return ERR_PTR(-ENAMETOOLONG); reiserfs_write_lock(dir->i_sb); de.de_gen_number_bit_string = NULL; retval = reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de); pathrelse(&path_to_entry); if (retval == NAME_FOUND) { inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&de.de_dir_id); if (!inode || IS_ERR(inode)) { reiserfs_write_unlock(dir->i_sb); return ERR_PTR(-EACCES); } /* * Propagate the private flag so we know we're * in the priv tree */ if (IS_PRIVATE(dir)) inode->i_flags |= S_PRIVATE; } reiserfs_write_unlock(dir->i_sb); if (retval == IO_ERROR) { return ERR_PTR(-EIO); } return d_splice_alias(inode, dentry); }
int reiserfs_lookup(struct vop_cachedlookup_args *ap) { int error, retval; struct vnode *vdp = ap->a_dvp; struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; int flags = cnp->cn_flags; struct thread *td = cnp->cn_thread; struct cpu_key *saved_ino; struct vnode *vp; struct vnode *pdp; /* Saved dp during symlink work */ struct reiserfs_node *dp; struct reiserfs_dir_entry de; INITIALIZE_PATH(path_to_entry); char c = cnp->cn_nameptr[cnp->cn_namelen]; cnp->cn_nameptr[cnp->cn_namelen] = '\0'; reiserfs_log(LOG_DEBUG, "looking for `%s', %ld (%s)\n", cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_pnbuf); cnp->cn_nameptr[cnp->cn_namelen] = c; vp = NULL; dp = VTOI(vdp); if (REISERFS_MAX_NAME(dp->i_reiserfs->s_blocksize) < cnp->cn_namelen) return (ENAMETOOLONG); reiserfs_log(LOG_DEBUG, "searching entry\n"); de.de_gen_number_bit_string = 0; retval = reiserfs_find_entry(dp, cnp->cn_nameptr, cnp->cn_namelen, &path_to_entry, &de); pathrelse(&path_to_entry); if (retval == NAME_FOUND) { reiserfs_log(LOG_DEBUG, "found\n"); } else { reiserfs_log(LOG_DEBUG, "not found\n"); } if (retval == NAME_FOUND) { #if 0 /* Hide the .reiserfs_priv directory */ if (reiserfs_xattrs(dp->i_reiserfs) && !old_format_only(dp->i_reiserfs) && REISERFS_SB(dp->i_reiserfs)->priv_root && REISERFS_SB(dp->i_reiserfs)->priv_root->d_inode && de.de_objectid == le32toh(INODE_PKEY(REISERFS_SB( dp->i_reiserfs)->priv_root->d_inode)->k_objectid)) { return (EACCES); } #endif reiserfs_log(LOG_DEBUG, "reading vnode\n"); pdp = vdp; if (flags & ISDOTDOT) { saved_ino = (struct cpu_key *)&(de.de_dir_id); VOP_UNLOCK(pdp, 0); error = reiserfs_iget(vdp->v_mount, saved_ino, &vp, td); vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); if (error != 0) return (error); *vpp = vp; } else if (de.de_objectid == dp->i_number && de.de_dir_id == dp->i_ino) { VREF(vdp); /* We want ourself, ie "." */ *vpp = vdp; } else { if ((error = reiserfs_iget(vdp->v_mount, (struct cpu_key *)&(de.de_dir_id), &vp, td)) != 0) return (error); *vpp = vp; } /* * Propogate the priv_object flag so we know we're in the * priv tree */ /*if (is_reiserfs_priv_object(dir)) REISERFS_I(inode)->i_flags |= i_priv_object;*/ } else { if (retval == IO_ERROR) { reiserfs_log(LOG_DEBUG, "IO error\n"); return (EIO); } return (ENOENT); } /* Insert name into cache if appropriate. */ if (cnp->cn_flags & MAKEENTRY) cache_enter(vdp, *vpp, cnp); reiserfs_log(LOG_DEBUG, "done\n"); return (0); }
/* look for uncompleted unlinks and truncates and complete them */ static void finish_unfinished (struct super_block * s) { INITIALIZE_PATH (path); struct cpu_key max_cpu_key, obj_key; struct key save_link_key; int retval; struct item_head * ih; struct buffer_head * bh; int item_pos; char * item; int done; struct inode * inode; int truncate; /* compose key to look for "save" links */ max_cpu_key.version = KEY_FORMAT_3_5; max_cpu_key.on_disk_key = MAX_KEY; max_cpu_key.key_length = 3; done = 0; s -> u.reiserfs_sb.s_is_unlinked_ok = 1; while (1) { retval = search_item (s, &max_cpu_key, &path); if (retval != ITEM_NOT_FOUND) { reiserfs_warning ("vs-2140: finish_unfinished: search_by_key returned %d\n", retval); break; } bh = get_last_bh (&path); item_pos = get_item_pos (&path); if (item_pos != B_NR_ITEMS (bh)) { reiserfs_warning ("vs-2060: finish_unfinished: wrong position found\n"); break; } item_pos --; ih = B_N_PITEM_HEAD (bh, item_pos); if (le32_to_cpu (ih->ih_key.k_dir_id) != MAX_KEY_OBJECTID) /* there are no "save" links anymore */ break; save_link_key = ih->ih_key; if (is_indirect_le_ih (ih)) truncate = 1; else truncate = 0; /* reiserfs_iget needs k_dirid and k_objectid only */ item = B_I_PITEM (bh, ih); obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__u32 *)item); obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid); obj_key.on_disk_key.u.k_offset_v1.k_offset = 0; obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0; pathrelse (&path); inode = reiserfs_iget (s, &obj_key); if (!inode) { /* the unlink almost completed, it just did not manage to remove "save" link and release objectid */ reiserfs_warning ("vs-2180: finish_unfinished: iget failed for %K\n", &obj_key); remove_save_link_only (s, &save_link_key, 1); continue; } if (!truncate && inode->i_nlink) { /* file is not unlinked */ reiserfs_warning ("vs-2185: finish_unfinished: file %K is not unlinked\n", &obj_key); remove_save_link_only (s, &save_link_key, 0); continue; } if (truncate && S_ISDIR (inode->i_mode) ) { /* We got a truncate request for a dir which is impossible. The only imaginable way is to execute unfinished truncate request then boot into old kernel, remove the file and create dir with the same key. */ reiserfs_warning("green-2101: impossible truncate on a directory %k. Please report\n", INODE_PKEY (inode)); remove_save_link_only (s, &save_link_key, 0); truncate = 0; iput (inode); continue; } if (truncate) { inode -> u.reiserfs_i.i_flags |= i_link_saved_truncate_mask; /* not completed truncate found. New size was committed together with "save" link */ reiserfs_warning ("Truncating %k to %Ld ..", INODE_PKEY (inode), inode->i_size); reiserfs_truncate_file (inode, 0/*don't update modification time*/); remove_save_link (inode, truncate); } else { inode -> u.reiserfs_i.i_flags |= i_link_saved_unlink_mask; /* not completed unlink (rmdir) found */ reiserfs_warning ("Removing %k..", INODE_PKEY (inode)); /* removal gets completed in iput */ } iput (inode); printk ("done\n"); done ++; } s -> u.reiserfs_sb.s_is_unlinked_ok = 0; pathrelse (&path); if (done) reiserfs_warning ("There were %d uncompleted unlinks/truncates. " "Completed\n", done); }