Beispiel #1
0
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);
}
Beispiel #2
0
static void handle_attrs( struct super_block *s )
{
	struct reiserfs_super_block * rs;

	if( reiserfs_attrs( s ) ) {
		rs = SB_DISK_SUPER_BLOCK (s);
		if( old_format_only(s) ) {
			reiserfs_warning( "reiserfs: cannot support attributes on 3.5.x disk format\n" );
			s -> u.reiserfs_sb.s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
			return;
		}
		if( !( le32_to_cpu( rs -> s_flags ) & reiserfs_attrs_cleared ) ) {
				reiserfs_warning( "reiserfs: cannot support attributes until flag is set in super-block\n" );
				s -> u.reiserfs_sb.s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
		}
	}
}
Beispiel #3
0
static int xattr_mount_check(struct super_block *s)
{
	/* We need generation numbers to ensure that the oid mapping is correct
	 * v3.5 filesystems don't have them. */
	if (old_format_only(s)) {
		if (reiserfs_xattrs_optional(s)) {
			/* Old format filesystem, but optional xattrs have
			 * been enabled. Error out. */
			reiserfs_warning(s, "jdm-2005",
					 "xattrs/ACLs not supported "
					 "on pre-v3.6 format filesystems. "
					 "Failing mount.");
			return -EOPNOTSUPP;
		}
	}

	return 0;
}
Beispiel #4
0
int reiserfs_version_in_proc( char *buffer, char **start, off_t offset,
			      int count, int *eof, void *data )
{
	int len = 0;
	struct super_block *sb;
    
	sb = procinfo_prologue( ( kdev_t ) ( int ) data );
	if( sb == NULL )
		return -ENOENT;
	len += sprintf( &buffer[ len ], "%s format\twith checks %s\n",
			old_format_only( sb ) ? "old" : "new",
#if defined( CONFIG_REISERFS_CHECK )
			"on"
#else
			"off"
#endif
		);
	procinfo_epilogue( sb );
	return reiserfs_proc_tail( len, buffer, start, offset, count, eof );
}
Beispiel #5
0
static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
	struct inode *inode = filp->f_path.dentry->d_inode;
	struct cpu_key pos_key;	/* key of current position in the directory (key of directory entry) */
	INITIALIZE_PATH(path_to_entry);
	struct buffer_head *bh;
	int item_num, entry_num;
	const struct reiserfs_key *rkey;
	struct item_head *ih, tmp_ih;
	int search_res;
	char *local_buf;
	loff_t next_pos;
	char small_buf[32];	/* avoid kmalloc if we can */
	struct reiserfs_dir_entry de;
	int ret = 0;

	reiserfs_write_lock(inode->i_sb);

	reiserfs_check_lock_depth(inode->i_sb, "readdir");

	/* form key for search the next directory entry using f_pos field of
	   file structure */
	make_cpu_key(&pos_key, inode,
		     (filp->f_pos) ? (filp->f_pos) : DOT_OFFSET, TYPE_DIRENTRY,
		     3);
	next_pos = cpu_key_k_offset(&pos_key);

	/*  reiserfs_warning (inode->i_sb, "reiserfs_readdir 1: f_pos = %Ld", filp->f_pos); */

	path_to_entry.reada = PATH_READA;
	while (1) {
	      research:
		/* search the directory item, containing entry with specified key */
		search_res =
		    search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry,
					&de);
		if (search_res == IO_ERROR) {
			// FIXME: we could just skip part of directory which could
			// not be read
			ret = -EIO;
			goto out;
		}
		entry_num = de.de_entry_num;
		bh = de.de_bh;
		item_num = de.de_item_num;
		ih = de.de_ih;
		store_ih(&tmp_ih, ih);

		/* we must have found item, that is item of this directory, */
		RFALSE(COMP_SHORT_KEYS(&(ih->ih_key), &pos_key),
		       "vs-9000: found item %h does not match to dir we readdir %K",
		       ih, &pos_key);
		RFALSE(item_num > B_NR_ITEMS(bh) - 1,
		       "vs-9005 item_num == %d, item amount == %d",
		       item_num, B_NR_ITEMS(bh));

		/* and entry must be not more than number of entries in the item */
		RFALSE(I_ENTRY_COUNT(ih) < entry_num,
		       "vs-9010: entry number is too big %d (%d)",
		       entry_num, I_ENTRY_COUNT(ih));

		if (search_res == POSITION_FOUND
		    || entry_num < I_ENTRY_COUNT(ih)) {
			/* go through all entries in the directory item beginning from the entry, that has been found */
			struct reiserfs_de_head *deh =
			    B_I_DEH(bh, ih) + entry_num;

			for (; entry_num < I_ENTRY_COUNT(ih);
			     entry_num++, deh++) {
				int d_reclen;
				char *d_name;
				off_t d_off;
				ino_t d_ino;

				if (!de_visible(deh))
					/* it is hidden entry */
					continue;
				d_reclen = entry_length(bh, ih, entry_num);
				d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
				if (!d_name[d_reclen - 1])
					d_reclen = strlen(d_name);

				if (d_reclen >
				    REISERFS_MAX_NAME(inode->i_sb->
						      s_blocksize)) {
					/* too big to send back to VFS */
					continue;
				}

				/* Ignore the .reiserfs_priv entry */
				if (reiserfs_xattrs(inode->i_sb) &&
				    !old_format_only(inode->i_sb) &&
				    filp->f_path.dentry == inode->i_sb->s_root &&
				    REISERFS_SB(inode->i_sb)->priv_root &&
				    REISERFS_SB(inode->i_sb)->priv_root->d_inode
				    && deh_objectid(deh) ==
				    le32_to_cpu(INODE_PKEY
						(REISERFS_SB(inode->i_sb)->
						 priv_root->d_inode)->
						k_objectid)) {
					continue;
				}

				d_off = deh_offset(deh);
				filp->f_pos = d_off;
				d_ino = deh_objectid(deh);
				if (d_reclen <= 32) {
					local_buf = small_buf;
				} else {
					local_buf = kmalloc(d_reclen,
							    GFP_NOFS);
					if (!local_buf) {
						pathrelse(&path_to_entry);
						ret = -ENOMEM;
						goto out;
					}
					if (item_moved(&tmp_ih, &path_to_entry)) {
						kfree(local_buf);
						goto research;
					}
				}
				// Note, that we copy name to user space via temporary
				// buffer (local_buf) because filldir will block if
				// user space buffer is swapped out. At that time
				// entry can move to somewhere else
				memcpy(local_buf, d_name, d_reclen);
				if (filldir
				    (dirent, local_buf, d_reclen, d_off, d_ino,
				     DT_UNKNOWN) < 0) {
					if (local_buf != small_buf) {
						kfree(local_buf);
					}
					goto end;
				}
				if (local_buf != small_buf) {
					kfree(local_buf);
				}
				// next entry should be looked for with such offset
				next_pos = deh_offset(deh) + 1;

				if (item_moved(&tmp_ih, &path_to_entry)) {
					goto research;
				}
			}	/* for */
		}

		if (item_num != B_NR_ITEMS(bh) - 1)
			// end of directory has been reached
			goto end;

		/* item we went through is last item of node. Using right
		   delimiting key check is it directory end */
		rkey = get_rkey(&path_to_entry, inode->i_sb);
		if (!comp_le_keys(rkey, &MIN_KEY)) {
			/* set pos_key to key, that is the smallest and greater
			   that key of the last entry in the item */
			set_cpu_key_k_offset(&pos_key, next_pos);
			continue;
		}

		if (COMP_SHORT_KEYS(rkey, &pos_key)) {
			// end of directory has been reached
			goto end;
		}

		/* directory continues in the right neighboring block */
		set_cpu_key_k_offset(&pos_key,
				     le_key_k_offset(KEY_FORMAT_3_5, rkey));

	}			/* while */

      end:
	filp->f_pos = next_pos;
	pathrelse(&path_to_entry);
	reiserfs_check_path(&path_to_entry);
      out:
	reiserfs_write_unlock(inode->i_sb);
	return ret;
}
static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
	int retval;
	struct inode *inode;
	struct reiserfs_transaction_handle th;
	struct reiserfs_security_handle security;
	int lock_depth;
	/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
	int jbegin_count =
	    JOURNAL_PER_BALANCE_CNT * 3 +
	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));

	dquot_initialize(dir);

