static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
		      dev_t dev)
{
	struct gfs2_inode *dip = GFS2_I(dir);
	struct gfs2_sbd *sdp = GFS2_SB(dir);
	struct gfs2_holder ghs[2];
	struct inode *inode;

	gfs2_holder_init(dip->i_gl, 0, 0, ghs);

	inode = gfs2_createi(ghs, &dentry->d_name, mode, dev);
	if (IS_ERR(inode)) {
		gfs2_holder_uninit(ghs);
		return PTR_ERR(inode);
	}

	gfs2_trans_end(sdp);
	gfs2_inplace_release(dip);
	gfs2_quota_unlock(dip);
	gfs2_qadata_put(dip);

	gfs2_glock_dq_uninit_m(2, ghs);

	d_instantiate(dentry, inode);
	mark_inode_dirty(inode);

	return 0;
}
Esempio n. 2
0
static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
                        const char *symname)
{
    struct gfs2_inode *dip = GFS2_I(dir), *ip;
    struct gfs2_sbd *sdp = GFS2_SB(dir);
    struct gfs2_holder ghs[2];
    struct inode *inode;
    struct buffer_head *dibh;
    int size;
    int error;

    /* Must be stuffed with a null terminator for gfs2_follow_link() */
    size = strlen(symname);
    if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1)
        return -ENAMETOOLONG;

    gfs2_holder_init(dip->i_gl, 0, 0, ghs);

    inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO, 0);
    if (IS_ERR(inode)) {
        gfs2_holder_uninit(ghs);
        return PTR_ERR(inode);
    }

    ip = ghs[1].gh_gl->gl_object;

    ip->i_disksize = size;
    i_size_write(inode, size);

    error = gfs2_meta_inode_buffer(ip, &dibh);

    if (!gfs2_assert_withdraw(sdp, !error)) {
        gfs2_dinode_out(ip, dibh->b_data);
        memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname,
               size);
        brelse(dibh);
    }

    gfs2_trans_end(sdp);
    if (dip->i_alloc->al_rgd)
        gfs2_inplace_release(dip);
    gfs2_quota_unlock(dip);
    gfs2_alloc_put(dip);

    gfs2_glock_dq_uninit_m(2, ghs);

    d_instantiate(dentry, inode);
    mark_inode_dirty(inode);

    return 0;
}
Esempio n. 3
0
static int gfs2_create(struct inode *dir, struct dentry *dentry,
		       int mode, struct nameidata *nd)
{
	struct gfs2_inode *dip = GFS2_I(dir);
	struct gfs2_sbd *sdp = GFS2_SB(dir);
	struct gfs2_holder ghs[2];
	struct inode *inode;

	gfs2_holder_init(dip->i_gl, 0, 0, ghs);

	for (;;) {
		inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0);
		if (!IS_ERR(inode)) {
			gfs2_trans_end(sdp);
			if (dip->i_alloc->al_rgd)
				gfs2_inplace_release(dip);
			gfs2_quota_unlock(dip);
			gfs2_alloc_put(dip);
			gfs2_glock_dq_uninit_m(2, ghs);
			mark_inode_dirty(inode);
			break;
		} else if (PTR_ERR(inode) != -EEXIST ||
			   (nd && (nd->intent.open.flags & O_EXCL))) {
			gfs2_holder_uninit(ghs);
			return PTR_ERR(inode);
		}

		inode = gfs2_lookupi(dir, &dentry->d_name, 0, nd);
		if (inode) {
			if (!IS_ERR(inode)) {
				gfs2_holder_uninit(ghs);
				break;
			} else {
				gfs2_holder_uninit(ghs);
				return PTR_ERR(inode);
			}
		}
	}

	d_instantiate(dentry, inode);

	return 0;
}
static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
	struct gfs2_inode *dip = GFS2_I(dir), *ip;
	struct gfs2_sbd *sdp = GFS2_SB(dir);
	struct gfs2_holder ghs[2];
	struct inode *inode;
	struct buffer_head *dibh;
	int error;

	gfs2_holder_init(dip->i_gl, 0, 0, ghs);

	inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode, 0);
	if (IS_ERR(inode)) {
		gfs2_holder_uninit(ghs);
		return PTR_ERR(inode);
	}

	ip = ghs[1].gh_gl->gl_object;

	ip->i_inode.i_nlink = 2;
	ip->i_disksize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
	ip->i_diskflags |= GFS2_DIF_JDATA;
	ip->i_entries = 2;

	error = gfs2_meta_inode_buffer(ip, &dibh);

	if (!gfs2_assert_withdraw(sdp, !error)) {
		struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
		struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
		struct qstr str;

		gfs2_str2qstr(&str, ".");
		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
		gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent);
		dent->de_inum = di->di_num; /* already GFS2 endian */
		dent->de_type = cpu_to_be16(DT_DIR);
		di->di_entries = cpu_to_be32(1);

		gfs2_str2qstr(&str, "..");
		dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
		gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);

		gfs2_inum_out(dip, dent);
		dent->de_type = cpu_to_be16(DT_DIR);

		gfs2_dinode_out(ip, di);

		brelse(dibh);
	}

	error = gfs2_change_nlink(dip, +1);
	gfs2_assert_withdraw(sdp, !error); /* dip already pinned */

	gfs2_trans_end(sdp);
	gfs2_inplace_release(dip);
	gfs2_quota_unlock(dip);
	gfs2_qadata_put(dip);

	gfs2_glock_dq_uninit_m(2, ghs);

	d_instantiate(dentry, inode);
	mark_inode_dirty(inode);

	return 0;
}