Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d36c3018 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  hppfs_lookup(): don't open-code lookup_one_len()
  hppfs: fix dentry leak
  cramfs: get_cramfs_inode() returns ERR_PTR() on failure
  ufs should use d_splice_alias()
  fix exofs ->get_parent()
  ceph analog of cifs build_path_from_dentry() race fix
  cifs: build_path_from_dentry() race fix
parents a406721d 0916a5e4
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -1438,12 +1438,15 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
	struct dentry *temp;
	char *path;
	int len, pos;
	unsigned seq;

	if (dentry == NULL)
		return ERR_PTR(-EINVAL);

retry:
	len = 0;
	seq = read_seqbegin(&rename_lock);
	rcu_read_lock();
	for (temp = dentry; !IS_ROOT(temp);) {
		struct inode *inode = temp->d_inode;
		if (inode && ceph_snap(inode) == CEPH_SNAPDIR)
@@ -1455,10 +1458,12 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
			len += 1 + temp->d_name.len;
		temp = temp->d_parent;
		if (temp == NULL) {
			rcu_read_unlock();
			pr_err("build_path corrupt dentry %p\n", dentry);
			return ERR_PTR(-EINVAL);
		}
	}
	rcu_read_unlock();
	if (len)
		len--;  /* no leading '/' */

@@ -1467,9 +1472,12 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
		return ERR_PTR(-ENOMEM);
	pos = len;
	path[pos] = 0;	/* trailing null */
	rcu_read_lock();
	for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) {
		struct inode *inode = temp->d_inode;
		struct inode *inode;

		spin_lock(&temp->d_lock);
		inode = temp->d_inode;
		if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
			dout("build_path path+%d: %p SNAPDIR\n",
			     pos, temp);
@@ -1478,21 +1486,26 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
			break;
		} else {
			pos -= temp->d_name.len;
			if (pos < 0)
			if (pos < 0) {
				spin_unlock(&temp->d_lock);
				break;
			}
			strncpy(path + pos, temp->d_name.name,
				temp->d_name.len);
		}
		spin_unlock(&temp->d_lock);
		if (pos)
			path[--pos] = '/';
		temp = temp->d_parent;
		if (temp == NULL) {
			rcu_read_unlock();
			pr_err("build_path corrupt dentry\n");
			kfree(path);
			return ERR_PTR(-EINVAL);
		}
	}
	if (pos != 0) {
	rcu_read_unlock();
	if (pos != 0 || read_seqretry(&rename_lock, seq)) {
		pr_err("build_path did not end path lookup where "
		       "expected, namelen is %d, pos is %d\n", len, pos);
		/* presumably this is only possible if racing with a
+12 −1
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ build_path_from_dentry(struct dentry *direntry)
	char dirsep;
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
	unsigned seq;

	if (direntry == NULL)
		return NULL;  /* not much we can do if dentry is freed and
@@ -68,22 +69,29 @@ build_path_from_dentry(struct dentry *direntry)
		dfsplen = 0;
cifs_bp_rename_retry:
	namelen = dfsplen;
	seq = read_seqbegin(&rename_lock);
	rcu_read_lock();
	for (temp = direntry; !IS_ROOT(temp);) {
		namelen += (1 + temp->d_name.len);
		temp = temp->d_parent;
		if (temp == NULL) {
			cERROR(1, "corrupt dentry");
			rcu_read_unlock();
			return NULL;
		}
	}
	rcu_read_unlock();

	full_path = kmalloc(namelen+1, GFP_KERNEL);
	if (full_path == NULL)
		return full_path;
	full_path[namelen] = 0;	/* trailing null */
	rcu_read_lock();
	for (temp = direntry; !IS_ROOT(temp);) {
		spin_lock(&temp->d_lock);
		namelen -= 1 + temp->d_name.len;
		if (namelen < 0) {
			spin_unlock(&temp->d_lock);
			break;
		} else {
			full_path[namelen] = dirsep;
@@ -91,14 +99,17 @@ build_path_from_dentry(struct dentry *direntry)
				temp->d_name.len);
			cFYI(0, "name: %s", full_path + namelen);
		}
		spin_unlock(&temp->d_lock);
		temp = temp->d_parent;
		if (temp == NULL) {
			cERROR(1, "corrupt dentry");
			rcu_read_unlock();
			kfree(full_path);
			return NULL;
		}
	}
	if (namelen != dfsplen) {
	rcu_read_unlock();
	if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
		cERROR(1, "did not end path lookup where expected namelen is %d",
			namelen);
		/* presumably this is only possible if racing with a rename
+12 −10
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ static DEFINE_MUTEX(read_mutex);
/* These macros may change in future, to provide better st_ino semantics. */
#define OFFSET(x)	((x)->i_ino)

static unsigned long cramino(struct cramfs_inode *cino, unsigned int offset)
static unsigned long cramino(const struct cramfs_inode *cino, unsigned int offset)
{
	if (!cino->offset)
		return offset + 1;
@@ -61,7 +61,7 @@ static unsigned long cramino(struct cramfs_inode *cino, unsigned int offset)
}

static struct inode *get_cramfs_inode(struct super_block *sb,
	struct cramfs_inode *cramfs_inode, unsigned int offset)
	const struct cramfs_inode *cramfs_inode, unsigned int offset)
{
	struct inode *inode;
	static struct timespec zerotime;
@@ -317,7 +317,7 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
	/* Set it all up.. */
	sb->s_op = &cramfs_ops;
	root = get_cramfs_inode(sb, &super.root, 0);
	if (!root)
	if (IS_ERR(root))
		goto out;
	sb->s_root = d_alloc_root(root);
	if (!sb->s_root) {
@@ -423,6 +423,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	unsigned int offset = 0;
	struct inode *inode = NULL;
	int sorted;

	mutex_lock(&read_mutex);
@@ -449,8 +450,8 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s

		for (;;) {
			if (!namelen) {
				mutex_unlock(&read_mutex);
				return ERR_PTR(-EIO);
				inode = ERR_PTR(-EIO);
				goto out;
			}
			if (name[namelen-1])
				break;
@@ -462,17 +463,18 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
		if (retval > 0)
			continue;
		if (!retval) {
			struct cramfs_inode entry = *de;
			mutex_unlock(&read_mutex);
			d_add(dentry, get_cramfs_inode(dir->i_sb, &entry, dir_off));
			return NULL;
			inode = get_cramfs_inode(dir->i_sb, de, dir_off);
			break;
		}
		/* else (retval < 0) */
		if (sorted)
			break;
	}
out:
	mutex_unlock(&read_mutex);
	d_add(dentry, NULL);
	if (IS_ERR(inode))
		return ERR_CAST(inode);
	d_add(dentry, inode);
	return NULL;
}

+1 −1
Original line number Diff line number Diff line
@@ -913,7 +913,7 @@ struct dentry *exofs_get_parent(struct dentry *child)
	unsigned long ino = exofs_parent_ino(child);

	if (!ino)
		return NULL;
		return ERR_PTR(-ESTALE);

	return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino));
}
+9 −22
Original line number Diff line number Diff line
@@ -139,7 +139,8 @@ static int file_removed(struct dentry *dentry, const char *file)
static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
				   struct nameidata *nd)
{
	struct dentry *proc_dentry, *new, *parent;
	struct dentry *proc_dentry, *parent;
	struct qstr *name = &dentry->d_name;
	struct inode *inode;
	int err, deleted;

@@ -149,23 +150,9 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
	else if (deleted)
		return ERR_PTR(-ENOENT);

