diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-12 18:09:35 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-12 18:09:35 -0800 |
commit | 4d58967783611c5676820b8d47a9b6b0bb456995 (patch) | |
tree | 6a20281fbff1a1a4e88d65d5851e51d8d6b2f02e /fs/gfs2/quota.c | |
parent | 33caf82acf4dc420bf0f0136b886f7b27ecf90c5 (diff) | |
parent | a93a99838248bdab49db2eaac00236847670bc7f (diff) |
Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull GFS2 updates from Bob Peterson:
"Here is a list of patches we've accumulated for GFS2 for the current
upstream merge window. Last window's set was short, but I warned that
this one would be bigger, and so it is. We've got 19 patches:
- A patch from Abhi Das to propagate the GFS2_DIF_SYSTEM bit so that
newly added journals don't get flagged, deleted, and recreated by
fsck.gfs2.
- Two patches from Andreas Gruenbacher to improve GFS2 performance
where extended attributes are involved.
- A patch from Andy Price to fix a suspicious rcu dereference error.
- Two patches from Ben Marzinski that rework how GFS2's NFS cookies
are managed. This fixes readdir problems with nfs-over-gfs2.
- A patch from Ben Marzinski that fixes a race in unmounting GFS2.
- A set of four patches from me to move the resource group
reservations inside the gfs2 inode to improve performance and fix a
bug whereby get_write_access improperly prevented some operations
like chown.
- A patch from me to spinlock-protect the setting of system statfs
file data. This was causing small discrepancies between df and du.
- A patch from me to reintroduce a timeout while clearing glocks
which was accidentally dropped some time ago.
- A patch from me to wait for iopen glock dequeues in order to
improve deleting of files that were unlinked from a different
cluster node.
- A patch from me to ensure metadata address spaces get truncated
when an inode is evicted.
- A patch from me to fix a bug in which a memory leak could occur in
some error cases when inodes were trying to be created.
- A patch to consistently use iopen glocks to transition from the
unlinked state to the deleted state.
- A patch to fix a glock reference count error when inode creation
fails.
- A patch from Junxiao Bi to fix an flock panic.
- A patch from Markus Elfring that removes an unnecessary if"
* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
gfs2: fix flock panic issue
GFS2: Don't do glock put on when inode creation fails
GFS2: Always use iopen glock for gl_deletes
GFS2: Release iopen glock in gfs2_create_inode error cases
GFS2: Truncate address space mapping when deleting an inode
GFS2: Wait for iopen glock dequeues
gfs2: clear journal live bit in gfs2_log_flush
gfs2: change gfs2 readdir cookie
gfs2: keep offset when splitting dir leaf blocks
GFS2: Reintroduce a timeout in function gfs2_gl_hash_clear
GFS2: Update master statfs buffer with sd_statfs_spin locked
GFS2: Reduce size of incore inode
GFS2: Make rgrp reservations part of the gfs2_inode structure
GFS2: Extract quota data from reservations structure (revert 5407e24)
gfs2: Extended attribute readahead optimization
gfs2: Extended attribute readahead
GFS2: Use rht_for_each_entry_rcu in glock_hash_walk
GFS2: Delete an unnecessary check before the function call "iput"
gfs2: Automatically set GFS2_DIF_SYSTEM flag on system files
Diffstat (limited to 'fs/gfs2/quota.c')
-rw-r--r-- | fs/gfs2/quota.c | 117 |
1 files changed, 76 insertions, 41 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 3a31226531ea..be6d9c450b22 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -388,7 +388,7 @@ static int bh_get(struct gfs2_quota_data *qd) error = gfs2_block_map(&ip->i_inode, block, &bh_map, 0); if (error) goto fail; - error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh); + error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, 0, &bh); if (error) goto fail; error = -EIO; @@ -527,37 +527,70 @@ static void qdsb_put(struct gfs2_quota_data *qd) qd_put(qd); } +/** + * gfs2_qa_alloc - make sure we have a quota allocations data structure, + * if necessary + * @ip: the inode for this reservation + */ +int gfs2_qa_alloc(struct gfs2_inode *ip) +{ + int error = 0; + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); + + if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) + return 0; + + down_write(&ip->i_rw_mutex); + if (ip->i_qadata == NULL) { + ip->i_qadata = kmem_cache_zalloc(gfs2_qadata_cachep, GFP_NOFS); + if (!ip->i_qadata) + error = -ENOMEM; + } + up_write(&ip->i_rw_mutex); + return error; +} + +void gfs2_qa_delete(struct gfs2_inode *ip, atomic_t *wcount) +{ + down_write(&ip->i_rw_mutex); + if (ip->i_qadata && ((wcount == NULL) || (atomic_read(wcount) <= 1))) { + kmem_cache_free(gfs2_qadata_cachep, ip->i_qadata); + ip->i_qadata = NULL; + } + up_write(&ip->i_rw_mutex); +} + int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_quota_data **qd; int error; - if (ip->i_res == NULL) { - error = gfs2_rs_alloc(ip); + if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) + return 0; + + if (ip->i_qadata == NULL) { + error = gfs2_rsqa_alloc(ip); if (error) return error; } - qd = ip->i_res->rs_qa_qd; + qd = ip->i_qadata->qa_qd; - if (gfs2_assert_warn(sdp, !ip->i_res->rs_qa_qd_num) || + if (gfs2_assert_warn(sdp, !ip->i_qadata->qa_qd_num) || gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags))) return -EIO; - if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) - return 0; - error = qdsb_get(sdp, make_kqid_uid(ip->i_inode.i_uid), qd); if (error) goto out; - ip->i_res->rs_qa_qd_num++; + ip->i_qadata->qa_qd_num++; qd++; error = qdsb_get(sdp, make_kqid_gid(ip->i_inode.i_gid), qd); if (error) goto out; - ip->i_res->rs_qa_qd_num++; + ip->i_qadata->qa_qd_num++; qd++; if (!uid_eq(uid, NO_UID_QUOTA_CHANGE) && @@ -565,7 +598,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) error = qdsb_get(sdp, make_kqid_uid(uid), qd); if (error) goto out; - ip->i_res->rs_qa_qd_num++; + ip->i_qadata->qa_qd_num++; qd++; } @@ -574,7 +607,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) error = qdsb_get(sdp, make_kqid_gid(gid), qd); if (error) goto out; - ip->i_res->rs_qa_qd_num++; + ip->i_qadata->qa_qd_num++; qd++; } @@ -587,17 +620,17 @@ out: void gfs2_quota_unhold(struct gfs2_inode *ip) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - unsigned int x; + u32 x; - if (ip->i_res == NULL) + if (ip->i_qadata == NULL) return; gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)); - for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { - qdsb_put(ip->i_res->rs_qa_qd[x]); - ip->i_res->rs_qa_qd[x] = NULL; + for (x = 0; x < ip->i_qadata->qa_qd_num; x++) { + qdsb_put(ip->i_qadata->qa_qd[x]); + ip->i_qadata->qa_qd[x] = NULL; } - ip->i_res->rs_qa_qd_num = 0; + ip->i_qadata->qa_qd_num = 0; } static int sort_qd(const void *a, const void *b) @@ -843,7 +876,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) unsigned int nalloc = 0, blocks; int error; - error = gfs2_rs_alloc(ip); + error = gfs2_rsqa_alloc(ip); if (error) return error; @@ -1003,23 +1036,23 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_quota_data *qd; - unsigned int x; + u32 x; int error = 0; - error = gfs2_quota_hold(ip, uid, gid); - if (error) - return error; - if (capable(CAP_SYS_RESOURCE) || sdp->sd_args.ar_quota != GFS2_QUOTA_ON) return 0; - sort(ip->i_res->rs_qa_qd, ip->i_res->rs_qa_qd_num, + error = gfs2_quota_hold(ip, uid, gid); + if (error) + return error; + + sort(ip->i_qadata->qa_qd, ip->i_qadata->qa_qd_num, sizeof(struct gfs2_quota_data *), sort_qd, NULL); - for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { - qd = ip->i_res->rs_qa_qd[x]; - error = do_glock(qd, NO_FORCE, &ip->i_res->rs_qa_qd_ghs[x]); + for (x = 0; x < ip->i_qadata->qa_qd_num; x++) { + qd = ip->i_qadata->qa_qd[x]; + error = do_glock(qd, NO_FORCE, &ip->i_qadata->qa_qd_ghs[x]); if (error) break; } @@ -1028,7 +1061,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) set_bit(GIF_QD_LOCKED, &ip->i_flags); else { while (x--) - gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]); + gfs2_glock_dq_uninit(&ip->i_qadata->qa_qd_ghs[x]); gfs2_quota_unhold(ip); } @@ -1076,20 +1109,20 @@ void gfs2_quota_unlock(struct gfs2_inode *ip) struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_quota_data *qda[4]; unsigned int count = 0; - unsigned int x; + u32 x; int found; if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags)) goto out; - for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { + for (x = 0; x < ip->i_qadata->qa_qd_num; x++) { struct gfs2_quota_data *qd; int sync; - qd = ip->i_res->rs_qa_qd[x]; + qd = ip->i_qadata->qa_qd[x]; sync = need_sync(qd); - gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]); + gfs2_glock_dq_uninit(&ip->i_qadata->qa_qd_ghs[x]); if (!sync) continue; @@ -1158,7 +1191,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid, struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_quota_data *qd; s64 value, warn, limit; - unsigned int x; + u32 x; int error = 0; ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */ @@ -1168,8 +1201,8 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid, if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON) return 0; - for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { - qd = ip->i_res->rs_qa_qd[x]; + for (x = 0; x < ip->i_qadata->qa_qd_num; x++) { + qd = ip->i_qadata->qa_qd[x]; if (!(qid_eq(qd->qd_id, make_kqid_uid(uid)) || qid_eq(qd->qd_id, make_kqid_gid(gid)))) @@ -1216,15 +1249,17 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change, kuid_t uid, kgid_t gid) { struct gfs2_quota_data *qd; - unsigned int x; + u32 x; + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change)) + if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON || + gfs2_assert_warn(sdp, change)) return; if (ip->i_diskflags & GFS2_DIF_SYSTEM) return; - for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { - qd = ip->i_res->rs_qa_qd[x]; + for (x = 0; x < ip->i_qadata->qa_qd_num; x++) { + qd = ip->i_qadata->qa_qd[x]; if (qid_eq(qd->qd_id, make_kqid_uid(uid)) || qid_eq(qd->qd_id, make_kqid_gid(gid))) { @@ -1635,7 +1670,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, if (error) return error; - error = gfs2_rs_alloc(ip); + error = gfs2_rsqa_alloc(ip); if (error) goto out_put; |