Exemplo n.º 1
0
static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
			 kgid_t gid, struct device *dev)
{
	struct dentry *dentry;
	struct path path;
	int err;

	dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
	if (dentry == ERR_PTR(-ENOENT)) {
		create_path(nodename);
		dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
	}
	if (IS_ERR(dentry))
		return PTR_ERR(dentry);

	err = vfs_mknod(d_inode(path.dentry), dentry, mode, dev->devt, &path);
	if (!err) {
		struct iattr newattrs;

		newattrs.ia_mode = mode;
		newattrs.ia_uid = uid;
		newattrs.ia_gid = gid;
		newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
		mutex_lock(&d_inode(dentry)->i_mutex);
		notify_change(dentry, &newattrs, NULL);
		mutex_unlock(&d_inode(dentry)->i_mutex);

		/* mark as kernel-created inode */
		d_inode(dentry)->i_private = &thread;
	}
	done_path_create(&path, dentry);
	return err;
}
Exemplo n.º 2
0
static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
			dev_t dev)
{
	int err;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path;

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
	if (err)
		goto out;

	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	unlock_dir(lower_parent_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);
#ifdef NEKTECH_LOGGER /*NEKTECH LOGGING*/
            nektech_logger (dir, dentry, NEKTECH_MKNOD);
#endif          /*NEKTECH LOGGING*/
	
	return err;
}
Exemplo n.º 3
0
static int amfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
			dev_t dev)
{
	int err;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path;

	amfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
	if (err)
		goto out;

	err = amfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, amfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	unlock_dir(lower_parent_dentry);
	amfs_put_lower_path(dentry, &lower_path);
	return err;
}
static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
			dev_t dev)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path;

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;
	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
	if (err)
		goto out;

	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);
	return err;
}
Exemplo n.º 5
0
static int
ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
	int rc;
	struct dentry *lower_dentry;
	struct vfsmount *lower_mnt;
	struct dentry *lower_dir_dentry;

	lower_dentry = ecryptfs_dentry_to_lower(dentry);
	lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
	lower_dir_dentry = lock_parent(lower_dentry);
	rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
		       dev);
	if (rc || !lower_dentry->d_inode)
		goto out;
	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
	if (rc)
		goto out;
	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
out:
	unlock_dir(lower_dir_dentry);
	if (!dentry->d_inode)
		d_drop(dentry);
	return rc;
}
Exemplo n.º 6
0
static int bpf_obj_do_pin(const struct filename *pathname, void *raw,
			  enum bpf_type type)
{
	struct dentry *dentry;
	struct inode *dir;
	struct path path;
	umode_t mode;
	dev_t devt;
	int ret;

	dentry = kern_path_create(AT_FDCWD, pathname->name, &path, 0);
	if (IS_ERR(dentry))
		return PTR_ERR(dentry);

	mode = S_IFREG | ((S_IRUSR | S_IWUSR) & ~current_umask());
	devt = MKDEV(UNNAMED_MAJOR, type);

	ret = security_path_mknod(&path, dentry, mode, devt);
	if (ret)
		goto out;

	dir = d_inode(path.dentry);
	if (dir->i_op != &bpf_dir_iops) {
		ret = -EPERM;
		goto out;
	}

	dentry->d_fsdata = raw;
	ret = vfs_mknod(dir, dentry, mode, devt);
	dentry->d_fsdata = NULL;
out:
	done_path_create(&path, dentry);
	return ret;
}
Exemplo n.º 7
0
int	do_mknod (struct inode *inode, const char *name, int len, int mode,
	          int dev)
{
#if USE_DENTRY_F
	struct dentry	*tmp_dent;
#endif
	int		ret_code;

	DOWN(&(inode->i_sem));

#if USE_DENTRY_F
		/* Create a temporary negative dentry for the target. */

	ret_code = ovlfs_inode_get_child_dentry(inode, name, len, &tmp_dent,
	                                        OVLFS_DENT_GET_NEGATIVE);

	if ( ret_code == 0 )
	{
			/* Use the vfs_mknod function to do the dirty work. */

		ret_code = vfs_mknod(inode, tmp_dent, mode, dev);

		dput(tmp_dent);
	}
#else
	IMARK(inode);
	ret_code = inode->i_op->mknod(inode, name, len, data->mode, data->dev);
#endif

	UP(&(inode->i_sem));

	return	ret_code;
}
Exemplo n.º 8
0
/**
 * Adds device entry to the device list and creates file system entry
 * @TODO: Use linked list for devices as well
 */
