1153323Srodrigc/*
2159451Srodrigc * Copyright (c) 2000,2005 Silicon Graphics, Inc.
3159451Srodrigc * All Rights Reserved.
4153323Srodrigc *
5159451Srodrigc * This program is free software; you can redistribute it and/or
6159451Srodrigc * modify it under the terms of the GNU General Public License as
7153323Srodrigc * published by the Free Software Foundation.
8153323Srodrigc *
9159451Srodrigc * This program is distributed in the hope that it would be useful,
10159451Srodrigc * but WITHOUT ANY WARRANTY; without even the implied warranty of
11159451Srodrigc * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12159451Srodrigc * GNU General Public License for more details.
13153323Srodrigc *
14159451Srodrigc * You should have received a copy of the GNU General Public License
15159451Srodrigc * along with this program; if not, write the Free Software Foundation,
16159451Srodrigc * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17153323Srodrigc */
18153323Srodrigc#include "xfs.h"
19159451Srodrigc#include "xfs_fs.h"
20153323Srodrigc#include "xfs_types.h"
21159451Srodrigc#include "xfs_bit.h"
22159451Srodrigc#include "xfs_log.h"
23153323Srodrigc#include "xfs_inum.h"
24153323Srodrigc#include "xfs_trans.h"
25153323Srodrigc#include "xfs_sb.h"
26153323Srodrigc#include "xfs_ag.h"
27153323Srodrigc#include "xfs_dir.h"
28153323Srodrigc#include "xfs_dir2.h"
29153323Srodrigc#include "xfs_dmapi.h"
30153323Srodrigc#include "xfs_mount.h"
31159451Srodrigc#include "xfs_bmap_btree.h"
32153323Srodrigc#include "xfs_alloc_btree.h"
33153323Srodrigc#include "xfs_ialloc_btree.h"
34153323Srodrigc#include "xfs_dir_sf.h"
35153323Srodrigc#include "xfs_dir2_sf.h"
36159451Srodrigc#include "xfs_attr_sf.h"
37153323Srodrigc#include "xfs_dinode.h"
38159451Srodrigc#include "xfs_inode.h"
39159451Srodrigc#include "xfs_btree.h"
40159451Srodrigc#include "xfs_ialloc.h"
41159451Srodrigc#include "xfs_trans_priv.h"
42153323Srodrigc#include "xfs_inode_item.h"
43153323Srodrigc
44153323Srodrigc#ifdef XFS_TRANS_DEBUG
45153323SrodrigcSTATIC void
46153323Srodrigcxfs_trans_inode_broot_debug(
47153323Srodrigc	xfs_inode_t	*ip);
48153323Srodrigc#else
49153323Srodrigc#define	xfs_trans_inode_broot_debug(ip)
50153323Srodrigc#endif
51153323Srodrigc
52153323Srodrigc
53153323Srodrigc/*
54153323Srodrigc * Get and lock the inode for the caller if it is not already
55153323Srodrigc * locked within the given transaction.  If it is already locked
56153323Srodrigc * within the transaction, just increment its lock recursion count
57153323Srodrigc * and return a pointer to it.
58153323Srodrigc *
59153323Srodrigc * For an inode to be locked in a transaction, the inode lock, as
60153323Srodrigc * opposed to the io lock, must be taken exclusively.  This ensures
61153323Srodrigc * that the inode can be involved in only 1 transaction at a time.
62153323Srodrigc * Lock recursion is handled on the io lock, but only for lock modes
63153323Srodrigc * of equal or lesser strength.  That is, you can recur on the io lock
64153323Srodrigc * held EXCL with a SHARED request but not vice versa.  Also, if
65153323Srodrigc * the inode is already a part of the transaction then you cannot
66153323Srodrigc * go from not holding the io lock to having it EXCL or SHARED.
67153323Srodrigc *
68153323Srodrigc * Use the inode cache routine xfs_inode_incore() to find the inode
69153323Srodrigc * if it is already owned by this transaction.
70153323Srodrigc *
71153323Srodrigc * If we don't already own the inode, use xfs_iget() to get it.
72153323Srodrigc * Since the inode log item structure is embedded in the incore
73153323Srodrigc * inode structure and is initialized when the inode is brought
74153323Srodrigc * into memory, there is nothing to do with it here.
75153323Srodrigc *
76153323Srodrigc * If the given transaction pointer is NULL, just call xfs_iget().
77153323Srodrigc * This simplifies code which must handle both cases.
78153323Srodrigc */
79153323Srodrigcint
80153323Srodrigcxfs_trans_iget(
81153323Srodrigc	xfs_mount_t	*mp,
82153323Srodrigc	xfs_trans_t	*tp,
83153323Srodrigc	xfs_ino_t	ino,
84159451Srodrigc	uint		flags,
85153323Srodrigc	uint		lock_flags,
86153323Srodrigc	xfs_inode_t	**ipp)
87153323Srodrigc{
88153323Srodrigc	int			error;
89153323Srodrigc	xfs_inode_t		*ip;
90153323Srodrigc	xfs_inode_log_item_t	*iip;
91153323Srodrigc
92153323Srodrigc	/*
93153323Srodrigc	 * If the transaction pointer is NULL, just call the normal
94153323Srodrigc	 * xfs_iget().
95153323Srodrigc	 */
96159451Srodrigc	if (tp == NULL)
97159451Srodrigc		return xfs_iget(mp, NULL, ino, flags, lock_flags, ipp, 0);
98153323Srodrigc
99153323Srodrigc	/*
100153323Srodrigc	 * If we find the inode in core with this transaction
101153323Srodrigc	 * pointer in its i_transp field, then we know we already
102153323Srodrigc	 * have it locked.  In this case we just increment the lock
103153323Srodrigc	 * recursion count and return the inode to the caller.
104153323Srodrigc	 * Assert that the inode is already locked in the mode requested
105153323Srodrigc	 * by the caller.  We cannot do lock promotions yet, so
106153323Srodrigc	 * die if someone gets this wrong.
107153323Srodrigc	 */
108153323Srodrigc	if ((ip = xfs_inode_incore(tp->t_mountp, ino, tp)) != NULL) {
109153323Srodrigc		/*
110153323Srodrigc		 * Make sure that the inode lock is held EXCL and
111153323Srodrigc		 * that the io lock is never upgraded when the inode
112153323Srodrigc		 * is already a part of the transaction.
113153323Srodrigc		 */
114153323Srodrigc		ASSERT(ip->i_itemp != NULL);
115153323Srodrigc		ASSERT(lock_flags & XFS_ILOCK_EXCL);
116153323Srodrigc		ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
117153323Srodrigc		ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
118153323Srodrigc		       ismrlocked(&ip->i_iolock, MR_UPDATE));
119153323Srodrigc		ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
120153323Srodrigc		       (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_EXCL));
121153323Srodrigc		ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
122153323Srodrigc		       ismrlocked(&ip->i_iolock, (MR_UPDATE | MR_ACCESS)));
123153323Srodrigc		ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
124153323Srodrigc		       (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_ANY));
125153323Srodrigc
126153323Srodrigc		if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) {
127153323Srodrigc			ip->i_itemp->ili_iolock_recur++;
128153323Srodrigc		}
129153323Srodrigc		if (lock_flags & XFS_ILOCK_EXCL) {
130153323Srodrigc			ip->i_itemp->ili_ilock_recur++;
131153323Srodrigc		}
132153323Srodrigc		*ipp = ip;
133153323Srodrigc		return 0;
134153323Srodrigc	}
135153323Srodrigc
136153323Srodrigc	ASSERT(lock_flags & XFS_ILOCK_EXCL);
137159451Srodrigc	error = xfs_iget(tp->t_mountp, tp, ino, flags, lock_flags, &ip, 0);
138153323Srodrigc	if (error) {
139153323Srodrigc		return error;
140153323Srodrigc	}
141153323Srodrigc	ASSERT(ip != NULL);
142153323Srodrigc
143153323Srodrigc	/*
144153323Srodrigc	 * Get a log_item_desc to point at the new item.
145153323Srodrigc	 */
146153323Srodrigc	if (ip->i_itemp == NULL)
147153323Srodrigc		xfs_inode_item_init(ip, mp);
148153323Srodrigc	iip = ip->i_itemp;
149153323Srodrigc	(void) xfs_trans_add_item(tp, (xfs_log_item_t *)(iip));
150153323Srodrigc
151153323Srodrigc	xfs_trans_inode_broot_debug(ip);
152153323Srodrigc
153153323Srodrigc	/*
154153323Srodrigc	 * If the IO lock has been acquired, mark that in
155153323Srodrigc	 * the inode log item so we'll know to unlock it
156153323Srodrigc	 * when the transaction commits.
157153323Srodrigc	 */
158153323Srodrigc	ASSERT(iip->ili_flags == 0);
159153323Srodrigc	if (lock_flags & XFS_IOLOCK_EXCL) {
160153323Srodrigc		iip->ili_flags |= XFS_ILI_IOLOCKED_EXCL;
161153323Srodrigc	} else if (lock_flags & XFS_IOLOCK_SHARED) {
162153323Srodrigc		iip->ili_flags |= XFS_ILI_IOLOCKED_SHARED;
163153323Srodrigc	}
164153323Srodrigc
165153323Srodrigc	/*
166153323Srodrigc	 * Initialize i_transp so we can find it with xfs_inode_incore()
167153323Srodrigc	 * above.
168153323Srodrigc	 */
169153323Srodrigc	ip->i_transp = tp;
170153323Srodrigc
171153323Srodrigc	*ipp = ip;
172153323Srodrigc	return 0;
173153323Srodrigc}
174153323Srodrigc
175153323Srodrigc/*
176153323Srodrigc * Add the locked inode to the transaction.
177153323Srodrigc * The inode must be locked, and it cannot be associated with any
178153323Srodrigc * transaction.  The caller must specify the locks already held
179153323Srodrigc * on the inode.
180153323Srodrigc */
181153323Srodrigcvoid
182153323Srodrigcxfs_trans_ijoin(
183153323Srodrigc	xfs_trans_t	*tp,
184153323Srodrigc	xfs_inode_t	*ip,
185153323Srodrigc	uint		lock_flags)
186153323Srodrigc{
187153323Srodrigc	xfs_inode_log_item_t	*iip;
188153323Srodrigc
189153323Srodrigc	ASSERT(ip->i_transp == NULL);
190153323Srodrigc	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
191153323Srodrigc	ASSERT(lock_flags & XFS_ILOCK_EXCL);
192153323Srodrigc	if (ip->i_itemp == NULL)
193153323Srodrigc		xfs_inode_item_init(ip, ip->i_mount);
194153323Srodrigc	iip = ip->i_itemp;
195153323Srodrigc	ASSERT(iip->ili_flags == 0);
196153323Srodrigc	ASSERT(iip->ili_ilock_recur == 0);
197153323Srodrigc	ASSERT(iip->ili_iolock_recur == 0);
198153323Srodrigc
199153323Srodrigc	/*
200153323Srodrigc	 * Get a log_item_desc to point at the new item.
201153323Srodrigc	 */
202153323Srodrigc	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)(iip));
203153323Srodrigc
204153323Srodrigc	xfs_trans_inode_broot_debug(ip);
205153323Srodrigc
206153323Srodrigc	/*
207153323Srodrigc	 * If the IO lock is already held, mark that in the inode log item.
208153323Srodrigc	 */
209153323Srodrigc	if (lock_flags & XFS_IOLOCK_EXCL) {
210153323Srodrigc		iip->ili_flags |= XFS_ILI_IOLOCKED_EXCL;
211153323Srodrigc	} else if (lock_flags & XFS_IOLOCK_SHARED) {
212153323Srodrigc		iip->ili_flags |= XFS_ILI_IOLOCKED_SHARED;
213153323Srodrigc	}
214153323Srodrigc
215153323Srodrigc	/*
216153323Srodrigc	 * Initialize i_transp so we can find it with xfs_inode_incore()
217153323Srodrigc	 * in xfs_trans_iget() above.
218153323Srodrigc	 */
219153323Srodrigc	ip->i_transp = tp;
220153323Srodrigc}
221153323Srodrigc
222153323Srodrigc
223153323Srodrigc
224153323Srodrigc/*
225153323Srodrigc * Mark the inode as not needing to be unlocked when the inode item's
226153323Srodrigc * IOP_UNLOCK() routine is called.  The inode must already be locked
227153323Srodrigc * and associated with the given transaction.
228153323Srodrigc */
229153323Srodrigc/*ARGSUSED*/
230153323Srodrigcvoid
231153323Srodrigcxfs_trans_ihold(
232153323Srodrigc	xfs_trans_t	*tp,
233153323Srodrigc	xfs_inode_t	*ip)
234153323Srodrigc{
235153323Srodrigc	ASSERT(ip->i_transp == tp);
236153323Srodrigc	ASSERT(ip->i_itemp != NULL);
237153323Srodrigc	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
238153323Srodrigc
239153323Srodrigc	ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
240153323Srodrigc}
241153323Srodrigc
242153323Srodrigc
243153323Srodrigc/*
244153323Srodrigc * This is called to mark the fields indicated in fieldmask as needing
245153323Srodrigc * to be logged when the transaction is committed.  The inode must
246153323Srodrigc * already be associated with the given transaction.
247153323Srodrigc *
248153323Srodrigc * The values for fieldmask are defined in xfs_inode_item.h.  We always
249153323Srodrigc * log all of the core inode if any of it has changed, and we always log
250153323Srodrigc * all of the inline data/extents/b-tree root if any of them has changed.
251153323Srodrigc */
252153323Srodrigcvoid
253153323Srodrigcxfs_trans_log_inode(
254153323Srodrigc	xfs_trans_t	*tp,
255153323Srodrigc	xfs_inode_t	*ip,
256153323Srodrigc	uint		flags)
257153323Srodrigc{
258153323Srodrigc	xfs_log_item_desc_t	*lidp;
259153323Srodrigc
260153323Srodrigc	ASSERT(ip->i_transp == tp);
261153323Srodrigc	ASSERT(ip->i_itemp != NULL);
262153323Srodrigc	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
263153323Srodrigc
264153323Srodrigc	lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp));
265153323Srodrigc	ASSERT(lidp != NULL);
266153323Srodrigc
267153323Srodrigc	tp->t_flags |= XFS_TRANS_DIRTY;
268153323Srodrigc	lidp->lid_flags |= XFS_LID_DIRTY;
269153323Srodrigc
270153323Srodrigc	/*
271153323Srodrigc	 * Always OR in the bits from the ili_last_fields field.
272153323Srodrigc	 * This is to coordinate with the xfs_iflush() and xfs_iflush_done()
273153323Srodrigc	 * routines in the eventual clearing of the ilf_fields bits.
274153323Srodrigc	 * See the big comment in xfs_iflush() for an explanation of
275159451Srodrigc	 * this coordination mechanism.
276153323Srodrigc	 */
277153323Srodrigc	flags |= ip->i_itemp->ili_last_fields;
278153323Srodrigc	ip->i_itemp->ili_format.ilf_fields |= flags;
279153323Srodrigc}
280153323Srodrigc
281153323Srodrigc#ifdef XFS_TRANS_DEBUG
282153323Srodrigc/*
283153323Srodrigc * Keep track of the state of the inode btree root to make sure we
284153323Srodrigc * log it properly.
285153323Srodrigc */
286153323SrodrigcSTATIC void
287153323Srodrigcxfs_trans_inode_broot_debug(
288153323Srodrigc	xfs_inode_t	*ip)
289153323Srodrigc{
290153323Srodrigc	xfs_inode_log_item_t	*iip;
291153323Srodrigc
292153323Srodrigc	ASSERT(ip->i_itemp != NULL);
293153323Srodrigc	iip = ip->i_itemp;
294153323Srodrigc	if (iip->ili_root_size != 0) {
295153323Srodrigc		ASSERT(iip->ili_orig_root != NULL);
296153323Srodrigc		kmem_free(iip->ili_orig_root, iip->ili_root_size);
297153323Srodrigc		iip->ili_root_size = 0;
298153323Srodrigc		iip->ili_orig_root = NULL;
299153323Srodrigc	}
300153323Srodrigc	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
301153323Srodrigc		ASSERT((ip->i_df.if_broot != NULL) &&
302153323Srodrigc		       (ip->i_df.if_broot_bytes > 0));
303153323Srodrigc		iip->ili_root_size = ip->i_df.if_broot_bytes;
304153323Srodrigc		iip->ili_orig_root =
305153323Srodrigc			(char*)kmem_alloc(iip->ili_root_size, KM_SLEEP);
306153323Srodrigc		memcpy(iip->ili_orig_root, (char*)(ip->i_df.if_broot),
307153323Srodrigc		      iip->ili_root_size);
308153323Srodrigc	}
309153323Srodrigc}
310153323Srodrigc#endif
311