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.

at v2.6.12-rc2 342 lines 9.8 kB view raw
1/* 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 59 21 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 31 */ 32 33#include "xfs.h" 34#include "xfs_macros.h" 35#include "xfs_types.h" 36#include "xfs_inum.h" 37#include "xfs_log.h" 38#include "xfs_trans.h" 39#include "xfs_sb.h" 40#include "xfs_ag.h" 41#include "xfs_dir.h" 42#include "xfs_dir2.h" 43#include "xfs_dmapi.h" 44#include "xfs_mount.h" 45#include "xfs_trans_priv.h" 46#include "xfs_alloc_btree.h" 47#include "xfs_bmap_btree.h" 48#include "xfs_ialloc_btree.h" 49#include "xfs_btree.h" 50#include "xfs_ialloc.h" 51#include "xfs_attr_sf.h" 52#include "xfs_dir_sf.h" 53#include "xfs_dir2_sf.h" 54#include "xfs_dinode.h" 55#include "xfs_inode_item.h" 56#include "xfs_inode.h" 57 58#ifdef XFS_TRANS_DEBUG 59STATIC void 60xfs_trans_inode_broot_debug( 61 xfs_inode_t *ip); 62#else 63#define xfs_trans_inode_broot_debug(ip) 64#endif 65 66 67/* 68 * Get and lock the inode for the caller if it is not already 69 * locked within the given transaction. If it is already locked 70 * within the transaction, just increment its lock recursion count 71 * and return a pointer to it. 72 * 73 * For an inode to be locked in a transaction, the inode lock, as 74 * opposed to the io lock, must be taken exclusively. This ensures 75 * that the inode can be involved in only 1 transaction at a time. 76 * Lock recursion is handled on the io lock, but only for lock modes 77 * of equal or lesser strength. That is, you can recur on the io lock 78 * held EXCL with a SHARED request but not vice versa. Also, if 79 * the inode is already a part of the transaction then you cannot 80 * go from not holding the io lock to having it EXCL or SHARED. 81 * 82 * Use the inode cache routine xfs_inode_incore() to find the inode 83 * if it is already owned by this transaction. 84 * 85 * If we don't already own the inode, use xfs_iget() to get it. 86 * Since the inode log item structure is embedded in the incore 87 * inode structure and is initialized when the inode is brought 88 * into memory, there is nothing to do with it here. 89 * 90 * If the given transaction pointer is NULL, just call xfs_iget(). 91 * This simplifies code which must handle both cases. 92 */ 93int 94xfs_trans_iget( 95 xfs_mount_t *mp, 96 xfs_trans_t *tp, 97 xfs_ino_t ino, 98 uint flags, 99 uint lock_flags, 100 xfs_inode_t **ipp) 101{ 102 int error; 103 xfs_inode_t *ip; 104 xfs_inode_log_item_t *iip; 105 106 /* 107 * If the transaction pointer is NULL, just call the normal 108 * xfs_iget(). 109 */ 110 if (tp == NULL) 111 return xfs_iget(mp, NULL, ino, flags, lock_flags, ipp, 0); 112 113 /* 114 * If we find the inode in core with this transaction 115 * pointer in its i_transp field, then we know we already 116 * have it locked. In this case we just increment the lock 117 * recursion count and return the inode to the caller. 118 * Assert that the inode is already locked in the mode requested 119 * by the caller. We cannot do lock promotions yet, so 120 * die if someone gets this wrong. 121 */ 122 if ((ip = xfs_inode_incore(tp->t_mountp, ino, tp)) != NULL) { 123 /* 124 * Make sure that the inode lock is held EXCL and 125 * that the io lock is never upgraded when the inode 126 * is already a part of the transaction. 127 */ 128 ASSERT(ip->i_itemp != NULL); 129 ASSERT(lock_flags & XFS_ILOCK_EXCL); 130 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); 131 ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) || 132 ismrlocked(&ip->i_iolock, MR_UPDATE)); 133 ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) || 134 (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_EXCL)); 135 ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) || 136 ismrlocked(&ip->i_iolock, (MR_UPDATE | MR_ACCESS))); 137 ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) || 138 (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_ANY)); 139 140 if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) { 141 ip->i_itemp->ili_iolock_recur++; 142 } 143 if (lock_flags & XFS_ILOCK_EXCL) { 144 ip->i_itemp->ili_ilock_recur++; 145 } 146 *ipp = ip; 147 return 0; 148 } 149 150 ASSERT(lock_flags & XFS_ILOCK_EXCL); 151 error = xfs_iget(tp->t_mountp, tp, ino, flags, lock_flags, &ip, 0); 152 if (error) { 153 return error; 154 } 155 ASSERT(ip != NULL); 156 157 /* 158 * Get a log_item_desc to point at the new item. 159 */ 160 if (ip->i_itemp == NULL) 161 xfs_inode_item_init(ip, mp); 162 iip = ip->i_itemp; 163 (void) xfs_trans_add_item(tp, (xfs_log_item_t *)(iip)); 164 165 xfs_trans_inode_broot_debug(ip); 166 167 /* 168 * If the IO lock has been acquired, mark that in 169 * the inode log item so we'll know to unlock it 170 * when the transaction commits. 171 */ 172 ASSERT(iip->ili_flags == 0); 173 if (lock_flags & XFS_IOLOCK_EXCL) { 174 iip->ili_flags |= XFS_ILI_IOLOCKED_EXCL; 175 } else if (lock_flags & XFS_IOLOCK_SHARED) { 176 iip->ili_flags |= XFS_ILI_IOLOCKED_SHARED; 177 } 178 179 /* 180 * Initialize i_transp so we can find it with xfs_inode_incore() 181 * above. 182 */ 183 ip->i_transp = tp; 184 185 *ipp = ip; 186 return 0; 187} 188 189/* 190 * Add the locked inode to the transaction. 191 * The inode must be locked, and it cannot be associated with any 192 * transaction. The caller must specify the locks already held 193 * on the inode. 194 */ 195void 196xfs_trans_ijoin( 197 xfs_trans_t *tp, 198 xfs_inode_t *ip, 199 uint lock_flags) 200{ 201 xfs_inode_log_item_t *iip; 202 203 ASSERT(ip->i_transp == NULL); 204 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); 205 ASSERT(lock_flags & XFS_ILOCK_EXCL); 206 if (ip->i_itemp == NULL) 207 xfs_inode_item_init(ip, ip->i_mount); 208 iip = ip->i_itemp; 209 ASSERT(iip->ili_flags == 0); 210 ASSERT(iip->ili_ilock_recur == 0); 211 ASSERT(iip->ili_iolock_recur == 0); 212 213 /* 214 * Get a log_item_desc to point at the new item. 215 */ 216 (void) xfs_trans_add_item(tp, (xfs_log_item_t*)(iip)); 217 218 xfs_trans_inode_broot_debug(ip); 219 220 /* 221 * If the IO lock is already held, mark that in the inode log item. 222 */ 223 if (lock_flags & XFS_IOLOCK_EXCL) { 224 iip->ili_flags |= XFS_ILI_IOLOCKED_EXCL; 225 } else if (lock_flags & XFS_IOLOCK_SHARED) { 226 iip->ili_flags |= XFS_ILI_IOLOCKED_SHARED; 227 } 228 229 /* 230 * Initialize i_transp so we can find it with xfs_inode_incore() 231 * in xfs_trans_iget() above. 232 */ 233 ip->i_transp = tp; 234} 235 236 237 238/* 239 * Mark the inode as not needing to be unlocked when the inode item's 240 * IOP_UNLOCK() routine is called. The inode must already be locked 241 * and associated with the given transaction. 242 */ 243/*ARGSUSED*/ 244void 245xfs_trans_ihold( 246 xfs_trans_t *tp, 247 xfs_inode_t *ip) 248{ 249 ASSERT(ip->i_transp == tp); 250 ASSERT(ip->i_itemp != NULL); 251 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); 252 253 ip->i_itemp->ili_flags |= XFS_ILI_HOLD; 254} 255 256/* 257 * Cancel the previous inode hold request made on this inode 258 * for this transaction. 259 */ 260/*ARGSUSED*/ 261void 262xfs_trans_ihold_release( 263 xfs_trans_t *tp, 264 xfs_inode_t *ip) 265{ 266 ASSERT(ip->i_transp == tp); 267 ASSERT(ip->i_itemp != NULL); 268 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); 269 ASSERT(ip->i_itemp->ili_flags & XFS_ILI_HOLD); 270 271 ip->i_itemp->ili_flags &= ~XFS_ILI_HOLD; 272} 273 274 275/* 276 * This is called to mark the fields indicated in fieldmask as needing 277 * to be logged when the transaction is committed. The inode must 278 * already be associated with the given transaction. 279 * 280 * The values for fieldmask are defined in xfs_inode_item.h. We always 281 * log all of the core inode if any of it has changed, and we always log 282 * all of the inline data/extents/b-tree root if any of them has changed. 283 */ 284void 285xfs_trans_log_inode( 286 xfs_trans_t *tp, 287 xfs_inode_t *ip, 288 uint flags) 289{ 290 xfs_log_item_desc_t *lidp; 291 292 ASSERT(ip->i_transp == tp); 293 ASSERT(ip->i_itemp != NULL); 294 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); 295 296 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp)); 297 ASSERT(lidp != NULL); 298 299 tp->t_flags |= XFS_TRANS_DIRTY; 300 lidp->lid_flags |= XFS_LID_DIRTY; 301 302 /* 303 * Always OR in the bits from the ili_last_fields field. 304 * This is to coordinate with the xfs_iflush() and xfs_iflush_done() 305 * routines in the eventual clearing of the ilf_fields bits. 306 * See the big comment in xfs_iflush() for an explanation of 307 * this coorination mechanism. 308 */ 309 flags |= ip->i_itemp->ili_last_fields; 310 ip->i_itemp->ili_format.ilf_fields |= flags; 311} 312 313#ifdef XFS_TRANS_DEBUG 314/* 315 * Keep track of the state of the inode btree root to make sure we 316 * log it properly. 317 */ 318STATIC void 319xfs_trans_inode_broot_debug( 320 xfs_inode_t *ip) 321{ 322 xfs_inode_log_item_t *iip; 323 324 ASSERT(ip->i_itemp != NULL); 325 iip = ip->i_itemp; 326 if (iip->ili_root_size != 0) { 327 ASSERT(iip->ili_orig_root != NULL); 328 kmem_free(iip->ili_orig_root, iip->ili_root_size); 329 iip->ili_root_size = 0; 330 iip->ili_orig_root = NULL; 331 } 332 if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) { 333 ASSERT((ip->i_df.if_broot != NULL) && 334 (ip->i_df.if_broot_bytes > 0)); 335 iip->ili_root_size = ip->i_df.if_broot_bytes; 336 iip->ili_orig_root = 337 (char*)kmem_alloc(iip->ili_root_size, KM_SLEEP); 338 memcpy(iip->ili_orig_root, (char*)(ip->i_df.if_broot), 339 iip->ili_root_size); 340 } 341} 342#endif