#ifdef DISPLACE_NEW_PACKING_LOCALITIES
	/* set flag that new packing locality created and new blocks for the content     * of that directory are not displaced yet */
	REISERFS_I(dir)->new_packing_locality = 1;
#endif
	mode = S_IFDIR | mode;
	if (!(inode = new_inode(dir->i_sb))) {
		return -ENOMEM;
	}
	new_inode_init(inode, dir, mode);

	jbegin_count += reiserfs_cache_default_acl(dir);
	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
	if (retval < 0) {
		drop_new_inode(inode);
		return retval;
	}
	jbegin_count += retval;
	lock_depth = reiserfs_write_lock_once(dir->i_sb);

	retval = journal_begin(&th, dir->i_sb, jbegin_count);
	if (retval) {
		drop_new_inode(inode);
		goto out_failed;
	}

	/* inc the link count now, so another writer doesn't overflow it while
	 ** we sleep later on.
	 */
	INC_DIR_INODE_NLINK(dir)

	    retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ ,
					old_format_only(dir->i_sb) ?
					EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
					dentry, inode, &security);
	if (retval) {
		DEC_DIR_INODE_NLINK(dir)
		goto out_failed;
	}

	reiserfs_update_inode_transaction(inode);
	reiserfs_update_inode_transaction(dir);

	inode->i_op = &reiserfs_dir_inode_operations;
	inode->i_fop = &reiserfs_dir_operations;

	// note, _this_ add_entry will not update dir's stat data
	retval =
	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
			       dentry->d_name.len, inode, 1 /*visible */ );
	if (retval) {
		int err;
		clear_nlink(inode);
		DEC_DIR_INODE_NLINK(dir);
		reiserfs_update_sd(&th, inode);
		err = journal_end(&th, dir->i_sb, jbegin_count);
		if (err)
			retval = err;
		unlock_new_inode(inode);
		iput(inode);
		goto out_failed;
	}
	// the above add_entry did not update dir's stat data
	reiserfs_update_sd(&th, dir);

	unlock_new_inode(inode);
	d_instantiate(dentry, inode);
	retval = journal_end(&th, dir->i_sb, jbegin_count);