int device_register (device_t *dev, const char *filename) {
  device_t *tmp = ll_devices;

//  kprintf ("device_register (device_t *dev, const char *%s) {\n", filename);

  // There are no devices yet, this is the first device. Special case
  if (ll_devices == NULL) {
    ll_devices = dev;
    dev->next = NULL;
  } else {
    // See if device already exists
    while (tmp) {
      if (tmp->major_num == dev->major_num && tmp->minor_num == dev->minor_num) return 0;
      tmp = (device_t *)tmp->next;
    }

    // Send end of device list
    tmp = ll_devices;
    while (tmp->next) tmp = (device_t *)tmp->next;

    // Add device to end
    tmp->next = (struct device_t *)dev;
    dev->next = NULL;
  }


  // Create device node
  vfs_node_t node;
  vfs_get_node_from_path ("DEVICE:/", &node);
  vfs_mknod (&node, filename, FS_BLOCKDEVICE, dev->major_num, dev->minor_num);

  return 1;
}
Exemplo n.º 9
0
static int handle_create(const char *nodename, umode_t mode, struct device *dev)
{
    struct dentry *dentry;
    struct path path;
    int err;

    dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
    if (dentry == ERR_PTR(-ENOENT)) {
        create_path(nodename);
        dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
    }
    if (IS_ERR(dentry))
        return PTR_ERR(dentry);

    err = vfs_mknod(path.dentry->d_inode,
                    dentry, mode, dev->devt);
    if (!err) {
        struct iattr newattrs;

        /* fixup possibly umasked mode */
        newattrs.ia_mode = mode;
        newattrs.ia_valid = ATTR_MODE;
        mutex_lock(&dentry->d_inode->i_mutex);
        notify_change(dentry, &newattrs);
        mutex_unlock(&dentry->d_inode->i_mutex);

        /* mark as kernel-created inode */
        dentry->d_inode->i_private = &thread;
    }
    done_path_create(&path, dentry);
    return err;
}
Exemplo n.º 10
0
int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
{
	int err;
	struct dentry *d;

	IMustLock(dir);

	d = path->dentry;
	path->dentry = d->d_parent;
	err = security_path_mknod(path, d, mode, new_encode_dev(dev));
	path->dentry = d;
	if (unlikely(err))
		goto out;

	err = vfs_mknod(dir, path->dentry, mode, dev);
	if (!err) {
		struct path tmp = *path;
		int did;

		vfsub_update_h_iattr(&tmp, &did);
		if (did) {
			tmp.dentry = path->dentry->d_parent;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
		}
		/*ignore*/
	}

out:
	return err;
}
Exemplo n.º 11
0
void op_write(const char **params, int nparams) {
  assert(nparams > 1);
  inode_t *ino = vfs_open(params[0], &dummy_access);

  if (!ino) {
    /* Find parent. */
    char *str = NULL;
    int i;
    for (i = strlen(params[0]); i >= 0; --i) {
      if (params[0][i] == '/') {
        str = kmalloc(i+1);
        strncpy(str, params[0], i);
        str[i] = '\0';
        break;
      }
    }
    assert(str && "Parent directory not found!");

    ino = vfs_open(str, &dummy_access);
    assert(ino && "Parent directory not found!");

    vfs_mknod(ino, &params[0][i+1], it_file, 0755, 0, 0);
    vfs_close(ino);
    ino = vfs_open(params[0], &dummy_access);

    assert(ino && "File not found after having created it!");
  }

  assert(ino && "File not found!");
  assert(ino->type == it_file && "File is not a regular file!");

  vfs_write(ino, 0, (void*)params[1], strlen(params[1]));
  vfs_close(ino);
}
Exemplo n.º 12
0
static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
			dev_t dev)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path;

	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb));

	sdcardfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;
	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
	if (err)
		goto out;

	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	sdcardfs_put_lower_path(dentry, &lower_path);
	REVERT_CRED();
	return err;
}
Exemplo n.º 13
0
static int ccfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
	int rc;
	struct dentry *lower_dentry;
	struct dentry *lower_dir_dentry;
		
	lower_dentry = ccfs_get_nested_dentry(dentry);
	lower_dir_dentry = lock_parent(lower_dentry);
	
	mdbg(INFO3,"MKNOD w/ lower_dentry->d_name.name = [%s]", lower_dentry->d_name.name);
	
	rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
	if (rc || !lower_dentry->d_inode)
		goto out;
	rc = ccfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
	if (rc)
		goto out;
	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
