History

GFS2: Allocate block for xattr at inode alloc time, if required

This is another step towards improving the allocation of xattr blocks at inode allocation time. Here we take advantage of Christoph's recent work on ACLs to allocate a block for the xattrs early if we know that we will be adding ACLs to the inode later on. The advantage of that is that it is much more likely that we'll get a contiguous run of two blocks where the first is the inode and the second is the xattr block. We still have to fall back to the original system in case we don't get the requested two contiguous blocks, or in case the ACLs are too large to fit into the block. Future patches will move more of the ACL setting code further up the gfs2_inode_create() function. Also, I'd like to be able to do the same thing with the xattrs from LSMs in due course, too. That way we should be able to slowly reduce the number of independent transactions, at least in the most common cases.

Steven Whitehouse committed 12 years ago

Commit b2c8b3e1 parent 885bcec3 files · +46 −10Browse files

Unified · Split

3 files
  1. fs/gfs2/inode.c +43 −7
  2. fs/gfs2/rgrp.c +1 −1
  3. include/uapi/linux/gfs2_ondisk.h +2 −2
fs/gfs2/inode.c+43−7
@@ -376,12 +376,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip, · 375 unmodified lines
376376 inode->i_gid = current_fsgid();
377377 }
378378
379−static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
379+static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks)
380380 {
381381 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
382− struct gfs2_alloc_parms ap = { .target = RES_DINODE, .aflags = flags, };
382+ struct gfs2_alloc_parms ap = { .target = *dblocks, .aflags = flags, };
383383 int error;
384− int dblocks = 1;
385384
386385 error = gfs2_quota_lock_check(ip);
387386 if (error)
@@ -391,11 +390,11 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags) · 3 unmodified lines
391390 if (error)
392391 goto out_quota;
393392
394− error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, 0);
393+ error = gfs2_trans_begin(sdp, (*dblocks * RES_RG_BIT) + RES_STATFS + RES_QUOTA, 0);
395394 if (error)
396395 goto out_ipreserv;
397396
398− error = gfs2_alloc_blocks(ip, &ip->i_no_addr, &dblocks, 1, &ip->i_generation);
397+ error = gfs2_alloc_blocks(ip, &ip->i_no_addr, dblocks, 1, &ip->i_generation);
399398 ip->i_no_formal_ino = ip->i_generation;
400399 ip->i_inode.i_ino = ip->i_no_addr;
401400 ip->i_goal = ip->i_no_addr;
@@ -427,6 +426,33 @@ static void gfs2_init_dir(struct buffer_head *dibh, · 25 unmodified lines
427426
428427 }
429428
429+/**
430+ * gfs2_init_xattr - Initialise an xattr block for a new inode
431+ * @ip: The inode in question
432+ *
433+ * This sets up an empty xattr block for a new inode, ready to
434+ * take any ACLs, LSM xattrs, etc.
435+ */
436+
437+static void gfs2_init_xattr(struct gfs2_inode *ip)
438+{
439+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
440+ struct buffer_head *bh;
441+ struct gfs2_ea_header *ea;
442+
443+ bh = gfs2_meta_new(ip->i_gl, ip->i_eattr);
444+ gfs2_trans_add_meta(ip->i_gl, bh);
445+ gfs2_metatype_set(bh, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
446+ gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
447+
448+ ea = GFS2_EA_BH2FIRST(bh);
449+ ea->ea_rec_len = cpu_to_be32(sdp->sd_jbsize);
450+ ea->ea_type = GFS2_EATYPE_UNUSED;
451+ ea->ea_flags = GFS2_EAFLAG_LAST;
452+
453+ brelse(bh);
454+}
455+
430456 /**
431457 * init_dinode - Fill in a new dinode structure
432458 * @dip: The directory this inode is being created in
@@ -580,6 +606,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 147 unmodified lines
580606 struct dentry *d;
581607 int error;
582608 u32 aflags = 0;
609+ unsigned blocks = 1;
583610 struct gfs2_diradd da = { .bh = NULL, };
584611
585612 if (!name->len || name->len > GFS2_FNAMESIZE)
@@ -676,10 +703,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 90 unmodified lines
676703 (dip->i_diskflags & GFS2_DIF_TOPDIR))
677704 aflags |= GFS2_AF_ORLOV;
678705
679− error = alloc_dinode(ip, aflags);
706+ if (default_acl || acl)
707+ blocks++;
708+
709+ error = alloc_dinode(ip, aflags, &blocks);
680710 if (error)
681711 goto fail_free_inode;
682712
713+ gfs2_set_inode_blocks(inode, blocks);
714+
683715 error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
684716 if (error)
685717 goto fail_free_inode;
@@ -689,10 +721,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 3 unmodified lines
689721 if (error)
690722 goto fail_free_inode;
691723
692− error = gfs2_trans_begin(sdp, RES_DINODE, 0);
724+ error = gfs2_trans_begin(sdp, blocks, 0);
693725 if (error)
694726 goto fail_gunlock2;
695727
728+ if (blocks > 1) {
729+ ip->i_eattr = ip->i_no_addr + 1;
730+ gfs2_init_xattr(ip);
731+ }
696732 init_dinode(dip, ip, symname);
697733 gfs2_trans_end(sdp);
698734
fs/gfs2/rgrp.c+1−1
@@ -2296,7 +2296,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, · 2295 unmodified lines
22962296
22972297 gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0);
22982298 if (dinode)
2299− gfs2_trans_add_unrevoke(sdp, block, 1);
2299+ gfs2_trans_add_unrevoke(sdp, block, *nblocks);
23002300
23012301 gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid);
23022302
include/uapi/linux/gfs2_ondisk.h+2−2
@@ -347,9 +347,9 @@ struct gfs2_leaf { · 346 unmodified lines
347347 * metadata header. Each inode, if it has extended attributes, will
348348 * have either a single block containing the extended attribute headers
349349 * or a single indirect block pointing to blocks containing the
350− * extended attribure headers.
350+ * extended attribute headers.
351351 *
352− * The maximim size of the data part of an extended attribute is 64k
352+ * The maximum size of the data part of an extended attribute is 64k
353353 * so the number of blocks required depends upon block size. Since the
354354 * block size also determines the number of pointers in an indirect
355355 * block, its a fairly complicated calculation to work out the maximum

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t