out_failed:
	reiserfs_write_unlock_once(dir->i_sb, lock_depth);
	return retval;
}
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);
}
int
reiserfs_readdir(struct vop_readdir_args  /* {
		struct vnode *a_vp;
		struct uio *a_uio;
		struct ucred *a_cred;
		int *a_eofflag;
		int *a_ncookies;
		u_long **a_cookies;
	} */*ap)
{
	int error = 0;
	struct dirent dstdp;
	struct uio *uio = ap->a_uio;

	off_t next_pos;
	struct buf *bp;
	struct item_head *ih;
	struct cpu_key pos_key;
	const struct key *rkey;
	struct reiserfs_node *ip;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);
	int entry_num, item_num, search_res;

	/* The NFS part */
	int ncookies = 0;
	u_long *cookies = NULL;

	/*
	 * Form key for search the next directory entry using f_pos field of
	 * file structure
	 */
	ip = VTOI(ap->a_vp);
	make_cpu_key(&pos_key,
	    ip, uio->uio_offset ? uio->uio_offset : DOT_OFFSET,
	    TYPE_DIRENTRY, 3);
	next_pos = cpu_key_k_offset(&pos_key);

	reiserfs_log(LOG_DEBUG, "listing entries for "
	    "(objectid=%d, dirid=%d)\n",
	    pos_key.on_disk_key.k_objectid, pos_key.on_disk_key.k_dir_id);
	reiserfs_log(LOG_DEBUG, "uio_offset = %jd, uio_resid = %d\n",
	    (intmax_t)uio->uio_offset, uio->uio_resid);

	if (ap->a_ncookies && ap->a_cookies) {
		cookies = (u_long *)malloc(
		    uio->uio_resid / 16 * sizeof(u_long),
		    M_REISERFSCOOKIES, M_WAITOK);
	}

	while (1) {
		//research:
		/*
		 * Search the directory item, containing entry with
		 * specified key
		 */
		reiserfs_log(LOG_DEBUG, "search directory to read\n");
		search_res = search_by_entry_key(ip->i_reiserfs, &pos_key,
		    &path_to_entry, &de);
		if (search_res == IO_ERROR) {
			error = EIO;
			goto out;
		}

		entry_num = de.de_entry_num;
		item_num  = de.de_item_num;
		bp = de.de_bp;
		ih = de.de_ih;

		if (search_res == POSITION_FOUND ||
		    entry_num < I_ENTRY_COUNT(ih)) {
			/*
			 * Go through all entries in the directory item
			 * beginning from the entry, that has been found.
			 */
			struct reiserfs_de_head *deh = B_I_DEH(bp, ih) +
			    entry_num;

			if (ap->a_ncookies == NULL) {
				cookies = NULL;
			} else {
				//ncookies = 
			}

			reiserfs_log(LOG_DEBUG,
			    "walking through directory entries\n");
			for (; entry_num < I_ENTRY_COUNT(ih);
			    entry_num++, deh++) {
				int d_namlen;
				char *d_name;
				off_t d_off;
				ino_t d_ino;

				if (!de_visible(deh)) {
					/* It is hidden entry */
					continue;
				}

				d_namlen = entry_length(bp, ih, entry_num);
				d_name   = B_I_DEH_ENTRY_FILE_NAME(bp, ih, deh);
				if (!d_name[d_namlen - 1])
					d_namlen = strlen(d_name);
				reiserfs_log(LOG_DEBUG, "  - `%s' (len=%d)\n",
				    d_name, d_namlen);

				if (d_namlen > REISERFS_MAX_NAME(
				    ip->i_reiserfs->s_blocksize)) {
					/* Too big to send back to VFS */
					continue;
				}

#if 0
				/* Ignore the .reiserfs_priv entry */
				if (reiserfs_xattrs(ip->i_reiserfs) &&
				    !old_format_only(ip->i_reiserfs) &&
				    filp->f_dentry == ip->i_reiserfs->s_root &&
				    REISERFS_SB(ip->i_reiserfs)->priv_root &&
				    REISERFS_SB(ip->i_reiserfs)->priv_root->d_inode &&
				    deh_objectid(deh) ==
				    le32toh(INODE_PKEY(REISERFS_SB(
				    ip->i_reiserfs)->priv_root->d_inode)->k_objectid)) {
					continue;
				}
#endif

				d_off = deh_offset(deh);
				d_ino = deh_objectid(deh);
				uio->uio_offset = d_off;

				/* Copy to user land */
				dstdp.d_fileno = d_ino;
				dstdp.d_type   = DT_UNKNOWN;
				dstdp.d_namlen = d_namlen;
				dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
				bcopy(d_name, dstdp.d_name, dstdp.d_namlen);
				bzero(dstdp.d_name + dstdp.d_namlen,
				    dstdp.d_reclen -
				    offsetof(struct dirent, d_name) -
				    dstdp.d_namlen);

				if (d_namlen > 0) {
					if (dstdp.d_reclen <= uio->uio_resid) {
						reiserfs_log(LOG_DEBUG, "     copying to user land\n");
						error = uiomove(&dstdp,
						    dstdp.d_reclen, uio);
						if (error)
							goto end;
						if (cookies != NULL) {
							cookies[ncookies] =
							    d_off;
							ncookies++;
						}
					} else
						break;
				} else {
					error = EIO;
					break;
				}

				next_pos = deh_offset(deh) + 1;
			}
			reiserfs_log(LOG_DEBUG, "...done\n");
		}

		reiserfs_log(LOG_DEBUG, "checking item num (%d == %d ?)\n",
		    item_num, B_NR_ITEMS(bp) - 1);
		if (item_num != B_NR_ITEMS(bp) - 1) {
			/* End of directory has been reached */
			reiserfs_log(LOG_DEBUG, "end reached\n");
			if (ap->a_eofflag)
				*ap->a_eofflag = 1;
			goto end;
		}

		/*
		 * Item we went through is last item of node. Using right
		 * delimiting key check is it directory end
		 */
		reiserfs_log(LOG_DEBUG, "get right key\n");
		rkey = get_rkey(&path_to_entry, ip->i_reiserfs);
		reiserfs_log(LOG_DEBUG, "right key = (objectid=%d, dirid=%d)\n",
		    rkey->k_objectid, rkey->k_dir_id);

		reiserfs_log(LOG_DEBUG, "compare it to MIN_KEY\n");
		reiserfs_log(LOG_DEBUG, "MIN KEY = (objectid=%d, dirid=%d)\n",
		    MIN_KEY.k_objectid, MIN_KEY.k_dir_id);
		if (comp_le_keys(rkey, &MIN_KEY) == 0) {
			/* Set pos_key to key, that is the smallest and greater
			 * that key of the last entry in the item */
			reiserfs_log(LOG_DEBUG, "continuing on the right\n");
			set_cpu_key_k_offset(&pos_key, next_pos);
			continue;
		}

		reiserfs_log(LOG_DEBUG, "compare it to pos_key\n");
		reiserfs_log(LOG_DEBUG, "pos key = (objectid=%d, dirid=%d)\n",
		    pos_key.on_disk_key.k_objectid,
		    pos_key.on_disk_key.k_dir_id);
		if (COMP_SHORT_KEYS(rkey, &pos_key)) {
			/* End of directory has been reached */
			reiserfs_log(LOG_DEBUG, "end reached (right)\n");
			if (ap->a_eofflag)
				*ap->a_eofflag = 1;
			goto end;
		}

		/* Directory continues in the right neighboring block */
		reiserfs_log(LOG_DEBUG, "continuing with a new offset\n");
		set_cpu_key_k_offset(&pos_key,
		    le_key_k_offset(KEY_FORMAT_3_5, rkey));
		reiserfs_log(LOG_DEBUG,
		    "new pos key = (objectid=%d, dirid=%d)\n",
		    pos_key.on_disk_key.k_objectid,
		    pos_key.on_disk_key.k_dir_id);
	}