out:
	unlock_dir(lower_dir_dentry);
	if (!dentry->d_inode)
		d_drop(dentry);
	return rc;
}
Exemplo n.º 14
0
void op_mkdir(const char **params, int nparams) {
  inode_t *ino = vfs_open(params[0], &dummy_access);

  assert(!ino && "Directory exists!");
    
  /* Find parent. */
  char *str = NULL;
  int i;
  for (i = strlen(params[0]); i >= 0; --i) {
    if (params[0][i] == '/') {
      str = kmalloc(i+1);
      strncpy(str, params[0], i);
      str[i] = '\0';
      break;
    }
  }
  assert(str && "Parent directory not found!");

  ino = vfs_open(str, &dummy_access);
  assert(ino && "Parent directory not found!");

  vfs_mknod(ino, &params[0][i+1], it_dir, 0777, 0, 0);

  ino = vfs_open(params[0], &dummy_access);
  assert(ino && "Directory not found after having created it!");
  
  vfs_close(ino);
}
void __u2fs_mknod(struct work_struct *work)
{
	struct sioq_args *args = container_of(work, struct sioq_args, work);
	struct mknod_args *m = &args->mknod;

	args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
	complete(&args->comp);
}
static int u2fs_mknod(struct inode *dir, struct dentry *dentry, int mode,
			dev_t dev)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path;
	struct dentry *ret = NULL;

	/* creating parent directories if destination is read-only */
	if((U2FS_D(dentry)->lower_path[LEFT].dentry) == NULL && 
		(U2FS_D(dentry)->lower_path[LEFT].mnt) == NULL){

		ret = create_parents(dir, dentry, dentry->d_name.name);

		if (!ret || IS_ERR(ret)) {
				err = PTR_ERR(ret);
				if (!IS_COPYUP_ERR(err))
					printk(KERN_ERR
				      	 "u2fs: create_parents for "
			     		  "u2fs_mknod failed"
				      	 "err=%d\n", err);
				goto out_copyup;
		}
		u2fs_postcopyup_setmnt(dentry);
		u2fs_put_reset_lower_path(dentry, RIGHT);
	}

	u2fs_get_lower_path(dentry, &lower_path, LEFT);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;
	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
	if (err)
		goto out;

	err = u2fs_interpose(dentry, dir->i_sb, &lower_path, LEFT);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, u2fs_lower_inode(dir, LEFT));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	u2fs_put_lower_path(dentry, &lower_path);
out_copyup:
	return err;
}
Exemplo n.º 17
0
int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
		   dev_t dev)
{
	int err;

	LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
	IMustLock(dir);

	err = vfs_mknod(dir, dentry, mode, dev);
	if (!err) {
		/* dir inode is locked */
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
	}
	return err;
}
Exemplo n.º 18
0
//====================================================================
// Create a node for this device under the given path using the given
// device number. Returns 0 on success and non-zero on failure.
static int create_fs_node(const char *dev_path, dev_t undelete_minor_devnode) {
    struct dentry *dentry;
    struct path path;
    int lookup_flags = 0;
    umode_t mode = S_IRUGO | S_IFCHR;
    int err;

    dentry = kern_path_create(AT_FDCWD, dev_path, &path, lookup_flags);
    if (IS_ERR(dentry)) {
        return PTR_ERR(dentry);
    }
    err = security_path_mknod(&path, dentry, mode, undelete_minor_devnode);
    if (!err) {
        err = vfs_mknod(path.dentry->d_inode, dentry,
                        mode, undelete_minor_devnode);
    }
    done_path_create(&path, dentry);
    return err;
}
Exemplo n.º 19
0
static int
ecryptfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
	int rc;
	struct dentry *lower_dentry;
	struct dentry *lower_dir_dentry;

	lower_dentry = ecryptfs_dentry_to_lower(dentry);
	lower_dir_dentry = lock_parent(lower_dentry);
	rc = vfs_mknod(d_inode(lower_dir_dentry), lower_dentry, mode, dev);
	if (rc || d_really_is_negative(lower_dentry))
		goto out;
	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
	if (rc)
		goto out;
	fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
	fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
