Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-linus-v3.11-rc1-2' of git://oss.sgi.com/xfs/xfs

Pull more xfs updates from Ben Myers:
"Here are a fix for xfs_fsr, a cleanup in bulkstat, a cleanup in
xfs_open_by_handle, updated mount options documentation, a cleanup in
xfs_bmapi_write, a fix for the size of dquot log reservations, a fix
for sgid inheritance when acls are in use, a fix for cleaning up
quotainfo structures, and some more of the work which allows group and
project quotas to be used together.

We had a few more in this last quota category that we might have liked
to get in, but it looks there are still a few items that need to be
addressed.

- fix for xfs_fsr returning -EINVAL
- cleanup in xfs_bulkstat
- cleanup in xfs_open_by_handle
- update mount options documentation
- clean up local format handling in xfs_bmapi_write
- fix dquot log reservations which were too small
- fix sgid inheritance for subdirectories when default acls are in use
- add project quota fields to various structures
- fix teardown of quotainfo structures when quotas are turned off"

* tag 'for-linus-v3.11-rc1-2' of git://oss.sgi.com/xfs/xfs:
xfs: Fix the logic check for all quotas being turned off
xfs: Add pquota fields where gquota is used.
xfs: fix sgid inheritance for subdirectories inheriting default acls [V3]
xfs: dquot log reservations are too small
xfs: remove local fork format handling from xfs_bmapi_write()
xfs: update mount options documentation
xfs: use get_unused_fd_flags(0) instead of get_unused_fd()
xfs: clean up unused codes at xfs_bulkstat()
xfs: use XFS_BMAP_BMDR_SPACE vs. XFS_BROOT_SIZE_ADJ