end:
	uio->uio_offset = next_pos;
	pathrelse(&path_to_entry);
	reiserfs_check_path(&path_to_entry);
out:
	if (error && cookies != NULL) {
		free(cookies, M_REISERFSCOOKIES);
	} else if (ap->a_ncookies != NULL && ap->a_cookies != NULL) {
		*ap->a_ncookies = ncookies;
		*ap->a_cookies  = cookies;
	}
	return (error);
}
Beispiel #9
0
static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
{
    int retval;
    struct inode * inode;
    struct reiserfs_transaction_handle th ;
    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
    int locked;

#ifdef DISPLACE_NEW_PACKING_LOCALITIES
    /* set flag that new packing locality created and new blocks for the content     * of that directory are not displaced yet */
    REISERFS_I(dir)->new_packing_locality = 1;
#endif
    mode = S_IFDIR | mode;
    if (!(inode = new_inode(dir->i_sb))) {
	return -ENOMEM ;
    }
    retval = new_inode_init(inode, dir, mode);
    if (retval)
        return retval;

    locked = reiserfs_cache_default_acl (dir);

    reiserfs_write_lock(dir->i_sb);
    if (locked)
        reiserfs_write_lock_xattrs (dir->i_sb);
    journal_begin(&th, dir->i_sb, jbegin_count) ;

    /* inc the link count now, so another writer doesn't overflow it while
    ** we sleep later on.
    */
    INC_DIR_INODE_NLINK(dir)

    retval = reiserfs_new_inode (&th, dir, mode, 0/*symlink*/,
				old_format_only (dir->i_sb) ? 
				EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
				dentry, inode);
    if (locked)
        reiserfs_write_unlock_xattrs (dir->i_sb);

    if (retval) {
	dir->i_nlink-- ;
	goto out_failed;
    }
    reiserfs_update_inode_transaction(inode) ;
    reiserfs_update_inode_transaction(dir) ;

    inode->i_op = &reiserfs_dir_inode_operations;
    inode->i_fop = &reiserfs_dir_operations;

    // note, _this_ add_entry will not update dir's stat data
    retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, 
				inode, 1/*visible*/);
    if (retval) {
	inode->i_nlink = 0;
	DEC_DIR_INODE_NLINK(dir);
	reiserfs_update_sd (&th, inode);
	journal_end(&th, dir->i_sb, jbegin_count) ;
	iput (inode);
	goto out_failed;
    }

    // the above add_entry did not update dir's stat data
    reiserfs_update_sd (&th, dir);

    d_instantiate(dentry, inode);
    journal_end(&th, dir->i_sb, jbegin_count) ;