out:
	unlock_dir(lower_dir_dentry);
	if (d_really_is_negative(dentry))
		d_drop(dentry);
	return rc;
}
Exemplo n.º 20
0
hwgfs_handle_t
hwgfs_register(
	hwgfs_handle_t		dir,
	const char		*name,
	unsigned int		flags,
	unsigned int		major,
	unsigned int		minor,
	umode_t			mode,
	void			*ops,
	void			*info)
{
	dev_t			devnum = MKDEV(major, minor);
	struct inode		*parent_inode;
	struct dentry		*dentry;
	int			error;

	error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
	if (likely(!error)) {
		error = vfs_mknod(parent_inode, dentry, mode, devnum);
		if (likely(!error)) {
			/*
			 * Do this inside parents i_sem to avoid racing
			 * with lookups.
			 */
			if (S_ISCHR(mode))
				dentry->d_inode->i_fop = ops;
			dentry->d_fsdata = info;
			up(&parent_inode->i_sem);
		} else {
			up(&parent_inode->i_sem);
			dput(dentry);
			dentry = NULL;
                }
	}

	return dentry;
}
Exemplo n.º 21
0
int devtmpfs_create_node(struct device *dev)
{
	const char *tmp = NULL;
	const char *nodename;
	const struct cred *curr_cred;
	mode_t mode = 0;
	struct nameidata nd;
	struct dentry *dentry;
	int err;

	if (!dev_mnt)
		return 0;

	nodename = device_get_devnode(dev, &mode, &tmp);
	if (!nodename)
		return -ENOMEM;

	if (mode == 0)
		mode = 0600;
	if (is_blockdev(dev))
		mode |= S_IFBLK;
	else
		mode |= S_IFCHR;

	curr_cred = override_creds(&init_cred);

	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
			      nodename, LOOKUP_PARENT, &nd);
	if (err == -ENOENT) {
		create_path(nodename);
		err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
				      nodename, LOOKUP_PARENT, &nd);
	}
	if (err)
		goto out;

	dentry = lookup_create(&nd, 0);
	if (!IS_ERR(dentry)) {
		err = vfs_mknod(nd.path.dentry->d_inode,
				dentry, mode, dev->devt);
		if (!err) {
			struct iattr newattrs;

			/* fixup possibly umasked mode */
			newattrs.ia_mode = mode;
			newattrs.ia_valid = ATTR_MODE;
			mutex_lock(&dentry->d_inode->i_mutex);
			notify_change(dentry, &newattrs);
			mutex_unlock(&dentry->d_inode->i_mutex);

			/* mark as kernel-created inode */
			dentry->d_inode->i_private = &dev_mnt;
		}
		dput(dentry);
	} else {
		err = PTR_ERR(dentry);
	}

	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
	path_put(&nd.path);
