aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 14:40:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 14:40:24 -0400
commit239dab4636f7f5f971ac39b5ca84254cff112cac (patch)
treeba16a01035dd13bb87795911da436b6295f9b341 /fs/xfs
parentf1c410885288e0042099960ee9e0c260dfea4cfb (diff)
parentc31ad439e8d111bf911c9cc80619cebde411a44d (diff)
Merge tag 'for-linus-v3.11-rc1-2' of git://oss.sgi.com/xfs/xfs
Pull more xfs updates from Ben Myers: "Here are a fix for xfs_fsr, a cleanup in bulkstat, a cleanup in xfs_open_by_handle, updated mount options documentation, a cleanup in xfs_bmapi_write, a fix for the size of dquot log reservations, a fix for sgid inheritance when acls are in use, a fix for cleaning up quotainfo structures, and some more of the work which allows group and project quotas to be used together. We had a few more in this last quota category that we might have liked to get in, but it looks there are still a few items that need to be addressed. - fix for xfs_fsr returning -EINVAL - cleanup in xfs_bulkstat - cleanup in xfs_open_by_handle - update mount options documentation - clean up local format handling in xfs_bmapi_write - fix dquot log reservations which were too small - fix sgid inheritance for subdirectories when default acls are in use - add project quota fields to various structures - fix teardown of quotainfo structures when quotas are turned off" * tag 'for-linus-v3.11-rc1-2' of git://oss.sgi.com/xfs/xfs: xfs: Fix the logic check for all quotas being turned off xfs: Add pquota fields where gquota is used. xfs: fix sgid inheritance for subdirectories inheriting default acls [V3] xfs: dquot log reservations are too small xfs: remove local fork format handling from xfs_bmapi_write() xfs: update mount options documentation xfs: use get_unused_fd_flags(0) instead of get_unused_fd() xfs: clean up unused codes at xfs_bulkstat() xfs: use XFS_BMAP_BMDR_SPACE vs. XFS_BROOT_SIZE_ADJ
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_attr_leaf.c2
-rw-r--r--fs/xfs/xfs_bmap.c199
-rw-r--r--fs/xfs/xfs_bmap.h1
-rw-r--r--fs/xfs/xfs_dinode.h3
-rw-r--r--fs/xfs/xfs_dir2_block.c20
-rw-r--r--fs/xfs/xfs_dquot.c15
-rw-r--r--fs/xfs/xfs_dquot.h7
-rw-r--r--fs/xfs/xfs_icache.c1
-rw-r--r--fs/xfs/xfs_inode.c14
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_ioctl.c16
-rw-r--r--fs/xfs/xfs_iops.c24
-rw-r--r--fs/xfs/xfs_itable.c28
-rw-r--r--fs/xfs/xfs_qm.c243
-rw-r--r--fs/xfs/xfs_qm.h20
-rw-r--r--fs/xfs/xfs_qm_bhv.c10
-rw-r--r--fs/xfs/xfs_qm_syscalls.c24
-rw-r--r--fs/xfs/xfs_quota.h65
-rw-r--r--fs/xfs/xfs_symlink.c10
-rw-r--r--fs/xfs/xfs_trans_dquot.c35
-rw-r--r--fs/xfs/xfs_vnodeops.c13
21 files changed, 435 insertions, 316 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 31d3cd129269..b800fbcafc7f 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -690,6 +690,8 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
690 sf = (xfs_attr_shortform_t *)tmpbuffer; 690 sf = (xfs_attr_shortform_t *)tmpbuffer;
691 691
692 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); 692 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
693 xfs_bmap_local_to_extents_empty(dp, XFS_ATTR_FORK);
694
693 bp = NULL; 695 bp = NULL;
694 error = xfs_da_grow_inode(args, &blkno); 696 error = xfs_da_grow_inode(args, &blkno);
695 if (error) { 697 if (error) {
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 89042848f9ec..05c698ccb238 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -1161,6 +1161,24 @@ xfs_bmap_extents_to_btree(
1161 * since the file data needs to get logged so things will stay consistent. 1161 * since the file data needs to get logged so things will stay consistent.
1162 * (The bmap-level manipulations are ok, though). 1162 * (The bmap-level manipulations are ok, though).
1163 */ 1163 */
1164void
1165xfs_bmap_local_to_extents_empty(
1166 struct xfs_inode *ip,
1167 int whichfork)
1168{
1169 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
1170
1171 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
1172 ASSERT(ifp->if_bytes == 0);
1173 ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
1174
1175 xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
1176 ifp->if_flags &= ~XFS_IFINLINE;
1177 ifp->if_flags |= XFS_IFEXTENTS;
1178 XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
1179}
1180
1181
1164STATIC int /* error */ 1182STATIC int /* error */
1165xfs_bmap_local_to_extents( 1183xfs_bmap_local_to_extents(
1166 xfs_trans_t *tp, /* transaction pointer */ 1184 xfs_trans_t *tp, /* transaction pointer */
@@ -1174,9 +1192,12 @@ xfs_bmap_local_to_extents(
1174 struct xfs_inode *ip, 1192 struct xfs_inode *ip,
1175 struct xfs_ifork *ifp)) 1193 struct xfs_ifork *ifp))
1176{ 1194{
1177 int error; /* error return value */ 1195 int error = 0;
1178 int flags; /* logging flags returned */ 1196 int flags; /* logging flags returned */
1179 xfs_ifork_t *ifp; /* inode fork pointer */ 1197 xfs_ifork_t *ifp; /* inode fork pointer */
1198 xfs_alloc_arg_t args; /* allocation arguments */
1199 xfs_buf_t *bp; /* buffer for extent block */
1200 xfs_bmbt_rec_host_t *ep; /* extent record pointer */
1180 1201
1181 /* 1202 /*
1182 * We don't want to deal with the case of keeping inode data inline yet. 1203 * We don't want to deal with the case of keeping inode data inline yet.
@@ -1185,68 +1206,65 @@ xfs_bmap_local_to_extents(
1185 ASSERT(!(S_ISREG(ip->i_d.di_mode) && whichfork == XFS_DATA_FORK)); 1206 ASSERT(!(S_ISREG(ip->i_d.di_mode) && whichfork == XFS_DATA_FORK));
1186 ifp = XFS_IFORK_PTR(ip, whichfork); 1207 ifp = XFS_IFORK_PTR(ip, whichfork);
1187 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); 1208 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
1209
1210 if (!ifp->if_bytes) {
1211 xfs_bmap_local_to_extents_empty(ip, whichfork);
1212 flags = XFS_ILOG_CORE;
1213 goto done;
1214 }
1215
1188 flags = 0; 1216 flags = 0;
1189 error = 0; 1217 error = 0;
1190 if (ifp->if_bytes) { 1218 ASSERT((ifp->if_flags & (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) ==
1191 xfs_alloc_arg_t args; /* allocation arguments */ 1219 XFS_IFINLINE);
1192 xfs_buf_t *bp; /* buffer for extent block */ 1220 memset(&args, 0, sizeof(args));
1193 xfs_bmbt_rec_host_t *ep;/* extent record pointer */ 1221 args.tp = tp;
1194 1222 args.mp = ip->i_mount;
1195 ASSERT((ifp->if_flags & 1223 args.firstblock = *firstblock;
1196 (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); 1224 /*
1197 memset(&args, 0, sizeof(args)); 1225 * Allocate a block. We know we need only one, since the
1198 args.tp = tp; 1226 * file currently fits in an inode.
1199 args.mp = ip->i_mount; 1227 */
1200 args.firstblock = *firstblock; 1228 if (*firstblock == NULLFSBLOCK) {
1201 /* 1229 args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
1202 * Allocate a block. We know we need only one, since the 1230 args.type = XFS_ALLOCTYPE_START_BNO;
1203 * file currently fits in an inode.
1204 */
1205 if (*firstblock == NULLFSBLOCK) {
1206 args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
1207 args.type = XFS_ALLOCTYPE_START_BNO;
1208 } else {
1209 args.fsbno = *firstblock;
1210 args.type = XFS_ALLOCTYPE_NEAR_BNO;
1211 }
1212 args.total = total;
1213 args.minlen = args.maxlen = args.prod = 1;
1214 error = xfs_alloc_vextent(&args);
1215 if (error)
1216 goto done;
1217
1218 /* Can't fail, the space was reserved. */
1219 ASSERT(args.fsbno != NULLFSBLOCK);
1220 ASSERT(args.len == 1);
1221 *firstblock = args.fsbno;
1222 bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
1223
1224 /* initialise the block and copy the data */
1225 init_fn(tp, bp, ip, ifp);
1226
1227 /* account for the change in fork size and log everything */
1228 xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
1229 xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
1230 xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
1231 xfs_iext_add(ifp, 0, 1);
1232 ep = xfs_iext_get_ext(ifp, 0);
1233 xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
1234 trace_xfs_bmap_post_update(ip, 0,
1235 whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0,
1236 _THIS_IP_);
1237 XFS_IFORK_NEXT_SET(ip, whichfork, 1);
1238 ip->i_d.di_nblocks = 1;
1239 xfs_trans_mod_dquot_byino(tp, ip,
1240 XFS_TRANS_DQ_BCOUNT, 1L);
1241 flags |= xfs_ilog_fext(whichfork);
1242 } else { 1231 } else {
1243 ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); 1232 args.fsbno = *firstblock;
1244 xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork); 1233 args.type = XFS_ALLOCTYPE_NEAR_BNO;
1245 } 1234 }
1246 ifp->if_flags &= ~XFS_IFINLINE; 1235 args.total = total;
1247 ifp->if_flags |= XFS_IFEXTENTS; 1236 args.minlen = args.maxlen = args.prod = 1;
1248 XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); 1237 error = xfs_alloc_vextent(&args);
1238 if (error)
1239 goto done;
1240
1241 /* Can't fail, the space was reserved. */
1242 ASSERT(args.fsbno != NULLFSBLOCK);
1243 ASSERT(args.len == 1);
1244 *firstblock = args.fsbno;
1245 bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
1246
1247 /* initialise the block and copy the data */
1248 init_fn(tp, bp, ip, ifp);
1249
1250 /* account for the change in fork size and log everything */
1251 xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
1252 xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
1253 xfs_bmap_local_to_extents_empty(ip, whichfork);
1249 flags |= XFS_ILOG_CORE; 1254 flags |= XFS_ILOG_CORE;
1255
1256 xfs_iext_add(ifp, 0, 1);
1257 ep = xfs_iext_get_ext(ifp, 0);
1258 xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
1259 trace_xfs_bmap_post_update(ip, 0,
1260 whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0,
1261 _THIS_IP_);
1262 XFS_IFORK_NEXT_SET(ip, whichfork, 1);
1263 ip->i_d.di_nblocks = 1;
1264 xfs_trans_mod_dquot_byino(tp, ip,
1265 XFS_TRANS_DQ_BCOUNT, 1L);
1266 flags |= xfs_ilog_fext(whichfork);
1267
1250done: 1268done:
1251 *logflagsp = flags; 1269 *logflagsp = flags;
1252 return error; 1270 return error;
@@ -1323,25 +1341,6 @@ xfs_bmap_add_attrfork_extents(
1323} 1341}
1324 1342
1325/* 1343/*
1326 * Block initialisation function for local to extent format conversion.
1327 *
1328 * This shouldn't actually be called by anyone, so make sure debug kernels cause
1329 * a noticable failure.
1330 */
1331STATIC void
1332xfs_bmap_local_to_extents_init_fn(
1333 struct xfs_trans *tp,
1334 struct xfs_buf *bp,
1335 struct xfs_inode *ip,
1336 struct xfs_ifork *ifp)
1337{
1338 ASSERT(0);
1339 bp->b_ops = &xfs_bmbt_buf_ops;
1340 memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
1341 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF);
1342}
1343
1344/*
1345 * Called from xfs_bmap_add_attrfork to handle local format files. Each 1344 * Called from xfs_bmap_add_attrfork to handle local format files. Each
1346 * different data fork content type needs a different callout to do the 1345 * different data fork content type needs a different callout to do the
1347 * conversion. Some are basic and only require special block initialisation 1346 * conversion. Some are basic and only require special block initialisation
@@ -1381,9 +1380,9 @@ xfs_bmap_add_attrfork_local(
1381 flags, XFS_DATA_FORK, 1380 flags, XFS_DATA_FORK,
1382 xfs_symlink_local_to_remote); 1381 xfs_symlink_local_to_remote);
1383 1382
1384 return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, 1383 /* should only be called for types that support local format data */
1385 XFS_DATA_FORK, 1384 ASSERT(0);
1386 xfs_bmap_local_to_extents_init_fn); 1385 return EFSCORRUPTED;
1387} 1386}
1388 1387
1389/* 1388/*
@@ -4907,20 +4906,19 @@ xfs_bmapi_write(
4907 orig_mval = mval; 4906 orig_mval = mval;
4908 orig_nmap = *nmap; 4907 orig_nmap = *nmap;
4909#endif 4908#endif
4909 whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4910 XFS_ATTR_FORK : XFS_DATA_FORK;
4910 4911
4911 ASSERT(*nmap >= 1); 4912 ASSERT(*nmap >= 1);
4912 ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); 4913 ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
4913 ASSERT(!(flags & XFS_BMAPI_IGSTATE)); 4914 ASSERT(!(flags & XFS_BMAPI_IGSTATE));
4914 ASSERT(tp != NULL); 4915 ASSERT(tp != NULL);
4915 ASSERT(len > 0); 4916 ASSERT(len > 0);
4916 4917 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL);
4917 whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4918 XFS_ATTR_FORK : XFS_DATA_FORK;
4919 4918
4920 if (unlikely(XFS_TEST_ERROR( 4919 if (unlikely(XFS_TEST_ERROR(
4921 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && 4920 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4922 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && 4921 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
4923 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
4924 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { 4922 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
4925 XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp); 4923 XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp);
4926 return XFS_ERROR(EFSCORRUPTED); 4924 return XFS_ERROR(EFSCORRUPTED);
@@ -4933,37 +4931,6 @@ xfs_bmapi_write(
4933 4931
4934 XFS_STATS_INC(xs_blk_mapw); 4932 XFS_STATS_INC(xs_blk_mapw);
4935 4933
4936 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4937 /*
4938 * XXX (dgc): This assumes we are only called for inodes that
4939 * contain content neutral data in local format. Anything that
4940 * contains caller-specific data in local format that needs
4941 * transformation to move to a block format needs to do the
4942 * conversion to extent format itself.
4943 *
4944 * Directory data forks and attribute forks handle this
4945 * themselves, but with the addition of metadata verifiers every
4946 * data fork in local format now contains caller specific data
4947 * and as such conversion through this function is likely to be
4948 * broken.
4949 *
4950 * The only likely user of this branch is for remote symlinks,
4951 * but we cannot overwrite the data fork contents of the symlink
4952 * (EEXIST occurs higher up the stack) and so it will never go
4953 * from local format to extent format here. Hence I don't think
4954 * this branch is ever executed intentionally and we should
4955 * consider removing it and asserting that xfs_bmapi_write()
4956 * cannot be called directly on local format forks. i.e. callers
4957 * are completely responsible for local to extent format
4958 * conversion, not xfs_bmapi_write().
4959 */
4960 error = xfs_bmap_local_to_extents(tp, ip, firstblock, total,
4961 &bma.logflags, whichfork,
4962 xfs_bmap_local_to_extents_init_fn);
4963 if (error)
4964 goto error0;
4965 }
4966
4967 if (*firstblock == NULLFSBLOCK) { 4934 if (*firstblock == NULLFSBLOCK) {
4968 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) 4935 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
4969 bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; 4936 bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 5f469c3516eb..1cf1292d29b7 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -172,6 +172,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
172#endif 172#endif
173 173
174int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); 174int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
175void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
175void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len, 176void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len,
176 struct xfs_bmap_free *flist, struct xfs_mount *mp); 177 struct xfs_bmap_free *flist, struct xfs_mount *mp);
177void xfs_bmap_cancel(struct xfs_bmap_free *flist); 178void xfs_bmap_cancel(struct xfs_bmap_free *flist);
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index f7a0e95d197a..07d735a80a0f 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -132,9 +132,6 @@ typedef enum xfs_dinode_fmt {
132#define XFS_LITINO(mp, version) \ 132#define XFS_LITINO(mp, version) \
133 ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version))) 133 ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version)))
134 134
135#define XFS_BROOT_SIZE_ADJ(ip) \
136 (XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))
137
138/* 135/*
139 * Inode data & attribute fork sizes, per inode. 136 * Inode data & attribute fork sizes, per inode.
140 */ 137 */
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 09aea0247d96..5e7fbd72cf52 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -29,6 +29,7 @@
29#include "xfs_dinode.h" 29#include "xfs_dinode.h"
30#include "xfs_inode.h" 30#include "xfs_inode.h"
31#include "xfs_inode_item.h" 31#include "xfs_inode_item.h"
32#include "xfs_bmap.h"
32#include "xfs_buf_item.h" 33#include "xfs_buf_item.h"
33#include "xfs_dir2.h" 34#include "xfs_dir2.h"
34#include "xfs_dir2_format.h" 35#include "xfs_dir2_format.h"
@@ -1164,13 +1165,15 @@ xfs_dir2_sf_to_block(
1164 __be16 *tagp; /* end of data entry */ 1165 __be16 *tagp; /* end of data entry */
1165 xfs_trans_t *tp; /* transaction pointer */ 1166 xfs_trans_t *tp; /* transaction pointer */
1166 struct xfs_name name; 1167 struct xfs_name name;
1168 struct xfs_ifork *ifp;
1167 1169
1168 trace_xfs_dir2_sf_to_block(args); 1170 trace_xfs_dir2_sf_to_block(args);
1169 1171
1170 dp = args->dp; 1172 dp = args->dp;
1171 tp = args->trans; 1173 tp = args->trans;
1172 mp = dp->i_mount; 1174 mp = dp->i_mount;
1173 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 1175 ifp = XFS_IFORK_PTR(dp, XFS_DATA_FORK);
1176 ASSERT(ifp->if_flags & XFS_IFINLINE);
1174 /* 1177 /*
1175 * Bomb out if the shortform directory is way too short. 1178 * Bomb out if the shortform directory is way too short.
1176 */ 1179 */
@@ -1179,22 +1182,23 @@ xfs_dir2_sf_to_block(
1179 return XFS_ERROR(EIO); 1182 return XFS_ERROR(EIO);
1180 } 1183 }
1181 1184
1182 oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 1185 oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data;
1183 1186
1184 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 1187 ASSERT(ifp->if_bytes == dp->i_d.di_size);
1185 ASSERT(dp->i_df.if_u1.if_data != NULL); 1188 ASSERT(ifp->if_u1.if_data != NULL);
1186 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count)); 1189 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count));
1190 ASSERT(dp->i_d.di_nextents == 0);
1187 1191
1188 /* 1192 /*
1189 * Copy the directory into a temporary buffer. 1193 * Copy the directory into a temporary buffer.
1190 * Then pitch the incore inode data so we can make extents. 1194 * Then pitch the incore inode data so we can make extents.
1191 */ 1195 */
1192 sfp = kmem_alloc(dp->i_df.if_bytes, KM_SLEEP); 1196 sfp = kmem_alloc(ifp->if_bytes, KM_SLEEP);
1193 memcpy(sfp, oldsfp, dp->i_df.if_bytes); 1197 memcpy(sfp, oldsfp, ifp->if_bytes);
1194 1198
1195 xfs_idata_realloc(dp, -dp->i_df.if_bytes, XFS_DATA_FORK); 1199 xfs_idata_realloc(dp, -ifp->if_bytes, XFS_DATA_FORK);
1200 xfs_bmap_local_to_extents_empty(dp, XFS_DATA_FORK);
1196 dp->i_d.di_size = 0; 1201 dp->i_d.di_size = 0;
1197 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1198 1202
1199 /* 1203 /*
1200 * Add block 0 to the inode. 1204 * Add block 0 to the inode.
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index f01012de06d0..0adf27ecf3f1 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -936,6 +936,7 @@ xfs_qm_dqput_final(
936{ 936{
937 struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; 937 struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo;
938 struct xfs_dquot *gdqp; 938 struct xfs_dquot *gdqp;
939 struct xfs_dquot *pdqp;
939 940
940 trace_xfs_dqput_free(dqp); 941 trace_xfs_dqput_free(dqp);
941 942
@@ -949,21 +950,29 @@ xfs_qm_dqput_final(
949 950
950 /* 951 /*
951 * If we just added a udquot to the freelist, then we want to release 952 * If we just added a udquot to the freelist, then we want to release
952 * the gdquot reference that it (probably) has. Otherwise it'll keep 953 * the gdquot/pdquot reference that it (probably) has. Otherwise it'll
953 * the gdquot from getting reclaimed. 954 * keep the gdquot/pdquot from getting reclaimed.
954 */ 955 */
955 gdqp = dqp->q_gdquot; 956 gdqp = dqp->q_gdquot;
956 if (gdqp) { 957 if (gdqp) {
957 xfs_dqlock(gdqp); 958 xfs_dqlock(gdqp);
958 dqp->q_gdquot = NULL; 959 dqp->q_gdquot = NULL;
959 } 960 }
961
962 pdqp = dqp->q_pdquot;
963 if (pdqp) {
964 xfs_dqlock(pdqp);
965 dqp->q_pdquot = NULL;
966 }
960 xfs_dqunlock(dqp); 967 xfs_dqunlock(dqp);
961 968
962 /* 969 /*
963 * If we had a group quota hint, release it now. 970 * If we had a group/project quota hint, release it now.
964 */ 971 */
965 if (gdqp) 972 if (gdqp)
966 xfs_qm_dqput(gdqp); 973 xfs_qm_dqput(gdqp);
974 if (pdqp)
975 xfs_qm_dqput(pdqp);
967} 976}
968 977
969/* 978/*
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index b596626249b8..55abbca2883d 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -53,6 +53,7 @@ typedef struct xfs_dquot {
53 xfs_fileoff_t q_fileoffset; /* offset in quotas file */ 53 xfs_fileoff_t q_fileoffset; /* offset in quotas file */
54 54
55 struct xfs_dquot*q_gdquot; /* group dquot, hint only */ 55 struct xfs_dquot*q_gdquot; /* group dquot, hint only */
56 struct xfs_dquot*q_pdquot; /* project dquot, hint only */
56 xfs_disk_dquot_t q_core; /* actual usage & quotas */ 57 xfs_disk_dquot_t q_core; /* actual usage & quotas */
57 xfs_dq_logitem_t q_logitem; /* dquot log item */ 58 xfs_dq_logitem_t q_logitem; /* dquot log item */
58 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ 59 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */
@@ -118,8 +119,9 @@ static inline int xfs_this_quota_on(struct xfs_mount *mp, int type)
118 case XFS_DQ_USER: 119 case XFS_DQ_USER:
119 return XFS_IS_UQUOTA_ON(mp); 120 return XFS_IS_UQUOTA_ON(mp);
120 case XFS_DQ_GROUP: 121 case XFS_DQ_GROUP:
122 return XFS_IS_GQUOTA_ON(mp);
121 case XFS_DQ_PROJ: 123 case XFS_DQ_PROJ:
122 return XFS_IS_OQUOTA_ON(mp); 124 return XFS_IS_PQUOTA_ON(mp);
123 default: 125 default:
124 return 0; 126 return 0;
125 } 127 }
@@ -131,8 +133,9 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
131 case XFS_DQ_USER: 133 case XFS_DQ_USER:
132 return ip->i_udquot; 134 return ip->i_udquot;
133 case XFS_DQ_GROUP: 135 case XFS_DQ_GROUP:
134 case XFS_DQ_PROJ:
135 return ip->i_gdquot; 136 return ip->i_gdquot;
137 case XFS_DQ_PROJ:
138 return ip->i_pdquot;
136 default: 139 default:
137 return NULL; 140 return NULL;
138 } 141 }
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 9560dc1f15a9..3f90e1ceb8d6 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -337,6 +337,7 @@ xfs_iget_cache_miss(
337 iflags |= XFS_IDONTCACHE; 337 iflags |= XFS_IDONTCACHE;
338 ip->i_udquot = NULL; 338 ip->i_udquot = NULL;
339 ip->i_gdquot = NULL; 339 ip->i_gdquot = NULL;
340 ip->i_pdquot = NULL;
340 xfs_iflags_set(ip, iflags); 341 xfs_iflags_set(ip, iflags);
341 342
342 /* insert the new inode */ 343 /* insert the new inode */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 9ecfe1e559fc..b78481f99d9d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2156,8 +2156,8 @@ xfs_iroot_realloc(
2156 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, 2156 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
2157 (int)new_size); 2157 (int)new_size);
2158 ifp->if_broot_bytes = (int)new_size; 2158 ifp->if_broot_bytes = (int)new_size;
2159 ASSERT(ifp->if_broot_bytes <= 2159 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
2160 XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip)); 2160 XFS_IFORK_SIZE(ip, whichfork));
2161 memmove(np, op, cur_max * (uint)sizeof(xfs_dfsbno_t)); 2161 memmove(np, op, cur_max * (uint)sizeof(xfs_dfsbno_t));
2162 return; 2162 return;
2163 } 2163 }
@@ -2210,8 +2210,9 @@ xfs_iroot_realloc(
2210 kmem_free(ifp->if_broot); 2210 kmem_free(ifp->if_broot);
2211 ifp->if_broot = new_broot; 2211 ifp->if_broot = new_broot;
2212 ifp->if_broot_bytes = (int)new_size; 2212 ifp->if_broot_bytes = (int)new_size;
2213 ASSERT(ifp->if_broot_bytes <= 2213 if (ifp->if_broot)
2214 XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip)); 2214 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
2215 XFS_IFORK_SIZE(ip, whichfork));
2215 return; 2216 return;
2216} 2217}
2217 2218
@@ -2522,9 +2523,8 @@ xfs_iflush_fork(
2522 if ((iip->ili_fields & brootflag[whichfork]) && 2523 if ((iip->ili_fields & brootflag[whichfork]) &&
2523 (ifp->if_broot_bytes > 0)) { 2524 (ifp->if_broot_bytes > 0)) {
2524 ASSERT(ifp->if_broot != NULL); 2525 ASSERT(ifp->if_broot != NULL);
2525 ASSERT(ifp->if_broot_bytes <= 2526 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
2526 (XFS_IFORK_SIZE(ip, whichfork) + 2527 XFS_IFORK_SIZE(ip, whichfork));
2527 XFS_BROOT_SIZE_ADJ(ip)));
2528 xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes, 2528 xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
2529 (xfs_bmdr_block_t *)cp, 2529 (xfs_bmdr_block_t *)cp,
2530 XFS_DFORK_SIZE(dip, mp, whichfork)); 2530 XFS_DFORK_SIZE(dip, mp, whichfork));
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 91129794aaec..b55fd347ab5b 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -250,6 +250,7 @@ typedef struct xfs_inode {
250 struct xfs_mount *i_mount; /* fs mount struct ptr */ 250 struct xfs_mount *i_mount; /* fs mount struct ptr */
251 struct xfs_dquot *i_udquot; /* user dquot */ 251 struct xfs_dquot *i_udquot; /* user dquot */
252 struct xfs_dquot *i_gdquot; /* group dquot */ 252 struct xfs_dquot *i_gdquot; /* group dquot */
253 struct xfs_dquot *i_pdquot; /* project dquot */
253 254
254 /* Inode location stuff */ 255 /* Inode location stuff */
255 xfs_ino_t i_ino; /* inode number (agno/agino)*/ 256 xfs_ino_t i_ino; /* inode number (agno/agino)*/
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 5e999680094a..6e2bca5d44d6 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -248,7 +248,7 @@ xfs_open_by_handle(
248 goto out_dput; 248 goto out_dput;
249 } 249 }
250 250
251 fd = get_unused_fd(); 251 fd = get_unused_fd_flags(0);
252 if (fd < 0) { 252 if (fd < 0) {
253 error = fd; 253 error = fd;
254 goto out_dput; 254 goto out_dput;
@@ -928,7 +928,7 @@ xfs_ioctl_setattr(
928 struct xfs_trans *tp; 928 struct xfs_trans *tp;
929 unsigned int lock_flags = 0; 929 unsigned int lock_flags = 0;
930 struct xfs_dquot *udqp = NULL; 930 struct xfs_dquot *udqp = NULL;
931 struct xfs_dquot *gdqp = NULL; 931 struct xfs_dquot *pdqp = NULL;
932 struct xfs_dquot *olddquot = NULL; 932 struct xfs_dquot *olddquot = NULL;
933 int code; 933 int code;
934 934
@@ -957,7 +957,7 @@ xfs_ioctl_setattr(
957 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) { 957 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
958 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid, 958 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
959 ip->i_d.di_gid, fa->fsx_projid, 959 ip->i_d.di_gid, fa->fsx_projid,
960 XFS_QMOPT_PQUOTA, &udqp, &gdqp); 960 XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
961 if (code) 961 if (code)
962 return code; 962 return code;
963 } 963 }
@@ -994,8 +994,8 @@ xfs_ioctl_setattr(
994 XFS_IS_PQUOTA_ON(mp) && 994 XFS_IS_PQUOTA_ON(mp) &&
995 xfs_get_projid(ip) != fa->fsx_projid) { 995 xfs_get_projid(ip) != fa->fsx_projid) {
996 ASSERT(tp); 996 ASSERT(tp);
997 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, 997 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
998 capable(CAP_FOWNER) ? 998 pdqp, capable(CAP_FOWNER) ?
999 XFS_QMOPT_FORCE_RES : 0); 999 XFS_QMOPT_FORCE_RES : 0);
1000 if (code) /* out of quota */ 1000 if (code) /* out of quota */
1001 goto error_return; 1001 goto error_return;
@@ -1113,7 +1113,7 @@ xfs_ioctl_setattr(
1113 if (xfs_get_projid(ip) != fa->fsx_projid) { 1113 if (xfs_get_projid(ip) != fa->fsx_projid) {
1114 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) { 1114 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1115 olddquot = xfs_qm_vop_chown(tp, ip, 1115 olddquot = xfs_qm_vop_chown(tp, ip,
1116 &ip->i_gdquot, gdqp); 1116 &ip->i_pdquot, pdqp);
1117 } 1117 }
1118 xfs_set_projid(ip, fa->fsx_projid); 1118 xfs_set_projid(ip, fa->fsx_projid);
1119 1119
@@ -1160,13 +1160,13 @@ xfs_ioctl_setattr(
1160 */ 1160 */
1161 xfs_qm_dqrele(olddquot); 1161 xfs_qm_dqrele(olddquot);
1162 xfs_qm_dqrele(udqp); 1162 xfs_qm_dqrele(udqp);
1163 xfs_qm_dqrele(gdqp); 1163 xfs_qm_dqrele(pdqp);
1164 1164
1165 return code; 1165 return code;
1166 1166
1167 error_return: 1167 error_return:
1168 xfs_qm_dqrele(udqp); 1168 xfs_qm_dqrele(udqp);
1169 xfs_qm_dqrele(gdqp); 1169 xfs_qm_dqrele(pdqp);
1170 xfs_trans_cancel(tp, 0); 1170 xfs_trans_cancel(tp, 0);
1171 if (lock_flags) 1171 if (lock_flags)
1172 xfs_iunlock(ip, lock_flags); 1172 xfs_iunlock(ip, lock_flags);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index c69bbc493cb0..96dda62d497b 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -467,9 +467,6 @@ xfs_setattr_mode(
467 ASSERT(tp); 467 ASSERT(tp);
468 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 468 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
469 469
470 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
471 mode &= ~S_ISGID;
472
473 ip->i_d.di_mode &= S_IFMT; 470 ip->i_d.di_mode &= S_IFMT;
474 ip->i_d.di_mode |= mode & ~S_IFMT; 471 ip->i_d.di_mode |= mode & ~S_IFMT;
475 472
@@ -495,15 +492,18 @@ xfs_setattr_nonsize(
495 492
496 trace_xfs_setattr(ip); 493 trace_xfs_setattr(ip);
497 494
498 if (mp->m_flags & XFS_MOUNT_RDONLY) 495 /* If acls are being inherited, we already have this checked */
499 return XFS_ERROR(EROFS); 496 if (!(flags & XFS_ATTR_NOACL)) {
497 if (mp->m_flags & XFS_MOUNT_RDONLY)
498 return XFS_ERROR(EROFS);
500 499
501 if (XFS_FORCED_SHUTDOWN(mp)) 500 if (XFS_FORCED_SHUTDOWN(mp))
502 return XFS_ERROR(EIO); 501 return XFS_ERROR(EIO);
503 502
504 error = -inode_change_ok(inode, iattr); 503 error = -inode_change_ok(inode, iattr);
505 if (error) 504 if (error)
506 return XFS_ERROR(error); 505 return XFS_ERROR(error);
506 }
507 507
508 ASSERT((mask & ATTR_SIZE) == 0); 508 ASSERT((mask & ATTR_SIZE) == 0);
509 509
@@ -539,7 +539,7 @@ xfs_setattr_nonsize(
539 ASSERT(udqp == NULL); 539 ASSERT(udqp == NULL);
540 ASSERT(gdqp == NULL); 540 ASSERT(gdqp == NULL);
541 error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip), 541 error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
542 qflags, &udqp, &gdqp); 542 qflags, &udqp, &gdqp, NULL);
543 if (error) 543 if (error)
544 return error; 544 return error;
545 } 545 }
@@ -575,7 +575,7 @@ xfs_setattr_nonsize(
575 (XFS_IS_GQUOTA_ON(mp) && igid != gid))) { 575 (XFS_IS_GQUOTA_ON(mp) && igid != gid))) {
576 ASSERT(tp); 576 ASSERT(tp);
577 error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, 577 error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
578 capable(CAP_FOWNER) ? 578 NULL, capable(CAP_FOWNER) ?
579 XFS_QMOPT_FORCE_RES : 0); 579 XFS_QMOPT_FORCE_RES : 0);
580 if (error) /* out of quota */ 580 if (error) /* out of quota */
581 goto out_trans_cancel; 581 goto out_trans_cancel;
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index bc92c5306a17..b93e14b86754 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -221,7 +221,6 @@ xfs_bulkstat(
221 char __user *ubufp; /* pointer into user's buffer */ 221 char __user *ubufp; /* pointer into user's buffer */
222 int ubelem; /* spaces used in user's buffer */ 222 int ubelem; /* spaces used in user's buffer */
223 int ubused; /* bytes used by formatter */ 223 int ubused; /* bytes used by formatter */
224 xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */
225 224
226 /* 225 /*
227 * Get the last inode value, see if there's nothing to do. 226 * Get the last inode value, see if there's nothing to do.
@@ -263,7 +262,6 @@ xfs_bulkstat(
263 rval = 0; 262 rval = 0;
264 while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) { 263 while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) {
265 cond_resched(); 264 cond_resched();
266 bp = NULL;
267 error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); 265 error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
268 if (error) { 266 if (error) {
269 /* 267 /*
@@ -436,27 +434,7 @@ xfs_bulkstat(
436 irbp->ir_freecount < XFS_INODES_PER_CHUNK; 434 irbp->ir_freecount < XFS_INODES_PER_CHUNK;
437 chunkidx++, clustidx++, agino++) { 435 chunkidx++, clustidx++, agino++) {
438 ASSERT(chunkidx < XFS_INODES_PER_CHUNK); 436 ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
439 /* 437
440 * Recompute agbno if this is the
441 * first inode of the cluster.
442 *
443 * Careful with clustidx. There can be
444 * multiple clusters per chunk, a single
445 * cluster per chunk or a cluster that has
446 * inodes represented from several different
447 * chunks (if blocksize is large).
448 *
449 * Because of this, the starting clustidx is
450 * initialized to zero in this loop but must
451 * later be reset after reading in the cluster
452 * buffer.
453 */
454 if ((chunkidx & (nicluster - 1)) == 0) {
455 agbno = XFS_AGINO_TO_AGBNO(mp,
456 irbp->ir_startino) +
457 ((chunkidx & nimask) >>
458 mp->m_sb.sb_inopblog);
459 }
460 ino = XFS_AGINO_TO_INO(mp, agno, agino); 438 ino = XFS_AGINO_TO_INO(mp, agno, agino);
461 /* 439 /*
462 * Skip if this inode is free. 440 * Skip if this inode is free.
@@ -502,10 +480,6 @@ xfs_bulkstat(
502 480
503 cond_resched(); 481 cond_resched();
504 } 482 }
505
506 if (bp)
507 xfs_buf_relse(bp);
508
509 /* 483 /*
510 * Set up for the next loop iteration. 484 * Set up for the next loop iteration.
511 */ 485 */
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 7a3e007b49f4..d320794d03ce 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -137,6 +137,7 @@ xfs_qm_dqpurge(
137 struct xfs_mount *mp = dqp->q_mount; 137 struct xfs_mount *mp = dqp->q_mount;
138 struct xfs_quotainfo *qi = mp->m_quotainfo; 138 struct xfs_quotainfo *qi = mp->m_quotainfo;
139 struct xfs_dquot *gdqp = NULL; 139 struct xfs_dquot *gdqp = NULL;
140 struct xfs_dquot *pdqp = NULL;
140 141
141 xfs_dqlock(dqp); 142 xfs_dqlock(dqp);
142 if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { 143 if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -145,8 +146,7 @@ xfs_qm_dqpurge(
145 } 146 }
146 147
147 /* 148 /*
148 * If this quota has a group hint attached, prepare for releasing it 149 * If this quota has a hint attached, prepare for releasing it now.
149 * now.
150 */ 150 */
151 gdqp = dqp->q_gdquot; 151 gdqp = dqp->q_gdquot;
152 if (gdqp) { 152 if (gdqp) {
@@ -154,6 +154,12 @@ xfs_qm_dqpurge(
154 dqp->q_gdquot = NULL; 154 dqp->q_gdquot = NULL;
155 } 155 }
156 156
157 pdqp = dqp->q_pdquot;
158 if (pdqp) {
159 xfs_dqlock(pdqp);
160 dqp->q_pdquot = NULL;
161 }
162
157 dqp->dq_flags |= XFS_DQ_FREEING; 163 dqp->dq_flags |= XFS_DQ_FREEING;
158 164
159 xfs_dqflock(dqp); 165 xfs_dqflock(dqp);
@@ -208,6 +214,8 @@ xfs_qm_dqpurge(
208 214
209 if (gdqp) 215 if (gdqp)
210 xfs_qm_dqput(gdqp); 216 xfs_qm_dqput(gdqp);
217 if (pdqp)
218 xfs_qm_dqput(pdqp);
211 return 0; 219 return 0;
212} 220}
213 221
@@ -364,6 +372,10 @@ xfs_qm_unmount_quotas(
364 IRELE(mp->m_quotainfo->qi_gquotaip); 372 IRELE(mp->m_quotainfo->qi_gquotaip);
365 mp->m_quotainfo->qi_gquotaip = NULL; 373 mp->m_quotainfo->qi_gquotaip = NULL;
366 } 374 }
375 if (mp->m_quotainfo->qi_pquotaip) {
376 IRELE(mp->m_quotainfo->qi_pquotaip);
377 mp->m_quotainfo->qi_pquotaip = NULL;
378 }
367 } 379 }
368} 380}
369 381
@@ -410,7 +422,10 @@ xfs_qm_dqattach_one(
410 * be reclaimed as long as we have a ref from inode and we 422 * be reclaimed as long as we have a ref from inode and we
411 * hold the ilock. 423 * hold the ilock.
412 */ 424 */
413 dqp = udqhint->q_gdquot; 425 if (type == XFS_DQ_GROUP)
426 dqp = udqhint->q_gdquot;
427 else
428 dqp = udqhint->q_pdquot;
414 if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { 429 if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) {
415 ASSERT(*IO_idqpp == NULL); 430 ASSERT(*IO_idqpp == NULL);
416 431
@@ -453,28 +468,42 @@ xfs_qm_dqattach_one(
453 468
454 469
455/* 470/*
456 * Given a udquot and gdquot, attach a ptr to the group dquot in the 471 * Given a udquot and group/project type, attach the group/project
457 * udquot as a hint for future lookups. 472 * dquot pointer to the udquot as a hint for future lookups.
458 */ 473 */
459STATIC void 474STATIC void
460xfs_qm_dqattach_grouphint( 475xfs_qm_dqattach_hint(
461 xfs_dquot_t *udq, 476 struct xfs_inode *ip,
462 xfs_dquot_t *gdq) 477 int type)
463{ 478{
464 xfs_dquot_t *tmp; 479 struct xfs_dquot **dqhintp;
480 struct xfs_dquot *dqp;
481 struct xfs_dquot *udq = ip->i_udquot;
482
483 ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
465 484
466 xfs_dqlock(udq); 485 xfs_dqlock(udq);
467 486
468 tmp = udq->q_gdquot; 487 if (type == XFS_DQ_GROUP) {
469 if (tmp) { 488 dqp = ip->i_gdquot;
470 if (tmp == gdq) 489 dqhintp = &udq->q_gdquot;
490 } else {
491 dqp = ip->i_pdquot;
492 dqhintp = &udq->q_pdquot;
493 }
494
495 if (*dqhintp) {
496 struct xfs_dquot *tmp;
497
498 if (*dqhintp == dqp)
471 goto done; 499 goto done;
472 500
473 udq->q_gdquot = NULL; 501 tmp = *dqhintp;
502 *dqhintp = NULL;
474 xfs_qm_dqrele(tmp); 503 xfs_qm_dqrele(tmp);
475 } 504 }
476 505
477 udq->q_gdquot = xfs_qm_dqhold(gdq); 506 *dqhintp = xfs_qm_dqhold(dqp);
478done: 507done:
479 xfs_dqunlock(udq); 508 xfs_dqunlock(udq);
480} 509}
@@ -527,12 +556,8 @@ xfs_qm_dqattach_locked(
527 } 556 }
528 557
529 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 558 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
530 if (XFS_IS_OQUOTA_ON(mp)) { 559 if (XFS_IS_GQUOTA_ON(mp)) {
531 error = XFS_IS_GQUOTA_ON(mp) ? 560 error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
532 xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
533 flags & XFS_QMOPT_DQALLOC,
534 ip->i_udquot, &ip->i_gdquot) :
535 xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
536 flags & XFS_QMOPT_DQALLOC, 561 flags & XFS_QMOPT_DQALLOC,
537 ip->i_udquot, &ip->i_gdquot); 562 ip->i_udquot, &ip->i_gdquot);
538 /* 563 /*
@@ -544,14 +569,28 @@ xfs_qm_dqattach_locked(
544 nquotas++; 569 nquotas++;
545 } 570 }
546 571
572 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
573 if (XFS_IS_PQUOTA_ON(mp)) {
574 error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
575 flags & XFS_QMOPT_DQALLOC,
576 ip->i_udquot, &ip->i_pdquot);
577 /*
578 * Don't worry about the udquot that we may have
579 * attached above. It'll get detached, if not already.
580 */
581 if (error)
582 goto done;
583 nquotas++;
584 }
585
547 /* 586 /*
548 * Attach this group quota to the user quota as a hint. 587 * Attach this group/project quota to the user quota as a hint.
549 * This WON'T, in general, result in a thrash. 588 * This WON'T, in general, result in a thrash.
550 */ 589 */
551 if (nquotas == 2) { 590 if (nquotas > 1 && ip->i_udquot) {
552 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 591 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
553 ASSERT(ip->i_udquot); 592 ASSERT(ip->i_gdquot || !XFS_IS_GQUOTA_ON(mp));
554 ASSERT(ip->i_gdquot); 593 ASSERT(ip->i_pdquot || !XFS_IS_PQUOTA_ON(mp));
555 594
556 /* 595 /*
557 * We do not have i_udquot locked at this point, but this check 596 * We do not have i_udquot locked at this point, but this check
@@ -560,7 +599,10 @@ xfs_qm_dqattach_locked(
560 * succeed in general. 599 * succeed in general.
561 */ 600 */
562 if (ip->i_udquot->q_gdquot != ip->i_gdquot) 601 if (ip->i_udquot->q_gdquot != ip->i_gdquot)
563 xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); 602 xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP);
603
604 if (ip->i_udquot->q_pdquot != ip->i_pdquot)
605 xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ);
564 } 606 }
565 607
566 done: 608 done:
@@ -568,8 +610,10 @@ xfs_qm_dqattach_locked(
568 if (!error) { 610 if (!error) {
569 if (XFS_IS_UQUOTA_ON(mp)) 611 if (XFS_IS_UQUOTA_ON(mp))
570 ASSERT(ip->i_udquot); 612 ASSERT(ip->i_udquot);
571 if (XFS_IS_OQUOTA_ON(mp)) 613 if (XFS_IS_GQUOTA_ON(mp))
572 ASSERT(ip->i_gdquot); 614 ASSERT(ip->i_gdquot);
615 if (XFS_IS_PQUOTA_ON(mp))
616 ASSERT(ip->i_pdquot);
573 } 617 }
574 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 618 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
575#endif 619#endif
@@ -602,7 +646,7 @@ void
602xfs_qm_dqdetach( 646xfs_qm_dqdetach(
603 xfs_inode_t *ip) 647 xfs_inode_t *ip)
604{ 648{
605 if (!(ip->i_udquot || ip->i_gdquot)) 649 if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot))
606 return; 650 return;
607 651
608 trace_xfs_dquot_dqdetach(ip); 652 trace_xfs_dquot_dqdetach(ip);
@@ -616,6 +660,10 @@ xfs_qm_dqdetach(
616 xfs_qm_dqrele(ip->i_gdquot); 660 xfs_qm_dqrele(ip->i_gdquot);
617 ip->i_gdquot = NULL; 661 ip->i_gdquot = NULL;
618 } 662 }
663 if (ip->i_pdquot) {
664 xfs_qm_dqrele(ip->i_pdquot);
665 ip->i_pdquot = NULL;
666 }
619} 667}
620 668
621int 669int
@@ -660,6 +708,7 @@ xfs_qm_init_quotainfo(
660 708
661 INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS); 709 INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS);
662 INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS); 710 INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS);
711 INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS);
663 mutex_init(&qinf->qi_tree_lock); 712 mutex_init(&qinf->qi_tree_lock);
664 713
665 INIT_LIST_HEAD(&qinf->qi_lru_list); 714 INIT_LIST_HEAD(&qinf->qi_lru_list);
@@ -761,6 +810,10 @@ xfs_qm_destroy_quotainfo(
761 IRELE(qi->qi_gquotaip); 810 IRELE(qi->qi_gquotaip);
762 qi->qi_gquotaip = NULL; 811 qi->qi_gquotaip = NULL;
763 } 812 }
813 if (qi->qi_pquotaip) {
814 IRELE(qi->qi_pquotaip);
815 qi->qi_pquotaip = NULL;
816 }
764 mutex_destroy(&qi->qi_quotaofflock); 817 mutex_destroy(&qi->qi_quotaofflock);
765 kmem_free(qi); 818 kmem_free(qi);
766 mp->m_quotainfo = NULL; 819 mp->m_quotainfo = NULL;
@@ -1269,13 +1322,14 @@ xfs_qm_quotacheck(
1269 LIST_HEAD (buffer_list); 1322 LIST_HEAD (buffer_list);
1270 struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip; 1323 struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip;
1271 struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip; 1324 struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip;
1325 struct xfs_inode *pip = mp->m_quotainfo->qi_pquotaip;
1272 1326
1273 count = INT_MAX; 1327 count = INT_MAX;
1274 structsz = 1; 1328 structsz = 1;
1275 lastino = 0; 1329 lastino = 0;
1276 flags = 0; 1330 flags = 0;
1277 1331
1278 ASSERT(uip || gip); 1332 ASSERT(uip || gip || pip);
1279 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 1333 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
1280 1334
1281 xfs_notice(mp, "Quotacheck needed: Please wait."); 1335 xfs_notice(mp, "Quotacheck needed: Please wait.");
@@ -1294,13 +1348,19 @@ xfs_qm_quotacheck(
1294 } 1348 }
1295 1349
1296 if (gip) { 1350 if (gip) {
1297 error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ? 1351 error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA,
1298 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA,
1299 &buffer_list); 1352 &buffer_list);
1300 if (error) 1353 if (error)
1301 goto error_return; 1354 goto error_return;
1302 flags |= XFS_IS_GQUOTA_ON(mp) ? 1355 flags |= XFS_GQUOTA_CHKD;
1303 XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD; 1356 }
1357
1358 if (pip) {
1359 error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA,
1360 &buffer_list);
1361 if (error)
1362 goto error_return;
1363 flags |= XFS_PQUOTA_CHKD;
1304 } 1364 }
1305 1365
1306 do { 1366 do {
@@ -1397,6 +1457,7 @@ xfs_qm_init_quotainos(
1397{ 1457{
1398 struct xfs_inode *uip = NULL; 1458 struct xfs_inode *uip = NULL;
1399 struct xfs_inode *gip = NULL; 1459 struct xfs_inode *gip = NULL;
1460 struct xfs_inode *pip = NULL;
1400 int error; 1461 int error;
1401 __int64_t sbflags = 0; 1462 __int64_t sbflags = 0;
1402 uint flags = 0; 1463 uint flags = 0;
@@ -1415,7 +1476,7 @@ xfs_qm_init_quotainos(
1415 if (error) 1476 if (error)
1416 return XFS_ERROR(error); 1477 return XFS_ERROR(error);
1417 } 1478 }
1418 if (XFS_IS_OQUOTA_ON(mp) && 1479 if (XFS_IS_GQUOTA_ON(mp) &&
1419 mp->m_sb.sb_gquotino != NULLFSINO) { 1480 mp->m_sb.sb_gquotino != NULLFSINO) {
1420 ASSERT(mp->m_sb.sb_gquotino > 0); 1481 ASSERT(mp->m_sb.sb_gquotino > 0);
1421 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 1482 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -1423,6 +1484,15 @@ xfs_qm_init_quotainos(
1423 if (error) 1484 if (error)
1424 goto error_rele; 1485 goto error_rele;
1425 } 1486 }
1487 /* XXX: Use gquotino for now */
1488 if (XFS_IS_PQUOTA_ON(mp) &&
1489 mp->m_sb.sb_gquotino != NULLFSINO) {
1490 ASSERT(mp->m_sb.sb_gquotino > 0);
1491 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
1492 0, 0, &pip);
1493 if (error)
1494 goto error_rele;
1495 }
1426 } else { 1496 } else {
1427 flags |= XFS_QMOPT_SBVERSION; 1497 flags |= XFS_QMOPT_SBVERSION;
1428 sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | 1498 sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
@@ -1430,7 +1500,7 @@ xfs_qm_init_quotainos(
1430 } 1500 }
1431 1501
1432 /* 1502 /*
1433 * Create the two inodes, if they don't exist already. The changes 1503 * Create the three inodes, if they don't exist already. The changes
1434 * made above will get added to a transaction and logged in one of 1504 * made above will get added to a transaction and logged in one of
1435 * the qino_alloc calls below. If the device is readonly, 1505 * the qino_alloc calls below. If the device is readonly,
1436 * temporarily switch to read-write to do this. 1506 * temporarily switch to read-write to do this.
@@ -1444,17 +1514,27 @@ xfs_qm_init_quotainos(
1444 1514
1445 flags &= ~XFS_QMOPT_SBVERSION; 1515 flags &= ~XFS_QMOPT_SBVERSION;
1446 } 1516 }
1447 if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) { 1517 if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
1448 flags |= (XFS_IS_GQUOTA_ON(mp) ?
1449 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
1450 error = xfs_qm_qino_alloc(mp, &gip, 1518 error = xfs_qm_qino_alloc(mp, &gip,
1451 sbflags | XFS_SB_GQUOTINO, flags); 1519 sbflags | XFS_SB_GQUOTINO,
1520 flags | XFS_QMOPT_GQUOTA);
1521 if (error)
1522 goto error_rele;
1523
1524 flags &= ~XFS_QMOPT_SBVERSION;
1525 }
1526 if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
1527 /* XXX: Use XFS_SB_GQUOTINO for now */
1528 error = xfs_qm_qino_alloc(mp, &pip,
1529 sbflags | XFS_SB_GQUOTINO,
1530 flags | XFS_QMOPT_PQUOTA);
1452 if (error) 1531 if (error)
1453 goto error_rele; 1532 goto error_rele;
1454 } 1533 }
1455 1534
1456 mp->m_quotainfo->qi_uquotaip = uip; 1535 mp->m_quotainfo->qi_uquotaip = uip;
1457 mp->m_quotainfo->qi_gquotaip = gip; 1536 mp->m_quotainfo->qi_gquotaip = gip;
1537 mp->m_quotainfo->qi_pquotaip = pip;
1458 1538
1459 return 0; 1539 return 0;
1460 1540
@@ -1463,6 +1543,8 @@ error_rele:
1463 IRELE(uip); 1543 IRELE(uip);
1464 if (gip) 1544 if (gip)
1465 IRELE(gip); 1545 IRELE(gip);
1546 if (pip)
1547 IRELE(pip);
1466 return XFS_ERROR(error); 1548 return XFS_ERROR(error);
1467} 1549}
1468 1550
@@ -1657,11 +1739,13 @@ xfs_qm_vop_dqalloc(
1657 prid_t prid, 1739 prid_t prid,
1658 uint flags, 1740 uint flags,
1659 struct xfs_dquot **O_udqpp, 1741 struct xfs_dquot **O_udqpp,
1660 struct xfs_dquot **O_gdqpp) 1742 struct xfs_dquot **O_gdqpp,
1743 struct xfs_dquot **O_pdqpp)
1661{ 1744{
1662 struct xfs_mount *mp = ip->i_mount; 1745 struct xfs_mount *mp = ip->i_mount;
1663 struct xfs_dquot *uq = NULL; 1746 struct xfs_dquot *uq = NULL;
1664 struct xfs_dquot *gq = NULL; 1747 struct xfs_dquot *gq = NULL;
1748 struct xfs_dquot *pq = NULL;
1665 int error; 1749 int error;
1666 uint lockflags; 1750 uint lockflags;
1667 1751
@@ -1741,24 +1825,25 @@ xfs_qm_vop_dqalloc(
1741 ASSERT(ip->i_gdquot); 1825 ASSERT(ip->i_gdquot);
1742 gq = xfs_qm_dqhold(ip->i_gdquot); 1826 gq = xfs_qm_dqhold(ip->i_gdquot);
1743 } 1827 }
1744 } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { 1828 }
1829 if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
1745 if (xfs_get_projid(ip) != prid) { 1830 if (xfs_get_projid(ip) != prid) {
1746 xfs_iunlock(ip, lockflags); 1831 xfs_iunlock(ip, lockflags);
1747 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, 1832 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
1748 XFS_DQ_PROJ, 1833 XFS_DQ_PROJ,
1749 XFS_QMOPT_DQALLOC | 1834 XFS_QMOPT_DQALLOC |
1750 XFS_QMOPT_DOWARN, 1835 XFS_QMOPT_DOWARN,
1751 &gq); 1836 &pq);
1752 if (error) { 1837 if (error) {
1753 ASSERT(error != ENOENT); 1838 ASSERT(error != ENOENT);
1754 goto error_rele; 1839 goto error_rele;
1755 } 1840 }
1756 xfs_dqunlock(gq); 1841 xfs_dqunlock(pq);
1757 lockflags = XFS_ILOCK_SHARED; 1842 lockflags = XFS_ILOCK_SHARED;
1758 xfs_ilock(ip, lockflags); 1843 xfs_ilock(ip, lockflags);
1759 } else { 1844 } else {
1760 ASSERT(ip->i_gdquot); 1845 ASSERT(ip->i_pdquot);
1761 gq = xfs_qm_dqhold(ip->i_gdquot); 1846 pq = xfs_qm_dqhold(ip->i_pdquot);
1762 } 1847 }
1763 } 1848 }
1764 if (uq) 1849 if (uq)
@@ -1773,9 +1858,15 @@ xfs_qm_vop_dqalloc(
1773 *O_gdqpp = gq; 1858 *O_gdqpp = gq;
1774 else if (gq) 1859 else if (gq)
1775 xfs_qm_dqrele(gq); 1860 xfs_qm_dqrele(gq);
1861 if (O_pdqpp)
1862 *O_pdqpp = pq;
1863 else if (pq)
1864 xfs_qm_dqrele(pq);
1776 return 0; 1865 return 0;
1777 1866
1778error_rele: 1867error_rele:
1868 if (gq)
1869 xfs_qm_dqrele(gq);
1779 if (uq) 1870 if (uq)
1780 xfs_qm_dqrele(uq); 1871 xfs_qm_dqrele(uq);
1781 return error; 1872 return error;
@@ -1830,14 +1921,17 @@ xfs_qm_vop_chown_reserve(
1830 struct xfs_inode *ip, 1921 struct xfs_inode *ip,
1831 struct xfs_dquot *udqp, 1922 struct xfs_dquot *udqp,
1832 struct xfs_dquot *gdqp, 1923 struct xfs_dquot *gdqp,
1924 struct xfs_dquot *pdqp,
1833 uint flags) 1925 uint flags)
1834{ 1926{
1835 struct xfs_mount *mp = ip->i_mount; 1927 struct xfs_mount *mp = ip->i_mount;
1836 uint delblks, blkflags, prjflags = 0; 1928 uint delblks, blkflags, prjflags = 0;
1837 struct xfs_dquot *udq_unres = NULL; 1929 struct xfs_dquot *udq_unres = NULL;
1838 struct xfs_dquot *gdq_unres = NULL; 1930 struct xfs_dquot *gdq_unres = NULL;
1931 struct xfs_dquot *pdq_unres = NULL;
1839 struct xfs_dquot *udq_delblks = NULL; 1932 struct xfs_dquot *udq_delblks = NULL;
1840 struct xfs_dquot *gdq_delblks = NULL; 1933 struct xfs_dquot *gdq_delblks = NULL;
1934 struct xfs_dquot *pdq_delblks = NULL;
1841 int error; 1935 int error;
1842 1936
1843 1937
@@ -1861,24 +1955,28 @@ xfs_qm_vop_chown_reserve(
1861 udq_unres = ip->i_udquot; 1955 udq_unres = ip->i_udquot;
1862 } 1956 }
1863 } 1957 }
1864 if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { 1958 if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
1865 if (XFS_IS_PQUOTA_ON(ip->i_mount) && 1959 ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) {
1866 xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id)) 1960 gdq_delblks = gdqp;
1867 prjflags = XFS_QMOPT_ENOSPC; 1961 if (delblks) {
1868 1962 ASSERT(ip->i_gdquot);
1869 if (prjflags || 1963 gdq_unres = ip->i_gdquot;
1870 (XFS_IS_GQUOTA_ON(ip->i_mount) && 1964 }
1871 ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) { 1965 }
1872 gdq_delblks = gdqp; 1966
1873 if (delblks) { 1967 if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
1874 ASSERT(ip->i_gdquot); 1968 xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) {
1875 gdq_unres = ip->i_gdquot; 1969 prjflags = XFS_QMOPT_ENOSPC;
1876 } 1970 pdq_delblks = pdqp;
1971 if (delblks) {
1972 ASSERT(ip->i_pdquot);
1973 pdq_unres = ip->i_pdquot;
1877 } 1974 }
1878 } 1975 }
1879 1976
1880 error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 1977 error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
1881 udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1, 1978 udq_delblks, gdq_delblks, pdq_delblks,
1979 ip->i_d.di_nblocks, 1,
1882 flags | blkflags | prjflags); 1980 flags | blkflags | prjflags);
1883 if (error) 1981 if (error)
1884 return error; 1982 return error;
@@ -1893,16 +1991,17 @@ xfs_qm_vop_chown_reserve(
1893 /* 1991 /*
1894 * Do the reservations first. Unreservation can't fail. 1992 * Do the reservations first. Unreservation can't fail.
1895 */ 1993 */
1896 ASSERT(udq_delblks || gdq_delblks); 1994 ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
1897 ASSERT(udq_unres || gdq_unres); 1995 ASSERT(udq_unres || gdq_unres || pdq_unres);
1898 error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 1996 error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
1899 udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0, 1997 udq_delblks, gdq_delblks, pdq_delblks,
1998 (xfs_qcnt_t)delblks, 0,
1900 flags | blkflags | prjflags); 1999 flags | blkflags | prjflags);
1901 if (error) 2000 if (error)
1902 return error; 2001 return error;
1903 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2002 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
1904 udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0, 2003 udq_unres, gdq_unres, pdq_unres,
1905 blkflags); 2004 -((xfs_qcnt_t)delblks), 0, blkflags);
1906 } 2005 }
1907 2006
1908 return (0); 2007 return (0);
@@ -1941,7 +2040,8 @@ xfs_qm_vop_create_dqattach(
1941 struct xfs_trans *tp, 2040 struct xfs_trans *tp,
1942 struct xfs_inode *ip, 2041 struct xfs_inode *ip,
1943 struct xfs_dquot *udqp, 2042 struct xfs_dquot *udqp,
1944 struct xfs_dquot *gdqp) 2043 struct xfs_dquot *gdqp,
2044 struct xfs_dquot *pdqp)
1945{ 2045{
1946 struct xfs_mount *mp = tp->t_mountp; 2046 struct xfs_mount *mp = tp->t_mountp;
1947 2047
@@ -1961,13 +2061,18 @@ xfs_qm_vop_create_dqattach(
1961 } 2061 }
1962 if (gdqp) { 2062 if (gdqp) {
1963 ASSERT(ip->i_gdquot == NULL); 2063 ASSERT(ip->i_gdquot == NULL);
1964 ASSERT(XFS_IS_OQUOTA_ON(mp)); 2064 ASSERT(XFS_IS_GQUOTA_ON(mp));
1965 ASSERT((XFS_IS_GQUOTA_ON(mp) ? 2065 ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
1966 ip->i_d.di_gid : xfs_get_projid(ip)) ==
1967 be32_to_cpu(gdqp->q_core.d_id));
1968
1969 ip->i_gdquot = xfs_qm_dqhold(gdqp); 2066 ip->i_gdquot = xfs_qm_dqhold(gdqp);
1970 xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); 2067 xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
1971 } 2068 }
2069 if (pdqp) {
2070 ASSERT(ip->i_pdquot == NULL);
2071 ASSERT(XFS_IS_PQUOTA_ON(mp));
2072 ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
2073
2074 ip->i_pdquot = xfs_qm_dqhold(pdqp);
2075 xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1);
2076 }
1972} 2077}
1973 2078
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index bdb4f8b95207..579d6a02a5b6 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -44,9 +44,11 @@ extern struct kmem_zone *xfs_qm_dqtrxzone;
44typedef struct xfs_quotainfo { 44typedef struct xfs_quotainfo {
45 struct radix_tree_root qi_uquota_tree; 45 struct radix_tree_root qi_uquota_tree;
46 struct radix_tree_root qi_gquota_tree; 46 struct radix_tree_root qi_gquota_tree;
47 struct radix_tree_root qi_pquota_tree;
47 struct mutex qi_tree_lock; 48 struct mutex qi_tree_lock;
48 xfs_inode_t *qi_uquotaip; /* user quota inode */ 49 struct xfs_inode *qi_uquotaip; /* user quota inode */
49 xfs_inode_t *qi_gquotaip; /* group quota inode */ 50 struct xfs_inode *qi_gquotaip; /* group quota inode */
51 struct xfs_inode *qi_pquotaip; /* project quota inode */
50 struct list_head qi_lru_list; 52 struct list_head qi_lru_list;
51 struct mutex qi_lru_lock; 53 struct mutex qi_lru_lock;
52 int qi_lru_count; 54 int qi_lru_count;
@@ -78,8 +80,9 @@ xfs_dquot_tree(
78 case XFS_DQ_USER: 80 case XFS_DQ_USER:
79 return &qi->qi_uquota_tree; 81 return &qi->qi_uquota_tree;
80 case XFS_DQ_GROUP: 82 case XFS_DQ_GROUP:
81 case XFS_DQ_PROJ:
82 return &qi->qi_gquota_tree; 83 return &qi->qi_gquota_tree;
84 case XFS_DQ_PROJ:
85 return &qi->qi_pquota_tree;
83 default: 86 default:
84 ASSERT(0); 87 ASSERT(0);
85 } 88 }
@@ -93,8 +96,9 @@ xfs_dq_to_quota_inode(struct xfs_dquot *dqp)
93 case XFS_DQ_USER: 96 case XFS_DQ_USER:
94 return dqp->q_mount->m_quotainfo->qi_uquotaip; 97 return dqp->q_mount->m_quotainfo->qi_uquotaip;
95 case XFS_DQ_GROUP: 98 case XFS_DQ_GROUP:
96 case XFS_DQ_PROJ:
97 return dqp->q_mount->m_quotainfo->qi_gquotaip; 99 return dqp->q_mount->m_quotainfo->qi_gquotaip;
100 case XFS_DQ_PROJ:
101 return dqp->q_mount->m_quotainfo->qi_pquotaip;
98 default: 102 default:
99 ASSERT(0); 103 ASSERT(0);
100 } 104 }
@@ -107,18 +111,20 @@ extern void xfs_trans_mod_dquot(struct xfs_trans *,
107 struct xfs_dquot *, uint, long); 111 struct xfs_dquot *, uint, long);
108extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, 112extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
109 struct xfs_mount *, struct xfs_dquot *, 113 struct xfs_mount *, struct xfs_dquot *,
110 struct xfs_dquot *, long, long, uint); 114 struct xfs_dquot *, struct xfs_dquot *,
115 long, long, uint);
111extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *); 116extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *);
112extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *); 117extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *);
113 118
114/* 119/*
115 * We keep the usr and grp dquots separately so that locking will be easier 120 * We keep the usr, grp, and prj dquots separately so that locking will be
116 * to do at commit time. All transactions that we know of at this point 121 * easier to do at commit time. All transactions that we know of at this point
117 * affect no more than two dquots of one type. Hence, the TRANS_MAXDQS value. 122 * affect no more than two dquots of one type. Hence, the TRANS_MAXDQS value.
118 */ 123 */
119enum { 124enum {
120 XFS_QM_TRANS_USR = 0, 125 XFS_QM_TRANS_USR = 0,
121 XFS_QM_TRANS_GRP, 126 XFS_QM_TRANS_GRP,
127 XFS_QM_TRANS_PRJ,
122 XFS_QM_TRANS_DQTYPES 128 XFS_QM_TRANS_DQTYPES
123}; 129};
124#define XFS_QM_TRANS_MAXDQS 2 130#define XFS_QM_TRANS_MAXDQS 2
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index 2d02eac1c9a8..437a52d91f6d 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -112,16 +112,16 @@ xfs_qm_newmount(
112 112
113 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || 113 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
114 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || 114 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) ||
115 (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
116 (!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) ||
117 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || 115 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
118 (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) && 116 (!gquotaondisk && XFS_IS_GQUOTA_ON(mp)) ||
117 (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
118 (!pquotaondisk && XFS_IS_PQUOTA_ON(mp))) &&
119 xfs_dev_is_read_only(mp, "changing quota state")) { 119 xfs_dev_is_read_only(mp, "changing quota state")) {
120 xfs_warn(mp, "please mount with%s%s%s%s.", 120 xfs_warn(mp, "please mount with%s%s%s%s.",
121 (!quotaondisk ? "out quota" : ""), 121 (!quotaondisk ? "out quota" : ""),
122 (uquotaondisk ? " usrquota" : ""), 122 (uquotaondisk ? " usrquota" : ""),
123 (pquotaondisk ? " prjquota" : ""), 123 (gquotaondisk ? " grpquota" : ""),
124 (gquotaondisk ? " grpquota" : "")); 124 (pquotaondisk ? " prjquota" : ""));
125 return XFS_ERROR(EPERM); 125 return XFS_ERROR(EPERM);
126 } 126 }
127 127
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index a08801ae24e2..e4f8b2d6f38b 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -119,7 +119,8 @@ xfs_qm_scall_quotaoff(
119 dqtype |= XFS_QMOPT_GQUOTA; 119 dqtype |= XFS_QMOPT_GQUOTA;
120 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD); 120 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
121 inactivate_flags |= XFS_GQUOTA_ACTIVE; 121 inactivate_flags |= XFS_GQUOTA_ACTIVE;
122 } else if (flags & XFS_PQUOTA_ACCT) { 122 }
123 if (flags & XFS_PQUOTA_ACCT) {
123 dqtype |= XFS_QMOPT_PQUOTA; 124 dqtype |= XFS_QMOPT_PQUOTA;
124 flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD); 125 flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
125 inactivate_flags |= XFS_PQUOTA_ACTIVE; 126 inactivate_flags |= XFS_PQUOTA_ACTIVE;
@@ -198,10 +199,9 @@ xfs_qm_scall_quotaoff(
198 } 199 }
199 200
200 /* 201 /*
201 * If quotas is completely disabled, close shop. 202 * If all quotas are completely turned off, close shop.
202 */ 203 */
203 if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) || 204 if (mp->m_qflags == 0) {
204 ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
205 mutex_unlock(&q->qi_quotaofflock); 205 mutex_unlock(&q->qi_quotaofflock);
206 xfs_qm_destroy_quotainfo(mp); 206 xfs_qm_destroy_quotainfo(mp);
207 return (0); 207 return (0);
@@ -214,10 +214,14 @@ xfs_qm_scall_quotaoff(
214 IRELE(q->qi_uquotaip); 214 IRELE(q->qi_uquotaip);
215 q->qi_uquotaip = NULL; 215 q->qi_uquotaip = NULL;
216 } 216 }
217 if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && q->qi_gquotaip) { 217 if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
218 IRELE(q->qi_gquotaip); 218 IRELE(q->qi_gquotaip);
219 q->qi_gquotaip = NULL; 219 q->qi_gquotaip = NULL;
220 } 220 }
221 if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
222 IRELE(q->qi_pquotaip);
223 q->qi_pquotaip = NULL;
224 }
221 225
222out_unlock: 226out_unlock:
223 mutex_unlock(&q->qi_quotaofflock); 227 mutex_unlock(&q->qi_quotaofflock);
@@ -859,9 +863,11 @@ xfs_dqrele_inode(
859{ 863{
860 /* skip quota inodes */ 864 /* skip quota inodes */
861 if (ip == ip->i_mount->m_quotainfo->qi_uquotaip || 865 if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
862 ip == ip->i_mount->m_quotainfo->qi_gquotaip) { 866 ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
867 ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
863 ASSERT(ip->i_udquot == NULL); 868 ASSERT(ip->i_udquot == NULL);
864 ASSERT(ip->i_gdquot == NULL); 869 ASSERT(ip->i_gdquot == NULL);
870 ASSERT(ip->i_pdquot == NULL);
865 return 0; 871 return 0;
866 } 872 }
867 873
@@ -870,10 +876,14 @@ xfs_dqrele_inode(
870 xfs_qm_dqrele(ip->i_udquot); 876 xfs_qm_dqrele(ip->i_udquot);
871 ip->i_udquot = NULL; 877 ip->i_udquot = NULL;
872 } 878 }
873 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) { 879 if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
874 xfs_qm_dqrele(ip->i_gdquot); 880 xfs_qm_dqrele(ip->i_gdquot);
875 ip->i_gdquot = NULL; 881 ip->i_gdquot = NULL;
876 } 882 }
883 if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
884 xfs_qm_dqrele(ip->i_pdquot);
885 ip->i_pdquot = NULL;
886 }
877 xfs_iunlock(ip, XFS_ILOCK_EXCL); 887 xfs_iunlock(ip, XFS_ILOCK_EXCL);
878 return 0; 888 return 0;
879} 889}
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index c3483bab9cde..b14f42c714b6 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -108,11 +108,28 @@ typedef struct xfs_dqblk {
108 { XFS_DQ_FREEING, "FREEING" } 108 { XFS_DQ_FREEING, "FREEING" }
109 109
110/* 110/*
111 * In the worst case, when both user and group quotas are on, 111 * We have the possibility of all three quota types being active at once, and
112 * we can have a max of three dquots changing in a single transaction. 112 * hence free space modification requires modification of all three current
113 * dquots in a single transaction. For this case we need to have a reservation
114 * of at least 3 dquots.
115 *
116 * However, a chmod operation can change both UID and GID in a single
117 * transaction, resulting in requiring {old, new} x {uid, gid} dquots to be
118 * modified. Hence for this case we need to reserve space for at least 4 dquots.
119 *
120 * And in the worst case, there's a rename operation that can be modifying up to
121 * 4 inodes with dquots attached to them. In reality, the only inodes that can
122 * have their dquots modified are the source and destination directory inodes
123 * due to directory name creation and removal. That can require space allocation
124 * and/or freeing on both directory inodes, and hence all three dquots on each
125 * inode can be modified. And if the directories are world writeable, all the
126 * dquots can be unique and so 6 dquots can be modified....
127 *
128 * And, of course, we also need to take into account the dquot log format item
129 * used to describe each dquot.
113 */ 130 */
114#define XFS_DQUOT_LOGRES(mp) (sizeof(xfs_disk_dquot_t) * 3) 131#define XFS_DQUOT_LOGRES(mp) \
115 132 ((sizeof(struct xfs_dq_logformat) + sizeof(struct xfs_disk_dquot)) * 6)
116 133
117/* 134/*
118 * These are the structures used to lay out dquots and quotaoff 135 * These are the structures used to lay out dquots and quotaoff
@@ -271,10 +288,10 @@ typedef struct xfs_qoff_logformat {
271 * we didn't have the inode locked, the appropriate dquot(s) will be 288 * we didn't have the inode locked, the appropriate dquot(s) will be
272 * attached atomically. 289 * attached atomically.
273 */ 290 */
274#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ 291#define XFS_NOT_DQATTACHED(mp, ip) \
275 (ip)->i_udquot == NULL) || \ 292 ((XFS_IS_UQUOTA_ON(mp) && (ip)->i_udquot == NULL) || \
276 (XFS_IS_OQUOTA_ON(mp) && \ 293 (XFS_IS_GQUOTA_ON(mp) && (ip)->i_gdquot == NULL) || \
277 (ip)->i_gdquot == NULL)) 294 (XFS_IS_PQUOTA_ON(mp) && (ip)->i_pdquot == NULL))
278 295
279#define XFS_QM_NEED_QUOTACHECK(mp) \ 296#define XFS_QM_NEED_QUOTACHECK(mp) \
280 ((XFS_IS_UQUOTA_ON(mp) && \ 297 ((XFS_IS_UQUOTA_ON(mp) && \
@@ -284,14 +301,6 @@ typedef struct xfs_qoff_logformat {
284 (XFS_IS_PQUOTA_ON(mp) && \ 301 (XFS_IS_PQUOTA_ON(mp) && \
285 (mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD) == 0)) 302 (mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD) == 0))
286 303
287#define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
288 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
289 XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD)
290
291#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
292 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
293 XFS_PQUOTA_ENFD|XFS_PQUOTA_CHKD)
294
295#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ 304#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
296 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ 305 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
297 XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD|\ 306 XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD|\
@@ -329,17 +338,18 @@ extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
329 struct xfs_inode *, long, long, uint); 338 struct xfs_inode *, long, long, uint);
330extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, 339extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
331 struct xfs_mount *, struct xfs_dquot *, 340 struct xfs_mount *, struct xfs_dquot *,
332 struct xfs_dquot *, long, long, uint); 341 struct xfs_dquot *, struct xfs_dquot *, long, long, uint);
333 342
334extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint, 343extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint,
335 struct xfs_dquot **, struct xfs_dquot **); 344 struct xfs_dquot **, struct xfs_dquot **, struct xfs_dquot **);
336extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *, 345extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *,
337 struct xfs_dquot *, struct xfs_dquot *); 346 struct xfs_dquot *, struct xfs_dquot *, struct xfs_dquot *);
338extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **); 347extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **);
339extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *, 348extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *,
340 struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *); 349 struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *);
341extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *, 350extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *,
342 struct xfs_dquot *, struct xfs_dquot *, uint); 351 struct xfs_dquot *, struct xfs_dquot *,
352 struct xfs_dquot *, uint);
343extern int xfs_qm_dqattach(struct xfs_inode *, uint); 353extern int xfs_qm_dqattach(struct xfs_inode *, uint);
344extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint); 354extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint);
345extern void xfs_qm_dqdetach(struct xfs_inode *); 355extern void xfs_qm_dqdetach(struct xfs_inode *);
@@ -353,10 +363,12 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);
353#else 363#else
354static inline int 364static inline int
355xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid, 365xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid,
356 uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp) 366 uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp,
367 struct xfs_dquot **pdqp)
357{ 368{
358 *udqp = NULL; 369 *udqp = NULL;
359 *gdqp = NULL; 370 *gdqp = NULL;
371 *pdqp = NULL;
360 return 0; 372 return 0;
361} 373}
362#define xfs_trans_dup_dqinfo(tp, tp2) 374#define xfs_trans_dup_dqinfo(tp, tp2)
@@ -371,14 +383,15 @@ static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
371} 383}
372static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, 384static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
373 struct xfs_mount *mp, struct xfs_dquot *udqp, 385 struct xfs_mount *mp, struct xfs_dquot *udqp,
374 struct xfs_dquot *gdqp, long nblks, long nions, uint flags) 386 struct xfs_dquot *gdqp, struct xfs_dquot *pdqp,
387 long nblks, long nions, uint flags)
375{ 388{
376 return 0; 389 return 0;
377} 390}
378#define xfs_qm_vop_create_dqattach(tp, ip, u, g) 391#define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
379#define xfs_qm_vop_rename_dqattach(it) (0) 392#define xfs_qm_vop_rename_dqattach(it) (0)
380#define xfs_qm_vop_chown(tp, ip, old, new) (NULL) 393#define xfs_qm_vop_chown(tp, ip, old, new) (NULL)
381#define xfs_qm_vop_chown_reserve(tp, ip, u, g, fl) (0) 394#define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl) (0)
382#define xfs_qm_dqattach(ip, fl) (0) 395#define xfs_qm_dqattach(ip, fl) (0)
383#define xfs_qm_dqattach_locked(ip, fl) (0) 396#define xfs_qm_dqattach_locked(ip, fl) (0)
384#define xfs_qm_dqdetach(ip) 397#define xfs_qm_dqdetach(ip)
@@ -392,8 +405,8 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
392 405
393#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \ 406#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \
394 xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags) 407 xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags)
395#define xfs_trans_reserve_quota(tp, mp, ud, gd, nb, ni, f) \ 408#define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \
396 xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \ 409 xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
397 f | XFS_QMOPT_RES_REGBLKS) 410 f | XFS_QMOPT_RES_REGBLKS)
398 411
399extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, 412extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *,
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index e830fb56e27f..f4895b662fcb 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -360,6 +360,7 @@ xfs_symlink(
360 prid_t prid; 360 prid_t prid;
361 struct xfs_dquot *udqp = NULL; 361 struct xfs_dquot *udqp = NULL;
362 struct xfs_dquot *gdqp = NULL; 362 struct xfs_dquot *gdqp = NULL;
363 struct xfs_dquot *pdqp = NULL;
363 uint resblks; 364 uint resblks;
364 365
365 *ipp = NULL; 366 *ipp = NULL;
@@ -386,7 +387,7 @@ xfs_symlink(
386 * Make sure that we have allocated dquot(s) on disk. 387 * Make sure that we have allocated dquot(s) on disk.
387 */ 388 */
388 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, 389 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
389 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 390 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp);
390 if (error) 391 if (error)
391 goto std_return; 392 goto std_return;
392 393
@@ -427,7 +428,8 @@ xfs_symlink(
427 /* 428 /*
428 * Reserve disk quota : blocks and inode. 429 * Reserve disk quota : blocks and inode.
429 */ 430 */
430 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); 431 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
432 pdqp, resblks, 1, 0);
431 if (error) 433 if (error)
432 goto error_return; 434 goto error_return;
433 435
@@ -465,7 +467,7 @@ xfs_symlink(
465 /* 467 /*
466 * Also attach the dquot(s) to it, if applicable. 468 * Also attach the dquot(s) to it, if applicable.
467 */ 469 */
468 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); 470 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
469 471
470 if (resblks) 472 if (resblks)
471 resblks -= XFS_IALLOC_SPACE_RES(mp); 473 resblks -= XFS_IALLOC_SPACE_RES(mp);
@@ -563,6 +565,7 @@ xfs_symlink(
563 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 565 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
564 xfs_qm_dqrele(udqp); 566 xfs_qm_dqrele(udqp);
565 xfs_qm_dqrele(gdqp); 567 xfs_qm_dqrele(gdqp);
568 xfs_qm_dqrele(pdqp);
566 569
567 *ipp = ip; 570 *ipp = ip;
568 return 0; 571 return 0;
@@ -576,6 +579,7 @@ xfs_symlink(
576 xfs_trans_cancel(tp, cancel_flags); 579 xfs_trans_cancel(tp, cancel_flags);
577 xfs_qm_dqrele(udqp); 580 xfs_qm_dqrele(udqp);
578 xfs_qm_dqrele(gdqp); 581 xfs_qm_dqrele(gdqp);
582 xfs_qm_dqrele(pdqp);
579 583
580 if (unlock_dp_on_error) 584 if (unlock_dp_on_error)
581 xfs_iunlock(dp, XFS_ILOCK_EXCL); 585 xfs_iunlock(dp, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 3ba64d540168..61407a847b86 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -163,8 +163,10 @@ xfs_trans_mod_dquot_byino(
163 163
164 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) 164 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
165 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); 165 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
166 if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot) 166 if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot)
167 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); 167 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
168 if (XFS_IS_PQUOTA_ON(mp) && ip->i_pdquot)
169 (void) xfs_trans_mod_dquot(tp, ip->i_pdquot, field, delta);
168} 170}
169 171
170STATIC struct xfs_dqtrx * 172STATIC struct xfs_dqtrx *
@@ -177,8 +179,12 @@ xfs_trans_get_dqtrx(
177 179
178 if (XFS_QM_ISUDQ(dqp)) 180 if (XFS_QM_ISUDQ(dqp))
179 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR]; 181 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR];
180 else 182 else if (XFS_QM_ISGDQ(dqp))
181 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP]; 183 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
184 else if (XFS_QM_ISPDQ(dqp))
185 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_PRJ];
186 else
187 return NULL;
182 188
183 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { 189 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
184 if (qa[i].qt_dquot == NULL || 190 if (qa[i].qt_dquot == NULL ||
@@ -291,11 +297,10 @@ xfs_trans_mod_dquot(
291 297
292 298
293/* 299/*
294 * Given an array of dqtrx structures, lock all the dquots associated 300 * Given an array of dqtrx structures, lock all the dquots associated and join
295 * and join them to the transaction, provided they have been modified. 301 * them to the transaction, provided they have been modified. We know that the
296 * We know that the highest number of dquots (of one type - usr OR grp), 302 * highest number of dquots of one type - usr, grp OR prj - involved in a
297 * involved in a transaction is 2 and that both usr and grp combined - 3. 303 * transaction is 2 so we don't need to make this very generic.
298 * So, we don't attempt to make this very generic.
299 */ 304 */
300STATIC void 305STATIC void
301xfs_trans_dqlockedjoin( 306xfs_trans_dqlockedjoin(
@@ -728,8 +733,8 @@ error_return:
728 733
729/* 734/*
730 * Given dquot(s), make disk block and/or inode reservations against them. 735 * Given dquot(s), make disk block and/or inode reservations against them.
731 * The fact that this does the reservation against both the usr and 736 * The fact that this does the reservation against user, group and
732 * grp/prj quotas is important, because this follows a both-or-nothing 737 * project quotas is important, because this follows a all-or-nothing
733 * approach. 738 * approach.
734 * 739 *
735 * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. 740 * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
@@ -744,6 +749,7 @@ xfs_trans_reserve_quota_bydquots(
744 struct xfs_mount *mp, 749 struct xfs_mount *mp,
745 struct xfs_dquot *udqp, 750 struct xfs_dquot *udqp,
746 struct xfs_dquot *gdqp, 751 struct xfs_dquot *gdqp,
752 struct xfs_dquot *pdqp,
747 long nblks, 753 long nblks,
748 long ninos, 754 long ninos,
749 uint flags) 755 uint flags)
@@ -771,11 +777,21 @@ xfs_trans_reserve_quota_bydquots(
771 goto unwind_usr; 777 goto unwind_usr;
772 } 778 }
773 779
780 if (pdqp) {
781 error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags);
782 if (error)
783 goto unwind_grp;
784 }
785
774 /* 786 /*
775 * Didn't change anything critical, so, no need to log 787 * Didn't change anything critical, so, no need to log
776 */ 788 */
777 return 0; 789 return 0;
778 790
791unwind_grp:
792 flags |= XFS_QMOPT_FORCE_RES;
793 if (gdqp)
794 xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags);
779unwind_usr: 795unwind_usr:
780 flags |= XFS_QMOPT_FORCE_RES; 796 flags |= XFS_QMOPT_FORCE_RES;
781 if (udqp) 797 if (udqp)
@@ -817,6 +833,7 @@ xfs_trans_reserve_quota_nblks(
817 */ 833 */
818 return xfs_trans_reserve_quota_bydquots(tp, mp, 834 return xfs_trans_reserve_quota_bydquots(tp, mp,
819 ip->i_udquot, ip->i_gdquot, 835 ip->i_udquot, ip->i_gdquot,
836 ip->i_pdquot,
820 nblks, ninos, flags); 837 nblks, ninos, flags);
821} 838}
822 839
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 42c0ef288aeb..dc730ac272be 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -489,6 +489,7 @@ xfs_create(
489 prid_t prid; 489 prid_t prid;
490 struct xfs_dquot *udqp = NULL; 490 struct xfs_dquot *udqp = NULL;
491 struct xfs_dquot *gdqp = NULL; 491 struct xfs_dquot *gdqp = NULL;
492 struct xfs_dquot *pdqp = NULL;
492 uint resblks; 493 uint resblks;
493 uint log_res; 494 uint log_res;
494 uint log_count; 495 uint log_count;
@@ -507,7 +508,8 @@ xfs_create(
507 * Make sure that we have allocated dquot(s) on disk. 508 * Make sure that we have allocated dquot(s) on disk.
508 */ 509 */
509 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, 510 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
510 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 511 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
512 &udqp, &gdqp, &pdqp);
511 if (error) 513 if (error)
512 return error; 514 return error;
513 515
@@ -559,7 +561,8 @@ xfs_create(
559 /* 561 /*
560 * Reserve disk quota and the inode. 562 * Reserve disk quota and the inode.
561 */ 563 */
562 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); 564 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
565 pdqp, resblks, 1, 0);
563 if (error) 566 if (error)
564 goto out_trans_cancel; 567 goto out_trans_cancel;
565 568
@@ -623,7 +626,7 @@ xfs_create(
623 * These ids of the inode couldn't have changed since the new 626 * These ids of the inode couldn't have changed since the new
624 * inode has been locked ever since it was created. 627 * inode has been locked ever since it was created.
625 */ 628 */
626 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); 629 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
627 630
628 error = xfs_bmap_finish(&tp, &free_list, &committed); 631 error = xfs_bmap_finish(&tp, &free_list, &committed);
629 if (error) 632 if (error)
@@ -635,6 +638,7 @@ xfs_create(
635 638
636 xfs_qm_dqrele(udqp); 639 xfs_qm_dqrele(udqp);
637 xfs_qm_dqrele(gdqp); 640 xfs_qm_dqrele(gdqp);
641 xfs_qm_dqrele(pdqp);
638 642
639 *ipp = ip; 643 *ipp = ip;
640 return 0; 644 return 0;
@@ -656,6 +660,7 @@ xfs_create(
656 660
657 xfs_qm_dqrele(udqp); 661 xfs_qm_dqrele(udqp);
658 xfs_qm_dqrele(gdqp); 662 xfs_qm_dqrele(gdqp);
663 xfs_qm_dqrele(pdqp);
659 664
660 if (unlock_dp_on_error) 665 if (unlock_dp_on_error)
661 xfs_iunlock(dp, XFS_ILOCK_EXCL); 666 xfs_iunlock(dp, XFS_ILOCK_EXCL);
@@ -1568,7 +1573,7 @@ xfs_free_file_space(
1568 } 1573 }
1569 xfs_ilock(ip, XFS_ILOCK_EXCL); 1574 xfs_ilock(ip, XFS_ILOCK_EXCL);
1570 error = xfs_trans_reserve_quota(tp, mp, 1575 error = xfs_trans_reserve_quota(tp, mp,
1571 ip->i_udquot, ip->i_gdquot, 1576 ip->i_udquot, ip->i_gdquot, ip->i_pdquot,
1572 resblks, 0, XFS_QMOPT_RES_REGBLKS); 1577 resblks, 0, XFS_QMOPT_RES_REGBLKS);
1573 if (error) 1578 if (error)
1574 goto error1; 1579 goto error1;