+638 -418
+204 -103
Documentation/filesystems/xfs.txt
··· 18 18 ============= 19 19 20 20 When mounting an XFS filesystem, the following options are accepted. 21 + For boolean mount options, the names with the (*) suffix is the 22 + default behaviour. 21 23 22 24 allocsize=size 23 25 Sets the buffered I/O end-of-file preallocation size when ··· 27 25 Valid values for this option are page size (typically 4KiB) 28 26 through to 1GiB, inclusive, in power-of-2 increments. 29 27 30 - attr2/noattr2 31 - The options enable/disable (default is disabled for backward 32 - compatibility on-disk) an "opportunistic" improvement to be 33 - made in the way inline extended attributes are stored on-disk. 34 - When the new form is used for the first time (by setting or 35 - removing extended attributes) the on-disk superblock feature 36 - bit field will be updated to reflect this format being in use. 28 + The default behaviour is for dynamic end-of-file 29 + preallocation size, which uses a set of heuristics to 30 + optimise the preallocation size based on the current 31 + allocation patterns within the file and the access patterns 32 + to the file. Specifying a fixed allocsize value turns off 33 + the dynamic behaviour. 34 + 35 + attr2 36 + noattr2 37 + The options enable/disable an "opportunistic" improvement to 38 + be made in the way inline extended attributes are stored 39 + on-disk. When the new form is used for the first time when 40 + attr2 is selected (either when setting or removing extended 41 + attributes) the on-disk superblock feature bit field will be 42 + updated to reflect this format being in use. 43 + 44 + The default behaviour is determined by the on-disk feature 45 + bit indicating that attr2 behaviour is active. If either 46 + mount option it set, then that becomes the new default used 47 + by the filesystem. 37 48 38 49 CRC enabled filesystems always use the attr2 format, and so 39 50 will reject the noattr2 mount option if it is set. 40 51 41 - barrier 42 - Enables the use of block layer write barriers for writes into 43 - the journal and unwritten extent conversion. This allows for 44 - drive level write caching to be enabled, for devices that 45 - support write barriers. 52 + barrier (*) 53 + nobarrier 54 + Enables/disables the use of block layer write barriers for 55 + writes into the journal and for data integrity operations. 56 + This allows for drive level write caching to be enabled, for 57 + devices that support write barriers. 46 58 47 59 discard 48 - Issue command to let the block device reclaim space freed by the 49 - filesystem. This is useful for SSD devices, thinly provisioned 50 - LUNs and virtual machine images, but may have a performance 51 - impact. 60 + nodiscard (*) 61 + Enable/disable the issuing of commands to let the block 62 + device reclaim space freed by the filesystem. This is 63 + useful for SSD devices, thinly provisioned LUNs and virtual 64 + machine images, but may have a performance impact. 52 65 53 - dmapi 54 - Enable the DMAPI (Data Management API) event callouts. 55 - Use with the "mtpt" option. 66 + Note: It is currently recommended that you use the fstrim 67 + application to discard unused blocks rather than the discard 68 + mount option because the performance impact of this option 69 + is quite severe. 56 70 57 - grpid/bsdgroups and nogrpid/sysvgroups 58 - These options define what group ID a newly created file gets. 59 - When grpid is set, it takes the group ID of the directory in 60 - which it is created; otherwise (the default) it takes the fsgid 61 - of the current process, unless the directory has the setgid bit 62 - set, in which case it takes the gid from the parent directory, 63 - and also gets the setgid bit set if it is a directory itself. 71 + grpid/bsdgroups 72 + nogrpid/sysvgroups (*) 73 + These options define what group ID a newly created file 74 + gets. When grpid is set, it takes the group ID of the 75 + directory in which it is created; otherwise it takes the 76 + fsgid of the current process, unless the directory has the 77 + setgid bit set, in which case it takes the gid from the 78 + parent directory, and also gets the setgid bit set if it is 79 + a directory itself. 64 80 65 - ihashsize=value 66 - In memory inode hashes have been removed, so this option has 67 - no function as of August 2007. Option is deprecated. 81 + filestreams 82 + Make the data allocator use the filestreams allocation mode 83 + across the entire filesystem rather than just on directories 84 + configured to use it. 68 85 69 - ikeep/noikeep 70 - When ikeep is specified, XFS does not delete empty inode clusters 71 - and keeps them around on disk. ikeep is the traditional XFS 72 - behaviour. When noikeep is specified, empty inode clusters 73 - are returned to the free space pool. The default is noikeep for 74 - non-DMAPI mounts, while ikeep is the default when DMAPI is in use. 75 - 76 - inode64 77 - Indicates that XFS is allowed to create inodes at any location 78 - in the filesystem, including those which will result in inode 79 - numbers occupying more than 32 bits of significance. This is 80 - the default allocation option. Applications which do not handle 81 - inode numbers bigger than 32 bits, should use inode32 option. 86 + ikeep 87 + noikeep (*) 88 + When ikeep is specified, XFS does not delete empty inode 89 + clusters and keeps them around on disk. When noikeep is 90 + specified, empty inode clusters are returned to the free 91 + space pool. 82 92 83 93 inode32 84 - Indicates that XFS is limited to create inodes at locations which 85 - will not result in inode numbers with more than 32 bits of 86 - significance. This is provided for backwards compatibility, since 87 - 64 bits inode numbers might cause problems for some applications 88 - that cannot handle large inode numbers. 94 + inode64 (*) 95 + When inode32 is specified, it indicates that XFS limits 96 + inode creation to locations which will not result in inode 97 + numbers with more than 32 bits of significance. 89 98 90 - largeio/nolargeio 99 + When inode64 is specified, it indicates that XFS is allowed 100 + to create inodes at any location in the filesystem, 101 + including those which will result in inode numbers occupying 102 + more than 32 bits of significance. 103 + 104 + inode32 is provided for backwards compatibility with older 105 + systems and applications, since 64 bits inode numbers might 106 + cause problems for some applications that cannot handle 107 + large inode numbers. If applications are in use which do 108 + not handle inode numbers bigger than 32 bits, the inode32 109 + option should be specified. 110 + 111 + 112 + largeio 113 + nolargeio (*) 91 114 If "nolargeio" is specified, the optimal I/O reported in 92 - st_blksize by stat(2) will be as small as possible to allow user 93 - applications to avoid inefficient read/modify/write I/O. 94 - If "largeio" specified, a filesystem that has a "swidth" specified 95 - will return the "swidth" value (in bytes) in st_blksize. If the 96 - filesystem does not have a "swidth" specified but does specify 97 - an "allocsize" then "allocsize" (in bytes) will be returned 98 - instead. 99 - If neither of these two options are specified, then filesystem 100 - will behave as if "nolargeio" was specified. 115 + st_blksize by stat(2) will be as small as possible to allow 116 + user applications to avoid inefficient read/modify/write 117 + I/O. This is typically the page size of the machine, as 118 + this is the granularity of the page cache. 119 + 120 + If "largeio" specified, a filesystem that was created with a 121 + "swidth" specified will return the "swidth" value (in bytes) 122 + in st_blksize. If the filesystem does not have a "swidth" 123 + specified but does specify an "allocsize" then "allocsize" 124 + (in bytes) will be returned instead. Otherwise the behaviour 125 + is the same as if "nolargeio" was specified. 101 126 102 127 logbufs=value 103 - Set the number of in-memory log buffers. Valid numbers range 104 - from 2-8 inclusive. 105 - The default value is 8 buffers for filesystems with a 106 - blocksize of 64KiB, 4 buffers for filesystems with a blocksize 107 - of 32KiB, 3 buffers for filesystems with a blocksize of 16KiB 108 - and 2 buffers for all other configurations. Increasing the 109 - number of buffers may increase performance on some workloads 110 - at the cost of the memory used for the additional log buffers 111 - and their associated control structures. 128 + Set the number of in-memory log buffers. Valid numbers 129 + range from 2-8 inclusive. 130 + 131 + The default value is 8 buffers. 132 + 133 + If the memory cost of 8 log buffers is too high on small 134 + systems, then it may be reduced at some cost to performance 135 + on metadata intensive workloads. The logbsize option below 136 + controls the size of each buffer and so is also relevent to 137 + this case. 112 138 113 139 logbsize=value 114 - Set the size of each in-memory log buffer. 115 - Size may be specified in bytes, or in kilobytes with a "k" suffix. 116 - Valid sizes for version 1 and version 2 logs are 16384 (16k) and 117 - 32768 (32k). Valid sizes for version 2 logs also include 118 - 65536 (64k), 131072 (128k) and 262144 (256k). 119 - The default value for machines with more than 32MiB of memory 120 - is 32768, machines with less memory use 16384 by default. 140 + Set the size of each in-memory log buffer. The size may be 141 + specified in bytes, or in kilobytes with a "k" suffix. 142 + Valid sizes for version 1 and version 2 logs are 16384 (16k) 143 + and 32768 (32k). Valid sizes for version 2 logs also 144 + include 65536 (64k), 131072 (128k) and 262144 (256k). The 145 + logbsize must be an integer multiple of the log 146 + stripe unit configured at mkfs time. 147 + 148 + The default value for for version 1 logs is 32768, while the 149 + default value for version 2 logs is MAX(32768, log_sunit). 121 150 122 151 logdev=device and rtdev=device 123 152 Use an external log (metadata journal) and/or real-time device. ··· 157 124 optional, and the log section can be separate from the data 158 125 section or contained within it. 159 126 160 - mtpt=mountpoint 161 - Use with the "dmapi" option. The value specified here will be 162 - included in the DMAPI mount event, and should be the path of 163 - the actual mountpoint that is used. 164 - 165 127 noalign 166 - Data allocations will not be aligned at stripe unit boundaries. 167 - 168 - noatime 169 - Access timestamps are not updated when a file is read. 128 + Data allocations will not be aligned at stripe unit 129 + boundaries. This is only relevant to filesystems created 130 + with non-zero data alignment parameters (sunit, swidth) by 131 + mkfs. 170 132 171 133 norecovery 172 134 The filesystem will be mounted without running log recovery. ··· 172 144 the mount will fail. 173 145 174 146 nouuid 175 - Don't check for double mounted file systems using the file system uuid. 176 - This is useful to mount LVM snapshot volumes. 147 + Don't check for double mounted file systems using the file 148 + system uuid. This is useful to mount LVM snapshot volumes, 149 + and often used in combination with "norecovery" for mounting 150 + read-only snapshots. 151 + 152 + noquota 153 + Forcibly turns off all quota accounting and enforcement 154 + within the filesystem. 177 155 178 156 uquota/usrquota/uqnoenforce/quota 179 157 User disk quota accounting enabled, and limits (optionally) ··· 194 160 enforced. Refer to xfs_quota(8) for further details. 195 161 196 162 sunit=value and swidth=value 197 - Used to specify the stripe unit and width for a RAID device or 198 - a stripe volume. "value" must be specified in 512-byte block 199 - units. 200 - If this option is not specified and the filesystem was made on 201 - a stripe volume or the stripe width or unit were specified for 202 - the RAID device at mkfs time, then the mount system call will 203 - restore the value from the superblock. For filesystems that 204 - are made directly on RAID devices, these options can be used 205 - to override the information in the superblock if the underlying 206 - disk layout changes after the filesystem has been created. 207 - The "swidth" option is required if the "sunit" option has been 208 - specified, and must be a multiple of the "sunit" value. 163 + Used to specify the stripe unit and width for a RAID device 164 + or a stripe volume. "value" must be specified in 512-byte 165 + block units. These options are only relevant to filesystems 166 + that were created with non-zero data alignment parameters. 167 + 168 + The sunit and swidth parameters specified must be compatible 169 + with the existing filesystem alignment characteristics. In 170 + general, that means the only valid changes to sunit are 171 + increasing it by a power-of-2 multiple. Valid swidth values 172 + are any integer multiple of a valid sunit value. 173 + 174 + Typically the only time these mount options are necessary if 175 + after an underlying RAID device has had it's geometry 176 + modified, such as adding a new disk to a RAID5 lun and 177 + reshaping it. 209 178 210 179 swalloc 211 180 Data allocations will be rounded up to stripe width boundaries 212 181 when the current end of file is being extended and the file 213 182 size is larger than the stripe width size. 214 183 184 + wsync 185 + When specified, all filesystem namespace operations are 186 + executed synchronously. This ensures that when the namespace 187 + operation (create, unlink, etc) completes, the change to the 188 + namespace is on stable storage. This is useful in HA setups 189 + where failover must not result in clients seeing 190 + inconsistent namespace presentation during or after a 191 + failover event. 192 + 193 + 194 + Deprecated Mount Options 195 + ======================== 196 + 197 + delaylog/nodelaylog 198 + Delayed logging is the only logging method that XFS supports 199 + now, so these mount options are now ignored. 200 + 201 + Due for removal in 3.12. 202 + 203 + ihashsize=value 204 + In memory inode hashes have been removed, so this option has 205 + no function as of August 2007. Option is deprecated. 206 + 207 + Due for removal in 3.12. 208 + 209 + irixsgid 210 + This behaviour is now controlled by a sysctl, so the mount 211 + option is ignored. 212 + 213 + Due for removal in 3.12. 214 + 215 + osyncisdsync 216 + osyncisosync 217 + O_SYNC and O_DSYNC are fully supported, so there is no need 218 + for these options any more. 219 + 220 + Due for removal in 3.12. 215 221 216 222 sysctls 217 223 ======= ··· 263 189 in /proc/fs/xfs/stat. It then immediately resets to "0". 264 190 265 191 fs.xfs.xfssyncd_centisecs (Min: 100 Default: 3000 Max: 720000) 266 - The interval at which the xfssyncd thread flushes metadata 267 - out to disk. This thread will flush log activity out, and 268 - do some processing on unlinked inodes. 192 + The interval at which the filesystem flushes metadata 193 + out to disk and runs internal cache cleanup routines. 269 194 270 - fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000) 271 - The interval at which xfsbufd scans the dirty metadata buffers list. 195 + fs.xfs.filestream_centisecs (Min: 1 Default: 3000 Max: 360000) 196 + The interval at which the filesystem ages filestreams cache 197 + references and returns timed-out AGs back to the free stream 198 + pool. 272 199 273 - fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000) 274 - The age at which xfsbufd flushes dirty metadata buffers to disk. 200 + fs.xfs.speculative_prealloc_lifetime 201 + (Units: seconds Min: 1 Default: 300 Max: 86400) 202 + The interval at which the background scanning for inodes 203 + with unused speculative preallocation runs. The scan 204 + removes unused preallocation from clean inodes and releases 205 + the unused space back to the free pool. 275 206 276 207 fs.xfs.error_level (Min: 0 Default: 3 Max: 11) 277 208 A volume knob for error reporting when internal errors occur. ··· 333 254 by the xfs_io(8) chattr command on a directory to be 334 255 inherited by files in that directory. 335 256 257 + fs.xfs.inherit_nodefrag (Min: 0 Default: 1 Max: 1) 258 + Setting this to "1" will cause the "nodefrag" flag set 259 + by the xfs_io(8) chattr command on a directory to be 260 + inherited by files in that directory. 261 + 336 262 fs.xfs.rotorstep (Min: 1 Default: 1 Max: 256) 337 263 In "inode32" allocation mode, this option determines how many 338 264 files the allocator attempts to allocate in the same allocation 339 265 group before moving to the next allocation group. The intent 340 266 is to control the rate at which the allocator moves between 341 267 allocation groups when allocating extents for new files. 268 + 269 + Deprecated Sysctls 270 + ================== 271 + 272 + fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000) 273 + Dirty metadata is now tracked by the log subsystem and 274 + flushing is driven by log space and idling demands. The 275 + xfsbufd no longer exists, so this syctl does nothing. 276 + 277 + Due for removal in 3.14. 278 + 279 + fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000) 280 + Dirty metadata is now tracked by the log subsystem and 281 + flushing is driven by log space and idling demands. The 282 + xfsbufd no longer exists, so this syctl does nothing. 283 + 284 + Due for removal in 3.14.
+2
fs/xfs/xfs_attr_leaf.c
··· 690 690 sf = (xfs_attr_shortform_t *)tmpbuffer; 691 691 692 692 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); 693 + xfs_bmap_local_to_extents_empty(dp, XFS_ATTR_FORK); 694 + 693 695 bp = NULL; 694 696 error = xfs_da_grow_inode(args, &blkno); 695 697 if (error) {
+83 -116
fs/xfs/xfs_bmap.c
··· 1161 1161 * since the file data needs to get logged so things will stay consistent. 1162 1162 * (The bmap-level manipulations are ok, though). 1163 1163 */ 1164 + void 1165 + xfs_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 + 1164 1182 STATIC int /* error */ 1165 1183 xfs_bmap_local_to_extents( 1166 1184 xfs_trans_t *tp, /* transaction pointer */ ··· 1192 1174 struct xfs_inode *ip, 1193 1175 struct xfs_ifork *ifp)) 1194 1176 { 1195 - int error; /* error return value */ 1177 + int error = 0; 1196 1178 int flags; /* logging flags returned */ 1197 1179 xfs_ifork_t *ifp; /* inode fork pointer */ 1180 + xfs_alloc_arg_t args; /* allocation arguments */ 1181 + xfs_buf_t *bp; /* buffer for extent block */ 1182 + xfs_bmbt_rec_host_t *ep; /* extent record pointer */ 1198 1183 1199 1184 /* 1200 1185 * We don't want to deal with the case of keeping inode data inline yet. ··· 1206 1185 ASSERT(!(S_ISREG(ip->i_d.di_mode) && whichfork == XFS_DATA_FORK)); 1207 1186 ifp = XFS_IFORK_PTR(ip, whichfork); 1208 1187 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); 1188 + 1189 + if (!ifp->if_bytes) { 1190 + xfs_bmap_local_to_extents_empty(ip, whichfork); 1191 + flags = XFS_ILOG_CORE; 1192 + goto done; 1193 + } 1194 + 1209 1195 flags = 0; 1210 1196 error = 0; 1211 - if (ifp->if_bytes) { 1212 - xfs_alloc_arg_t args; /* allocation arguments */ 1213 - xfs_buf_t *bp; /* buffer for extent block */ 1214 - xfs_bmbt_rec_host_t *ep;/* extent record pointer */ 1215 - 1216 - ASSERT((ifp->if_flags & 1217 - (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); 1218 - memset(&args, 0, sizeof(args)); 1219 - args.tp = tp; 1220 - args.mp = ip->i_mount; 1221 - args.firstblock = *firstblock; 1222 - /* 1223 - * Allocate a block. We know we need only one, since the 1224 - * file currently fits in an inode. 1225 - */ 1226 - if (*firstblock == NULLFSBLOCK) { 1227 - args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino); 1228 - args.type = XFS_ALLOCTYPE_START_BNO; 1229 - } else { 1230 - args.fsbno = *firstblock; 1231 - args.type = XFS_ALLOCTYPE_NEAR_BNO; 1232 - } 1233 - args.total = total; 1234 - args.minlen = args.maxlen = args.prod = 1; 1235 - error = xfs_alloc_vextent(&args); 1236 - if (error) 1237 - goto done; 1238 - 1239 - /* Can't fail, the space was reserved. */ 1240 - ASSERT(args.fsbno != NULLFSBLOCK); 1241 - ASSERT(args.len == 1); 1242 - *firstblock = args.fsbno; 1243 - bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0); 1244 - 1245 - /* initialise the block and copy the data */ 1246 - init_fn(tp, bp, ip, ifp); 1247 - 1248 - /* account for the change in fork size and log everything */ 1249 - xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); 1250 - xfs_bmap_forkoff_reset(args.mp, ip, whichfork); 1251 - xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); 1252 - xfs_iext_add(ifp, 0, 1); 1253 - ep = xfs_iext_get_ext(ifp, 0); 1254 - xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM); 1255 - trace_xfs_bmap_post_update(ip, 0, 1256 - whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0, 1257 - _THIS_IP_); 1258 - XFS_IFORK_NEXT_SET(ip, whichfork, 1); 1259 - ip->i_d.di_nblocks = 1; 1260 - xfs_trans_mod_dquot_byino(tp, ip, 1261 - XFS_TRANS_DQ_BCOUNT, 1L); 1262 - flags |= xfs_ilog_fext(whichfork); 1197 + ASSERT((ifp->if_flags & (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == 1198 + XFS_IFINLINE); 1199 + memset(&args, 0, sizeof(args)); 1200 + args.tp = tp; 1201 + args.mp = ip->i_mount; 1202 + args.firstblock = *firstblock; 1203 + /* 1204 + * Allocate a block. We know we need only one, since the 1205 + * file currently fits in an inode. 1206 + */ 1207 + if (*firstblock == NULLFSBLOCK) { 1208 + args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino); 1209 + args.type = XFS_ALLOCTYPE_START_BNO; 1263 1210 } else { 1264 - ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); 1265 - xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork); 1211 + args.fsbno = *firstblock; 1212 + args.type = XFS_ALLOCTYPE_NEAR_BNO; 1266 1213 } 1267 - ifp->if_flags &= ~XFS_IFINLINE; 1268 - ifp->if_flags |= XFS_IFEXTENTS; 1269 - XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); 1214 + args.total = total; 1215 + args.minlen = args.maxlen = args.prod = 1; 1216 + error = xfs_alloc_vextent(&args); 1217 + if (error) 1218 + goto done; 1219 + 1220 + /* Can't fail, the space was reserved. */ 1221 + ASSERT(args.fsbno != NULLFSBLOCK); 1222 + ASSERT(args.len == 1); 1223 + *firstblock = args.fsbno; 1224 + bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0); 1225 + 1226 + /* initialise the block and copy the data */ 1227 + init_fn(tp, bp, ip, ifp); 1228 + 1229 + /* account for the change in fork size and log everything */ 1230 + xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); 1231 + xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); 1232 + xfs_bmap_local_to_extents_empty(ip, whichfork); 1270 1233 flags |= XFS_ILOG_CORE; 1234 + 1235 + xfs_iext_add(ifp, 0, 1); 1236 + ep = xfs_iext_get_ext(ifp, 0); 1237 + xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM); 1238 + trace_xfs_bmap_post_update(ip, 0, 1239 + whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0, 1240 + _THIS_IP_); 1241 + XFS_IFORK_NEXT_SET(ip, whichfork, 1); 1242 + ip->i_d.di_nblocks = 1; 1243 + xfs_trans_mod_dquot_byino(tp, ip, 1244 + XFS_TRANS_DQ_BCOUNT, 1L); 1245 + flags |= xfs_ilog_fext(whichfork); 1246 + 1271 1247 done: 1272 1248 *logflagsp = flags; 1273 1249 return error; ··· 1341 1323 } 1342 1324 1343 1325 /* 1344 - * Block initialisation function for local to extent format conversion. 1345 - * 1346 - * This shouldn't actually be called by anyone, so make sure debug kernels cause 1347 - * a noticable failure. 1348 - */ 1349 - STATIC void 1350 - xfs_bmap_local_to_extents_init_fn( 1351 - struct xfs_trans *tp, 1352 - struct xfs_buf *bp, 1353 - struct xfs_inode *ip, 1354 - struct xfs_ifork *ifp) 1355 - { 1356 - ASSERT(0); 1357 - bp->b_ops = &xfs_bmbt_buf_ops; 1358 - memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); 1359 - xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF); 1360 - } 1361 - 1362 - /* 1363 1326 * Called from xfs_bmap_add_attrfork to handle local format files. Each 1364 1327 * different data fork content type needs a different callout to do the 1365 1328 * conversion. Some are basic and only require special block initialisation ··· 1380 1381 flags, XFS_DATA_FORK, 1381 1382 xfs_symlink_local_to_remote); 1382 1383 1383 - return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, 1384 - XFS_DATA_FORK, 1385 - xfs_bmap_local_to_extents_init_fn); 1384 + /* should only be called for types that support local format data */ 1385 + ASSERT(0); 1386 + return EFSCORRUPTED; 1386 1387 } 1387 1388 1388 1389 /* ··· 4906 4907 orig_mval = mval; 4907 4908 orig_nmap = *nmap; 4908 4909 #endif 4910 + whichfork = (flags & XFS_BMAPI_ATTRFORK) ? 4911 + XFS_ATTR_FORK : XFS_DATA_FORK; 4909 4912 4910 4913 ASSERT(*nmap >= 1); 4911 4914 ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); 4912 4915 ASSERT(!(flags & XFS_BMAPI_IGSTATE)); 4913 4916 ASSERT(tp != NULL); 4914 4917 ASSERT(len > 0); 4915 - 4916 - whichfork = (flags & XFS_BMAPI_ATTRFORK) ? 4917 - XFS_ATTR_FORK : XFS_DATA_FORK; 4918 + ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); 4918 4919 4919 4920 if (unlikely(XFS_TEST_ERROR( 4920 4921 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && 4921 - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && 4922 - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), 4922 + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), 4923 4923 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { 4924 4924 XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp); 4925 4925 return XFS_ERROR(EFSCORRUPTED); ··· 4930 4932 ifp = XFS_IFORK_PTR(ip, whichfork); 4931 4933 4932 4934 XFS_STATS_INC(xs_blk_mapw); 4933 - 4934 - if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { 4935 - /* 4936 - * XXX (dgc): This assumes we are only called for inodes that 4937 - * contain content neutral data in local format. Anything that 4938 - * contains caller-specific data in local format that needs 4939 - * transformation to move to a block format needs to do the 4940 - * conversion to extent format itself. 4941 - * 4942 - * Directory data forks and attribute forks handle this 4943 - * themselves, but with the addition of metadata verifiers every 4944 - * data fork in local format now contains caller specific data 4945 - * and as such conversion through this function is likely to be 4946 - * broken. 4947 - * 4948 - * The only likely user of this branch is for remote symlinks, 4949 - * but we cannot overwrite the data fork contents of the symlink 4950 - * (EEXIST occurs higher up the stack) and so it will never go 4951 - * from local format to extent format here. Hence I don't think 4952 - * this branch is ever executed intentionally and we should 4953 - * consider removing it and asserting that xfs_bmapi_write() 4954 - * cannot be called directly on local format forks. i.e. callers 4955 - * are completely responsible for local to extent format 4956 - * conversion, not xfs_bmapi_write(). 4957 - */ 4958 - error = xfs_bmap_local_to_extents(tp, ip, firstblock, total, 4959 - &bma.logflags, whichfork, 4960 - xfs_bmap_local_to_extents_init_fn); 4961 - if (error) 4962 - goto error0; 4963 - } 4964 4935 4965 4936 if (*firstblock == NULLFSBLOCK) { 4966 4937 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
+1
fs/xfs/xfs_bmap.h
··· 172 172 #endif 173 173 174 174 int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); 175 + void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); 175 176 void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len, 176 177 struct xfs_bmap_free *flist, struct xfs_mount *mp); 177 178 void xfs_bmap_cancel(struct xfs_bmap_free *flist);
-3
fs/xfs/xfs_dinode.h
··· 132 132 #define XFS_LITINO(mp, version) \ 133 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 136 * Inode data & attribute fork sizes, per inode. 140 137 */
+12 -8
fs/xfs/xfs_dir2_block.c
··· 29 29 #include "xfs_dinode.h" 30 30 #include "xfs_inode.h" 31 31 #include "xfs_inode_item.h" 32 + #include "xfs_bmap.h" 32 33 #include "xfs_buf_item.h" 33 34 #include "xfs_dir2.h" 34 35 #include "xfs_dir2_format.h" ··· 1165 1164 __be16 *tagp; /* end of data entry */ 1166 1165 xfs_trans_t *tp; /* transaction pointer */ 1167 1166 struct xfs_name name; 1167 + struct xfs_ifork *ifp; 1168 1168 1169 1169 trace_xfs_dir2_sf_to_block(args); 1170 1170 1171 1171 dp = args->dp; 1172 1172 tp = args->trans; 1173 1173 mp = dp->i_mount; 1174 - ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 1174 + ifp = XFS_IFORK_PTR(dp, XFS_DATA_FORK); 1175 + ASSERT(ifp->if_flags & XFS_IFINLINE); 1175 1176 /* 1176 1177 * Bomb out if the shortform directory is way too short. 1177 1178 */ ··· 1182 1179 return XFS_ERROR(EIO); 1183 1180 } 1184 1181 1185 - oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 1182 + oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data; 1186 1183 1187 - ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 1188 - ASSERT(dp->i_df.if_u1.if_data != NULL); 1184 + ASSERT(ifp->if_bytes == dp->i_d.di_size); 1185 + ASSERT(ifp->if_u1.if_data != NULL); 1189 1186 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count)); 1187 + ASSERT(dp->i_d.di_nextents == 0); 1190 1188 1191 1189 /* 1192 1190 * Copy the directory into a temporary buffer. 1193 1191 * Then pitch the incore inode data so we can make extents. 1194 1192 */ 1195 - sfp = kmem_alloc(dp->i_df.if_bytes, KM_SLEEP); 1196 - memcpy(sfp, oldsfp, dp->i_df.if_bytes); 1193 + sfp = kmem_alloc(ifp->if_bytes, KM_SLEEP); 1194 + memcpy(sfp, oldsfp, ifp->if_bytes); 1197 1195 1198 - xfs_idata_realloc(dp, -dp->i_df.if_bytes, XFS_DATA_FORK); 1196 + xfs_idata_realloc(dp, -ifp->if_bytes, XFS_DATA_FORK); 1197 + xfs_bmap_local_to_extents_empty(dp, XFS_DATA_FORK); 1199 1198 dp->i_d.di_size = 0; 1200 - xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 1201 1199 1202 1200 /* 1203 1201 * Add block 0 to the inode.
+12 -3
fs/xfs/xfs_dquot.c
··· 936 936 { 937 937 struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; 938 938 struct xfs_dquot *gdqp; 939 + struct xfs_dquot *pdqp; 939 940 940 941 trace_xfs_dqput_free(dqp); 941 942 ··· 950 949 951 950 /* 952 951 * If we just added a udquot to the freelist, then we want to release 953 - * the gdquot reference that it (probably) has. Otherwise it'll keep 954 - * the gdquot from getting reclaimed. 952 + * the gdquot/pdquot reference that it (probably) has. Otherwise it'll 953 + * keep the gdquot/pdquot from getting reclaimed. 955 954 */ 956 955 gdqp = dqp->q_gdquot; 957 956 if (gdqp) { 958 957 xfs_dqlock(gdqp); 959 958 dqp->q_gdquot = NULL; 960 959 } 960 + 961 + pdqp = dqp->q_pdquot; 962 + if (pdqp) { 963 + xfs_dqlock(pdqp); 964 + dqp->q_pdquot = NULL; 965 + } 961 966 xfs_dqunlock(dqp); 962 967 963 968 /* 964 - * If we had a group quota hint, release it now. 969 + * If we had a group/project quota hint, release it now. 965 970 */ 966 971 if (gdqp) 967 972 xfs_qm_dqput(gdqp); 973 + if (pdqp) 974 + xfs_qm_dqput(pdqp); 968 975 } 969 976 970 977 /*
+5 -2
fs/xfs/xfs_dquot.h
··· 53 53 xfs_fileoff_t q_fileoffset; /* offset in quotas file */ 54 54 55 55 struct xfs_dquot*q_gdquot; /* group dquot, hint only */ 56 + struct xfs_dquot*q_pdquot; /* project dquot, hint only */ 56 57 xfs_disk_dquot_t q_core; /* actual usage & quotas */ 57 58 xfs_dq_logitem_t q_logitem; /* dquot log item */ 58 59 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ ··· 119 118 case XFS_DQ_USER: 120 119 return XFS_IS_UQUOTA_ON(mp); 121 120 case XFS_DQ_GROUP: 121 + return XFS_IS_GQUOTA_ON(mp); 122 122 case XFS_DQ_PROJ: 123 - return XFS_IS_OQUOTA_ON(mp); 123 + return XFS_IS_PQUOTA_ON(mp); 124 124 default: 125 125 return 0; 126 126 } ··· 133 131 case XFS_DQ_USER: 134 132 return ip->i_udquot; 135 133 case XFS_DQ_GROUP: 136 - case XFS_DQ_PROJ: 137 134 return ip->i_gdquot; 135 + case XFS_DQ_PROJ: 136 + return ip->i_pdquot; 138 137 default: 139 138 return NULL; 140 139 }
+1
fs/xfs/xfs_icache.c
··· 337 337 iflags |= XFS_IDONTCACHE; 338 338 ip->i_udquot = NULL; 339 339 ip->i_gdquot = NULL; 340 + ip->i_pdquot = NULL; 340 341 xfs_iflags_set(ip, iflags); 341 342 342 343 /* insert the new inode */
+7 -7
fs/xfs/xfs_inode.c
··· 2156 2156 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, 2157 2157 (int)new_size); 2158 2158 ifp->if_broot_bytes = (int)new_size; 2159 - ASSERT(ifp->if_broot_bytes <= 2160 - XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip)); 2159 + ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= 2160 + XFS_IFORK_SIZE(ip, whichfork)); 2161 2161 memmove(np, op, cur_max * (uint)sizeof(xfs_dfsbno_t)); 2162 2162 return; 2163 2163 } ··· 2210 2210 kmem_free(ifp->if_broot); 2211 2211 ifp->if_broot = new_broot; 2212 2212 ifp->if_broot_bytes = (int)new_size; 2213 - ASSERT(ifp->if_broot_bytes <= 2214 - XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip)); 2213 + if (ifp->if_broot) 2214 + ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= 2215 + XFS_IFORK_SIZE(ip, whichfork)); 2215 2216 return; 2216 2217 } 2217 2218 ··· 2523 2522 if ((iip->ili_fields & brootflag[whichfork]) && 2524 2523 (ifp->if_broot_bytes > 0)) { 2525 2524 ASSERT(ifp->if_broot != NULL); 2526 - ASSERT(ifp->if_broot_bytes <= 2527 - (XFS_IFORK_SIZE(ip, whichfork) + 2528 - XFS_BROOT_SIZE_ADJ(ip))); 2525 + ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= 2526 + XFS_IFORK_SIZE(ip, whichfork)); 2529 2527 xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes, 2530 2528 (xfs_bmdr_block_t *)cp, 2531 2529 XFS_DFORK_SIZE(dip, mp, whichfork));
+1
fs/xfs/xfs_inode.h
··· 250 250 struct xfs_mount *i_mount; /* fs mount struct ptr */ 251 251 struct xfs_dquot *i_udquot; /* user dquot */ 252 252 struct xfs_dquot *i_gdquot; /* group dquot */ 253 + struct xfs_dquot *i_pdquot; /* project dquot */ 253 254 254 255 /* Inode location stuff */ 255 256 xfs_ino_t i_ino; /* inode number (agno/agino)*/
+8 -8
fs/xfs/xfs_ioctl.c
··· 248 248 goto out_dput; 249 249 } 250 250 251 - fd = get_unused_fd(); 251 + fd = get_unused_fd_flags(0); 252 252 if (fd < 0) { 253 253 error = fd; 254 254 goto out_dput; ··· 928 928 struct xfs_trans *tp; 929 929 unsigned int lock_flags = 0; 930 930 struct xfs_dquot *udqp = NULL; 931 - struct xfs_dquot *gdqp = NULL; 931 + struct xfs_dquot *pdqp = NULL; 932 932 struct xfs_dquot *olddquot = NULL; 933 933 int code; 934 934 ··· 957 957 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) { 958 958 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid, 959 959 ip->i_d.di_gid, fa->fsx_projid, 960 - XFS_QMOPT_PQUOTA, &udqp, &gdqp); 960 + XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp); 961 961 if (code) 962 962 return code; 963 963 } ··· 994 994 XFS_IS_PQUOTA_ON(mp) && 995 995 xfs_get_projid(ip) != fa->fsx_projid) { 996 996 ASSERT(tp); 997 - code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, 998 - capable(CAP_FOWNER) ? 997 + code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, 998 + pdqp, capable(CAP_FOWNER) ? 999 999 XFS_QMOPT_FORCE_RES : 0); 1000 1000 if (code) /* out of quota */ 1001 1001 goto error_return; ··· 1113 1113 if (xfs_get_projid(ip) != fa->fsx_projid) { 1114 1114 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) { 1115 1115 olddquot = xfs_qm_vop_chown(tp, ip, 1116 - &ip->i_gdquot, gdqp); 1116 + &ip->i_pdquot, pdqp); 1117 1117 } 1118 1118 xfs_set_projid(ip, fa->fsx_projid); 1119 1119 ··· 1160 1160 */ 1161 1161 xfs_qm_dqrele(olddquot); 1162 1162 xfs_qm_dqrele(udqp); 1163 - xfs_qm_dqrele(gdqp); 1163 + xfs_qm_dqrele(pdqp); 1164 1164 1165 1165 return code; 1166 1166 1167 1167 error_return: 1168 1168 xfs_qm_dqrele(udqp); 1169 - xfs_qm_dqrele(gdqp); 1169 + xfs_qm_dqrele(pdqp); 1170 1170 xfs_trans_cancel(tp, 0); 1171 1171 if (lock_flags) 1172 1172 xfs_iunlock(ip, lock_flags);
+12 -12
fs/xfs/xfs_iops.c
··· 467 467 ASSERT(tp); 468 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 470 ip->i_d.di_mode &= S_IFMT; 474 471 ip->i_d.di_mode |= mode & ~S_IFMT; 475 472 ··· 492 495 493 496 trace_xfs_setattr(ip); 494 497 495 - if (mp->m_flags & XFS_MOUNT_RDONLY) 496 - return XFS_ERROR(EROFS); 498 + /* If acls are being inherited, we already have this checked */ 499 + if (!(flags & XFS_ATTR_NOACL)) { 500 + if (mp->m_flags & XFS_MOUNT_RDONLY) 501 + return XFS_ERROR(EROFS); 497 502 498 - if (XFS_FORCED_SHUTDOWN(mp)) 499 - return XFS_ERROR(EIO); 503 + if (XFS_FORCED_SHUTDOWN(mp)) 504 + return XFS_ERROR(EIO); 500 505 501 - error = -inode_change_ok(inode, iattr); 502 - if (error) 503 - return XFS_ERROR(error); 506 + error = -inode_change_ok(inode, iattr); 507 + if (error) 508 + return XFS_ERROR(error); 509 + } 504 510 505 511 ASSERT((mask & ATTR_SIZE) == 0); 506 512 ··· 539 539 ASSERT(udqp == NULL); 540 540 ASSERT(gdqp == NULL); 541 541 error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip), 542 - qflags, &udqp, &gdqp); 542 + qflags, &udqp, &gdqp, NULL); 543 543 if (error) 544 544 return error; 545 545 } ··· 575 575 (XFS_IS_GQUOTA_ON(mp) && igid != gid))) { 576 576 ASSERT(tp); 577 577 error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, 578 - capable(CAP_FOWNER) ? 578 + NULL, capable(CAP_FOWNER) ? 579 579 XFS_QMOPT_FORCE_RES : 0); 580 580 if (error) /* out of quota */ 581 581 goto out_trans_cancel;
+1 -27
fs/xfs/xfs_itable.c
··· 221 221 char __user *ubufp; /* pointer into user's buffer */ 222 222 int ubelem; /* spaces used in user's buffer */ 223 223 int ubused; /* bytes used by formatter */ 224 - xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ 225 224 226 225 /* 227 226 * Get the last inode value, see if there's nothing to do. ··· 262 263 rval = 0; 263 264 while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) { 264 265 cond_resched(); 265 - bp = NULL; 266 266 error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); 267 267 if (error) { 268 268 /* ··· 434 436 irbp->ir_freecount < XFS_INODES_PER_CHUNK; 435 437 chunkidx++, clustidx++, agino++) { 436 438 ASSERT(chunkidx < XFS_INODES_PER_CHUNK); 437 - /* 438 - * Recompute agbno if this is the 439 - * first inode of the cluster. 440 - * 441 - * Careful with clustidx. There can be 442 - * multiple clusters per chunk, a single 443 - * cluster per chunk or a cluster that has 444 - * inodes represented from several different 445 - * chunks (if blocksize is large). 446 - * 447 - * Because of this, the starting clustidx is 448 - * initialized to zero in this loop but must 449 - * later be reset after reading in the cluster 450 - * buffer. 451 - */ 452 - if ((chunkidx & (nicluster - 1)) == 0) { 453 - agbno = XFS_AGINO_TO_AGBNO(mp, 454 - irbp->ir_startino) + 455 - ((chunkidx & nimask) >> 456 - mp->m_sb.sb_inopblog); 457 - } 439 + 458 440 ino = XFS_AGINO_TO_INO(mp, agno, agino); 459 441 /* 460 442 * Skip if this inode is free. ··· 480 502 481 503 cond_resched(); 482 504 } 483 - 484 - if (bp) 485 - xfs_buf_relse(bp); 486 - 487 505 /* 488 506 * Set up for the next loop iteration. 489 507 */
+173 -68
fs/xfs/xfs_qm.c
··· 137 137 struct xfs_mount *mp = dqp->q_mount; 138 138 struct xfs_quotainfo *qi = mp->m_quotainfo; 139 139 struct xfs_dquot *gdqp = NULL; 140 + struct xfs_dquot *pdqp = NULL; 140 141 141 142 xfs_dqlock(dqp); 142 143 if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { ··· 146 145 } 147 146 148 147 /* 149 - * If this quota has a group hint attached, prepare for releasing it 150 - * now. 148 + * If this quota has a hint attached, prepare for releasing it now. 151 149 */ 152 150 gdqp = dqp->q_gdquot; 153 151 if (gdqp) { 154 152 xfs_dqlock(gdqp); 155 153 dqp->q_gdquot = NULL; 154 + } 155 + 156 + pdqp = dqp->q_pdquot; 157 + if (pdqp) { 158 + xfs_dqlock(pdqp); 159 + dqp->q_pdquot = NULL; 156 160 } 157 161 158 162 dqp->dq_flags |= XFS_DQ_FREEING; ··· 214 208 215 209 if (gdqp) 216 210 xfs_qm_dqput(gdqp); 211 + if (pdqp) 212 + xfs_qm_dqput(pdqp); 217 213 return 0; 218 214 } 219 215 ··· 372 364 IRELE(mp->m_quotainfo->qi_gquotaip); 373 365 mp->m_quotainfo->qi_gquotaip = NULL; 374 366 } 367 + if (mp->m_quotainfo->qi_pquotaip) { 368 + IRELE(mp->m_quotainfo->qi_pquotaip); 369 + mp->m_quotainfo->qi_pquotaip = NULL; 370 + } 375 371 } 376 372 } 377 373 ··· 422 410 * be reclaimed as long as we have a ref from inode and we 423 411 * hold the ilock. 424 412 */ 425 - dqp = udqhint->q_gdquot; 413 + if (type == XFS_DQ_GROUP) 414 + dqp = udqhint->q_gdquot; 415 + else 416 + dqp = udqhint->q_pdquot; 426 417 if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { 427 418 ASSERT(*IO_idqpp == NULL); 428 419 ··· 468 453 469 454 470 455 /* 471 - * Given a udquot and gdquot, attach a ptr to the group dquot in the 472 - * udquot as a hint for future lookups. 456 + * Given a udquot and group/project type, attach the group/project 457 + * dquot pointer to the udquot as a hint for future lookups. 473 458 */ 474 459 STATIC void 475 - xfs_qm_dqattach_grouphint( 476 - xfs_dquot_t *udq, 477 - xfs_dquot_t *gdq) 460 + xfs_qm_dqattach_hint( 461 + struct xfs_inode *ip, 462 + int type) 478 463 { 479 - xfs_dquot_t *tmp; 464 + struct xfs_dquot **dqhintp; 465 + struct xfs_dquot *dqp; 466 + struct xfs_dquot *udq = ip->i_udquot; 467 + 468 + ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); 480 469 481 470 xfs_dqlock(udq); 482 471 483 - tmp = udq->q_gdquot; 484 - if (tmp) { 485 - if (tmp == gdq) 472 + if (type == XFS_DQ_GROUP) { 473 + dqp = ip->i_gdquot; 474 + dqhintp = &udq->q_gdquot; 475 + } else { 476 + dqp = ip->i_pdquot; 477 + dqhintp = &udq->q_pdquot; 478 + } 479 + 480 + if (*dqhintp) { 481 + struct xfs_dquot *tmp; 482 + 483 + if (*dqhintp == dqp) 486 484 goto done; 487 485 488 - udq->q_gdquot = NULL; 486 + tmp = *dqhintp; 487 + *dqhintp = NULL; 489 488 xfs_qm_dqrele(tmp); 490 489 } 491 490 492 - udq->q_gdquot = xfs_qm_dqhold(gdq); 491 + *dqhintp = xfs_qm_dqhold(dqp); 493 492 done: 494 493 xfs_dqunlock(udq); 495 494 } ··· 556 527 } 557 528 558 529 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 559 - if (XFS_IS_OQUOTA_ON(mp)) { 560 - error = XFS_IS_GQUOTA_ON(mp) ? 561 - xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, 562 - flags & XFS_QMOPT_DQALLOC, 563 - ip->i_udquot, &ip->i_gdquot) : 564 - xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, 530 + if (XFS_IS_GQUOTA_ON(mp)) { 531 + error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, 565 532 flags & XFS_QMOPT_DQALLOC, 566 533 ip->i_udquot, &ip->i_gdquot); 567 534 /* ··· 569 544 nquotas++; 570 545 } 571 546 547 + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 548 + if (XFS_IS_PQUOTA_ON(mp)) { 549 + error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, 550 + flags & XFS_QMOPT_DQALLOC, 551 + ip->i_udquot, &ip->i_pdquot); 552 + /* 553 + * Don't worry about the udquot that we may have 554 + * attached above. It'll get detached, if not already. 555 + */ 556 + if (error) 557 + goto done; 558 + nquotas++; 559 + } 560 + 572 561 /* 573 - * Attach this group quota to the user quota as a hint. 562 + * Attach this group/project quota to the user quota as a hint. 574 563 * This WON'T, in general, result in a thrash. 575 564 */ 576 - if (nquotas == 2) { 565 + if (nquotas > 1 && ip->i_udquot) { 577 566 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 578 - ASSERT(ip->i_udquot); 579 - ASSERT(ip->i_gdquot); 567 + ASSERT(ip->i_gdquot || !XFS_IS_GQUOTA_ON(mp)); 568 + ASSERT(ip->i_pdquot || !XFS_IS_PQUOTA_ON(mp)); 580 569 581 570 /* 582 571 * We do not have i_udquot locked at this point, but this check ··· 599 560 * succeed in general. 600 561 */ 601 562 if (ip->i_udquot->q_gdquot != ip->i_gdquot) 602 - xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); 563 + xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP); 564 + 565 + if (ip->i_udquot->q_pdquot != ip->i_pdquot) 566 + xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ); 603 567 } 604 568 605 569 done: ··· 610 568 if (!error) { 611 569 if (XFS_IS_UQUOTA_ON(mp)) 612 570 ASSERT(ip->i_udquot); 613 - if (XFS_IS_OQUOTA_ON(mp)) 571 + if (XFS_IS_GQUOTA_ON(mp)) 614 572 ASSERT(ip->i_gdquot); 573 + if (XFS_IS_PQUOTA_ON(mp)) 574 + ASSERT(ip->i_pdquot); 615 575 } 616 576 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 617 577 #endif ··· 646 602 xfs_qm_dqdetach( 647 603 xfs_inode_t *ip) 648 604 { 649 - if (!(ip->i_udquot || ip->i_gdquot)) 605 + if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot)) 650 606 return; 651 607 652 608 trace_xfs_dquot_dqdetach(ip); ··· 659 615 if (ip->i_gdquot) { 660 616 xfs_qm_dqrele(ip->i_gdquot); 661 617 ip->i_gdquot = NULL; 618 + } 619 + if (ip->i_pdquot) { 620 + xfs_qm_dqrele(ip->i_pdquot); 621 + ip->i_pdquot = NULL; 662 622 } 663 623 } 664 624 ··· 708 660 709 661 INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS); 710 662 INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS); 663 + INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS); 711 664 mutex_init(&qinf->qi_tree_lock); 712 665 713 666 INIT_LIST_HEAD(&qinf->qi_lru_list); ··· 809 760 if (qi->qi_gquotaip) { 810 761 IRELE(qi->qi_gquotaip); 811 762 qi->qi_gquotaip = NULL; 763 + } 764 + if (qi->qi_pquotaip) { 765 + IRELE(qi->qi_pquotaip); 766 + qi->qi_pquotaip = NULL; 812 767 } 813 768 mutex_destroy(&qi->qi_quotaofflock); 814 769 kmem_free(qi); ··· 1322 1269 LIST_HEAD (buffer_list); 1323 1270 struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip; 1324 1271 struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip; 1272 + struct xfs_inode *pip = mp->m_quotainfo->qi_pquotaip; 1325 1273 1326 1274 count = INT_MAX; 1327 1275 structsz = 1; 1328 1276 lastino = 0; 1329 1277 flags = 0; 1330 1278 1331 - ASSERT(uip || gip); 1279 + ASSERT(uip || gip || pip); 1332 1280 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 1333 1281 1334 1282 xfs_notice(mp, "Quotacheck needed: Please wait."); ··· 1348 1294 } 1349 1295 1350 1296 if (gip) { 1351 - error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ? 1352 - XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA, 1297 + error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA, 1353 1298 &buffer_list); 1354 1299 if (error) 1355 1300 goto error_return; 1356 - flags |= XFS_IS_GQUOTA_ON(mp) ? 1357 - XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD; 1301 + flags |= XFS_GQUOTA_CHKD; 1302 + } 1303 + 1304 + if (pip) { 1305 + error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA, 1306 + &buffer_list); 1307 + if (error) 1308 + goto error_return; 1309 + flags |= XFS_PQUOTA_CHKD; 1358 1310 } 1359 1311 1360 1312 do { ··· 1457 1397 { 1458 1398 struct xfs_inode *uip = NULL; 1459 1399 struct xfs_inode *gip = NULL; 1400 + struct xfs_inode *pip = NULL; 1460 1401 int error; 1461 1402 __int64_t sbflags = 0; 1462 1403 uint flags = 0; ··· 1476 1415 if (error) 1477 1416 return XFS_ERROR(error); 1478 1417 } 1479 - if (XFS_IS_OQUOTA_ON(mp) && 1418 + if (XFS_IS_GQUOTA_ON(mp) && 1480 1419 mp->m_sb.sb_gquotino != NULLFSINO) { 1481 1420 ASSERT(mp->m_sb.sb_gquotino > 0); 1482 1421 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 1483 1422 0, 0, &gip); 1423 + if (error) 1424 + goto error_rele; 1425 + } 1426 + /* XXX: Use gquotino for now */ 1427 + if (XFS_IS_PQUOTA_ON(mp) && 1428 + mp->m_sb.sb_gquotino != NULLFSINO) { 1429 + ASSERT(mp->m_sb.sb_gquotino > 0); 1430 + error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 1431 + 0, 0, &pip); 1484 1432 if (error) 1485 1433 goto error_rele; 1486 1434 } ··· 1500 1430 } 1501 1431 1502 1432 /* 1503 - * Create the two inodes, if they don't exist already. The changes 1433 + * Create the three inodes, if they don't exist already. The changes 1504 1434 * made above will get added to a transaction and logged in one of 1505 1435 * the qino_alloc calls below. If the device is readonly, 1506 1436 * temporarily switch to read-write to do this. ··· 1514 1444 1515 1445 flags &= ~XFS_QMOPT_SBVERSION; 1516 1446 } 1517 - if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) { 1518 - flags |= (XFS_IS_GQUOTA_ON(mp) ? 1519 - XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA); 1447 + if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) { 1520 1448 error = xfs_qm_qino_alloc(mp, &gip, 1521 - sbflags | XFS_SB_GQUOTINO, flags); 1449 + sbflags | XFS_SB_GQUOTINO, 1450 + flags | XFS_QMOPT_GQUOTA); 1451 + if (error) 1452 + goto error_rele; 1453 + 1454 + flags &= ~XFS_QMOPT_SBVERSION; 1455 + } 1456 + if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) { 1457 + /* XXX: Use XFS_SB_GQUOTINO for now */ 1458 + error = xfs_qm_qino_alloc(mp, &pip, 1459 + sbflags | XFS_SB_GQUOTINO, 1460 + flags | XFS_QMOPT_PQUOTA); 1522 1461 if (error) 1523 1462 goto error_rele; 1524 1463 } 1525 1464 1526 1465 mp->m_quotainfo->qi_uquotaip = uip; 1527 1466 mp->m_quotainfo->qi_gquotaip = gip; 1467 + mp->m_quotainfo->qi_pquotaip = pip; 1528 1468 1529 1469 return 0; 1530 1470 ··· 1543 1463 IRELE(uip); 1544 1464 if (gip) 1545 1465 IRELE(gip); 1466 + if (pip) 1467 + IRELE(pip); 1546 1468 return XFS_ERROR(error); 1547 1469 } 1548 1470 ··· 1739 1657 prid_t prid, 1740 1658 uint flags, 1741 1659 struct xfs_dquot **O_udqpp, 1742 - struct xfs_dquot **O_gdqpp) 1660 + struct xfs_dquot **O_gdqpp, 1661 + struct xfs_dquot **O_pdqpp) 1743 1662 { 1744 1663 struct xfs_mount *mp = ip->i_mount; 1745 1664 struct xfs_dquot *uq = NULL; 1746 1665 struct xfs_dquot *gq = NULL; 1666 + struct xfs_dquot *pq = NULL; 1747 1667 int error; 1748 1668 uint lockflags; 1749 1669 ··· 1825 1741 ASSERT(ip->i_gdquot); 1826 1742 gq = xfs_qm_dqhold(ip->i_gdquot); 1827 1743 } 1828 - } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { 1744 + } 1745 + if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { 1829 1746 if (xfs_get_projid(ip) != prid) { 1830 1747 xfs_iunlock(ip, lockflags); 1831 1748 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, 1832 1749 XFS_DQ_PROJ, 1833 1750 XFS_QMOPT_DQALLOC | 1834 1751 XFS_QMOPT_DOWARN, 1835 - &gq); 1752 + &pq); 1836 1753 if (error) { 1837 1754 ASSERT(error != ENOENT); 1838 1755 goto error_rele; 1839 1756 } 1840 - xfs_dqunlock(gq); 1757 + xfs_dqunlock(pq); 1841 1758 lockflags = XFS_ILOCK_SHARED; 1842 1759 xfs_ilock(ip, lockflags); 1843 1760 } else { 1844 - ASSERT(ip->i_gdquot); 1845 - gq = xfs_qm_dqhold(ip->i_gdquot); 1761 + ASSERT(ip->i_pdquot); 1762 + pq = xfs_qm_dqhold(ip->i_pdquot); 1846 1763 } 1847 1764 } 1848 1765 if (uq) ··· 1858 1773 *O_gdqpp = gq; 1859 1774 else if (gq) 1860 1775 xfs_qm_dqrele(gq); 1776 + if (O_pdqpp) 1777 + *O_pdqpp = pq; 1778 + else if (pq) 1779 + xfs_qm_dqrele(pq); 1861 1780 return 0; 1862 1781 1863 1782 error_rele: 1783 + if (gq) 1784 + xfs_qm_dqrele(gq); 1864 1785 if (uq) 1865 1786 xfs_qm_dqrele(uq); 1866 1787 return error; ··· 1921 1830 struct xfs_inode *ip, 1922 1831 struct xfs_dquot *udqp, 1923 1832 struct xfs_dquot *gdqp, 1833 + struct xfs_dquot *pdqp, 1924 1834 uint flags) 1925 1835 { 1926 1836 struct xfs_mount *mp = ip->i_mount; 1927 1837 uint delblks, blkflags, prjflags = 0; 1928 1838 struct xfs_dquot *udq_unres = NULL; 1929 1839 struct xfs_dquot *gdq_unres = NULL; 1840 + struct xfs_dquot *pdq_unres = NULL; 1930 1841 struct xfs_dquot *udq_delblks = NULL; 1931 1842 struct xfs_dquot *gdq_delblks = NULL; 1843 + struct xfs_dquot *pdq_delblks = NULL; 1932 1844 int error; 1933 1845 1934 1846 ··· 1955 1861 udq_unres = ip->i_udquot; 1956 1862 } 1957 1863 } 1958 - if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { 1959 - if (XFS_IS_PQUOTA_ON(ip->i_mount) && 1960 - xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id)) 1961 - prjflags = XFS_QMOPT_ENOSPC; 1864 + if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp && 1865 + ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) { 1866 + gdq_delblks = gdqp; 1867 + if (delblks) { 1868 + ASSERT(ip->i_gdquot); 1869 + gdq_unres = ip->i_gdquot; 1870 + } 1871 + } 1962 1872 1963 - if (prjflags || 1964 - (XFS_IS_GQUOTA_ON(ip->i_mount) && 1965 - ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) { 1966 - gdq_delblks = gdqp; 1967 - if (delblks) { 1968 - ASSERT(ip->i_gdquot); 1969 - gdq_unres = ip->i_gdquot; 1970 - } 1873 + if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp && 1874 + xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) { 1875 + prjflags = XFS_QMOPT_ENOSPC; 1876 + pdq_delblks = pdqp; 1877 + if (delblks) { 1878 + ASSERT(ip->i_pdquot); 1879 + pdq_unres = ip->i_pdquot; 1971 1880 } 1972 1881 } 1973 1882 1974 1883 error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 1975 - udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1, 1884 + udq_delblks, gdq_delblks, pdq_delblks, 1885 + ip->i_d.di_nblocks, 1, 1976 1886 flags | blkflags | prjflags); 1977 1887 if (error) 1978 1888 return error; ··· 1991 1893 /* 1992 1894 * Do the reservations first. Unreservation can't fail. 1993 1895 */ 1994 - ASSERT(udq_delblks || gdq_delblks); 1995 - ASSERT(udq_unres || gdq_unres); 1896 + ASSERT(udq_delblks || gdq_delblks || pdq_delblks); 1897 + ASSERT(udq_unres || gdq_unres || pdq_unres); 1996 1898 error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 1997 - udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0, 1899 + udq_delblks, gdq_delblks, pdq_delblks, 1900 + (xfs_qcnt_t)delblks, 0, 1998 1901 flags | blkflags | prjflags); 1999 1902 if (error) 2000 1903 return error; 2001 1904 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2002 - udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0, 2003 - blkflags); 1905 + udq_unres, gdq_unres, pdq_unres, 1906 + -((xfs_qcnt_t)delblks), 0, blkflags); 2004 1907 } 2005 1908 2006 1909 return (0); ··· 2040 1941 struct xfs_trans *tp, 2041 1942 struct xfs_inode *ip, 2042 1943 struct xfs_dquot *udqp, 2043 - struct xfs_dquot *gdqp) 1944 + struct xfs_dquot *gdqp, 1945 + struct xfs_dquot *pdqp) 2044 1946 { 2045 1947 struct xfs_mount *mp = tp->t_mountp; 2046 1948 ··· 2061 1961 } 2062 1962 if (gdqp) { 2063 1963 ASSERT(ip->i_gdquot == NULL); 2064 - ASSERT(XFS_IS_OQUOTA_ON(mp)); 2065 - ASSERT((XFS_IS_GQUOTA_ON(mp) ? 2066 - ip->i_d.di_gid : xfs_get_projid(ip)) == 2067 - be32_to_cpu(gdqp->q_core.d_id)); 2068 - 1964 + ASSERT(XFS_IS_GQUOTA_ON(mp)); 1965 + ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id)); 2069 1966 ip->i_gdquot = xfs_qm_dqhold(gdqp); 2070 1967 xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); 1968 + } 1969 + if (pdqp) { 1970 + ASSERT(ip->i_pdquot == NULL); 1971 + ASSERT(XFS_IS_PQUOTA_ON(mp)); 1972 + ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id)); 1973 + 1974 + ip->i_pdquot = xfs_qm_dqhold(pdqp); 1975 + xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1); 2071 1976 } 2072 1977 } 2073 1978
+13 -7
fs/xfs/xfs_qm.h
··· 44 44 typedef struct xfs_quotainfo { 45 45 struct radix_tree_root qi_uquota_tree; 46 46 struct radix_tree_root qi_gquota_tree; 47 + struct radix_tree_root qi_pquota_tree; 47 48 struct mutex qi_tree_lock; 48 - xfs_inode_t *qi_uquotaip; /* user quota inode */ 49 - xfs_inode_t *qi_gquotaip; /* group quota inode */ 49 + struct xfs_inode *qi_uquotaip; /* user quota inode */ 50 + struct xfs_inode *qi_gquotaip; /* group quota inode */ 51 + struct xfs_inode *qi_pquotaip; /* project quota inode */ 50 52 struct list_head qi_lru_list; 51 53 struct mutex qi_lru_lock; 52 54 int qi_lru_count; ··· 80 78 case XFS_DQ_USER: 81 79 return &qi->qi_uquota_tree; 82 80 case XFS_DQ_GROUP: 83 - case XFS_DQ_PROJ: 84 81 return &qi->qi_gquota_tree; 82 + case XFS_DQ_PROJ: 83 + return &qi->qi_pquota_tree; 85 84 default: 86 85 ASSERT(0); 87 86 } ··· 96 93 case XFS_DQ_USER: 97 94 return dqp->q_mount->m_quotainfo->qi_uquotaip; 98 95 case XFS_DQ_GROUP: 99 - case XFS_DQ_PROJ: 100 96 return dqp->q_mount->m_quotainfo->qi_gquotaip; 97 + case XFS_DQ_PROJ: 98 + return dqp->q_mount->m_quotainfo->qi_pquotaip; 101 99 default: 102 100 ASSERT(0); 103 101 } ··· 111 107 struct xfs_dquot *, uint, long); 112 108 extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, 113 109 struct xfs_mount *, struct xfs_dquot *, 114 - struct xfs_dquot *, long, long, uint); 110 + struct xfs_dquot *, struct xfs_dquot *, 111 + long, long, uint); 115 112 extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *); 116 113 extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *); 117 114 118 115 /* 119 - * We keep the usr and grp dquots separately so that locking will be easier 120 - * to do at commit time. All transactions that we know of at this point 116 + * We keep the usr, grp, and prj dquots separately so that locking will be 117 + * easier to do at commit time. All transactions that we know of at this point 121 118 * affect no more than two dquots of one type. Hence, the TRANS_MAXDQS value. 122 119 */ 123 120 enum { 124 121 XFS_QM_TRANS_USR = 0, 125 122 XFS_QM_TRANS_GRP, 123 + XFS_QM_TRANS_PRJ, 126 124 XFS_QM_TRANS_DQTYPES 127 125 }; 128 126 #define XFS_QM_TRANS_MAXDQS 2
+5 -5
fs/xfs/xfs_qm_bhv.c
··· 112 112 113 113 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || 114 114 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || 115 - (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) || 116 - (!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) || 117 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 119 xfs_dev_is_read_only(mp, "changing quota state")) { 120 120 xfs_warn(mp, "please mount with%s%s%s%s.", 121 121 (!quotaondisk ? "out quota" : ""), 122 122 (uquotaondisk ? " usrquota" : ""), 123 - (pquotaondisk ? " prjquota" : ""), 124 - (gquotaondisk ? " grpquota" : "")); 123 + (gquotaondisk ? " grpquota" : ""), 124 + (pquotaondisk ? " prjquota" : "")); 125 125 return XFS_ERROR(EPERM); 126 126 } 127 127
+17 -7
fs/xfs/xfs_qm_syscalls.c
··· 119 119 dqtype |= XFS_QMOPT_GQUOTA; 120 120 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD); 121 121 inactivate_flags |= XFS_GQUOTA_ACTIVE; 122 - } else if (flags & XFS_PQUOTA_ACCT) { 122 + } 123 + if (flags & XFS_PQUOTA_ACCT) { 123 124 dqtype |= XFS_QMOPT_PQUOTA; 124 125 flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD); 125 126 inactivate_flags |= XFS_PQUOTA_ACTIVE; ··· 199 198 } 200 199 201 200 /* 202 - * If quotas is completely disabled, close shop. 201 + * If all quotas are completely turned off, close shop. 203 202 */ 204 - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) || 205 - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) { 203 + if (mp->m_qflags == 0) { 206 204 mutex_unlock(&q->qi_quotaofflock); 207 205 xfs_qm_destroy_quotainfo(mp); 208 206 return (0); ··· 214 214 IRELE(q->qi_uquotaip); 215 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 218 IRELE(q->qi_gquotaip); 219 219 q->qi_gquotaip = NULL; 220 + } 221 + if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) { 222 + IRELE(q->qi_pquotaip); 223 + q->qi_pquotaip = NULL; 220 224 } 221 225 222 226 out_unlock: ··· 863 859 { 864 860 /* skip quota inodes */ 865 861 if (ip == ip->i_mount->m_quotainfo->qi_uquotaip || 866 - ip == ip->i_mount->m_quotainfo->qi_gquotaip) { 862 + ip == ip->i_mount->m_quotainfo->qi_gquotaip || 863 + ip == ip->i_mount->m_quotainfo->qi_pquotaip) { 867 864 ASSERT(ip->i_udquot == NULL); 868 865 ASSERT(ip->i_gdquot == NULL); 866 + ASSERT(ip->i_pdquot == NULL); 869 867 return 0; 870 868 } 871 869 ··· 876 870 xfs_qm_dqrele(ip->i_udquot); 877 871 ip->i_udquot = NULL; 878 872 } 879 - if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) { 873 + if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) { 880 874 xfs_qm_dqrele(ip->i_gdquot); 881 875 ip->i_gdquot = NULL; 876 + } 877 + if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) { 878 + xfs_qm_dqrele(ip->i_pdquot); 879 + ip->i_pdquot = NULL; 882 880 } 883 881 xfs_iunlock(ip, XFS_ILOCK_EXCL); 884 882 return 0;
+39 -26
fs/xfs/xfs_quota.h
··· 108 108 { XFS_DQ_FREEING, "FREEING" } 109 109 110 110 /* 111 - * In the worst case, when both user and group quotas are on, 112 - * we can have a max of three dquots changing in a single transaction. 111 + * We have the possibility of all three quota types being active at once, and 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) 115 - 131 + #define XFS_DQUOT_LOGRES(mp) \ 132 + ((sizeof(struct xfs_dq_logformat) + sizeof(struct xfs_disk_dquot)) * 6) 116 133 117 134 /* 118 135 * These are the structures used to lay out dquots and quotaoff ··· 288 271 * we didn't have the inode locked, the appropriate dquot(s) will be 289 272 * attached atomically. 290 273 */ 291 - #define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ 292 - (ip)->i_udquot == NULL) || \ 293 - (XFS_IS_OQUOTA_ON(mp) && \ 294 - (ip)->i_gdquot == NULL)) 274 + #define XFS_NOT_DQATTACHED(mp, ip) \ 275 + ((XFS_IS_UQUOTA_ON(mp) && (ip)->i_udquot == NULL) || \ 276 + (XFS_IS_GQUOTA_ON(mp) && (ip)->i_gdquot == NULL) || \ 277 + (XFS_IS_PQUOTA_ON(mp) && (ip)->i_pdquot == NULL)) 295 278 296 279 #define XFS_QM_NEED_QUOTACHECK(mp) \ 297 280 ((XFS_IS_UQUOTA_ON(mp) && \ ··· 300 283 (mp->m_sb.sb_qflags & XFS_GQUOTA_CHKD) == 0) || \ 301 284 (XFS_IS_PQUOTA_ON(mp) && \ 302 285 (mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD) == 0)) 303 - 304 - #define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ 305 - XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ 306 - XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD) 307 - 308 - #define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ 309 - XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\ 310 - XFS_PQUOTA_ENFD|XFS_PQUOTA_CHKD) 311 286 312 287 #define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ 313 288 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ ··· 338 329 struct xfs_inode *, long, long, uint); 339 330 extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, 340 331 struct xfs_mount *, struct xfs_dquot *, 341 - struct xfs_dquot *, long, long, uint); 332 + struct xfs_dquot *, struct xfs_dquot *, long, long, uint); 342 333 343 334 extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint, 344 - struct xfs_dquot **, struct xfs_dquot **); 335 + struct xfs_dquot **, struct xfs_dquot **, struct xfs_dquot **); 345 336 extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *, 346 - struct xfs_dquot *, struct xfs_dquot *); 337 + struct xfs_dquot *, struct xfs_dquot *, struct xfs_dquot *); 347 338 extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **); 348 339 extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *, 349 340 struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *); 350 341 extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *, 351 - struct xfs_dquot *, struct xfs_dquot *, uint); 342 + struct xfs_dquot *, struct xfs_dquot *, 343 + struct xfs_dquot *, uint); 352 344 extern int xfs_qm_dqattach(struct xfs_inode *, uint); 353 345 extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint); 354 346 extern void xfs_qm_dqdetach(struct xfs_inode *); ··· 363 353 #else 364 354 static inline int 365 355 xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid, 366 - uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp) 356 + uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp, 357 + struct xfs_dquot **pdqp) 367 358 { 368 359 *udqp = NULL; 369 360 *gdqp = NULL; 361 + *pdqp = NULL; 370 362 return 0; 371 363 } 372 364 #define xfs_trans_dup_dqinfo(tp, tp2) ··· 383 371 } 384 372 static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, 385 373 struct xfs_mount *mp, struct xfs_dquot *udqp, 386 - struct xfs_dquot *gdqp, long nblks, long nions, uint flags) 374 + struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, 375 + long nblks, long nions, uint flags) 387 376 { 388 377 return 0; 389 378 } 390 - #define xfs_qm_vop_create_dqattach(tp, ip, u, g) 379 + #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p) 391 380 #define xfs_qm_vop_rename_dqattach(it) (0) 392 381 #define xfs_qm_vop_chown(tp, ip, old, new) (NULL) 393 - #define xfs_qm_vop_chown_reserve(tp, ip, u, g, fl) (0) 382 + #define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl) (0) 394 383 #define xfs_qm_dqattach(ip, fl) (0) 395 384 #define xfs_qm_dqattach_locked(ip, fl) (0) 396 385 #define xfs_qm_dqdetach(ip) ··· 405 392 406 393 #define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \ 407 394 xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags) 408 - #define xfs_trans_reserve_quota(tp, mp, ud, gd, nb, ni, f) \ 409 - xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \ 395 + #define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \ 396 + xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \ 410 397 f | XFS_QMOPT_RES_REGBLKS) 411 398 412 399 extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *,
+7 -3
fs/xfs/xfs_symlink.c
··· 360 360 prid_t prid; 361 361 struct xfs_dquot *udqp = NULL; 362 362 struct xfs_dquot *gdqp = NULL; 363 + struct xfs_dquot *pdqp = NULL; 363 364 uint resblks; 364 365 365 366 *ipp = NULL; ··· 387 386 * Make sure that we have allocated dquot(s) on disk. 388 387 */ 389 388 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, 390 - XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 389 + XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); 391 390 if (error) 392 391 goto std_return; 393 392 ··· 428 427 /* 429 428 * Reserve disk quota : blocks and inode. 430 429 */ 431 - error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); 430 + error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, 431 + pdqp, resblks, 1, 0); 432 432 if (error) 433 433 goto error_return; 434 434 ··· 467 465 /* 468 466 * Also attach the dquot(s) to it, if applicable. 469 467 */ 470 - xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); 468 + xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); 471 469 472 470 if (resblks) 473 471 resblks -= XFS_IALLOC_SPACE_RES(mp); ··· 565 563 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 566 564 xfs_qm_dqrele(udqp); 567 565 xfs_qm_dqrele(gdqp); 566 + xfs_qm_dqrele(pdqp); 568 567 569 568 *ipp = ip; 570 569 return 0; ··· 579 576 xfs_trans_cancel(tp, cancel_flags); 580 577 xfs_qm_dqrele(udqp); 581 578 xfs_qm_dqrele(gdqp); 579 + xfs_qm_dqrele(pdqp); 582 580 583 581 if (unlock_dp_on_error) 584 582 xfs_iunlock(dp, XFS_ILOCK_EXCL);
+26 -9
fs/xfs/xfs_trans_dquot.c
··· 163 163 164 164 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) 165 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 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 170 172 STATIC struct xfs_dqtrx * ··· 179 177 180 178 if (XFS_QM_ISUDQ(dqp)) 181 179 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR]; 182 - else 180 + else if (XFS_QM_ISGDQ(dqp)) 183 181 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP]; 182 + else if (XFS_QM_ISPDQ(dqp)) 183 + qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_PRJ]; 184 + else 185 + return NULL; 184 186 185 187 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { 186 188 if (qa[i].qt_dquot == NULL || ··· 297 291 298 292 299 293 /* 300 - * Given an array of dqtrx structures, lock all the dquots associated 301 - * and join them to the transaction, provided they have been modified. 302 - * We know that the highest number of dquots (of one type - usr OR grp), 303 - * involved in a transaction is 2 and that both usr and grp combined - 3. 304 - * So, we don't attempt to make this very generic. 294 + * Given an array of dqtrx structures, lock all the dquots associated and join 295 + * them to the transaction, provided they have been modified. We know that the 296 + * highest number of dquots of one type - usr, grp OR prj - involved in a 297 + * transaction is 2 so we don't need to make this very generic. 305 298 */ 306 299 STATIC void 307 300 xfs_trans_dqlockedjoin( ··· 733 728 734 729 /* 735 730 * Given dquot(s), make disk block and/or inode reservations against them. 736 - * The fact that this does the reservation against both the usr and 737 - * grp/prj quotas is important, because this follows a both-or-nothing 731 + * The fact that this does the reservation against user, group and 732 + * project quotas is important, because this follows a all-or-nothing 738 733 * approach. 739 734 * 740 735 * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. ··· 749 744 struct xfs_mount *mp, 750 745 struct xfs_dquot *udqp, 751 746 struct xfs_dquot *gdqp, 747 + struct xfs_dquot *pdqp, 752 748 long nblks, 753 749 long ninos, 754 750 uint flags) ··· 777 771 goto unwind_usr; 778 772 } 779 773 774 + if (pdqp) { 775 + error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags); 776 + if (error) 777 + goto unwind_grp; 778 + } 779 + 780 780 /* 781 781 * Didn't change anything critical, so, no need to log 782 782 */ 783 783 return 0; 784 784 785 + unwind_grp: 786 + flags |= XFS_QMOPT_FORCE_RES; 787 + if (gdqp) 788 + xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags); 785 789 unwind_usr: 786 790 flags |= XFS_QMOPT_FORCE_RES; 787 791 if (udqp) ··· 833 817 */ 834 818 return xfs_trans_reserve_quota_bydquots(tp, mp, 835 819 ip->i_udquot, ip->i_gdquot, 820 + ip->i_pdquot, 836 821 nblks, ninos, flags); 837 822 } 838 823
+9 -4
fs/xfs/xfs_vnodeops.c
··· 489 489 prid_t prid; 490 490 struct xfs_dquot *udqp = NULL; 491 491 struct xfs_dquot *gdqp = NULL; 492 + struct xfs_dquot *pdqp = NULL; 492 493 uint resblks; 493 494 uint log_res; 494 495 uint log_count; ··· 508 507 * Make sure that we have allocated dquot(s) on disk. 509 508 */ 510 509 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, 511 - XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 510 + XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, 511 + &udqp, &gdqp, &pdqp); 512 512 if (error) 513 513 return error; 514 514 ··· 561 559 /* 562 560 * Reserve disk quota and the inode. 563 561 */ 564 - error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); 562 + error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, 563 + pdqp, resblks, 1, 0); 565 564 if (error) 566 565 goto out_trans_cancel; 567 566 ··· 626 623 * These ids of the inode couldn't have changed since the new 627 624 * inode has been locked ever since it was created. 628 625 */ 629 - xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); 626 + xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); 630 627 631 628 error = xfs_bmap_finish(&tp, &free_list, &committed); 632 629 if (error) ··· 638 635 639 636 xfs_qm_dqrele(udqp); 640 637 xfs_qm_dqrele(gdqp); 638 + xfs_qm_dqrele(pdqp); 641 639 642 640 *ipp = ip; 643 641 return 0; ··· 660 656 661 657 xfs_qm_dqrele(udqp); 662 658 xfs_qm_dqrele(gdqp); 659 + xfs_qm_dqrele(pdqp); 663 660 664 661 if (unlock_dp_on_error) 665 662 xfs_iunlock(dp, XFS_ILOCK_EXCL); ··· 1573 1568 } 1574 1569 xfs_ilock(ip, XFS_ILOCK_EXCL); 1575 1570 error = xfs_trans_reserve_quota(tp, mp, 1576 - ip->i_udquot, ip->i_gdquot, 1571 + ip->i_udquot, ip->i_gdquot, ip->i_pdquot, 1577 1572 resblks, 0, XFS_QMOPT_RES_REGBLKS); 1578 1573 if (error) 1579 1574 goto error1;