out:
	kfree(tmp);
	revert_creds(curr_cred);
	return err;
}
Exemplo n.º 22
0
int create_sto_nod(dentry_t *dentry, int mode, int dev)
#endif
{
	int err = 0;
	inode_t *dir;
	dentry_t *hidden_sto_dentry;
	dentry_t *hidden_sto_dir_dentry;

	if(exists_in_storage(dentry)) {
		err = -EEXIST;
		goto out;
	}
	err = get_neg_sto_dentry(dentry);

	if (err) {
                printk(KERN_CRIT "mini_fo: create_sto_nod: ERROR getting neg. sto dentry.\n");
                goto out;
        }

	dir = dentry->d_parent->d_inode;
	hidden_sto_dentry = dtohd2(dentry);

	/* lock parent */
	hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent);

	err = PTR_ERR(hidden_sto_dir_dentry);
	if (IS_ERR(hidden_sto_dir_dentry))
		goto out;

	err = vfs_mknod(hidden_sto_dir_dentry->d_inode, hidden_sto_dentry, mode, dev);
	if(err)
		goto out_lock;

	if(!dtohd2(dentry)->d_inode) {
		printk(KERN_CRIT "mini_fo: create_sto_nod: creating storage inode failed [1].\n");
		err = -EINVAL; /* return something indicating failure */
		goto out_lock;
	}

	/* interpose the new inode */
	if(dtost(dentry) == DELETED) {
		dtost(dentry) = DEL_REWRITTEN;
		err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0);
		if(err)
			goto out_lock;
	}
	else if(dtost(dentry) == NON_EXISTANT) {
		dtost(dentry) = CREATED;
		err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0);
		if(err)
			goto out_lock;
	}
	else if(dtost(dentry) == UNMODIFIED) {
		dtost(dentry) = MODIFIED;
		/* interpose on new inode */
		if(itohi2(dentry->d_inode) != NULL) {
			printk(KERN_CRIT "mini_fo: create_sto_nod: error, invalid inode detected.\n");
			err = -EINVAL;
			goto out_lock;
		}
		itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode);
	}

	fist_copy_attr_timesizes(dir, hidden_sto_dir_dentry->d_inode);

 out_lock:
	dput(hidden_sto_dir_dentry);
 out:
	return err;
}
Exemplo n.º 23
0
SYSCALL_HANDLER3(sys_mknod, const char *path, mode_t mode, dev_t *dev) {
	*dev = vfs_mknod(path, mode, *dev);
}
Exemplo n.º 24
0
int copyup_named_dentry(struct inode *dir, struct dentry *dentry,
			int bstart, int new_bindex, char *name,
			int namelen, struct file **copyup_file, int len)
{
	struct dentry *new_hidden_dentry;
	struct dentry *old_hidden_dentry = NULL;
	struct super_block *sb;
	struct file *input_file = NULL;
	struct file *output_file = NULL;
	ssize_t read_bytes, write_bytes;
	mm_segment_t old_fs;
	int err = 0;
	char *buf;
	int old_bindex;
	int got_branch_input = -1;
	int got_branch_output = -1;
	int old_bstart;
	int old_bend;
	int size = len;
	struct dentry *new_hidden_parent_dentry;
	mm_segment_t oldfs;
	char *symbuf = NULL;
	uid_t saved_uid = current->fsuid;
	gid_t saved_gid = current->fsgid;

	print_entry_location();
	verify_locked(dentry);
	fist_print_dentry("IN: copyup_named_dentry", dentry);

	old_bindex = bstart;
	old_bstart = dbstart(dentry);
	old_bend = dbend(dentry);

	ASSERT(new_bindex >= 0);
	ASSERT(new_bindex < old_bindex);
	PASSERT(dir);
	PASSERT(dentry);

	sb = dir->i_sb;

	if ((err = is_robranch_super(sb, new_bindex)))
		goto out;

	/* Create the directory structure above this dentry. */
	new_hidden_dentry = create_parents_named(dir, dentry, name, new_bindex);
	PASSERT(new_hidden_dentry);
	if (IS_ERR(new_hidden_dentry)) {
		err = PTR_ERR(new_hidden_dentry);
		goto out;
	}

	fist_print_generic_dentry("Copyup Object", new_hidden_dentry);

	/* Now we actually create the object. */
	old_hidden_dentry = dtohd_index(dentry, old_bindex);
	PASSERT(old_hidden_dentry);
	PASSERT(old_hidden_dentry->d_inode);
	DGET(old_hidden_dentry);

	/* For symlinks, we must read the link before we lock the directory. */
	if (S_ISLNK(old_hidden_dentry->d_inode->i_mode)) {
		PASSERT(old_hidden_dentry->d_inode->i_op);
		PASSERT(old_hidden_dentry->d_inode->i_op->readlink);

		symbuf = KMALLOC(PATH_MAX, GFP_UNIONFS);
		if (!symbuf) {
			err = -ENOMEM;
			goto copyup_readlink_err;
		}

		oldfs = get_fs();
		set_fs(KERNEL_DS);
		err =
		    old_hidden_dentry->d_inode->i_op->
		    readlink(old_hidden_dentry, symbuf, PATH_MAX);
		set_fs(oldfs);
		if (err < 0)
			goto copyup_readlink_err;
		symbuf[err] = '\0';
	}

	/* Now we lock the parent, and create the object in the new branch. */
	new_hidden_parent_dentry = lock_parent(new_hidden_dentry);
	current->fsuid = new_hidden_parent_dentry->d_inode->i_uid;
	current->fsgid = new_hidden_parent_dentry->d_inode->i_gid;
	if (S_ISDIR(old_hidden_dentry->d_inode->i_mode)) {
		err = vfs_mkdir(new_hidden_parent_dentry->d_inode,
				new_hidden_dentry, S_IRWXU);
	} else if (S_ISLNK(old_hidden_dentry->d_inode->i_mode)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
		err = vfs_symlink(new_hidden_parent_dentry->d_inode,
				  new_hidden_dentry, symbuf);
#else
		err = vfs_symlink(new_hidden_parent_dentry->d_inode,
				  new_hidden_dentry, symbuf, S_IRWXU);
#endif
	} else if (S_ISBLK(old_hidden_dentry->d_inode->i_mode)
		   || S_ISCHR(old_hidden_dentry->d_inode->i_mode)
		   || S_ISFIFO(old_hidden_dentry->d_inode->i_mode)
		   || S_ISSOCK(old_hidden_dentry->d_inode->i_mode)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
		err = vfs_mknod(new_hidden_parent_dentry->d_inode,
				new_hidden_dentry,
				old_hidden_dentry->d_inode->i_mode,
				kdev_t_to_nr(old_hidden_dentry->d_inode->
					     i_rdev));
#else
		err = vfs_mknod(new_hidden_parent_dentry->d_inode,
				new_hidden_dentry,
				old_hidden_dentry->d_inode->i_mode,
				old_hidden_dentry->d_inode->i_rdev);
#endif
	} else if (S_ISREG(old_hidden_dentry->d_inode->i_mode)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
		err = vfs_create(new_hidden_parent_dentry->d_inode,
				 new_hidden_dentry, S_IRWXU);
#else
		err = vfs_create(new_hidden_parent_dentry->d_inode,
				 new_hidden_dentry, S_IRWXU, NULL);
#endif
	} else {
		char diemsg[100];
		snprintf(diemsg, sizeof(diemsg), "Unknown inode type %d\n",
			 old_hidden_dentry->d_inode->i_mode);
		FISTBUG(diemsg);
	}
	current->fsuid = saved_uid;
	current->fsgid = saved_gid;
	unlock_dir(new_hidden_parent_dentry);
      copyup_readlink_err:
	KFREE(symbuf);
	if (err) {
		/* get rid of the hidden dentry and all its traces */
		DPUT(new_hidden_dentry);
		set_dtohd_index(dentry, new_bindex, NULL);
		set_dbstart(dentry, old_bstart);
		set_dbend(dentry, old_bend);
		goto out;
	}

	/* We actually copyup the file here. */
	if (S_ISREG(old_hidden_dentry->d_inode->i_mode)) {
		mntget(stohiddenmnt_index(sb, old_bindex));
		branchget(sb, old_bindex);
		got_branch_input = old_bindex;
		input_file =
		    DENTRY_OPEN(old_hidden_dentry,
				stohiddenmnt_index(sb, old_bindex), O_RDONLY);
		if (IS_ERR(input_file)) {
			err = PTR_ERR(input_file);
			goto out;
		}
		if (!input_file->f_op || !input_file->f_op->read) {
			err = -EINVAL;
			goto out;
		}

		/* copy the new file */
		DGET(new_hidden_dentry);
		mntget(stohiddenmnt_index(sb, new_bindex));
		branchget(sb, new_bindex);
		got_branch_output = new_bindex;
		output_file =
		    DENTRY_OPEN(new_hidden_dentry,
				stohiddenmnt_index(sb, new_bindex), O_WRONLY);
		if (IS_ERR(output_file)) {
			err = PTR_ERR(output_file);
			goto out;
		}
		if (!output_file->f_op || !output_file->f_op->write) {
			err = -EINVAL;
			goto out;
		}

		/* allocating a buffer */
		buf = (char *)KMALLOC(PAGE_SIZE, GFP_UNIONFS);
		if (!buf) {
			err = -ENOMEM;
			goto out;
		}

		/* now read PAGE_SIZE bytes from offset 0 in a loop */
		old_fs = get_fs();

		input_file->f_pos = 0;
		output_file->f_pos = 0;

		set_fs(KERNEL_DS);
		do {
			if (len >= PAGE_SIZE)
				size = PAGE_SIZE;
			else if ((len < PAGE_SIZE) && (len > 0))
				size = len;

			len -= PAGE_SIZE;

			read_bytes =
			    input_file->f_op->read(input_file, buf, size,
						   &input_file->f_pos);
			if (read_bytes <= 0) {
				err = read_bytes;
				break;
			}

			write_bytes =
			    output_file->f_op->write(output_file, buf,
						     read_bytes,
						     &output_file->f_pos);
			if (write_bytes < 0 || (write_bytes < read_bytes)) {
				err = -EIO;
				break;
			}
		} while ((read_bytes > 0) && (len > 0));
		set_fs(old_fs);
		KFREE(buf);
	}

	/* Set permissions. */
	if ((err =
	     copyup_permissions(sb, old_hidden_dentry, new_hidden_dentry)))
		goto out;
	/* Selinux uses extended attributes for permissions. */
#if defined(UNIONFS_XATTR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20))
	if ((err = copyup_xattrs(old_hidden_dentry, new_hidden_dentry)))
		goto out;
#endif

	/* do not allow files getting deleted to be reinterposed */
	if (!d_deleted(dentry))
		unionfs_reinterpose(dentry);

      out:
	if (input_file && !IS_ERR(input_file)) {
		fput(input_file);
	} else {
		/* since input file was not opened, we need to explicitly
		 * dput the old_hidden_dentry
		 */
		DPUT(old_hidden_dentry);
	}

	/* in any case, we have to branchput */
	if (got_branch_input >= 0)
		branchput(sb, got_branch_input);

	if (output_file) {
		if (copyup_file && !err) {
			*copyup_file = output_file;
		} else {
			fput(output_file);
			branchput(sb, got_branch_output);
		}
	}

	fist_print_dentry("OUT: copyup_dentry", dentry);
	fist_print_inode("OUT: copyup_dentry", dentry->d_inode);

	print_exit_status(err);
	return err;
}
Exemplo n.º 25
0
int devtmpfs_create_node(struct device *dev)
{
	const char *tmp = NULL;
	const char *nodename;
	const struct cred *curr_cred;
	struct user_beancounter *curr_ub;
	mode_t mode = 0;
	struct nameidata nd;
	struct dentry *dentry;
	int err;
	struct vfsmount *dev_mnt = ve_devmnt();

	if (!dev_mnt)
		return 0;

	nodename = device_get_devnode(dev, &mode, &tmp);
	if (!nodename)
		return -ENOMEM;

	if (mode == 0)
		mode = 0600;
	if (is_blockdev(dev))
		mode |= S_IFBLK;
	else
		mode |= S_IFCHR;

	curr_ub = set_exec_ub(&ub0);
	curr_cred = override_creds(&init_cred);
	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
			      nodename, LOOKUP_PARENT, &nd);
	if (err == -ENOENT) {
		/* create missing parent directories */
		create_path(nodename);
		err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
				      nodename, LOOKUP_PARENT, &nd);
		if (err)
			goto out;
	}

	dentry = lookup_create(&nd, 0);
	if (!IS_ERR(dentry)) {
		int umask;

		umask = sys_umask(0000);
		err = vfs_mknod(nd.path.dentry->d_inode,
				dentry, mode, dev->devt);
		sys_umask(umask);
		/* mark as kernel created inode */
		if (!err)
			dentry->d_inode->i_private = &dev_mnt;
		dput(dentry);
	} else {
		err = PTR_ERR(dentry);
	}
	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);

	path_put(&nd.path);
