aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/xfs.txt317
-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
22 files changed, 644 insertions, 424 deletions
diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
index 83577f0232a0..12525b17d9ed 100644
--- a/Documentation/filesystems/xfs.txt
+++ b/Documentation/filesystems/xfs.txt
@@ -18,6 +18,8 @@ Mount Options
18============= 18=============
19 19
20When mounting an XFS filesystem, the following options are accepted. 20When mounting an XFS filesystem, the following options are accepted.
21For boolean mount options, the names with the (*) suffix is the
22default behaviour.
21 23
22 allocsize=size 24 allocsize=size
23 Sets the buffered I/O end-of-file preallocation size when 25 Sets the buffered I/O end-of-file preallocation size when
@@ -25,97 +27,128 @@ When mounting an XFS filesystem, the following options are accepted.
25 Valid values for this option are page size (typically 4KiB) 27 Valid values for this option are page size (typically 4KiB)
26 through to 1GiB, inclusive, in power-of-2 increments. 28 through to 1GiB, inclusive, in power-of-2 increments.
27 29
28 attr2/noattr2 30 The default behaviour is for dynamic end-of-file
29 The options enable/disable (default is disabled for backward 31 preallocation size, which uses a set of heuristics to
30 compatibility on-disk) an "opportunistic" improvement to be 32 optimise the preallocation size based on the current
31 made in the way inline extended attributes are stored on-disk. 33 allocation patterns within the file and the access patterns
32 When the new form is used for the first time (by setting or 34 to the file. Specifying a fixed allocsize value turns off
33 removing extended attributes) the on-disk superblock feature 35 the dynamic behaviour.
34 bit field will be updated to reflect this format being in use. 36
37 attr2
38 noattr2
39 The options enable/disable an "opportunistic" improvement to
40 be made in the way inline extended attributes are stored
41 on-disk. When the new form is used for the first time when
42 attr2 is selected (either when setting or removing extended
43 attributes) the on-disk superblock feature bit field will be
44 updated to reflect this format being in use.
45
46 The default behaviour is determined by the on-disk feature
47 bit indicating that attr2 behaviour is active. If either
48 mount option it set, then that becomes the new default used
49 by the filesystem.
35 50
36 CRC enabled filesystems always use the attr2 format, and so 51 CRC enabled filesystems always use the attr2 format, and so
37 will reject the noattr2 mount option if it is set. 52 will reject the noattr2 mount option if it is set.
38 53
39 barrier 54 barrier (*)
40 Enables the use of block layer write barriers for writes into 55 nobarrier
41 the journal and unwritten extent conversion. This allows for 56 Enables/disables the use of block layer write barriers for
42 drive level write caching to be enabled, for devices that 57 writes into the journal and for data integrity operations.
43 support write barriers. 58 This allows for drive level write caching to be enabled, for
59 devices that support write barriers.
44 60
45 discard 61 discard
46 Issue command to let the block device reclaim space freed by the 62 nodiscard (*)
47 filesystem. This is useful for SSD devices, thinly provisioned 63 Enable/disable the issuing of commands to let the block
48 LUNs and virtual machine images, but may have a performance 64 device reclaim space freed by the filesystem. This is
49 impact. 65 useful for SSD devices, thinly provisioned LUNs and virtual
50 66 machine images, but may have a performance impact.
51 dmapi 67
52 Enable the DMAPI (Data Management API) event callouts. 68 Note: It is currently recommended that you use the fstrim
53 Use with the "mtpt" option. 69 application to discard unused blocks rather than the discard
54 70 mount option because the performance impact of this option
55 grpid/bsdgroups and nogrpid/sysvgroups 71 is quite severe.
56 These options define what group ID a newly created file gets. 72
57 When grpid is set, it takes the group ID of the directory in 73 grpid/bsdgroups
58 which it is created; otherwise (the default) it takes the fsgid 74 nogrpid/sysvgroups (*)
59 of the current process, unless the directory has the setgid bit 75 These options define what group ID a newly created file
60 set, in which case it takes the gid from the parent directory, 76 gets. When grpid is set, it takes the group ID of the
61 and also gets the setgid bit set if it is a directory itself. 77 directory in which it is created; otherwise it takes the
62 78 fsgid of the current process, unless the directory has the
63 ihashsize=value 79 setgid bit set, in which case it takes the gid from the
64 In memory inode hashes have been removed, so this option has 80 parent directory, and also gets the setgid bit set if it is
65 no function as of August 2007. Option is deprecated. 81 a directory itself.
66 82
67 ikeep/noikeep 83 filestreams
68 When ikeep is specified, XFS does not delete empty inode clusters 84 Make the data allocator use the filestreams allocation mode
69 and keeps them around on disk. ikeep is the traditional XFS 85 across the entire filesystem rather than just on directories
70 behaviour. When noikeep is specified, empty inode clusters 86 configured to use it.
71 are returned to the free space pool. The default is noikeep for 87
72 non-DMAPI mounts, while ikeep is the default when DMAPI is in use. 88 ikeep
73 89 noikeep (*)
74 inode64 90 When ikeep is specified, XFS does not delete empty inode
75 Indicates that XFS is allowed to create inodes at any location 91 clusters and keeps them around on disk. When noikeep is
76 in the filesystem, including those which will result in inode 92 specified, empty inode clusters are returned to the free
77 numbers occupying more than 32 bits of significance. This is 93 space pool.
78 the default allocation option. Applications which do not handle
79 inode numbers bigger than 32 bits, should use inode32 option.
80 94
81 inode32 95 inode32
82 Indicates that XFS is limited to create inodes at locations which 96 inode64 (*)
83 will not result in inode numbers with more than 32 bits of 97 When inode32 is specified, it indicates that XFS limits
84 significance. This is provided for backwards compatibility, since 98 inode creation to locations which will not result in inode
85 64 bits inode numbers might cause problems for some applications 99 numbers with more than 32 bits of significance.
86 that cannot handle large inode numbers. 100
87 101 When inode64 is specified, it indicates that XFS is allowed
88 largeio/nolargeio 102 to create inodes at any location in the filesystem,
103 including those which will result in inode numbers occupying
104 more than 32 bits of significance.
105
106 inode32 is provided for backwards compatibility with older
107 systems and applications, since 64 bits inode numbers might
108 cause problems for some applications that cannot handle
109 large inode numbers. If applications are in use which do
110 not handle inode numbers bigger than 32 bits, the inode32
111 option should be specified.
112
113
114 largeio
115 nolargeio (*)
89 If "nolargeio" is specified, the optimal I/O reported in 116 If "nolargeio" is specified, the optimal I/O reported in
90 st_blksize by stat(2) will be as small as possible to allow user 117 st_blksize by stat(2) will be as small as possible to allow
91 applications to avoid inefficient read/modify/write I/O. 118 user applications to avoid inefficient read/modify/write
92 If "largeio" specified, a filesystem that has a "swidth" specified 119 I/O. This is typically the page size of the machine, as
93 will return the "swidth" value (in bytes) in st_blksize. If the 120 this is the granularity of the page cache.
94 filesystem does not have a "swidth" specified but does specify 121
95 an "allocsize" then "allocsize" (in bytes) will be returned 122 If "largeio" specified, a filesystem that was created with a
96 instead. 123 "swidth" specified will return the "swidth" value (in bytes)
97 If neither of these two options are specified, then filesystem 124 in st_blksize. If the filesystem does not have a "swidth"
98 will behave as if "nolargeio" was specified. 125 specified but does specify an "allocsize" then "allocsize"
126 (in bytes) will be returned instead. Otherwise the behaviour
127 is the same as if "nolargeio" was specified.
99 128
100 logbufs=value 129 logbufs=value
101 Set the number of in-memory log buffers. Valid numbers range 130 Set the number of in-memory log buffers. Valid numbers
102 from 2-8 inclusive. 131 range from 2-8 inclusive.
103 The default value is 8 buffers for filesystems with a 132
104 blocksize of 64KiB, 4 buffers for filesystems with a blocksize 133 The default value is 8 buffers.
105 of 32KiB, 3 buffers for filesystems with a blocksize of 16KiB 134
106 and 2 buffers for all other configurations. Increasing the 135 If the memory cost of 8 log buffers is too high on small
107 number of buffers may increase performance on some workloads 136 systems, then it may be reduced at some cost to performance
108 at the cost of the memory used for the additional log buffers 137 on metadata intensive workloads. The logbsize option below
109 and their associated control structures. 138 controls the size of each buffer and so is also relevent to
139 this case.
110 140
111 logbsize=value 141 logbsize=value
112 Set the size of each in-memory log buffer. 142 Set the size of each in-memory log buffer. The size may be
113 Size may be specified in bytes, or in kilobytes with a "k" suffix. 143 specified in bytes, or in kilobytes with a "k" suffix.
114 Valid sizes for version 1 and version 2 logs are 16384 (16k) and 144 Valid sizes for version 1 and version 2 logs are 16384 (16k)
115 32768 (32k). Valid sizes for version 2 logs also include 145 and 32768 (32k). Valid sizes for version 2 logs also
116 65536 (64k), 131072 (128k) and 262144 (256k). 146 include 65536 (64k), 131072 (128k) and 262144 (256k). The
117 The default value for machines with more than 32MiB of memory 147 logbsize must be an integer multiple of the log
118 is 32768, machines with less memory use 16384 by default. 148 stripe unit configured at mkfs time.
149
150 The default value for for version 1 logs is 32768, while the
151 default value for version 2 logs is MAX(32768, log_sunit).
119 152
120 logdev=device and rtdev=device 153 logdev=device and rtdev=device
121 Use an external log (metadata journal) and/or real-time device. 154 Use an external log (metadata journal) and/or real-time device.
@@ -124,16 +157,11 @@ When mounting an XFS filesystem, the following options are accepted.
124 optional, and the log section can be separate from the data 157 optional, and the log section can be separate from the data
125 section or contained within it. 158 section or contained within it.
126 159
127 mtpt=mountpoint
128 Use with the "dmapi" option. The value specified here will be
129 included in the DMAPI mount event, and should be the path of
130 the actual mountpoint that is used.
131
132 noalign 160 noalign
133 Data allocations will not be aligned at stripe unit boundaries. 161 Data allocations will not be aligned at stripe unit
134 162 boundaries. This is only relevant to filesystems created
135 noatime 163 with non-zero data alignment parameters (sunit, swidth) by
136 Access timestamps are not updated when a file is read. 164 mkfs.
137 165
138 norecovery 166 norecovery
139 The filesystem will be mounted without running log recovery. 167 The filesystem will be mounted without running log recovery.
@@ -144,8 +172,14 @@ When mounting an XFS filesystem, the following options are accepted.
144 the mount will fail. 172 the mount will fail.
145 173
146 nouuid 174 nouuid
147 Don't check for double mounted file systems using the file system uuid. 175 Don't check for double mounted file systems using the file
148 This is useful to mount LVM snapshot volumes. 176 system uuid. This is useful to mount LVM snapshot volumes,
177 and often used in combination with "norecovery" for mounting
178 read-only snapshots.
179
180 noquota
181 Forcibly turns off all quota accounting and enforcement
182 within the filesystem.
149 183
150 uquota/usrquota/uqnoenforce/quota 184 uquota/usrquota/uqnoenforce/quota
151 User disk quota accounting enabled, and limits (optionally) 185 User disk quota accounting enabled, and limits (optionally)
@@ -160,24 +194,64 @@ When mounting an XFS filesystem, the following options are accepted.
160 enforced. Refer to xfs_quota(8) for further details. 194 enforced. Refer to xfs_quota(8) for further details.
161 195
162 sunit=value and swidth=value 196 sunit=value and swidth=value
163 Used to specify the stripe unit and width for a RAID device or 197 Used to specify the stripe unit and width for a RAID device
164 a stripe volume. "value" must be specified in 512-byte block 198 or a stripe volume. "value" must be specified in 512-byte
165 units. 199 block units. These options are only relevant to filesystems
166 If this option is not specified and the filesystem was made on 200 that were created with non-zero data alignment parameters.
167 a stripe volume or the stripe width or unit were specified for 201
168 the RAID device at mkfs time, then the mount system call will 202 The sunit and swidth parameters specified must be compatible
169 restore the value from the superblock. For filesystems that 203 with the existing filesystem alignment characteristics. In
170 are made directly on RAID devices, these options can be used 204 general, that means the only valid changes to sunit are
171 to override the information in the superblock if the underlying 205 increasing it by a power-of-2 multiple. Valid swidth values
172 disk layout changes after the filesystem has been created. 206 are any integer multiple of a valid sunit value.
173 The "swidth" option is required if the "sunit" option has been 207
174 specified, and must be a multiple of the "sunit" value. 208 Typically the only time these mount options are necessary if
209 after an underlying RAID device has had it's geometry
210 modified, such as adding a new disk to a RAID5 lun and
211 reshaping it.
175 212
176 swalloc 213 swalloc
177 Data allocations will be rounded up to stripe width boundaries 214 Data allocations will be rounded up to stripe width boundaries
178 when the current end of file is being extended and the file 215 when the current end of file is being extended and the file
179 size is larger than the stripe width size. 216 size is larger than the stripe width size.
180 217
218 wsync
219 When specified, all filesystem namespace operations are
220 executed synchronously. This ensures that when the namespace
221 operation (create, unlink, etc) completes, the change to the
222 namespace is on stable storage. This is useful in HA setups
223 where failover must not result in clients seeing
224 inconsistent namespace presentation during or after a
225 failover event.
226
227
228Deprecated Mount Options
229========================
230
231 delaylog/nodelaylog
232 Delayed logging is the only logging method that XFS supports
233 now, so these mount options are now ignored.
234
235 Due for removal in 3.12.
236
237 ihashsize=value
238 In memory inode hashes have been removed, so this option has
239 no function as of August 2007. Option is deprecated.
240
241 Due for removal in 3.12.
242
243 irixsgid
244 This behaviour is now controlled by a sysctl, so the mount
245 option is ignored.
246
247 Due for removal in 3.12.
248
249 osyncisdsync
250 osyncisosync
251 O_SYNC and O_DSYNC are fully supported, so there is no need
252 for these options any more.
253
254 Due for removal in 3.12.
181 255
182sysctls 256sysctls
183======= 257=======
@@ -189,15 +263,20 @@ The following sysctls are available for the XFS filesystem:
189 in /proc/fs/xfs/stat. It then immediately resets to "0". 263 in /proc/fs/xfs/stat. It then immediately resets to "0".
190 264
191 fs.xfs.xfssyncd_centisecs (Min: 100 Default: 3000 Max: 720000) 265 fs.xfs.xfssyncd_centisecs (Min: 100 Default: 3000 Max: 720000)
192 The interval at which the xfssyncd thread flushes metadata 266 The interval at which the filesystem flushes metadata
193 out to disk. This thread will flush log activity out, and 267 out to disk and runs internal cache cleanup routines.
194 do some processing on unlinked inodes.
195 268
196 fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000) 269 fs.xfs.filestream_centisecs (Min: 1 Default: 3000 Max: 360000)
197 The interval at which xfsbufd scans the dirty metadata buffers list. 270 The interval at which the filesystem ages filestreams cache
271 references and returns timed-out AGs back to the free stream
272 pool.
198 273
199 fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000) 274 fs.xfs.speculative_prealloc_lifetime
200 The age at which xfsbufd flushes dirty metadata buffers to disk. 275 (Units: seconds Min: 1 Default: 300 Max: 86400)
276 The interval at which the background scanning for inodes
277 with unused speculative preallocation runs. The scan
278 removes unused preallocation from clean inodes and releases
279 the unused space back to the free pool.
201 280
202 fs.xfs.error_level (Min: 0 Default: 3 Max: 11) 281 fs.xfs.error_level (Min: 0 Default: 3 Max: 11)
203 A volume knob for error reporting when internal errors occur. 282 A volume knob for error reporting when internal errors occur.
@@ -254,9 +333,31 @@ The following sysctls are available for the XFS filesystem:
254 by the xfs_io(8) chattr command on a directory to be 333 by the xfs_io(8) chattr command on a directory to be
255 inherited by files in that directory. 334 inherited by files in that directory.
256 335
336 fs.xfs.inherit_nodefrag (Min: 0 Default: 1 Max: 1)
337 Setting this to "1" will cause the "nodefrag" flag set
338 by the xfs_io(8) chattr command on a directory to be
339 inherited by files in that directory.
340
257 fs.xfs.rotorstep (Min: 1 Default: 1 Max: 256) 341 fs.xfs.rotorstep (Min: 1 Default: 1 Max: 256)
258 In "inode32" allocation mode, this option determines how many 342 In "inode32" allocation mode, this option determines how many
259 files the allocator attempts to allocate in the same allocation 343 files the allocator attempts to allocate in the same allocation
260 group before moving to the next allocation group. The intent 344 group before moving to the next allocation group. The intent
261 is to control the rate at which the allocator moves between 345 is to control the rate at which the allocator moves between
262 allocation groups when allocating extents for new files. 346 allocation groups when allocating extents for new files.
347
348Deprecated Sysctls
349==================
350
351 fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000)
352 Dirty metadata is now tracked by the log subsystem and
353 flushing is driven by log space and idling demands. The
354 xfsbufd no longer exists, so this syctl does nothing.
355
356 Due for removal in 3.14.
357
358 fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000)
359 Dirty metadata is now tracked by the log subsystem and
360 flushing is driven by log space and idling demands. The
361 xfsbufd no longer exists, so this syctl does nothing.
362
363 Due for removal in 3.14.
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;