	err = -ENOMEM;
	parent = HPPFS_I(ino)->proc_dentry;
	mutex_lock(&parent->d_inode->i_mutex);
	proc_dentry = d_lookup(parent, &dentry->d_name);
	if (proc_dentry == NULL) {
		proc_dentry = d_alloc(parent, &dentry->d_name);
		if (proc_dentry == NULL) {
			mutex_unlock(&parent->d_inode->i_mutex);
			goto out;
		}
		new = (*parent->d_inode->i_op->lookup)(parent->d_inode,
						       proc_dentry, NULL);
		if (new) {
			dput(proc_dentry);
			proc_dentry = new;
		}
	}
	proc_dentry = lookup_one_len(name->name, parent, name->len);
	mutex_unlock(&parent->d_inode->i_mutex);

	if (IS_ERR(proc_dentry))
@@ -174,13 +161,11 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
	err = -ENOMEM;
	inode = get_inode(ino->i_sb, proc_dentry);
	if (!inode)
		goto out_dput;
		goto out;

 	d_add(dentry, inode);
	return NULL;

 out_dput:
	dput(proc_dentry);
 out:
	return ERR_PTR(err);
}
@@ -690,8 +675,10 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
	struct inode *proc_ino = dentry->d_inode;
	struct inode *inode = new_inode(sb);

	if (!inode)
	if (!inode) {
		dput(dentry);
		return ERR_PTR(-ENOMEM);
	}

	if (S_ISDIR(dentry->d_inode->i_mode)) {
		inode->i_op = &hppfs_dir_iops;
@@ -704,7 +691,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
		inode->i_fop = &hppfs_file_fops;
	}

	HPPFS_I(inode)->proc_dentry = dget(dentry);
	HPPFS_I(inode)->proc_dentry = dentry;

	inode->i_uid = proc_ino->i_uid;
	inode->i_gid = proc_ino->i_gid;
@@ -737,7 +724,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
	sb->s_fs_info = proc_mnt;

	err = -ENOMEM;
	root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root);
	root_inode = get_inode(sb, dget(proc_mnt->mnt_sb->s_root));
	if (!root_inode)
		goto out_mntput;

Loading