out:
	kfree(tmp);
	revert_creds(curr_cred);
	(void)set_exec_ub(curr_ub);
	return err;
}
Exemplo n.º 26
0
static int unionfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
			 dev_t dev)
{
	int err = 0;
	struct dentry *lower_dentry = NULL;
	struct dentry *wh_dentry = NULL;
	struct dentry *lower_parent_dentry = NULL;
	struct dentry *parent;
	char *name = NULL;
	int valid = 0;

	unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
	parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
	unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);

	valid = __unionfs_d_revalidate(dentry, parent, false, 0);
	if (unlikely(!valid)) {
		err = -ESTALE;
		goto out;
	}

	/*
	 * It's only a bug if this dentry was not negative and couldn't be
	 * revalidated (shouldn't happen).
	 */
	BUG_ON(!valid && dentry->d_inode);

	lower_dentry = find_writeable_branch(dir, dentry);
	if (IS_ERR(lower_dentry)) {
		err = PTR_ERR(lower_dentry);
		goto out;
	}

	lower_parent_dentry = lock_parent(lower_dentry);
	if (IS_ERR(lower_parent_dentry)) {
		err = PTR_ERR(lower_parent_dentry);
		goto out_unlock;
	}

	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
	if (!err) {
		err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
		if (!err) {
			unionfs_copy_attr_times(dir);
			fsstack_copy_inode_size(dir,
						lower_parent_dentry->d_inode);
			/* update no. of links on parent directory */
			set_nlink(dir, unionfs_get_nlinks(dir));
		}
	}