out_failed:
    reiserfs_write_unlock(dir->i_sb);
    return retval;
}
/* this first locks inode (neither reads nor sync are permitted),
   reads tail through page cache, insert direct item. When direct item
   inserted successfully inode is left locked. Return value is always
   what we expect from it (number of cut bytes). But when tail remains
   in the unformatted node, we set mode to SKIP_BALANCING and unlock
   inode */
int indirect2direct (struct reiserfs_transaction_handle *th, 
		     struct inode * p_s_inode,
		     struct page *page, 
		     struct path * p_s_path, /* path to the indirect item. */
		     const struct cpu_key * p_s_item_key, /* Key to look for unformatted node pointer to be cut. */
		     loff_t n_new_file_size, /* New file size. */
		     char * p_c_mode)
{
    struct super_block * p_s_sb = p_s_inode->i_sb;
    struct item_head      s_ih;
    unsigned long n_block_size = p_s_sb->s_blocksize;
    char * tail;
    int tail_len, round_tail_len;
    loff_t pos, pos1; /* position of first byte of the tail */
    struct cpu_key key;

    p_s_sb->u.reiserfs_sb.s_indirect2direct ++;

    *p_c_mode = M_SKIP_BALANCING;

    /* store item head path points to. */
    copy_item_head (&s_ih, PATH_PITEM_HEAD(p_s_path));

    tail_len = (n_new_file_size & (n_block_size - 1));
    if (!old_format_only (p_s_sb))
	round_tail_len = ROUND_UP (tail_len);
    else
	round_tail_len = tail_len;

    pos = le_ih_k_offset (&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * p_s_sb->s_blocksize;
    pos1 = pos;

    // we are protected by i_sem. The tail can not disapper, not
    // append can be done either
    // we are in truncate or packing tail in file_release

    tail = (char *)kmap(page) ; /* this can schedule */

    if (path_changed (&s_ih, p_s_path)) {
	/* re-search indirect item */
	if ( search_for_position_by_key (p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND )
	    reiserfs_panic(p_s_sb, "PAP-5520: indirect2direct: "
			   "item to be converted %k does not exist", p_s_item_key);
	copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
#ifdef CONFIG_REISERFS_CHECK
	pos = le_ih_k_offset (&s_ih) - 1 + 
	    (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * p_s_sb->s_blocksize;
	if (pos != pos1)
	    reiserfs_panic (p_s_sb, "vs-5530: indirect2direct: "
			    "tail position changed while we were reading it");
#endif
    }


    /* Set direct item header to insert. */
    make_le_item_head (&s_ih, 0, inode_items_version (p_s_inode), pos1 + 1,
		       TYPE_DIRECT, round_tail_len, 0xffff/*ih_free_space*/);

    /* we want a pointer to the first byte of the tail in the page.
    ** the page was locked and this part of the page was up to date when
    ** indirect2direct was called, so we know the bytes are still valid
    */
    tail = tail + (pos & (PAGE_CACHE_SIZE - 1)) ;

    PATH_LAST_POSITION(p_s_path)++;

    key = *p_s_item_key;
    set_cpu_key_k_type (&key, TYPE_DIRECT);
    key.key_length = 4;
    /* Insert tail as new direct item in the tree */
    if ( reiserfs_insert_item(th, p_s_path, &key, &s_ih,
			      tail ? tail : NULL) < 0 ) {
	/* No disk memory. So we can not convert last unformatted node
	   to the direct item.  In this case we used to adjust
	   indirect items's ih_free_space. Now ih_free_space is not
	   used, it would be ideal to write zeros to corresponding
	   unformatted node. For now i_size is considered as guard for
	   going out of file size */
	kunmap(page) ;
	return n_block_size - round_tail_len;
    }
    kunmap(page) ;

    /* this will invalidate all the buffers in the page after
    ** pos1
    */
    unmap_buffers(page, pos1) ;

    // note: we have now the same as in above direct2indirect
    // conversion: there are two keys which have matching first three
    // key components. They only differ by the fouhth one.

    /* We have inserted new direct item and must remove last
       unformatted node. */
    p_s_inode->i_blocks += (p_s_sb->s_blocksize / 512);
    *p_c_mode = M_CUT;

    /* we store position of first direct item in the in-core inode */
    //mark_file_with_tail (p_s_inode, pos1 + 1);
    p_s_inode->u.reiserfs_i.i_first_direct_byte = pos1 + 1;

    return n_block_size - round_tail_len;
}
Beispiel #11
0
int reiserfs_super_in_proc( char *buffer, char **start, off_t offset,
			    int count, int *eof, void *data )
{
	struct super_block *sb;
	struct reiserfs_sb_info *r;
	int len = 0;
    
	sb = procinfo_prologue( ( kdev_t ) ( int ) data );
	if( sb == NULL )
		return -ENOENT;
	r = &sb->u.reiserfs_sb;
	len += sprintf( &buffer[ len ], 
			"state: \t%s\n"
			"mount options: \t%s%s%s%s%s%s%s%s%s%s%s%s\n"
			"gen. counter: \t%i\n"
			"s_kmallocs: \t%i\n"
			"s_disk_reads: \t%i\n"
			"s_disk_writes: \t%i\n"
			"s_fix_nodes: \t%i\n"
			"s_do_balance: \t%i\n"
			"s_unneeded_left_neighbor: \t%i\n"
			"s_good_search_by_key_reada: \t%i\n"
			"s_bmaps: \t%i\n"
			"s_bmaps_without_search: \t%i\n"
			"s_direct2indirect: \t%i\n"
			"s_indirect2direct: \t%i\n"
			"\n"
			"max_hash_collisions: \t%i\n"

			"breads: \t%lu\n"
			"bread_misses: \t%lu\n"

			"search_by_key: \t%lu\n"
			"search_by_key_fs_changed: \t%lu\n"
			"search_by_key_restarted: \t%lu\n"
			
			"leaked_oid: \t%lu\n"
			"leaves_removable: \t%lu\n",

			SF( s_mount_state ) == REISERFS_VALID_FS ?
			"REISERFS_VALID_FS" : "REISERFS_ERROR_FS",
			reiserfs_r5_hash( sb ) ? "FORCE_R5 " : "",
			reiserfs_rupasov_hash( sb ) ? "FORCE_RUPASOV " : "",
			reiserfs_tea_hash( sb ) ? "FORCE_TEA " : "",
			reiserfs_hash_detect( sb ) ? "DETECT_HASH " : "",
			reiserfs_no_border( sb ) ? "NO_BORDER " : "BORDER ",
			reiserfs_no_unhashed_relocation( sb ) ? "NO_UNHASHED_RELOCATION " : "",
			reiserfs_hashed_relocation( sb ) ? "UNHASHED_RELOCATION " : "",
			reiserfs_test4( sb ) ? "TEST4 " : "",
			dont_have_tails( sb ) ? "NO_TAILS " : "TAILS ",
			replay_only( sb ) ? "REPLAY_ONLY " : "",
			reiserfs_dont_log( sb ) ? "DONT_LOG " : "LOG ",
			old_format_only( sb ) ? "CONV " : "",

			atomic_read( &r -> s_generation_counter ),
			SF( s_kmallocs ),
			SF( s_disk_reads ),
			SF( s_disk_writes ),
			SF( s_fix_nodes ),
			SF( s_do_balance ),
			SF( s_unneeded_left_neighbor ),
			SF( s_good_search_by_key_reada ),
			SF( s_bmaps ),
			SF( s_bmaps_without_search ),
			SF( s_direct2indirect ),
			SF( s_indirect2direct ),
			SFP( max_hash_collisions ),
			SFP( breads ),
			SFP( bread_miss ),
			SFP( search_by_key ),
			SFP( search_by_key_fs_changed ),
			SFP( search_by_key_restarted ),
			SFP( leaked_oid ),
			SFP( leaves_removable ) );

	procinfo_epilogue( sb );
	return reiserfs_proc_tail( len, buffer, start, offset, count, eof );
}