|
@@ -448,17 +448,18 @@ ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * ea_get_unstuffed - actually copies the unstuffed data into the
|
|
|
- * request buffer
|
|
|
+ * ea_iter_unstuffed - copies the unstuffed xattr data to/from the
|
|
|
+ * request buffer
|
|
|
* @ip: The GFS2 inode
|
|
|
* @ea: The extended attribute header structure
|
|
|
- * @data: The data to be copied
|
|
|
+ * @din: The data to be copied in
|
|
|
+ * @dout: The data to be copied out (one of din,dout will be NULL)
|
|
|
*
|
|
|
* Returns: errno
|
|
|
*/
|
|
|
|
|
|
-static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
|
|
|
- char *data)
|
|
|
+static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
|
|
|
+ const char *din, char *dout)
|
|
|
{
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
struct buffer_head **bh;
|
|
@@ -467,6 +468,8 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
|
|
|
__be64 *dataptrs = GFS2_EA2DATAPTRS(ea);
|
|
|
unsigned int x;
|
|
|
int error = 0;
|
|
|
+ unsigned char *pos;
|
|
|
+ unsigned cp_size;
|
|
|
|
|
|
bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
|
|
|
if (!bh)
|
|
@@ -497,12 +500,21 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- memcpy(data, bh[x]->b_data + sizeof(struct gfs2_meta_header),
|
|
|
- (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize);
|
|
|
+ pos = bh[x]->b_data + sizeof(struct gfs2_meta_header);
|
|
|
+ cp_size = (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize;
|
|
|
|
|
|
- amount -= sdp->sd_jbsize;
|
|
|
- data += sdp->sd_jbsize;
|
|
|
+ if (dout) {
|
|
|
+ memcpy(dout, pos, cp_size);
|
|
|
+ dout += sdp->sd_jbsize;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (din) {
|
|
|
+ gfs2_trans_add_bh(ip->i_gl, bh[x], 1);
|
|
|
+ memcpy(pos, din, cp_size);
|
|
|
+ din += sdp->sd_jbsize;
|
|
|
+ }
|
|
|
|
|
|
+ amount -= sdp->sd_jbsize;
|
|
|
brelse(bh[x]);
|
|
|
}
|
|
|
|
|
@@ -523,7 +535,7 @@ static int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el,
|
|
|
memcpy(data, GFS2_EA2DATA(el->el_ea), len);
|
|
|
return len;
|
|
|
}
|
|
|
- ret = ea_get_unstuffed(ip, el->el_ea, data);
|
|
|
+ ret = gfs2_iter_unstuffed(ip, el->el_ea, NULL, data);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
return len;
|
|
@@ -727,7 +739,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
|
|
|
goto out_gunlock_q;
|
|
|
|
|
|
error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
|
|
|
- blks + gfs2_rg_blocks(ip) +
|
|
|
+ blks + gfs2_rg_blocks(ip, blks) +
|
|
|
RES_DINODE + RES_STATFS + RES_QUOTA, 0);
|
|
|
if (error)
|
|
|
goto out_ipres;
|
|
@@ -1220,69 +1232,23 @@ static int gfs2_xattr_set(struct dentry *dentry, const char *name,
|
|
|
size, flags, type);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
|
|
|
struct gfs2_ea_header *ea, char *data)
|
|
|
{
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
- struct buffer_head **bh;
|
|
|
unsigned int amount = GFS2_EA_DATA_LEN(ea);
|
|
|
unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
|
|
|
- __be64 *dataptrs = GFS2_EA2DATAPTRS(ea);
|
|
|
- unsigned int x;
|
|
|
- int error;
|
|
|
-
|
|
|
- bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
|
|
|
- if (!bh)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- error = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0);
|
|
|
- if (error)
|
|
|
- goto out;
|
|
|
-
|
|
|
- for (x = 0; x < nptrs; x++) {
|
|
|
- error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
|
|
|
- bh + x);
|
|
|
- if (error) {
|
|
|
- while (x--)
|
|
|
- brelse(bh[x]);
|
|
|
- goto fail;
|
|
|
- }
|
|
|
- dataptrs++;
|
|
|
- }
|
|
|
-
|
|
|
- for (x = 0; x < nptrs; x++) {
|
|
|
- error = gfs2_meta_wait(sdp, bh[x]);
|
|
|
- if (error) {
|
|
|
- for (; x < nptrs; x++)
|
|
|
- brelse(bh[x]);
|
|
|
- goto fail;
|
|
|
- }
|
|
|
- if (gfs2_metatype_check(sdp, bh[x], GFS2_METATYPE_ED)) {
|
|
|
- for (; x < nptrs; x++)
|
|
|
- brelse(bh[x]);
|
|
|
- error = -EIO;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- gfs2_trans_add_bh(ip->i_gl, bh[x], 1);
|
|
|
-
|
|
|
- memcpy(bh[x]->b_data + sizeof(struct gfs2_meta_header), data,
|
|
|
- (sdp->sd_jbsize > amount) ? amount : sdp->sd_jbsize);
|
|
|
-
|
|
|
- amount -= sdp->sd_jbsize;
|
|
|
- data += sdp->sd_jbsize;
|
|
|
-
|
|
|
- brelse(bh[x]);
|
|
|
- }
|
|
|
+ int ret;
|
|
|
|
|
|
-out:
|
|
|
- kfree(bh);
|
|
|
- return error;
|
|
|
+ ret = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
-fail:
|
|
|
+ ret = gfs2_iter_unstuffed(ip, ea, data, NULL);
|
|
|
gfs2_trans_end(sdp);
|
|
|
- kfree(bh);
|
|
|
- return error;
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
|