out_unlock:
	unlock_dir(lower_parent_dentry);
out:
	dput(wh_dentry);
	kfree(name);

	if (!err) {
		unionfs_postcopyup_setmnt(dentry);
		unionfs_check_inode(dir);
		unionfs_check_dentry(dentry);
	}
	unionfs_unlock_dentry(dentry);
	unionfs_unlock_parent(dentry, parent);
	unionfs_read_unlock(dentry->d_sb);
	return err;
}
Exemplo n.º 27
0
static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
			 dev_t dev)
{
	int err = 0;
	struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
	struct dentry *hidden_parent_dentry = NULL;
	int bindex = 0, bstart;
	char *name = NULL;
	int whiteout_unlinked = 0;

	print_entry_location();
	lock_dentry(dentry);
	fist_print_dentry("IN unionfs_mknod", dentry);
	bstart = dbstart(dentry);

	hidden_dentry = dtohd(dentry);

	// check if whiteout exists in this branch, i.e. lookup .wh.foo first
	name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
	if (IS_ERR(name)) {
		err = PTR_ERR(name);
		goto out;
	}

	whiteout_dentry =
	    LOOKUP_ONE_LEN(name, hidden_dentry->d_parent,
			   dentry->d_name.len + WHLEN);
	if (IS_ERR(whiteout_dentry)) {
		err = PTR_ERR(whiteout_dentry);
		goto out;
	}

	if (!whiteout_dentry->d_inode) {
		DPUT(whiteout_dentry);
		whiteout_dentry = NULL;
	} else {
		/* found .wh.foo, unlink it */
		hidden_parent_dentry = lock_parent(whiteout_dentry);

		//found a.wh.foo entry, remove it then do vfs_mkdir
		if (!(err = is_robranch_super(dentry->d_sb, bstart)))
			err = vfs_unlink(hidden_parent_dentry->d_inode,
					 whiteout_dentry);
		DPUT(whiteout_dentry);

		unlock_dir(hidden_parent_dentry);

		if (err) {
			if (!IS_COPYUP_ERR(err))
				goto out;

			bstart--;
		} else {
			whiteout_unlinked = 1;
		}
	}

	for (bindex = bstart; bindex >= 0; bindex--) {
		hidden_dentry = dtohd_index(dentry, bindex);
		if (!hidden_dentry) {
			hidden_dentry = create_parents(dir, dentry, bindex);
			if (!hidden_dentry || IS_ERR(hidden_dentry)) {
				fist_dprint(8,
					    "hidden dentry NULL for bindex = %d\n",
					    bindex);
				continue;
			}
		}

		hidden_parent_dentry = lock_parent(hidden_dentry);
		if (IS_ERR(hidden_parent_dentry)) {
			err = PTR_ERR(hidden_parent_dentry);
			goto out;
		}
		if (!(err = is_robranch_super(dentry->d_sb, bindex))) {
			err = vfs_mknod(hidden_parent_dentry->d_inode,
					hidden_dentry, mode, dev);
		}
		/* XXX this could potentially return a negative hidden_dentry! */
		if (err || !hidden_dentry->d_inode) {
			unlock_dir(hidden_parent_dentry);
			/* break out of for, if error was NOT -EROFS */
			if (!IS_COPYUP_ERR(err))
				break;
		} else {
			err = unionfs_interpose(dentry, dir->i_sb, 0);
			if (!err) {
				fist_copy_attr_timesizes(dir,
							 hidden_parent_dentry->
							 d_inode);
				/* update number of links on parent directory */
				dir->i_nlink = get_nlinks(dir);
			}
			unlock_dir(hidden_parent_dentry);

			break;
		}
	}

      out:
	if (!dentry->d_inode)
		d_drop(dentry);

	if (name) {
		KFREE(name);
	}

	fist_print_dentry("OUT unionfs_mknod :", dentry);
	unlock_dentry(dentry);
	print_exit_status(err);
	return err;
}