diff options
| -rw-r--r-- | fs/gfs2/inode.c | 50 | ||||
| -rw-r--r-- | fs/gfs2/rgrp.c | 2 | ||||
| -rw-r--r-- | include/uapi/linux/gfs2_ondisk.h | 4 |
3 files changed, 46 insertions, 10 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 5c524180c98e..ec455b92091f 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
| @@ -376,12 +376,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip, | |||
| 376 | inode->i_gid = current_fsgid(); | 376 | inode->i_gid = current_fsgid(); |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | static int alloc_dinode(struct gfs2_inode *ip, u32 flags) | 379 | static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks) |
| 380 | { | 380 | { |
| 381 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 381 | 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, }; |
| 383 | int error; | 383 | int error; |
| 384 | int dblocks = 1; | ||
| 385 | 384 | ||
| 386 | error = gfs2_quota_lock_check(ip); | 385 | error = gfs2_quota_lock_check(ip); |
| 387 | if (error) | 386 | if (error) |
| @@ -391,11 +390,11 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags) | |||
| 391 | if (error) | 390 | if (error) |
| 392 | goto out_quota; | 391 | goto out_quota; |
| 393 | 392 | ||
| 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); |
| 395 | if (error) | 394 | if (error) |
| 396 | goto out_ipreserv; | 395 | goto out_ipreserv; |
| 397 | 396 | ||
| 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); |
| 399 | ip->i_no_formal_ino = ip->i_generation; | 398 | ip->i_no_formal_ino = ip->i_generation; |
| 400 | ip->i_inode.i_ino = ip->i_no_addr; | 399 | ip->i_inode.i_ino = ip->i_no_addr; |
| 401 | ip->i_goal = ip->i_no_addr; | 400 | ip->i_goal = ip->i_no_addr; |
| @@ -428,6 +427,33 @@ static void gfs2_init_dir(struct buffer_head *dibh, | |||
| 428 | } | 427 | } |
| 429 | 428 | ||
| 430 | /** | 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 | |||
| 456 | /** | ||
| 431 | * init_dinode - Fill in a new dinode structure | 457 | * init_dinode - Fill in a new dinode structure |
| 432 | * @dip: The directory this inode is being created in | 458 | * @dip: The directory this inode is being created in |
| 433 | * @ip: The inode | 459 | * @ip: The inode |
| @@ -580,6 +606,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
| 580 | struct dentry *d; | 606 | struct dentry *d; |
| 581 | int error; | 607 | int error; |
| 582 | u32 aflags = 0; | 608 | u32 aflags = 0; |
| 609 | unsigned blocks = 1; | ||
| 583 | struct gfs2_diradd da = { .bh = NULL, }; | 610 | struct gfs2_diradd da = { .bh = NULL, }; |
| 584 | 611 | ||
| 585 | if (!name->len || name->len > GFS2_FNAMESIZE) | 612 | if (!name->len || name->len > GFS2_FNAMESIZE) |
| @@ -676,10 +703,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
| 676 | (dip->i_diskflags & GFS2_DIF_TOPDIR)) | 703 | (dip->i_diskflags & GFS2_DIF_TOPDIR)) |
| 677 | aflags |= GFS2_AF_ORLOV; | 704 | aflags |= GFS2_AF_ORLOV; |
| 678 | 705 | ||
| 679 | error = alloc_dinode(ip, aflags); | 706 | if (default_acl || acl) |
| 707 | blocks++; | ||
| 708 | |||
| 709 | error = alloc_dinode(ip, aflags, &blocks); | ||
| 680 | if (error) | 710 | if (error) |
| 681 | goto fail_free_inode; | 711 | goto fail_free_inode; |
| 682 | 712 | ||
| 713 | gfs2_set_inode_blocks(inode, blocks); | ||
| 714 | |||
| 683 | error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); | 715 | error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); |
| 684 | if (error) | 716 | if (error) |
| 685 | goto fail_free_inode; | 717 | goto fail_free_inode; |
| @@ -689,10 +721,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
| 689 | if (error) | 721 | if (error) |
| 690 | goto fail_free_inode; | 722 | goto fail_free_inode; |
| 691 | 723 | ||
| 692 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | 724 | error = gfs2_trans_begin(sdp, blocks, 0); |
| 693 | if (error) | 725 | if (error) |
| 694 | goto fail_gunlock2; | 726 | goto fail_gunlock2; |
| 695 | 727 | ||
| 728 | if (blocks > 1) { | ||
| 729 | ip->i_eattr = ip->i_no_addr + 1; | ||
| 730 | gfs2_init_xattr(ip); | ||
| 731 | } | ||
| 696 | init_dinode(dip, ip, symname); | 732 | init_dinode(dip, ip, symname); |
| 697 | gfs2_trans_end(sdp); | 733 | gfs2_trans_end(sdp); |
| 698 | 734 | ||
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index a1da21349235..c13e4c5e9967 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
| @@ -2296,7 +2296,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, | |||
| 2296 | 2296 | ||
| 2297 | gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); | 2297 | gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); |
| 2298 | if (dinode) | 2298 | if (dinode) |
| 2299 | gfs2_trans_add_unrevoke(sdp, block, 1); | 2299 | gfs2_trans_add_unrevoke(sdp, block, *nblocks); |
| 2300 | 2300 | ||
| 2301 | gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid); | 2301 | gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid); |
| 2302 | 2302 | ||
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h index 0f24c07aed51..310020816809 100644 --- a/include/uapi/linux/gfs2_ondisk.h +++ b/include/uapi/linux/gfs2_ondisk.h | |||
| @@ -347,9 +347,9 @@ struct gfs2_leaf { | |||
| 347 | * metadata header. Each inode, if it has extended attributes, will | 347 | * metadata header. Each inode, if it has extended attributes, will |
| 348 | * have either a single block containing the extended attribute headers | 348 | * have either a single block containing the extended attribute headers |
| 349 | * or a single indirect block pointing to blocks containing the | 349 | * or a single indirect block pointing to blocks containing the |
| 350 | * extended attribure headers. | 350 | * extended attribute headers. |
| 351 | * | 351 | * |
| 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 |
| 353 | * so the number of blocks required depends upon block size. Since the | 353 | * so the number of blocks required depends upon block size. Since the |
| 354 | * block size also determines the number of pointers in an indirect | 354 | * block size also determines the number of pointers in an indirect |
| 355 | * block, its a fairly complicated calculation to work out the maximum | 355 | * block, its a fairly complicated calculation to work out the maximum |
