|
@@ -364,34 +364,34 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void munge_mode_uid_gid(struct gfs2_inode *dip, umode_t *mode,
|
|
|
- unsigned int *uid, unsigned int *gid)
|
|
|
+static void munge_mode_uid_gid(const struct gfs2_inode *dip,
|
|
|
+ struct inode *inode)
|
|
|
{
|
|
|
if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
|
|
|
(dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
|
|
|
- if (S_ISDIR(*mode))
|
|
|
- *mode |= S_ISUID;
|
|
|
+ if (S_ISDIR(inode->i_mode))
|
|
|
+ inode->i_mode |= S_ISUID;
|
|
|
else if (dip->i_inode.i_uid != current_fsuid())
|
|
|
- *mode &= ~07111;
|
|
|
- *uid = dip->i_inode.i_uid;
|
|
|
+ inode->i_mode &= ~07111;
|
|
|
+ inode->i_uid = dip->i_inode.i_uid;
|
|
|
} else
|
|
|
- *uid = current_fsuid();
|
|
|
+ inode->i_uid = current_fsuid();
|
|
|
|
|
|
if (dip->i_inode.i_mode & S_ISGID) {
|
|
|
- if (S_ISDIR(*mode))
|
|
|
- *mode |= S_ISGID;
|
|
|
- *gid = dip->i_inode.i_gid;
|
|
|
+ if (S_ISDIR(inode->i_mode))
|
|
|
+ inode->i_mode |= S_ISGID;
|
|
|
+ inode->i_gid = dip->i_inode.i_gid;
|
|
|
} else
|
|
|
- *gid = current_fsgid();
|
|
|
+ inode->i_gid = current_fsgid();
|
|
|
}
|
|
|
|
|
|
-static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
|
|
|
+static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
|
|
|
{
|
|
|
- struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
|
|
|
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
int error;
|
|
|
int dblocks = 1;
|
|
|
|
|
|
- error = gfs2_inplace_reserve(dip, RES_DINODE);
|
|
|
+ error = gfs2_inplace_reserve(ip, RES_DINODE, flags);
|
|
|
if (error)
|
|
|
goto out;
|
|
|
|
|
@@ -399,12 +399,15 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
|
|
|
if (error)
|
|
|
goto out_ipreserv;
|
|
|
|
|
|
- error = gfs2_alloc_blocks(dip, no_addr, &dblocks, 1, generation);
|
|
|
+ error = gfs2_alloc_blocks(ip, &ip->i_no_addr, &dblocks, 1, &ip->i_generation);
|
|
|
+ ip->i_no_formal_ino = ip->i_generation;
|
|
|
+ ip->i_inode.i_ino = ip->i_no_addr;
|
|
|
+ ip->i_goal = ip->i_no_addr;
|
|
|
|
|
|
gfs2_trans_end(sdp);
|
|
|
|
|
|
out_ipreserv:
|
|
|
- gfs2_inplace_release(dip);
|
|
|
+ gfs2_inplace_release(ip);
|
|
|
out:
|
|
|
return error;
|
|
|
}
|
|
@@ -429,52 +432,42 @@ static void gfs2_init_dir(struct buffer_head *dibh,
|
|
|
/**
|
|
|
* init_dinode - Fill in a new dinode structure
|
|
|
* @dip: The directory this inode is being created in
|
|
|
- * @gl: The glock covering the new inode
|
|
|
- * @inum: The inode number
|
|
|
- * @mode: The file permissions
|
|
|
- * @uid: The uid of the new inode
|
|
|
- * @gid: The gid of the new inode
|
|
|
- * @generation: The generation number of the new inode
|
|
|
- * @dev: The device number (if a device node)
|
|
|
+ * @ip: The inode
|
|
|
* @symname: The symlink destination (if a symlink)
|
|
|
- * @size: The inode size (ignored for directories)
|
|
|
* @bhp: The buffer head (returned to caller)
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
-static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
|
|
|
- const struct gfs2_inum_host *inum, umode_t mode,
|
|
|
- unsigned int uid, unsigned int gid,
|
|
|
- const u64 *generation, dev_t dev, const char *symname,
|
|
|
- unsigned size, struct buffer_head **bhp)
|
|
|
+static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
|
|
|
+ const char *symname, struct buffer_head **bhp)
|
|
|
{
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
|
|
|
struct gfs2_dinode *di;
|
|
|
struct buffer_head *dibh;
|
|
|
struct timespec tv = CURRENT_TIME;
|
|
|
|
|
|
- dibh = gfs2_meta_new(gl, inum->no_addr);
|
|
|
- gfs2_trans_add_bh(gl, dibh, 1);
|
|
|
+ dibh = gfs2_meta_new(ip->i_gl, ip->i_no_addr);
|
|
|
+ gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
|
|
gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI);
|
|
|
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
|
|
|
di = (struct gfs2_dinode *)dibh->b_data;
|
|
|
|
|
|
- di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino);
|
|
|
- di->di_num.no_addr = cpu_to_be64(inum->no_addr);
|
|
|
- di->di_mode = cpu_to_be32(mode);
|
|
|
- di->di_uid = cpu_to_be32(uid);
|
|
|
- di->di_gid = cpu_to_be32(gid);
|
|
|
+ di->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
|
|
|
+ di->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
|
|
|
+ di->di_mode = cpu_to_be32(ip->i_inode.i_mode);
|
|
|
+ di->di_uid = cpu_to_be32(ip->i_inode.i_uid);
|
|
|
+ di->di_gid = cpu_to_be32(ip->i_inode.i_gid);
|
|
|
di->di_nlink = 0;
|
|
|
- di->di_size = cpu_to_be64(size);
|
|
|
+ di->di_size = cpu_to_be64(ip->i_inode.i_size);
|
|
|
di->di_blocks = cpu_to_be64(1);
|
|
|
di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
|
|
|
- di->di_major = cpu_to_be32(MAJOR(dev));
|
|
|
- di->di_minor = cpu_to_be32(MINOR(dev));
|
|
|
- di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
|
|
|
- di->di_generation = cpu_to_be64(*generation);
|
|
|
+ di->di_major = cpu_to_be32(MAJOR(ip->i_inode.i_rdev));
|
|
|
+ di->di_minor = cpu_to_be32(MINOR(ip->i_inode.i_rdev));
|
|
|
+ di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_no_addr);
|
|
|
+ di->di_generation = cpu_to_be64(ip->i_generation);
|
|
|
di->di_flags = 0;
|
|
|
di->__pad1 = 0;
|
|
|
- di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0);
|
|
|
+ di->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) ? GFS2_FORMAT_DE : 0);
|
|
|
di->di_height = 0;
|
|
|
di->__pad2 = 0;
|
|
|
di->__pad3 = 0;
|
|
@@ -487,7 +480,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
|
|
|
di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
|
|
|
memset(&di->di_reserved, 0, sizeof(di->di_reserved));
|
|
|
|
|
|
- switch(mode & S_IFMT) {
|
|
|
+ switch(ip->i_inode.i_mode & S_IFMT) {
|
|
|
case S_IFREG:
|
|
|
if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
|
|
|
gfs2_tune_get(sdp, gt_new_files_jdata))
|
|
@@ -502,7 +495,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
|
|
|
gfs2_init_dir(dibh, dip);
|
|
|
break;
|
|
|
case S_IFLNK:
|
|
|
- memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size);
|
|
|
+ memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, ip->i_inode.i_size);
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -511,25 +504,22 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
|
|
|
*bhp = dibh;
|
|
|
}
|
|
|
|
|
|
-static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
|
|
|
- umode_t mode, const struct gfs2_inum_host *inum,
|
|
|
- const u64 *generation, dev_t dev, const char *symname,
|
|
|
- unsigned int size, struct buffer_head **bhp)
|
|
|
+static int make_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
|
|
|
+ const char *symname, struct buffer_head **bhp)
|
|
|
{
|
|
|
+ struct inode *inode = &ip->i_inode;
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
|
|
|
- unsigned int uid, gid;
|
|
|
int error;
|
|
|
|
|
|
- munge_mode_uid_gid(dip, &mode, &uid, &gid);
|
|
|
error = gfs2_rindex_update(sdp);
|
|
|
if (error)
|
|
|
return error;
|
|
|
|
|
|
- error = gfs2_quota_lock(dip, uid, gid);
|
|
|
+ error = gfs2_quota_lock(dip, inode->i_uid, inode->i_gid);
|
|
|
if (error)
|
|
|
return error;
|
|
|
|
|
|
- error = gfs2_quota_check(dip, uid, gid);
|
|
|
+ error = gfs2_quota_check(dip, inode->i_uid, inode->i_gid);
|
|
|
if (error)
|
|
|
goto out_quota;
|
|
|
|
|
@@ -537,8 +527,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
|
|
|
if (error)
|
|
|
goto out_quota;
|
|
|
|
|
|
- init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, symname, size, bhp);
|
|
|
- gfs2_quota_change(dip, +1, uid, gid);
|
|
|
+ init_dinode(dip, ip, symname, bhp);
|
|
|
+ gfs2_quota_change(dip, +1, inode->i_uid, inode->i_gid);
|
|
|
gfs2_trans_end(sdp);
|
|
|
|
|
|
out_quota:
|
|
@@ -570,7 +560,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
|
|
|
if (error)
|
|
|
goto fail_quota_locks;
|
|
|
|
|
|
- error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
|
|
|
+ error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
|
|
|
if (error)
|
|
|
goto fail_quota_locks;
|
|
|
|
|
@@ -657,19 +647,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|
|
struct inode *inode = NULL;
|
|
|
struct gfs2_inode *dip = GFS2_I(dir), *ip;
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
|
|
|
- struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
|
|
|
+ struct gfs2_glock *io_gl;
|
|
|
int error;
|
|
|
- u64 generation;
|
|
|
struct buffer_head *bh = NULL;
|
|
|
+ u32 aflags = 0;
|
|
|
|
|
|
if (!name->len || name->len > GFS2_FNAMESIZE)
|
|
|
return -ENAMETOOLONG;
|
|
|
|
|
|
- /* We need a reservation to allocate the new dinode block. The
|
|
|
- directory ip temporarily points to the reservation, but this is
|
|
|
- being done to get a set of contiguous blocks for the new dinode.
|
|
|
- Since this is a create, we don't have a sizehint yet, so it will
|
|
|
- have to use the minimum reservation size. */
|
|
|
error = gfs2_rs_alloc(dip);
|
|
|
if (error)
|
|
|
return error;
|
|
@@ -688,45 +673,72 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|
|
if (error)
|
|
|
goto fail_gunlock;
|
|
|
|
|
|
- error = alloc_dinode(dip, &inum.no_addr, &generation);
|
|
|
+ inode = new_inode(sdp->sd_vfs);
|
|
|
+ if (!inode) {
|
|
|
+ gfs2_glock_dq_uninit(ghs);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ ip = GFS2_I(inode);
|
|
|
+ error = gfs2_rs_alloc(ip);
|
|
|
if (error)
|
|
|
- goto fail_gunlock;
|
|
|
- inum.no_formal_ino = generation;
|
|
|
+ goto fail_free_inode;
|
|
|
+
|
|
|
+ set_bit(GIF_INVALID, &ip->i_flags);
|
|
|
+ inode->i_mode = mode;
|
|
|
+ inode->i_rdev = dev;
|
|
|
+ inode->i_size = size;
|
|
|
+ munge_mode_uid_gid(dip, inode);
|
|
|
+ ip->i_goal = dip->i_goal;
|
|
|
|
|
|
- error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops,
|
|
|
- LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
|
|
|
+ if ((GFS2_I(sdp->sd_root_dir->d_inode) == dip) ||
|
|
|
+ (dip->i_diskflags & GFS2_DIF_TOPDIR))
|
|
|
+ aflags |= GFS2_AF_ORLOV;
|
|
|
+
|
|
|
+ error = alloc_dinode(ip, aflags);
|
|
|
if (error)
|
|
|
- goto fail_gunlock;
|
|
|
+ goto fail_free_inode;
|
|
|
|
|
|
- error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, symname, size, &bh);
|
|
|
+ error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
|
|
|
if (error)
|
|
|
- goto fail_gunlock2;
|
|
|
+ goto fail_free_inode;
|
|
|
|
|
|
- inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr,
|
|
|
- inum.no_formal_ino, 0);
|
|
|
- if (IS_ERR(inode))
|
|
|
+ ip->i_gl->gl_object = ip;
|
|
|
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
|
|
|
+ if (error)
|
|
|
+ goto fail_free_inode;
|
|
|
+
|
|
|
+ error = make_dinode(dip, ip, symname, &bh);
|
|
|
+ if (error)
|
|
|
goto fail_gunlock2;
|
|
|
|
|
|
- ip = GFS2_I(inode);
|
|
|
- error = gfs2_inode_refresh(ip);
|
|
|
+ error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
|
|
|
if (error)
|
|
|
goto fail_gunlock2;
|
|
|
|
|
|
- error = gfs2_rs_alloc(ip);
|
|
|
+ error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
|
|
|
if (error)
|
|
|
goto fail_gunlock2;
|
|
|
|
|
|
+ ip->i_iopen_gh.gh_gl->gl_object = ip;
|
|
|
+ gfs2_glock_put(io_gl);
|
|
|
+ gfs2_set_iop(inode);
|
|
|
+ insert_inode_hash(inode);
|
|
|
+
|
|
|
+ error = gfs2_inode_refresh(ip);
|
|
|
+ if (error)
|
|
|
+ goto fail_gunlock3;
|
|
|
+
|
|
|
error = gfs2_acl_create(dip, inode);
|
|
|
if (error)
|
|
|
- goto fail_gunlock2;
|
|
|
+ goto fail_gunlock3;
|
|
|
|
|
|
error = gfs2_security_init(dip, ip, name);
|
|
|
if (error)
|
|
|
- goto fail_gunlock2;
|
|
|
+ goto fail_gunlock3;
|
|
|
|
|
|
error = link_dinode(dip, name, ip);
|
|
|
if (error)
|
|
|
- goto fail_gunlock2;
|
|
|
+ goto fail_gunlock3;
|
|
|
|
|
|
if (bh)
|
|
|
brelse(bh);
|
|
@@ -739,8 +751,20 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|
|
d_instantiate(dentry, inode);
|
|
|
return 0;
|
|
|
|
|
|
+fail_gunlock3:
|
|
|
+ gfs2_glock_dq_uninit(ghs + 1);
|
|
|
+ if (ip->i_gl)
|
|
|
+ gfs2_glock_put(ip->i_gl);
|
|
|
+ goto fail_gunlock;
|
|
|
+
|
|
|
fail_gunlock2:
|
|
|
gfs2_glock_dq_uninit(ghs + 1);
|
|
|
+fail_free_inode:
|
|
|
+ if (ip->i_gl)
|
|
|
+ gfs2_glock_put(ip->i_gl);
|
|
|
+ gfs2_rs_delete(ip);
|
|
|
+ free_inode_nonrcu(inode);
|
|
|
+ inode = NULL;
|
|
|
fail_gunlock:
|
|
|
gfs2_glock_dq_uninit(ghs);
|
|
|
if (inode && !IS_ERR(inode)) {
|
|
@@ -748,7 +772,6 @@ fail_gunlock:
|
|
|
iput(inode);
|
|
|
}
|
|
|
fail:
|
|
|
- gfs2_rs_delete(dip);
|
|
|
if (bh)
|
|
|
brelse(bh);
|
|
|
return error;
|
|
@@ -884,7 +907,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
|
|
if (error)
|
|
|
goto out_gunlock;
|
|
|
|
|
|
- error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
|
|
|
+ error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
|
|
|
if (error)
|
|
|
goto out_gunlock_q;
|
|
|
|
|
@@ -977,7 +1000,6 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
|
|
|
* gfs2_unlink_inode - Removes an inode from its parent dir and unlinks it
|
|
|
* @dip: The parent directory
|
|
|
* @name: The name of the entry in the parent directory
|
|
|
- * @bh: The inode buffer for the inode to be removed
|
|
|
* @inode: The inode to be removed
|
|
|
*
|
|
|
* Called with all the locks and in a transaction. This will only be
|
|
@@ -987,8 +1009,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
|
|
|
*/
|
|
|
|
|
|
static int gfs2_unlink_inode(struct gfs2_inode *dip,
|
|
|
- const struct dentry *dentry,
|
|
|
- struct buffer_head *bh)
|
|
|
+ const struct dentry *dentry)
|
|
|
{
|
|
|
struct inode *inode = dentry->d_inode;
|
|
|
struct gfs2_inode *ip = GFS2_I(inode);
|
|
@@ -1028,7 +1049,6 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(dir);
|
|
|
struct inode *inode = dentry->d_inode;
|
|
|
struct gfs2_inode *ip = GFS2_I(inode);
|
|
|
- struct buffer_head *bh;
|
|
|
struct gfs2_holder ghs[3];
|
|
|
struct gfs2_rgrpd *rgd;
|
|
|
int error;
|
|
@@ -1076,15 +1096,10 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
|
|
|
goto out_gunlock;
|
|
|
|
|
|
error = gfs2_trans_begin(sdp, 2*RES_DINODE + 3*RES_LEAF + RES_RG_BIT, 0);
|
|
|
- if (error)
|
|
|
- goto out_gunlock;
|
|
|
-
|
|
|
- error = gfs2_meta_inode_buffer(ip, &bh);
|
|
|
if (error)
|
|
|
goto out_end_trans;
|
|
|
|
|
|
- error = gfs2_unlink_inode(dip, dentry, bh);
|
|
|
- brelse(bh);
|
|
|
+ error = gfs2_unlink_inode(dip, dentry);
|
|
|
|
|
|
out_end_trans:
|
|
|
gfs2_trans_end(sdp);
|
|
@@ -1365,7 +1380,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|
|
if (error)
|
|
|
goto out_gunlock;
|
|
|
|
|
|
- error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres);
|
|
|
+ error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres, 0);
|
|
|
if (error)
|
|
|
goto out_gunlock_q;
|
|
|
|
|
@@ -1384,14 +1399,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|
|
|
|
|
/* Remove the target file, if it exists */
|
|
|
|
|
|
- if (nip) {
|
|
|
- struct buffer_head *bh;
|
|
|
- error = gfs2_meta_inode_buffer(nip, &bh);
|
|
|
- if (error)
|
|
|
- goto out_end_trans;
|
|
|
- error = gfs2_unlink_inode(ndip, ndentry, bh);
|
|
|
- brelse(bh);
|
|
|
- }
|
|
|
+ if (nip)
|
|
|
+ error = gfs2_unlink_inode(ndip, ndentry);
|
|
|
|
|
|
if (dir_rename) {
|
|
|
error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
|