aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-11-13 11:15:30 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-11-13 11:15:30 -0500
commiteea2078eaf2bcd4e5e8b2e08798071efedac5e17 (patch)
treee8b9f7ea55f098c6c73d4bdca2794f40ce619476 /fs
parentea991f06d851d58268eac6ce5c2152397757c958 (diff)
parent050e714eb2bc662e9df6bf048ce86b4fbdd9bcd3 (diff)
Merge git://oss.sgi.com:8090/xfs/xfs-2.6
* git://oss.sgi.com:8090/xfs/xfs-2.6: [XFS] Remove KERNEL_VERSION macros from xfs_dmapi.h [XFS] Prevent a deadlock when xfslogd unpins inodes. [XFS] Clean up i_flags and i_flags_lock handling. [XFS] 956664: dm_read_invis() changes i_atime [XFS] rename uio_read() to xfs_uio_read() [XFS] Keep lockdep happy. [XFS] 956618: Linux crashes on boot with XFS-DMAPI filesystem when
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/Makefile-linux-2.617
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_dmapi_priv.h28
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c4
-rw-r--r--fs/xfs/support/debug.c4
-rw-r--r--fs/xfs/support/move.c2
-rw-r--r--fs/xfs/support/move.h2
-rw-r--r--fs/xfs/xfs.h23
-rw-r--r--fs/xfs/xfs_dir2.c2
-rw-r--r--fs/xfs/xfs_dmapi.h22
-rw-r--r--fs/xfs/xfs_iget.c51
-rw-r--r--fs/xfs/xfs_inode.c64
-rw-r--r--fs/xfs/xfs_inode.h41
-rw-r--r--fs/xfs/xfs_vnodeops.c33
15 files changed, 189 insertions, 113 deletions
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index 291948d5085a..b49989bb89ad 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -21,22 +21,7 @@ EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char
21XFS_LINUX := linux-2.6 21XFS_LINUX := linux-2.6
22 22
23ifeq ($(CONFIG_XFS_DEBUG),y) 23ifeq ($(CONFIG_XFS_DEBUG),y)
24 EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG 24 EXTRA_CFLAGS += -g
25 EXTRA_CFLAGS += -DXFS_BUF_LOCK_TRACKING
26endif
27ifeq ($(CONFIG_XFS_TRACE),y)
28 EXTRA_CFLAGS += -DXFS_ALLOC_TRACE
29 EXTRA_CFLAGS += -DXFS_ATTR_TRACE
30 EXTRA_CFLAGS += -DXFS_BLI_TRACE
31 EXTRA_CFLAGS += -DXFS_BMAP_TRACE
32 EXTRA_CFLAGS += -DXFS_BMBT_TRACE
33 EXTRA_CFLAGS += -DXFS_DIR2_TRACE
34 EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
35 EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
36 EXTRA_CFLAGS += -DXFS_LOG_TRACE
37 EXTRA_CFLAGS += -DXFS_RW_TRACE
38 EXTRA_CFLAGS += -DXFS_BUF_TRACE
39 EXTRA_CFLAGS += -DXFS_VNODE_TRACE
40endif 25endif
41 26
42obj-$(CONFIG_XFS_FS) += xfs.o 27obj-$(CONFIG_XFS_FS) += xfs.o
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index db5f5a3608ca..d3382843698e 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -15,6 +15,7 @@
15 * along with this program; if not, write the Free Software Foundation, 15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include "xfs.h"
18#include <linux/stddef.h> 19#include <linux/stddef.h>
19#include <linux/errno.h> 20#include <linux/errno.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
@@ -31,7 +32,6 @@
31#include <linux/kthread.h> 32#include <linux/kthread.h>
32#include <linux/migrate.h> 33#include <linux/migrate.h>
33#include <linux/backing-dev.h> 34#include <linux/backing-dev.h>
34#include "xfs_linux.h"
35 35
36STATIC kmem_zone_t *xfs_buf_zone; 36STATIC kmem_zone_t *xfs_buf_zone;
37STATIC kmem_shaker_t xfs_buf_shake; 37STATIC kmem_shaker_t xfs_buf_shake;
@@ -1406,7 +1406,7 @@ xfs_alloc_bufhash(
1406 btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ 1406 btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */
1407 btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; 1407 btp->bt_hashmask = (1 << btp->bt_hashshift) - 1;
1408 btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) * 1408 btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) *
1409 sizeof(xfs_bufhash_t), KM_SLEEP); 1409 sizeof(xfs_bufhash_t), KM_SLEEP | KM_LARGE);
1410 for (i = 0; i < (1 << btp->bt_hashshift); i++) { 1410 for (i = 0; i < (1 << btp->bt_hashshift); i++) {
1411 spin_lock_init(&btp->bt_hash[i].bh_lock); 1411 spin_lock_init(&btp->bt_hash[i].bh_lock);
1412 INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); 1412 INIT_LIST_HEAD(&btp->bt_hash[i].bh_list);
diff --git a/fs/xfs/linux-2.6/xfs_dmapi_priv.h b/fs/xfs/linux-2.6/xfs_dmapi_priv.h
new file mode 100644
index 000000000000..a8b0b1685eed
--- /dev/null
+++ b/fs/xfs/linux-2.6/xfs_dmapi_priv.h
@@ -0,0 +1,28 @@
1/*
2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef __XFS_DMAPI_PRIV_H__
19#define __XFS_DMAPI_PRIV_H__
20
21/*
22 * Based on IO_ISDIRECT, decide which i_ flag is set.
23 */
24#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
25 DM_FLAGS_IMUX : 0)
26#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX)
27
28#endif /*__XFS_DMAPI_PRIV_H__*/
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index a74f854d91e6..74d094829a4d 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -341,8 +341,11 @@ xfs_open_by_handle(
341 put_unused_fd(new_fd); 341 put_unused_fd(new_fd);
342 return -XFS_ERROR(-PTR_ERR(filp)); 342 return -XFS_ERROR(-PTR_ERR(filp));
343 } 343 }
344 if (inode->i_mode & S_IFREG) 344 if (inode->i_mode & S_IFREG) {
345 /* invisible operation should not change atime */
346 filp->f_flags |= O_NOATIME;
345 filp->f_op = &xfs_invis_file_operations; 347 filp->f_op = &xfs_invis_file_operations;
348 }
346 349
347 fd_install(new_fd, filp); 350 fd_install(new_fd, filp);
348 return new_fd; 351 return new_fd;
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 38c4d128a8c0..de05abbbe7fd 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -227,9 +227,7 @@ xfs_initialize_vnode(
227 xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); 227 xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
228 xfs_set_inodeops(inode); 228 xfs_set_inodeops(inode);
229 229
230 spin_lock(&ip->i_flags_lock); 230 xfs_iflags_clear(ip, XFS_INEW);
231 ip->i_flags &= ~XFS_INEW;
232 spin_unlock(&ip->i_flags_lock);
233 barrier(); 231 barrier();
234 232
235 unlock_new_inode(inode); 233 unlock_new_inode(inode);
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index c75f68361e33..4363512d2f90 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -15,11 +15,9 @@
15 * along with this program; if not, write the Free Software Foundation, 15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18#include <xfs.h>
18#include "debug.h" 19#include "debug.h"
19#include "spin.h" 20#include "spin.h"
20#include <asm/page.h>
21#include <linux/sched.h>
22#include <linux/kernel.h>
23 21
24static char message[256]; /* keep it off the stack */ 22static char message[256]; /* keep it off the stack */
25static DEFINE_SPINLOCK(xfs_err_lock); 23static DEFINE_SPINLOCK(xfs_err_lock);
diff --git a/fs/xfs/support/move.c b/fs/xfs/support/move.c
index caefa17b80fe..ac8617ca3909 100644
--- a/fs/xfs/support/move.c
+++ b/fs/xfs/support/move.c
@@ -22,7 +22,7 @@
22 * as we go. 22 * as we go.
23 */ 23 */
24int 24int
25uio_read(caddr_t src, size_t len, struct uio *uio) 25xfs_uio_read(caddr_t src, size_t len, struct uio *uio)
26{ 26{
27 size_t count; 27 size_t count;
28 28
diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h
index 97a2498d2da3..977879c24ff5 100644
--- a/fs/xfs/support/move.h
+++ b/fs/xfs/support/move.h
@@ -65,6 +65,6 @@ struct uio {
65typedef struct uio uio_t; 65typedef struct uio uio_t;
66typedef struct iovec iovec_t; 66typedef struct iovec iovec_t;
67 67
68extern int uio_read (caddr_t, size_t, uio_t *); 68extern int xfs_uio_read (caddr_t, size_t, uio_t *);
69 69
70#endif /* __XFS_SUPPORT_MOVE_H__ */ 70#endif /* __XFS_SUPPORT_MOVE_H__ */
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
index 1a48dbb902a7..bf0a12040b13 100644
--- a/fs/xfs/xfs.h
+++ b/fs/xfs/xfs.h
@@ -17,5 +17,28 @@
17 */ 17 */
18#ifndef __XFS_H__ 18#ifndef __XFS_H__
19#define __XFS_H__ 19#define __XFS_H__
20
21#ifdef CONFIG_XFS_DEBUG
22#define STATIC
23#define DEBUG 1
24#define XFS_BUF_LOCK_TRACKING 1
25/* #define QUOTADEBUG 1 */
26#endif
27
28#ifdef CONFIG_XFS_TRACE
29#define XFS_ALLOC_TRACE 1
30#define XFS_ATTR_TRACE 1
31#define XFS_BLI_TRACE 1
32#define XFS_BMAP_TRACE 1
33#define XFS_BMBT_TRACE 1
34#define XFS_DIR2_TRACE 1
35#define XFS_DQUOT_TRACE 1
36#define XFS_ILOCK_TRACE 1
37#define XFS_LOG_TRACE 1
38#define XFS_RW_TRACE 1
39#define XFS_BUF_TRACE 1
40#define XFS_VNODE_TRACE 1
41#endif
42
20#include <linux-2.6/xfs_linux.h> 43#include <linux-2.6/xfs_linux.h>
21#endif /* __XFS_H__ */ 44#endif /* __XFS_H__ */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 8edbe1adb95b..8e8e5279334a 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -678,7 +678,7 @@ xfs_dir2_put_dirent64_uio(
678 idbp->d_off = pa->cook; 678 idbp->d_off = pa->cook;
679 idbp->d_name[namelen] = '\0'; 679 idbp->d_name[namelen] = '\0';
680 memcpy(idbp->d_name, pa->name, namelen); 680 memcpy(idbp->d_name, pa->name, namelen);
681 rval = uio_read((caddr_t)idbp, reclen, uio); 681 rval = xfs_uio_read((caddr_t)idbp, reclen, uio);
682 pa->done = (rval == 0); 682 pa->done = (rval == 0);
683 return rval; 683 return rval;
684} 684}
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 4e7865ad6f0e..adc3d251240d 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -157,27 +157,9 @@ typedef enum {
157#define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ 157#define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */
158 158
159/* 159/*
160 * Based on IO_ISDIRECT, decide which i_ flag is set. 160 * Pull in platform specific event flags defines
161 */ 161 */
162#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) 162#include "xfs_dmapi_priv.h"
163#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
164 DM_FLAGS_IMUX : 0)
165#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX)
166#endif
167
168#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \
169 (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22))
170#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
171 DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_IMUX)
172#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX)
173#endif
174
175#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21)
176#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
177 0 : DM_FLAGS_IMUX)
178#define DM_SEM_FLAG_WR (DM_FLAGS_IMUX)
179#endif
180
181 163
182/* 164/*
183 * Macros to turn caller specified delay/block flags into 165 * Macros to turn caller specified delay/block flags into
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index b73d216ecaf9..c1c89dac19cc 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -215,7 +215,7 @@ again:
215 * If INEW is set this inode is being set up 215 * If INEW is set this inode is being set up
216 * we need to pause and try again. 216 * we need to pause and try again.
217 */ 217 */
218 if (ip->i_flags & XFS_INEW) { 218 if (xfs_iflags_test(ip, XFS_INEW)) {
219 read_unlock(&ih->ih_lock); 219 read_unlock(&ih->ih_lock);
220 delay(1); 220 delay(1);
221 XFS_STATS_INC(xs_ig_frecycle); 221 XFS_STATS_INC(xs_ig_frecycle);
@@ -230,22 +230,50 @@ again:
230 * on its way out of the system, 230 * on its way out of the system,
231 * we need to pause and try again. 231 * we need to pause and try again.
232 */ 232 */
233 if (ip->i_flags & XFS_IRECLAIM) { 233 if (xfs_iflags_test(ip, XFS_IRECLAIM)) {
234 read_unlock(&ih->ih_lock); 234 read_unlock(&ih->ih_lock);
235 delay(1); 235 delay(1);
236 XFS_STATS_INC(xs_ig_frecycle); 236 XFS_STATS_INC(xs_ig_frecycle);
237 237
238 goto again; 238 goto again;
239 } 239 }
240 ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE));
241
242 /*
243 * If lookup is racing with unlink, then we
244 * should return an error immediately so we
245 * don't remove it from the reclaim list and
246 * potentially leak the inode.
247 */
248 if ((ip->i_d.di_mode == 0) &&
249 !(flags & XFS_IGET_CREATE)) {
250 read_unlock(&ih->ih_lock);
251 return ENOENT;
252 }
253
254 /*
255 * There may be transactions sitting in the
256 * incore log buffers or being flushed to disk
257 * at this time. We can't clear the
258 * XFS_IRECLAIMABLE flag until these
259 * transactions have hit the disk, otherwise we
260 * will void the guarantee the flag provides
261 * xfs_iunpin()
262 */
263 if (xfs_ipincount(ip)) {
264 read_unlock(&ih->ih_lock);
265 xfs_log_force(mp, 0,
266 XFS_LOG_FORCE|XFS_LOG_SYNC);
267 XFS_STATS_INC(xs_ig_frecycle);
268 goto again;
269 }
240 270
241 vn_trace_exit(vp, "xfs_iget.alloc", 271 vn_trace_exit(vp, "xfs_iget.alloc",
242 (inst_t *)__return_address); 272 (inst_t *)__return_address);
243 273
244 XFS_STATS_INC(xs_ig_found); 274 XFS_STATS_INC(xs_ig_found);
245 275
246 spin_lock(&ip->i_flags_lock); 276 xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
247 ip->i_flags &= ~XFS_IRECLAIMABLE;
248 spin_unlock(&ip->i_flags_lock);
249 version = ih->ih_version; 277 version = ih->ih_version;
250 read_unlock(&ih->ih_lock); 278 read_unlock(&ih->ih_lock);
251 xfs_ihash_promote(ih, ip, version); 279 xfs_ihash_promote(ih, ip, version);
@@ -299,10 +327,7 @@ finish_inode:
299 if (lock_flags != 0) 327 if (lock_flags != 0)
300 xfs_ilock(ip, lock_flags); 328 xfs_ilock(ip, lock_flags);
301 329
302 spin_lock(&ip->i_flags_lock); 330 xfs_iflags_clear(ip, XFS_ISTALE);
303 ip->i_flags &= ~XFS_ISTALE;
304 spin_unlock(&ip->i_flags_lock);
305
306 vn_trace_exit(vp, "xfs_iget.found", 331 vn_trace_exit(vp, "xfs_iget.found",
307 (inst_t *)__return_address); 332 (inst_t *)__return_address);
308 goto return_ip; 333 goto return_ip;
@@ -371,10 +396,7 @@ finish_inode:
371 ih->ih_next = ip; 396 ih->ih_next = ip;
372 ip->i_udquot = ip->i_gdquot = NULL; 397 ip->i_udquot = ip->i_gdquot = NULL;
373 ih->ih_version++; 398 ih->ih_version++;
374 spin_lock(&ip->i_flags_lock); 399 xfs_iflags_set(ip, XFS_INEW);
375 ip->i_flags |= XFS_INEW;
376 spin_unlock(&ip->i_flags_lock);
377
378 write_unlock(&ih->ih_lock); 400 write_unlock(&ih->ih_lock);
379 401
380 /* 402 /*
@@ -625,7 +647,7 @@ xfs_iput_new(xfs_inode_t *ip,
625 vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); 647 vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
626 648
627 if ((ip->i_d.di_mode == 0)) { 649 if ((ip->i_d.di_mode == 0)) {
628 ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE)); 650 ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
629 vn_mark_bad(vp); 651 vn_mark_bad(vp);
630 } 652 }
631 if (inode->i_state & I_NEW) 653 if (inode->i_state & I_NEW)
@@ -683,6 +705,7 @@ xfs_ireclaim(xfs_inode_t *ip)
683 /* 705 /*
684 * Free all memory associated with the inode. 706 * Free all memory associated with the inode.
685 */ 707 */
708 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
686 xfs_idestroy(ip); 709 xfs_idestroy(ip);
687} 710}
688 711
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index c27d7d495aa0..d72c80dbfbb1 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2193,7 +2193,7 @@ xfs_ifree_cluster(
2193 /* Inode not in memory or we found it already, 2193 /* Inode not in memory or we found it already,
2194 * nothing to do 2194 * nothing to do
2195 */ 2195 */
2196 if (!ip || (ip->i_flags & XFS_ISTALE)) { 2196 if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
2197 read_unlock(&ih->ih_lock); 2197 read_unlock(&ih->ih_lock);
2198 continue; 2198 continue;
2199 } 2199 }
@@ -2215,10 +2215,7 @@ xfs_ifree_cluster(
2215 2215
2216 if (ip == free_ip) { 2216 if (ip == free_ip) {
2217 if (xfs_iflock_nowait(ip)) { 2217 if (xfs_iflock_nowait(ip)) {
2218 spin_lock(&ip->i_flags_lock); 2218 xfs_iflags_set(ip, XFS_ISTALE);
2219 ip->i_flags |= XFS_ISTALE;
2220 spin_unlock(&ip->i_flags_lock);
2221
2222 if (xfs_inode_clean(ip)) { 2219 if (xfs_inode_clean(ip)) {
2223 xfs_ifunlock(ip); 2220 xfs_ifunlock(ip);
2224 } else { 2221 } else {
@@ -2231,9 +2228,7 @@ xfs_ifree_cluster(
2231 2228
2232 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { 2229 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
2233 if (xfs_iflock_nowait(ip)) { 2230 if (xfs_iflock_nowait(ip)) {
2234 spin_lock(&ip->i_flags_lock); 2231 xfs_iflags_set(ip, XFS_ISTALE);
2235 ip->i_flags |= XFS_ISTALE;
2236 spin_unlock(&ip->i_flags_lock);
2237 2232
2238 if (xfs_inode_clean(ip)) { 2233 if (xfs_inode_clean(ip)) {
2239 xfs_ifunlock(ip); 2234 xfs_ifunlock(ip);
@@ -2263,9 +2258,7 @@ xfs_ifree_cluster(
2263 AIL_LOCK(mp,s); 2258 AIL_LOCK(mp,s);
2264 iip->ili_flush_lsn = iip->ili_item.li_lsn; 2259 iip->ili_flush_lsn = iip->ili_item.li_lsn;
2265 AIL_UNLOCK(mp, s); 2260 AIL_UNLOCK(mp, s);
2266 spin_lock(&iip->ili_inode->i_flags_lock); 2261 xfs_iflags_set(ip, XFS_ISTALE);
2267 iip->ili_inode->i_flags |= XFS_ISTALE;
2268 spin_unlock(&iip->ili_inode->i_flags_lock);
2269 pre_flushed++; 2262 pre_flushed++;
2270 } 2263 }
2271 lip = lip->li_bio_list; 2264 lip = lip->li_bio_list;
@@ -2748,42 +2741,39 @@ xfs_iunpin(
2748{ 2741{
2749 ASSERT(atomic_read(&ip->i_pincount) > 0); 2742 ASSERT(atomic_read(&ip->i_pincount) > 0);
2750 2743
2751 if (atomic_dec_and_test(&ip->i_pincount)) { 2744 if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) {
2745
2752 /* 2746 /*
2753 * If the inode is currently being reclaimed, the 2747 * If the inode is currently being reclaimed, the link between
2754 * linux inode _and_ the xfs vnode may have been 2748 * the bhv_vnode and the xfs_inode will be broken after the
2755 * freed so we cannot reference either of them safely. 2749 * XFS_IRECLAIM* flag is set. Hence, if these flags are not
2756 * Hence we should not try to do anything to them 2750 * set, then we can move forward and mark the linux inode dirty
2757 * if the xfs inode is currently in the reclaim 2751 * knowing that it is still valid as it won't freed until after
2758 * path. 2752 * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The
2753 * i_flags_lock is used to synchronise the setting of the
2754 * XFS_IRECLAIM* flags and the breaking of the link, and so we
2755 * can execute atomically w.r.t to reclaim by holding this lock
2756 * here.
2759 * 2757 *
2760 * However, we still need to issue the unpin wakeup 2758 * However, we still need to issue the unpin wakeup call as the
2761 * call as the inode reclaim may be blocked waiting for 2759 * inode reclaim may be blocked waiting for the inode to become
2762 * the inode to become unpinned. 2760 * unpinned.
2763 */ 2761 */
2764 struct inode *inode = NULL;
2765 2762
2766 spin_lock(&ip->i_flags_lock); 2763 if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) {
2767 if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
2768 bhv_vnode_t *vp = XFS_ITOV_NULL(ip); 2764 bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
2765 struct inode *inode = NULL;
2766
2767 BUG_ON(vp == NULL);
2768 inode = vn_to_inode(vp);
2769 BUG_ON(inode->i_state & I_CLEAR);
2769 2770
2770 /* make sync come back and flush this inode */ 2771 /* make sync come back and flush this inode */
2771 if (vp) { 2772 if (!(inode->i_state & (I_NEW|I_FREEING)))
2772 inode = vn_to_inode(vp); 2773 mark_inode_dirty_sync(inode);
2773
2774 if (!(inode->i_state &
2775 (I_NEW|I_FREEING|I_CLEAR))) {
2776 inode = igrab(inode);
2777 if (inode)
2778 mark_inode_dirty_sync(inode);
2779 } else
2780 inode = NULL;
2781 }
2782 } 2774 }
2783 spin_unlock(&ip->i_flags_lock); 2775 spin_unlock(&ip->i_flags_lock);
2784 wake_up(&ip->i_ipin_wait); 2776 wake_up(&ip->i_ipin_wait);
2785 if (inode)
2786 iput(inode);
2787 } 2777 }
2788} 2778}
2789 2779
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index e96eb0835fe6..bc823720d88f 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -305,6 +305,47 @@ typedef struct xfs_inode {
305#endif 305#endif
306} xfs_inode_t; 306} xfs_inode_t;
307 307
308
309/*
310 * i_flags helper functions
311 */
312static inline void
313__xfs_iflags_set(xfs_inode_t *ip, unsigned short flags)
314{
315 ip->i_flags |= flags;
316}
317
318static inline void
319xfs_iflags_set(xfs_inode_t *ip, unsigned short flags)
320{
321 spin_lock(&ip->i_flags_lock);
322 __xfs_iflags_set(ip, flags);
323 spin_unlock(&ip->i_flags_lock);
324}
325
326static inline void
327xfs_iflags_clear(xfs_inode_t *ip, unsigned short flags)
328{
329 spin_lock(&ip->i_flags_lock);
330 ip->i_flags &= ~flags;
331 spin_unlock(&ip->i_flags_lock);
332}
333
334static inline int
335__xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
336{
337 return (ip->i_flags & flags);
338}
339
340static inline int
341xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
342{
343 int ret;
344 spin_lock(&ip->i_flags_lock);
345 ret = __xfs_iflags_test(ip, flags);
346 spin_unlock(&ip->i_flags_lock);
347 return ret;
348}
308#endif /* __KERNEL__ */ 349#endif /* __KERNEL__ */
309 350
310 351
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 061e2ffdd1de..bda774a04b8f 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1013,7 +1013,7 @@ xfs_readlink(
1013 pathlen = (int)ip->i_d.di_size; 1013 pathlen = (int)ip->i_d.di_size;
1014 1014
1015 if (ip->i_df.if_flags & XFS_IFINLINE) { 1015 if (ip->i_df.if_flags & XFS_IFINLINE) {
1016 error = uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); 1016 error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
1017 } 1017 }
1018 else { 1018 else {
1019 /* 1019 /*
@@ -1044,7 +1044,7 @@ xfs_readlink(
1044 byte_cnt = pathlen; 1044 byte_cnt = pathlen;
1045 pathlen -= byte_cnt; 1045 pathlen -= byte_cnt;
1046 1046
1047 error = uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); 1047 error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
1048 xfs_buf_relse (bp); 1048 xfs_buf_relse (bp);
1049 } 1049 }
1050 1050
@@ -3827,11 +3827,16 @@ xfs_reclaim(
3827 */ 3827 */
3828 xfs_synchronize_atime(ip); 3828 xfs_synchronize_atime(ip);
3829 3829
3830 /* If we have nothing to flush with this inode then complete the 3830 /*
3831 * teardown now, otherwise break the link between the xfs inode 3831 * If we have nothing to flush with this inode then complete the
3832 * and the linux inode and clean up the xfs inode later. This 3832 * teardown now, otherwise break the link between the xfs inode and the
3833 * avoids flushing the inode to disk during the delete operation 3833 * linux inode and clean up the xfs inode later. This avoids flushing
3834 * itself. 3834 * the inode to disk during the delete operation itself.
3835 *
3836 * When breaking the link, we need to set the XFS_IRECLAIMABLE flag
3837 * first to ensure that xfs_iunpin() will never see an xfs inode
3838 * that has a linux inode being reclaimed. Synchronisation is provided
3839 * by the i_flags_lock.
3835 */ 3840 */
3836 if (!ip->i_update_core && (ip->i_itemp == NULL)) { 3841 if (!ip->i_update_core && (ip->i_itemp == NULL)) {
3837 xfs_ilock(ip, XFS_ILOCK_EXCL); 3842 xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -3840,13 +3845,13 @@ xfs_reclaim(
3840 } else { 3845 } else {
3841 xfs_mount_t *mp = ip->i_mount; 3846 xfs_mount_t *mp = ip->i_mount;
3842 3847
3843 /* Protect sync from us */ 3848 /* Protect sync and unpin from us */
3844 XFS_MOUNT_ILOCK(mp); 3849 XFS_MOUNT_ILOCK(mp);
3845 vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
3846 list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
3847 spin_lock(&ip->i_flags_lock); 3850 spin_lock(&ip->i_flags_lock);
3848 ip->i_flags |= XFS_IRECLAIMABLE; 3851 __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
3852 vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
3849 spin_unlock(&ip->i_flags_lock); 3853 spin_unlock(&ip->i_flags_lock);
3854 list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
3850 XFS_MOUNT_IUNLOCK(mp); 3855 XFS_MOUNT_IUNLOCK(mp);
3851 } 3856 }
3852 return 0; 3857 return 0;
@@ -3872,8 +3877,8 @@ xfs_finish_reclaim(
3872 */ 3877 */
3873 write_lock(&ih->ih_lock); 3878 write_lock(&ih->ih_lock);
3874 spin_lock(&ip->i_flags_lock); 3879 spin_lock(&ip->i_flags_lock);
3875 if ((ip->i_flags & XFS_IRECLAIM) || 3880 if (__xfs_iflags_test(ip, XFS_IRECLAIM) ||
3876 (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) { 3881 (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) {
3877 spin_unlock(&ip->i_flags_lock); 3882 spin_unlock(&ip->i_flags_lock);
3878 write_unlock(&ih->ih_lock); 3883 write_unlock(&ih->ih_lock);
3879 if (locked) { 3884 if (locked) {
@@ -3882,7 +3887,7 @@ xfs_finish_reclaim(
3882 } 3887 }
3883 return 1; 3888 return 1;
3884 } 3889 }
3885 ip->i_flags |= XFS_IRECLAIM; 3890 __xfs_iflags_set(ip, XFS_IRECLAIM);
3886 spin_unlock(&ip->i_flags_lock); 3891 spin_unlock(&ip->i_flags_lock);
3887 write_unlock(&ih->ih_lock); 3892 write_unlock(&ih->ih_lock);
3888 3893