aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-08-01 15:39:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-08-01 15:39:09 -0400
commitb8a327be3fbf05b5d3a935b4c03a3dcdb6db833e (patch)
tree96f4822dd4a1d5c43df5fe60382b6d39bbc2b671 /fs
parent46bd58eab21650fe820e4e3a27a6a134892cc2eb (diff)
parentf13fae2d2a9372a5155d20bc9da4c14f02193277 (diff)
Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-pull
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-pull: (64 commits) [XFS] Remove vn_revalidate calls in xfs. [XFS] Now that xfs_setattr is only used for attributes set from ->setattr [XFS] xfs_setattr currently doesn't just handle the attributes set through [XFS] fix use after free with external logs or real-time devices [XFS] A bug was found in xfs_bmap_add_extent_unwritten_real(). In a [XFS] fix compilation without CONFIG_PROC_FS [XFS] s/XFS_PURGE_INODE/IRELE/g s/VN_HOLD(XFS_ITOV())/IHOLD()/ [XFS] fix mount option parsing in remount [XFS] Disable queue flag test in barrier check. [XFS] streamline init/exit path [XFS] Fix up problem when CONFIG_XFS_POSIX_ACL is not set and yet we still [XFS] Don't assert if trying to mount with blocksize > pagesize [XFS] Don't update mtime on rename source [XFS] Allow xfs_bmbt_split() to fallback to the lowspace allocator [XFS] Restore the lowspace extent allocator algorithm [XFS] use minleft when allocating in xfs_bmbt_split() [XFS] attrmulti cleanup [XFS] Check for invalid flags in xfs_attrlist_by_handle. [XFS] Fix CI lookup in leaf-form directories [XFS] Use the generic xattr methods. ...
Diffstat (limited to 'fs')
-rw-r--r--fs/dcache.c102
-rw-r--r--fs/xfs/Makefile3
-rw-r--r--fs/xfs/linux-2.6/kmem.c6
-rw-r--r--fs/xfs/linux-2.6/kmem.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c14
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c376
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c345
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h8
-rw-r--r--fs/xfs/linux-2.6/xfs_stats.c15
-rw-r--r--fs/xfs/linux-2.6/xfs_stats.h12
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c938
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.c8
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c50
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h89
-rw-r--r--fs/xfs/linux-2.6/xfs_xattr.c330
-rw-r--r--fs/xfs/quota/xfs_dquot.c3
-rw-r--r--fs/xfs/quota/xfs_dquot.h2
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c4
-rw-r--r--fs/xfs/quota/xfs_qm.c24
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c12
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h3
-rw-r--r--fs/xfs/support/ktrace.c4
-rw-r--r--fs/xfs/support/uuid.c8
-rw-r--r--fs/xfs/support/uuid.h1
-rw-r--r--fs/xfs/xfs_acl.c21
-rw-r--r--fs/xfs/xfs_acl.h4
-rw-r--r--fs/xfs/xfs_attr.c608
-rw-r--r--fs/xfs/xfs_attr.h90
-rw-r--r--fs/xfs/xfs_attr_leaf.c99
-rw-r--r--fs/xfs/xfs_attr_leaf.h29
-rw-r--r--fs/xfs/xfs_attr_sf.h10
-rw-r--r--fs/xfs/xfs_bmap.c118
-rw-r--r--fs/xfs/xfs_bmap.h13
-rw-r--r--fs/xfs/xfs_bmap_btree.c76
-rw-r--r--fs/xfs/xfs_buf_item.c8
-rw-r--r--fs/xfs/xfs_clnt.h1
-rw-r--r--fs/xfs/xfs_da_btree.c48
-rw-r--r--fs/xfs/xfs_da_btree.h36
-rw-r--r--fs/xfs/xfs_dfrag.c4
-rw-r--r--fs/xfs/xfs_dir2.c125
-rw-r--r--fs/xfs/xfs_dir2.h6
-rw-r--r--fs/xfs/xfs_dir2_block.c56
-rw-r--r--fs/xfs/xfs_dir2_data.c5
-rw-r--r--fs/xfs/xfs_dir2_leaf.c93
-rw-r--r--fs/xfs/xfs_dir2_node.c402
-rw-r--r--fs/xfs/xfs_dir2_sf.c83
-rw-r--r--fs/xfs/xfs_dir2_sf.h6
-rw-r--r--fs/xfs/xfs_dir2_trace.c20
-rw-r--r--fs/xfs/xfs_dmapi.h2
-rw-r--r--fs/xfs/xfs_error.c13
-rw-r--r--fs/xfs/xfs_error.h1
-rw-r--r--fs/xfs/xfs_extfree_item.c6
-rw-r--r--fs/xfs/xfs_filestream.c4
-rw-r--r--fs/xfs/xfs_fs.h4
-rw-r--r--fs/xfs/xfs_fsops.c4
-rw-r--r--fs/xfs/xfs_inode.c165
-rw-r--r--fs/xfs/xfs_inode.h3
-rw-r--r--fs/xfs/xfs_inode_item.c7
-rw-r--r--fs/xfs/xfs_iomap.c10
-rw-r--r--fs/xfs/xfs_itable.c6
-rw-r--r--fs/xfs/xfs_log.c49
-rw-r--r--fs/xfs/xfs_log_priv.h6
-rw-r--r--fs/xfs/xfs_log_recover.c21
-rw-r--r--fs/xfs/xfs_mount.c118
-rw-r--r--fs/xfs/xfs_mount.h17
-rw-r--r--fs/xfs/xfs_mru_cache.c21
-rw-r--r--fs/xfs/xfs_rename.c22
-rw-r--r--fs/xfs/xfs_rtalloc.c2
-rw-r--r--fs/xfs/xfs_sb.h17
-rw-r--r--fs/xfs/xfs_trans.c4
-rw-r--r--fs/xfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/xfs_trans_item.c8
-rw-r--r--fs/xfs/xfs_vfsops.c610
-rw-r--r--fs/xfs/xfs_vfsops.h5
-rw-r--r--fs/xfs/xfs_vnodeops.c722
-rw-r--r--fs/xfs/xfs_vnodeops.h12
82 files changed, 3104 insertions, 3098 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index f2584d22cb45..101663d15e9f 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1220,6 +1220,107 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
1220 return new; 1220 return new;
1221} 1221}
1222 1222
1223/**
1224 * d_add_ci - lookup or allocate new dentry with case-exact name
1225 * @inode: the inode case-insensitive lookup has found
1226 * @dentry: the negative dentry that was passed to the parent's lookup func
1227 * @name: the case-exact name to be associated with the returned dentry
1228 *
1229 * This is to avoid filling the dcache with case-insensitive names to the
1230 * same inode, only the actual correct case is stored in the dcache for
1231 * case-insensitive filesystems.
1232 *
1233 * For a case-insensitive lookup match and if the the case-exact dentry
1234 * already exists in in the dcache, use it and return it.
1235 *
1236 * If no entry exists with the exact case name, allocate new dentry with
1237 * the exact case, and return the spliced entry.
1238 */
1239struct dentry *d_add_ci(struct inode *inode, struct dentry *dentry,
1240 struct qstr *name)
1241{
1242 int error;
1243 struct dentry *found;
1244 struct dentry *new;
1245
1246 /* Does a dentry matching the name exist already? */
1247 found = d_hash_and_lookup(dentry->d_parent, name);
1248 /* If not, create it now and return */
1249 if (!found) {
1250 new = d_alloc(dentry->d_parent, name);
1251 if (!new) {
1252 error = -ENOMEM;
1253 goto err_out;
1254 }
1255 found = d_splice_alias(inode, new);
1256 if (found) {
1257 dput(new);
1258 return found;
1259 }
1260 return new;
1261 }
1262 /* Matching dentry exists, check if it is negative. */
1263 if (found->d_inode) {
1264 if (unlikely(found->d_inode != inode)) {
1265 /* This can't happen because bad inodes are unhashed. */
1266 BUG_ON(!is_bad_inode(inode));
1267 BUG_ON(!is_bad_inode(found->d_inode));
1268 }
1269 /*
1270 * Already have the inode and the dentry attached, decrement
1271 * the reference count to balance the iget() done
1272 * earlier on. We found the dentry using d_lookup() so it
1273 * cannot be disconnected and thus we do not need to worry
1274 * about any NFS/disconnectedness issues here.
1275 */
1276 iput(inode);
1277 return found;
1278 }
1279 /*
1280 * Negative dentry: instantiate it unless the inode is a directory and
1281 * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED),
1282 * in which case d_move() that in place of the found dentry.
1283 */
1284 if (!S_ISDIR(inode->i_mode)) {
1285 /* Not a directory; everything is easy. */
1286 d_instantiate(found, inode);
1287 return found;
1288 }
1289 spin_lock(&dcache_lock);
1290 if (list_empty(&inode->i_dentry)) {
1291 /*
1292 * Directory without a 'disconnected' dentry; we need to do
1293 * d_instantiate() by hand because it takes dcache_lock which
1294 * we already hold.
1295 */
1296 list_add(&found->d_alias, &inode->i_dentry);
1297 found->d_inode = inode;
1298 spin_unlock(&dcache_lock);
1299 security_d_instantiate(found, inode);
1300 return found;
1301 }
1302 /*
1303 * Directory with a 'disconnected' dentry; get a reference to the
1304 * 'disconnected' dentry.
1305 */
1306 new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
1307 dget_locked(new);
1308 spin_unlock(&dcache_lock);
1309 /* Do security vodoo. */
1310 security_d_instantiate(found, inode);
1311 /* Move new in place of found. */
1312 d_move(new, found);
1313 /* Balance the iget() we did above. */
1314 iput(inode);
1315 /* Throw away found. */
1316 dput(found);
1317 /* Use new as the actual dentry. */
1318 return new;
1319
1320err_out:
1321 iput(inode);
1322 return ERR_PTR(error);
1323}
1223 1324
1224/** 1325/**
1225 * d_lookup - search for a dentry 1326 * d_lookup - search for a dentry
@@ -2254,6 +2355,7 @@ EXPORT_SYMBOL(d_path);
2254EXPORT_SYMBOL(d_prune_aliases); 2355EXPORT_SYMBOL(d_prune_aliases);
2255EXPORT_SYMBOL(d_rehash); 2356EXPORT_SYMBOL(d_rehash);
2256EXPORT_SYMBOL(d_splice_alias); 2357EXPORT_SYMBOL(d_splice_alias);
2358EXPORT_SYMBOL(d_add_ci);
2257EXPORT_SYMBOL(d_validate); 2359EXPORT_SYMBOL(d_validate);
2258EXPORT_SYMBOL(dget_locked); 2360EXPORT_SYMBOL(dget_locked);
2259EXPORT_SYMBOL(dput); 2361EXPORT_SYMBOL(dput);
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 36ec614e699a..737c9a425361 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -106,7 +106,8 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
106 xfs_iops.o \ 106 xfs_iops.o \
107 xfs_lrw.o \ 107 xfs_lrw.o \
108 xfs_super.o \ 108 xfs_super.o \
109 xfs_vnode.o) 109 xfs_vnode.o \
110 xfs_xattr.o)
110 111
111# Objects in support/ 112# Objects in support/
112xfs-y += $(addprefix support/, \ 113xfs-y += $(addprefix support/, \
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
index 9b1bb17a0501..1cd3b55ee3d2 100644
--- a/fs/xfs/linux-2.6/kmem.c
+++ b/fs/xfs/linux-2.6/kmem.c
@@ -90,7 +90,7 @@ kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize,
90} 90}
91 91
92void 92void
93kmem_free(void *ptr, size_t size) 93kmem_free(const void *ptr)
94{ 94{
95 if (!is_vmalloc_addr(ptr)) { 95 if (!is_vmalloc_addr(ptr)) {
96 kfree(ptr); 96 kfree(ptr);
@@ -100,7 +100,7 @@ kmem_free(void *ptr, size_t size)
100} 100}
101 101
102void * 102void *
103kmem_realloc(void *ptr, size_t newsize, size_t oldsize, 103kmem_realloc(const void *ptr, size_t newsize, size_t oldsize,
104 unsigned int __nocast flags) 104 unsigned int __nocast flags)
105{ 105{
106 void *new; 106 void *new;
@@ -110,7 +110,7 @@ kmem_realloc(void *ptr, size_t newsize, size_t oldsize,
110 if (new) 110 if (new)
111 memcpy(new, ptr, 111 memcpy(new, ptr,
112 ((oldsize < newsize) ? oldsize : newsize)); 112 ((oldsize < newsize) ? oldsize : newsize));
113 kmem_free(ptr, oldsize); 113 kmem_free(ptr);
114 } 114 }
115 return new; 115 return new;
116} 116}
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index a20683cf74dd..af6843c7ee4b 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -57,8 +57,8 @@ kmem_flags_convert(unsigned int __nocast flags)
57extern void *kmem_alloc(size_t, unsigned int __nocast); 57extern void *kmem_alloc(size_t, unsigned int __nocast);
58extern void *kmem_zalloc(size_t, unsigned int __nocast); 58extern void *kmem_zalloc(size_t, unsigned int __nocast);
59extern void *kmem_zalloc_greedy(size_t *, size_t, size_t, unsigned int __nocast); 59extern void *kmem_zalloc_greedy(size_t *, size_t, size_t, unsigned int __nocast);
60extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast); 60extern void *kmem_realloc(const void *, size_t, size_t, unsigned int __nocast);
61extern void kmem_free(void *, size_t); 61extern void kmem_free(const void *);
62 62
63/* 63/*
64 * Zone interfaces 64 * Zone interfaces
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index a55c3b26d840..0b211cba1909 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -409,7 +409,6 @@ xfs_start_buffer_writeback(
409STATIC void 409STATIC void
410xfs_start_page_writeback( 410xfs_start_page_writeback(
411 struct page *page, 411 struct page *page,
412 struct writeback_control *wbc,
413 int clear_dirty, 412 int clear_dirty,
414 int buffers) 413 int buffers)
415{ 414{
@@ -858,7 +857,7 @@ xfs_convert_page(
858 done = 1; 857 done = 1;
859 } 858 }
860 } 859 }
861 xfs_start_page_writeback(page, wbc, !page_dirty, count); 860 xfs_start_page_writeback(page, !page_dirty, count);
862 } 861 }
863 862
864 return done; 863 return done;
@@ -1130,7 +1129,7 @@ xfs_page_state_convert(
1130 SetPageUptodate(page); 1129 SetPageUptodate(page);
1131 1130
1132 if (startio) 1131 if (startio)
1133 xfs_start_page_writeback(page, wbc, 1, count); 1132 xfs_start_page_writeback(page, 1, count);
1134 1133
1135 if (ioend && iomap_valid) { 1134 if (ioend && iomap_valid) {
1136 offset = (iomap.iomap_offset + iomap.iomap_bsize - 1) >> 1135 offset = (iomap.iomap_offset + iomap.iomap_bsize - 1) >>
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 98e0e86093b4..9cc8f0213095 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -310,8 +310,7 @@ _xfs_buf_free_pages(
310 xfs_buf_t *bp) 310 xfs_buf_t *bp)
311{ 311{
312 if (bp->b_pages != bp->b_page_array) { 312 if (bp->b_pages != bp->b_page_array) {
313 kmem_free(bp->b_pages, 313 kmem_free(bp->b_pages);
314 bp->b_page_count * sizeof(struct page *));
315 } 314 }
316} 315}
317 316
@@ -1398,7 +1397,7 @@ STATIC void
1398xfs_free_bufhash( 1397xfs_free_bufhash(
1399 xfs_buftarg_t *btp) 1398 xfs_buftarg_t *btp)
1400{ 1399{
1401 kmem_free(btp->bt_hash, (1<<btp->bt_hashshift) * sizeof(xfs_bufhash_t)); 1400 kmem_free(btp->bt_hash);
1402 btp->bt_hash = NULL; 1401 btp->bt_hash = NULL;
1403} 1402}
1404 1403
@@ -1428,13 +1427,10 @@ xfs_unregister_buftarg(
1428 1427
1429void 1428void
1430xfs_free_buftarg( 1429xfs_free_buftarg(
1431 xfs_buftarg_t *btp, 1430 xfs_buftarg_t *btp)
1432 int external)
1433{ 1431{
1434 xfs_flush_buftarg(btp, 1); 1432 xfs_flush_buftarg(btp, 1);
1435 xfs_blkdev_issue_flush(btp); 1433 xfs_blkdev_issue_flush(btp);
1436 if (external)
1437 xfs_blkdev_put(btp->bt_bdev);
1438 xfs_free_bufhash(btp); 1434 xfs_free_bufhash(btp);
1439 iput(btp->bt_mapping->host); 1435 iput(btp->bt_mapping->host);
1440 1436
@@ -1444,7 +1440,7 @@ xfs_free_buftarg(
1444 xfs_unregister_buftarg(btp); 1440 xfs_unregister_buftarg(btp);
1445 kthread_stop(btp->bt_task); 1441 kthread_stop(btp->bt_task);
1446 1442
1447 kmem_free(btp, sizeof(*btp)); 1443 kmem_free(btp);
1448} 1444}
1449 1445
1450STATIC int 1446STATIC int
@@ -1575,7 +1571,7 @@ xfs_alloc_buftarg(
1575 return btp; 1571 return btp;
1576 1572
1577error: 1573error:
1578 kmem_free(btp, sizeof(*btp)); 1574 kmem_free(btp);
1579 return NULL; 1575 return NULL;
1580} 1576}
1581 1577
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index f948ec7ba9a4..29d1d4adc078 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -429,7 +429,7 @@ static inline void xfs_bdwrite(void *mp, xfs_buf_t *bp)
429 * Handling of buftargs. 429 * Handling of buftargs.
430 */ 430 */
431extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int); 431extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
432extern void xfs_free_buftarg(xfs_buftarg_t *, int); 432extern void xfs_free_buftarg(xfs_buftarg_t *);
433extern void xfs_wait_buftarg(xfs_buftarg_t *); 433extern void xfs_wait_buftarg(xfs_buftarg_t *);
434extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); 434extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
435extern int xfs_flush_buftarg(xfs_buftarg_t *, int); 435extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index c672b3238b14..987fe84f7b13 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -215,7 +215,7 @@ xfs_fs_get_parent(
215 struct xfs_inode *cip; 215 struct xfs_inode *cip;
216 struct dentry *parent; 216 struct dentry *parent;
217 217
218 error = xfs_lookup(XFS_I(child->d_inode), &xfs_name_dotdot, &cip); 218 error = xfs_lookup(XFS_I(child->d_inode), &xfs_name_dotdot, &cip, NULL);
219 if (unlikely(error)) 219 if (unlikely(error))
220 return ERR_PTR(-error); 220 return ERR_PTR(-error);
221 221
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 01939ba2d8de..acb978d9d085 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -48,6 +48,8 @@
48#include "xfs_dfrag.h" 48#include "xfs_dfrag.h"
49#include "xfs_fsops.h" 49#include "xfs_fsops.h"
50#include "xfs_vnodeops.h" 50#include "xfs_vnodeops.h"
51#include "xfs_quota.h"
52#include "xfs_inode_item.h"
51 53
52#include <linux/capability.h> 54#include <linux/capability.h>
53#include <linux/dcache.h> 55#include <linux/dcache.h>
@@ -468,6 +470,12 @@ xfs_attrlist_by_handle(
468 if (al_hreq.buflen > XATTR_LIST_MAX) 470 if (al_hreq.buflen > XATTR_LIST_MAX)
469 return -XFS_ERROR(EINVAL); 471 return -XFS_ERROR(EINVAL);
470 472
473 /*
474 * Reject flags, only allow namespaces.
475 */
476 if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE))
477 return -XFS_ERROR(EINVAL);
478
471 error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq, &inode); 479 error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq, &inode);
472 if (error) 480 if (error)
473 goto out; 481 goto out;
@@ -587,7 +595,7 @@ xfs_attrmulti_by_handle(
587 goto out; 595 goto out;
588 596
589 error = E2BIG; 597 error = E2BIG;
590 size = am_hreq.opcount * sizeof(attr_multiop_t); 598 size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
591 if (!size || size > 16 * PAGE_SIZE) 599 if (!size || size > 16 * PAGE_SIZE)
592 goto out_vn_rele; 600 goto out_vn_rele;
593 601
@@ -680,9 +688,9 @@ xfs_ioc_space(
680 return -XFS_ERROR(EFAULT); 688 return -XFS_ERROR(EFAULT);
681 689
682 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 690 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
683 attr_flags |= ATTR_NONBLOCK; 691 attr_flags |= XFS_ATTR_NONBLOCK;
684 if (ioflags & IO_INVIS) 692 if (ioflags & IO_INVIS)
685 attr_flags |= ATTR_DMI; 693 attr_flags |= XFS_ATTR_DMI;
686 694
687 error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos, 695 error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos,
688 NULL, attr_flags); 696 NULL, attr_flags);
@@ -873,6 +881,322 @@ xfs_ioc_fsgetxattr(
873 return 0; 881 return 0;
874} 882}
875 883
884STATIC void
885xfs_set_diflags(
886 struct xfs_inode *ip,
887 unsigned int xflags)
888{
889 unsigned int di_flags;
890
891 /* can't set PREALLOC this way, just preserve it */
892 di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
893 if (xflags & XFS_XFLAG_IMMUTABLE)
894 di_flags |= XFS_DIFLAG_IMMUTABLE;
895 if (xflags & XFS_XFLAG_APPEND)
896 di_flags |= XFS_DIFLAG_APPEND;
897 if (xflags & XFS_XFLAG_SYNC)
898 di_flags |= XFS_DIFLAG_SYNC;
899 if (xflags & XFS_XFLAG_NOATIME)
900 di_flags |= XFS_DIFLAG_NOATIME;
901 if (xflags & XFS_XFLAG_NODUMP)
902 di_flags |= XFS_DIFLAG_NODUMP;
903 if (xflags & XFS_XFLAG_PROJINHERIT)
904 di_flags |= XFS_DIFLAG_PROJINHERIT;
905 if (xflags & XFS_XFLAG_NODEFRAG)
906 di_flags |= XFS_DIFLAG_NODEFRAG;
907 if (xflags & XFS_XFLAG_FILESTREAM)
908 di_flags |= XFS_DIFLAG_FILESTREAM;
909 if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
910 if (xflags & XFS_XFLAG_RTINHERIT)
911 di_flags |= XFS_DIFLAG_RTINHERIT;
912 if (xflags & XFS_XFLAG_NOSYMLINKS)
913 di_flags |= XFS_DIFLAG_NOSYMLINKS;
914 if (xflags & XFS_XFLAG_EXTSZINHERIT)
915 di_flags |= XFS_DIFLAG_EXTSZINHERIT;
916 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
917 if (xflags & XFS_XFLAG_REALTIME)
918 di_flags |= XFS_DIFLAG_REALTIME;
919 if (xflags & XFS_XFLAG_EXTSIZE)
920 di_flags |= XFS_DIFLAG_EXTSIZE;
921 }
922
923 ip->i_d.di_flags = di_flags;
924}
925
926STATIC void
927xfs_diflags_to_linux(
928 struct xfs_inode *ip)
929{
930 struct inode *inode = XFS_ITOV(ip);
931 unsigned int xflags = xfs_ip2xflags(ip);
932
933 if (xflags & XFS_XFLAG_IMMUTABLE)
934 inode->i_flags |= S_IMMUTABLE;
935 else
936 inode->i_flags &= ~S_IMMUTABLE;
937 if (xflags & XFS_XFLAG_APPEND)
938 inode->i_flags |= S_APPEND;
939 else
940 inode->i_flags &= ~S_APPEND;
941 if (xflags & XFS_XFLAG_SYNC)
942 inode->i_flags |= S_SYNC;
943 else
944 inode->i_flags &= ~S_SYNC;
945 if (xflags & XFS_XFLAG_NOATIME)
946 inode->i_flags |= S_NOATIME;
947 else
948 inode->i_flags &= ~S_NOATIME;
949}
950
951#define FSX_PROJID 1
952#define FSX_EXTSIZE 2
953#define FSX_XFLAGS 4
954#define FSX_NONBLOCK 8
955
956STATIC int
957xfs_ioctl_setattr(
958 xfs_inode_t *ip,
959 struct fsxattr *fa,
960 int mask)
961{
962 struct xfs_mount *mp = ip->i_mount;
963 struct xfs_trans *tp;
964 unsigned int lock_flags = 0;
965 struct xfs_dquot *udqp = NULL, *gdqp = NULL;
966 struct xfs_dquot *olddquot = NULL;
967 int code;
968
969 xfs_itrace_entry(ip);
970
971 if (mp->m_flags & XFS_MOUNT_RDONLY)
972 return XFS_ERROR(EROFS);
973 if (XFS_FORCED_SHUTDOWN(mp))
974 return XFS_ERROR(EIO);
975
976 /*
977 * If disk quotas is on, we make sure that the dquots do exist on disk,
978 * before we start any other transactions. Trying to do this later
979 * is messy. We don't care to take a readlock to look at the ids
980 * in inode here, because we can't hold it across the trans_reserve.
981 * If the IDs do change before we take the ilock, we're covered
982 * because the i_*dquot fields will get updated anyway.
983 */
984 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
985 code = XFS_QM_DQVOPALLOC(mp, ip, ip->i_d.di_uid,
986 ip->i_d.di_gid, fa->fsx_projid,
987 XFS_QMOPT_PQUOTA, &udqp, &gdqp);
988 if (code)
989 return code;
990 }
991
992 /*
993 * For the other attributes, we acquire the inode lock and
994 * first do an error checking pass.
995 */
996 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
997 code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
998 if (code)
999 goto error_return;
1000
1001 lock_flags = XFS_ILOCK_EXCL;
1002 xfs_ilock(ip, lock_flags);
1003
1004 /*
1005 * CAP_FOWNER overrides the following restrictions:
1006 *
1007 * The user ID of the calling process must be equal
1008 * to the file owner ID, except in cases where the
1009 * CAP_FSETID capability is applicable.
1010 */
1011 if (current->fsuid != ip->i_d.di_uid && !capable(CAP_FOWNER)) {
1012 code = XFS_ERROR(EPERM);
1013 goto error_return;
1014 }
1015
1016 /*
1017 * Do a quota reservation only if projid is actually going to change.
1018 */
1019 if (mask & FSX_PROJID) {
1020 if (XFS_IS_PQUOTA_ON(mp) &&
1021 ip->i_d.di_projid != fa->fsx_projid) {
1022 ASSERT(tp);
1023 code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
1024 capable(CAP_FOWNER) ?
1025 XFS_QMOPT_FORCE_RES : 0);
1026 if (code) /* out of quota */
1027 goto error_return;
1028 }
1029 }
1030
1031 if (mask & FSX_EXTSIZE) {
1032 /*
1033 * Can't change extent size if any extents are allocated.
1034 */
1035 if (ip->i_d.di_nextents &&
1036 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
1037 fa->fsx_extsize)) {
1038 code = XFS_ERROR(EINVAL); /* EFBIG? */
1039 goto error_return;
1040 }
1041
1042 /*
1043 * Extent size must be a multiple of the appropriate block
1044 * size, if set at all.
1045 */
1046 if (fa->fsx_extsize != 0) {
1047 xfs_extlen_t size;
1048
1049 if (XFS_IS_REALTIME_INODE(ip) ||
1050 ((mask & FSX_XFLAGS) &&
1051 (fa->fsx_xflags & XFS_XFLAG_REALTIME))) {
1052 size = mp->m_sb.sb_rextsize <<
1053 mp->m_sb.sb_blocklog;
1054 } else {
1055 size = mp->m_sb.sb_blocksize;
1056 }
1057
1058 if (fa->fsx_extsize % size) {
1059 code = XFS_ERROR(EINVAL);
1060 goto error_return;
1061 }
1062 }
1063 }
1064
1065
1066 if (mask & FSX_XFLAGS) {
1067 /*
1068 * Can't change realtime flag if any extents are allocated.
1069 */
1070 if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
1071 (XFS_IS_REALTIME_INODE(ip)) !=
1072 (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1073 code = XFS_ERROR(EINVAL); /* EFBIG? */
1074 goto error_return;
1075 }
1076
1077 /*
1078 * If realtime flag is set then must have realtime data.
1079 */
1080 if ((fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1081 if ((mp->m_sb.sb_rblocks == 0) ||
1082 (mp->m_sb.sb_rextsize == 0) ||
1083 (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
1084 code = XFS_ERROR(EINVAL);
1085 goto error_return;
1086 }
1087 }
1088
1089 /*
1090 * Can't modify an immutable/append-only file unless
1091 * we have appropriate permission.
1092 */
1093 if ((ip->i_d.di_flags &
1094 (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
1095 (fa->fsx_xflags &
1096 (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
1097 !capable(CAP_LINUX_IMMUTABLE)) {
1098 code = XFS_ERROR(EPERM);
1099 goto error_return;
1100 }
1101 }
1102
1103 xfs_trans_ijoin(tp, ip, lock_flags);
1104 xfs_trans_ihold(tp, ip);
1105
1106 /*
1107 * Change file ownership. Must be the owner or privileged.
1108 * If the system was configured with the "restricted_chown"
1109 * option, the owner is not permitted to give away the file,
1110 * and can change the group id only to a group of which he
1111 * or she is a member.
1112 */
1113 if (mask & FSX_PROJID) {
1114 /*
1115 * CAP_FSETID overrides the following restrictions:
1116 *
1117 * The set-user-ID and set-group-ID bits of a file will be
1118 * cleared upon successful return from chown()
1119 */
1120 if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
1121 !capable(CAP_FSETID))
1122 ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
1123
1124 /*
1125 * Change the ownerships and register quota modifications
1126 * in the transaction.
1127 */
1128 if (ip->i_d.di_projid != fa->fsx_projid) {
1129 if (XFS_IS_PQUOTA_ON(mp)) {
1130 olddquot = XFS_QM_DQVOPCHOWN(mp, tp, ip,
1131 &ip->i_gdquot, gdqp);
1132 }
1133 ip->i_d.di_projid = fa->fsx_projid;
1134
1135 /*
1136 * We may have to rev the inode as well as
1137 * the superblock version number since projids didn't
1138 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
1139 */
1140 if (ip->i_d.di_version == XFS_DINODE_VERSION_1)
1141 xfs_bump_ino_vers2(tp, ip);
1142 }
1143
1144 }
1145
1146 if (mask & FSX_EXTSIZE)
1147 ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
1148 if (mask & FSX_XFLAGS) {
1149 xfs_set_diflags(ip, fa->fsx_xflags);
1150 xfs_diflags_to_linux(ip);
1151 }
1152
1153 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1154 xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
1155
1156 XFS_STATS_INC(xs_ig_attrchg);
1157
1158 /*
1159 * If this is a synchronous mount, make sure that the
1160 * transaction goes to disk before returning to the user.
1161 * This is slightly sub-optimal in that truncates require
1162 * two sync transactions instead of one for wsync filesystems.
1163 * One for the truncate and one for the timestamps since we
1164 * don't want to change the timestamps unless we're sure the
1165 * truncate worked. Truncates are less than 1% of the laddis
1166 * mix so this probably isn't worth the trouble to optimize.
1167 */
1168 if (mp->m_flags & XFS_MOUNT_WSYNC)
1169 xfs_trans_set_sync(tp);
1170 code = xfs_trans_commit(tp, 0);
1171 xfs_iunlock(ip, lock_flags);
1172
1173 /*
1174 * Release any dquot(s) the inode had kept before chown.
1175 */
1176 XFS_QM_DQRELE(mp, olddquot);
1177 XFS_QM_DQRELE(mp, udqp);
1178 XFS_QM_DQRELE(mp, gdqp);
1179
1180 if (code)
1181 return code;
1182
1183 if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE)) {
1184 XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL,
1185 NULL, DM_RIGHT_NULL, NULL, NULL, 0, 0,
1186 (mask & FSX_NONBLOCK) ? DM_FLAGS_NDELAY : 0);
1187 }
1188
1189 return 0;
1190
1191 error_return:
1192 XFS_QM_DQRELE(mp, udqp);
1193 XFS_QM_DQRELE(mp, gdqp);
1194 xfs_trans_cancel(tp, 0);
1195 if (lock_flags)
1196 xfs_iunlock(ip, lock_flags);
1197 return code;
1198}
1199
876STATIC int 1200STATIC int
877xfs_ioc_fssetxattr( 1201xfs_ioc_fssetxattr(
878 xfs_inode_t *ip, 1202 xfs_inode_t *ip,
@@ -880,31 +1204,16 @@ xfs_ioc_fssetxattr(
880 void __user *arg) 1204 void __user *arg)
881{ 1205{
882 struct fsxattr fa; 1206 struct fsxattr fa;
883 struct bhv_vattr *vattr; 1207 unsigned int mask;
884 int error;
885 int attr_flags;
886 1208
887 if (copy_from_user(&fa, arg, sizeof(fa))) 1209 if (copy_from_user(&fa, arg, sizeof(fa)))
888 return -EFAULT; 1210 return -EFAULT;
889 1211
890 vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); 1212 mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID;
891 if (unlikely(!vattr))
892 return -ENOMEM;
893
894 attr_flags = 0;
895 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1213 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
896 attr_flags |= ATTR_NONBLOCK; 1214 mask |= FSX_NONBLOCK;
897
898 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
899 vattr->va_xflags = fa.fsx_xflags;
900 vattr->va_extsize = fa.fsx_extsize;
901 vattr->va_projid = fa.fsx_projid;
902 1215
903 error = -xfs_setattr(ip, vattr, attr_flags, NULL); 1216 return -xfs_ioctl_setattr(ip, &fa, mask);
904 if (!error)
905 vn_revalidate(XFS_ITOV(ip)); /* update flags */
906 kfree(vattr);
907 return 0;
908} 1217}
909 1218
910STATIC int 1219STATIC int
@@ -926,10 +1235,9 @@ xfs_ioc_setxflags(
926 struct file *filp, 1235 struct file *filp,
927 void __user *arg) 1236 void __user *arg)
928{ 1237{
929 struct bhv_vattr *vattr; 1238 struct fsxattr fa;
930 unsigned int flags; 1239 unsigned int flags;
931 int attr_flags; 1240 unsigned int mask;
932 int error;
933 1241
934 if (copy_from_user(&flags, arg, sizeof(flags))) 1242 if (copy_from_user(&flags, arg, sizeof(flags)))
935 return -EFAULT; 1243 return -EFAULT;
@@ -939,22 +1247,12 @@ xfs_ioc_setxflags(
939 FS_SYNC_FL)) 1247 FS_SYNC_FL))
940 return -EOPNOTSUPP; 1248 return -EOPNOTSUPP;
941 1249
942 vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); 1250 mask = FSX_XFLAGS;
943 if (unlikely(!vattr))
944 return -ENOMEM;
945
946 attr_flags = 0;
947 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1251 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
948 attr_flags |= ATTR_NONBLOCK; 1252 mask |= FSX_NONBLOCK;
949 1253 fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
950 vattr->va_mask = XFS_AT_XFLAGS;
951 vattr->va_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
952 1254
953 error = -xfs_setattr(ip, vattr, attr_flags, NULL); 1255 return -xfs_ioctl_setattr(ip, &fa, mask);
954 if (likely(!error))
955 vn_revalidate(XFS_ITOV(ip)); /* update flags */
956 kfree(vattr);
957 return error;
958} 1256}
959 1257
960STATIC int 1258STATIC int
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 5fc61c824bb9..e88f51028086 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -181,23 +181,6 @@ xfs_ichgtime_fast(
181 mark_inode_dirty_sync(inode); 181 mark_inode_dirty_sync(inode);
182} 182}
183 183
184
185/*
186 * Pull the link count and size up from the xfs inode to the linux inode
187 */
188STATIC void
189xfs_validate_fields(
190 struct inode *inode)
191{
192 struct xfs_inode *ip = XFS_I(inode);
193 loff_t size;
194
195 /* we're under i_sem so i_size can't change under us */
196 size = XFS_ISIZE(ip);
197 if (i_size_read(inode) != size)
198 i_size_write(inode, size);
199}
200
201/* 184/*
202 * Hook in SELinux. This is not quite correct yet, what we really need 185 * Hook in SELinux. This is not quite correct yet, what we really need
203 * here (as we do for default ACLs) is a mechanism by which creation of 186 * here (as we do for default ACLs) is a mechanism by which creation of
@@ -245,8 +228,7 @@ STATIC void
245xfs_cleanup_inode( 228xfs_cleanup_inode(
246 struct inode *dir, 229 struct inode *dir,
247 struct inode *inode, 230 struct inode *inode,
248 struct dentry *dentry, 231 struct dentry *dentry)
249 int mode)
250{ 232{
251 struct xfs_name teardown; 233 struct xfs_name teardown;
252 234
@@ -257,10 +239,7 @@ xfs_cleanup_inode(
257 */ 239 */
258 xfs_dentry_to_name(&teardown, dentry); 240 xfs_dentry_to_name(&teardown, dentry);
259 241
260 if (S_ISDIR(mode)) 242 xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
261 xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
262 else
263 xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
264 iput(inode); 243 iput(inode);
265} 244}
266 245
@@ -275,7 +254,7 @@ xfs_vn_mknod(
275 struct xfs_inode *ip = NULL; 254 struct xfs_inode *ip = NULL;
276 xfs_acl_t *default_acl = NULL; 255 xfs_acl_t *default_acl = NULL;
277 struct xfs_name name; 256 struct xfs_name name;
278 attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; 257 int (*test_default_acl)(struct inode *) = _ACL_DEFAULT_EXISTS;
279 int error; 258 int error;
280 259
281 /* 260 /*
@@ -335,14 +314,11 @@ xfs_vn_mknod(
335 } 314 }
336 315
337 316
338 if (S_ISDIR(mode))
339 xfs_validate_fields(inode);
340 d_instantiate(dentry, inode); 317 d_instantiate(dentry, inode);
341 xfs_validate_fields(dir);
342 return -error; 318 return -error;
343 319
344 out_cleanup_inode: 320 out_cleanup_inode:
345 xfs_cleanup_inode(dir, inode, dentry, mode); 321 xfs_cleanup_inode(dir, inode, dentry);
346 out_free_acl: 322 out_free_acl:
347 if (default_acl) 323 if (default_acl)
348 _ACL_FREE(default_acl); 324 _ACL_FREE(default_acl);
@@ -382,7 +358,7 @@ xfs_vn_lookup(
382 return ERR_PTR(-ENAMETOOLONG); 358 return ERR_PTR(-ENAMETOOLONG);
383 359
384 xfs_dentry_to_name(&name, dentry); 360 xfs_dentry_to_name(&name, dentry);
385 error = xfs_lookup(XFS_I(dir), &name, &cip); 361 error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
386 if (unlikely(error)) { 362 if (unlikely(error)) {
387 if (unlikely(error != ENOENT)) 363 if (unlikely(error != ENOENT))
388 return ERR_PTR(-error); 364 return ERR_PTR(-error);
@@ -393,6 +369,46 @@ xfs_vn_lookup(
393 return d_splice_alias(cip->i_vnode, dentry); 369 return d_splice_alias(cip->i_vnode, dentry);
394} 370}
395 371
372STATIC struct dentry *
373xfs_vn_ci_lookup(
374 struct inode *dir,
375 struct dentry *dentry,
376 struct nameidata *nd)
377{
378 struct xfs_inode *ip;
379 struct xfs_name xname;
380 struct xfs_name ci_name;
381 struct qstr dname;
382 int error;
383
384 if (dentry->d_name.len >= MAXNAMELEN)
385 return ERR_PTR(-ENAMETOOLONG);
386
387 xfs_dentry_to_name(&xname, dentry);
388 error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name);
389 if (unlikely(error)) {
390 if (unlikely(error != ENOENT))
391 return ERR_PTR(-error);
392 /*
393 * call d_add(dentry, NULL) here when d_drop_negative_children
394 * is called in xfs_vn_mknod (ie. allow negative dentries
395 * with CI filesystems).
396 */
397 return NULL;
398 }
399
400 /* if exact match, just splice and exit */
401 if (!ci_name.name)
402 return d_splice_alias(ip->i_vnode, dentry);
403
404 /* else case-insensitive match... */
405 dname.name = ci_name.name;
406 dname.len = ci_name.len;
407 dentry = d_add_ci(ip->i_vnode, dentry, &dname);
408 kmem_free(ci_name.name);
409 return dentry;
410}
411
396STATIC int 412STATIC int
397xfs_vn_link( 413xfs_vn_link(
398 struct dentry *old_dentry, 414 struct dentry *old_dentry,
@@ -414,7 +430,6 @@ xfs_vn_link(
414 } 430 }
415 431
416 xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED); 432 xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
417 xfs_validate_fields(inode);
418 d_instantiate(dentry, inode); 433 d_instantiate(dentry, inode);
419 return 0; 434 return 0;
420} 435}
@@ -424,19 +439,23 @@ xfs_vn_unlink(
424 struct inode *dir, 439 struct inode *dir,
425 struct dentry *dentry) 440 struct dentry *dentry)
426{ 441{
427 struct inode *inode;
428 struct xfs_name name; 442 struct xfs_name name;
429 int error; 443 int error;
430 444
431 inode = dentry->d_inode;
432 xfs_dentry_to_name(&name, dentry); 445 xfs_dentry_to_name(&name, dentry);
433 446
434 error = xfs_remove(XFS_I(dir), &name, XFS_I(inode)); 447 error = -xfs_remove(XFS_I(dir), &name, XFS_I(dentry->d_inode));
435 if (likely(!error)) { 448 if (error)
436 xfs_validate_fields(dir); /* size needs update */ 449 return error;
437 xfs_validate_fields(inode); 450
438 } 451 /*
439 return -error; 452 * With unlink, the VFS makes the dentry "negative": no inode,
453 * but still hashed. This is incompatible with case-insensitive
454 * mode, so invalidate (unhash) the dentry in CI-mode.
455 */
456 if (xfs_sb_version_hasasciici(&XFS_M(dir->i_sb)->m_sb))
457 d_invalidate(dentry);
458 return 0;
440} 459}
441 460
442STATIC int 461STATIC int
@@ -466,36 +485,15 @@ xfs_vn_symlink(
466 goto out_cleanup_inode; 485 goto out_cleanup_inode;
467 486
468 d_instantiate(dentry, inode); 487 d_instantiate(dentry, inode);
469 xfs_validate_fields(dir);
470 xfs_validate_fields(inode);
471 return 0; 488 return 0;
472 489
473 out_cleanup_inode: 490 out_cleanup_inode:
474 xfs_cleanup_inode(dir, inode, dentry, 0); 491 xfs_cleanup_inode(dir, inode, dentry);
475 out: 492 out:
476 return -error; 493 return -error;
477} 494}
478 495
479STATIC int 496STATIC int
480xfs_vn_rmdir(
481 struct inode *dir,
482 struct dentry *dentry)
483{
484 struct inode *inode = dentry->d_inode;
485 struct xfs_name name;
486 int error;
487
488 xfs_dentry_to_name(&name, dentry);
489
490 error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
491 if (likely(!error)) {
492 xfs_validate_fields(inode);
493 xfs_validate_fields(dir);
494 }
495 return -error;
496}
497
498STATIC int
499xfs_vn_rename( 497xfs_vn_rename(
500 struct inode *odir, 498 struct inode *odir,
501 struct dentry *odentry, 499 struct dentry *odentry,
@@ -505,22 +503,13 @@ xfs_vn_rename(
505 struct inode *new_inode = ndentry->d_inode; 503 struct inode *new_inode = ndentry->d_inode;
506 struct xfs_name oname; 504 struct xfs_name oname;
507 struct xfs_name nname; 505 struct xfs_name nname;
508 int error;
509 506
510 xfs_dentry_to_name(&oname, odentry); 507 xfs_dentry_to_name(&oname, odentry);
511 xfs_dentry_to_name(&nname, ndentry); 508 xfs_dentry_to_name(&nname, ndentry);
512 509
513 error = xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode), 510 return -xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
514 XFS_I(ndir), &nname, new_inode ? 511 XFS_I(ndir), &nname, new_inode ?
515 XFS_I(new_inode) : NULL); 512 XFS_I(new_inode) : NULL);
516 if (likely(!error)) {
517 if (new_inode)
518 xfs_validate_fields(new_inode);
519 xfs_validate_fields(odir);
520 if (ndir != odir)
521 xfs_validate_fields(ndir);
522 }
523 return -error;
524} 513}
525 514
526/* 515/*
@@ -659,57 +648,9 @@ xfs_vn_getattr(
659STATIC int 648STATIC int
660xfs_vn_setattr( 649xfs_vn_setattr(
661 struct dentry *dentry, 650 struct dentry *dentry,
662 struct iattr *attr) 651 struct iattr *iattr)
663{ 652{
664 struct inode *inode = dentry->d_inode; 653 return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0, NULL);
665 unsigned int ia_valid = attr->ia_valid;
666 bhv_vattr_t vattr = { 0 };
667 int flags = 0;
668 int error;
669
670 if (ia_valid & ATTR_UID) {
671 vattr.va_mask |= XFS_AT_UID;
672 vattr.va_uid = attr->ia_uid;
673 }
674 if (ia_valid & ATTR_GID) {
675 vattr.va_mask |= XFS_AT_GID;
676 vattr.va_gid = attr->ia_gid;
677 }
678 if (ia_valid & ATTR_SIZE) {
679 vattr.va_mask |= XFS_AT_SIZE;
680 vattr.va_size = attr->ia_size;
681 }
682 if (ia_valid & ATTR_ATIME) {
683 vattr.va_mask |= XFS_AT_ATIME;
684 vattr.va_atime = attr->ia_atime;
685 inode->i_atime = attr->ia_atime;
686 }
687 if (ia_valid & ATTR_MTIME) {
688 vattr.va_mask |= XFS_AT_MTIME;
689 vattr.va_mtime = attr->ia_mtime;
690 }
691 if (ia_valid & ATTR_CTIME) {
692 vattr.va_mask |= XFS_AT_CTIME;
693 vattr.va_ctime = attr->ia_ctime;
694 }
695 if (ia_valid & ATTR_MODE) {
696 vattr.va_mask |= XFS_AT_MODE;
697 vattr.va_mode = attr->ia_mode;
698 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
699 inode->i_mode &= ~S_ISGID;
700 }
701
702 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET))
703 flags |= ATTR_UTIME;
704#ifdef ATTR_NO_BLOCK
705 if ((ia_valid & ATTR_NO_BLOCK))
706 flags |= ATTR_NONBLOCK;
707#endif
708
709 error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
710 if (likely(!error))
711 vn_revalidate(vn_from_inode(inode));
712 return -error;
713} 654}
714 655
715/* 656/*
@@ -727,109 +668,6 @@ xfs_vn_truncate(
727 WARN_ON(error); 668 WARN_ON(error);
728} 669}
729 670
730STATIC int
731xfs_vn_setxattr(
732 struct dentry *dentry,
733 const char *name,
734 const void *data,
735 size_t size,
736 int flags)
737{
738 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
739 char *attr = (char *)name;
740 attrnames_t *namesp;
741 int xflags = 0;
742 int error;
743
744 namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
745 if (!namesp)
746 return -EOPNOTSUPP;
747 attr += namesp->attr_namelen;
748 error = namesp->attr_capable(vp, NULL);
749 if (error)
750 return error;
751
752 /* Convert Linux syscall to XFS internal ATTR flags */
753 if (flags & XATTR_CREATE)
754 xflags |= ATTR_CREATE;
755 if (flags & XATTR_REPLACE)
756 xflags |= ATTR_REPLACE;
757 xflags |= namesp->attr_flag;
758 return namesp->attr_set(vp, attr, (void *)data, size, xflags);
759}
760
761STATIC ssize_t
762xfs_vn_getxattr(
763 struct dentry *dentry,
764 const char *name,
765 void *data,
766 size_t size)
767{
768 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
769 char *attr = (char *)name;
770 attrnames_t *namesp;
771 int xflags = 0;
772 ssize_t error;
773
774 namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
775 if (!namesp)
776 return -EOPNOTSUPP;
777 attr += namesp->attr_namelen;
778 error = namesp->attr_capable(vp, NULL);
779 if (error)
780 return error;
781
782 /* Convert Linux syscall to XFS internal ATTR flags */
783 if (!size) {
784 xflags |= ATTR_KERNOVAL;
785 data = NULL;
786 }
787 xflags |= namesp->attr_flag;
788 return namesp->attr_get(vp, attr, (void *)data, size, xflags);
789}
790
791STATIC ssize_t
792xfs_vn_listxattr(
793 struct dentry *dentry,
794 char *data,
795 size_t size)
796{
797 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
798 int error, xflags = ATTR_KERNAMELS;
799 ssize_t result;
800
801 if (!size)
802 xflags |= ATTR_KERNOVAL;
803 xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS;
804
805 error = attr_generic_list(vp, data, size, xflags, &result);
806 if (error < 0)
807 return error;
808 return result;
809}
810
811STATIC int
812xfs_vn_removexattr(
813 struct dentry *dentry,
814 const char *name)
815{
816 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
817 char *attr = (char *)name;
818 attrnames_t *namesp;
819 int xflags = 0;
820 int error;
821
822 namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
823 if (!namesp)
824 return -EOPNOTSUPP;
825 attr += namesp->attr_namelen;
826 error = namesp->attr_capable(vp, NULL);
827 if (error)
828 return error;
829 xflags |= namesp->attr_flag;
830 return namesp->attr_remove(vp, attr, xflags);
831}
832
833STATIC long 671STATIC long
834xfs_vn_fallocate( 672xfs_vn_fallocate(
835 struct inode *inode, 673 struct inode *inode,
@@ -853,18 +691,18 @@ xfs_vn_fallocate(
853 691
854 xfs_ilock(ip, XFS_IOLOCK_EXCL); 692 xfs_ilock(ip, XFS_IOLOCK_EXCL);
855 error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf, 693 error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
856 0, NULL, ATTR_NOLOCK); 694 0, NULL, XFS_ATTR_NOLOCK);
857 if (!error && !(mode & FALLOC_FL_KEEP_SIZE) && 695 if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
858 offset + len > i_size_read(inode)) 696 offset + len > i_size_read(inode))
859 new_size = offset + len; 697 new_size = offset + len;
860 698
861 /* Change file size if needed */ 699 /* Change file size if needed */
862 if (new_size) { 700 if (new_size) {
863 bhv_vattr_t va; 701 struct iattr iattr;
864 702
865 va.va_mask = XFS_AT_SIZE; 703 iattr.ia_valid = ATTR_SIZE;
866 va.va_size = new_size; 704 iattr.ia_size = new_size;
867 error = xfs_setattr(ip, &va, ATTR_NOLOCK, NULL); 705 error = xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK, NULL);
868 } 706 }
869 707
870 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 708 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
@@ -877,10 +715,10 @@ const struct inode_operations xfs_inode_operations = {
877 .truncate = xfs_vn_truncate, 715 .truncate = xfs_vn_truncate,
878 .getattr = xfs_vn_getattr, 716 .getattr = xfs_vn_getattr,
879 .setattr = xfs_vn_setattr, 717 .setattr = xfs_vn_setattr,
880 .setxattr = xfs_vn_setxattr, 718 .setxattr = generic_setxattr,
881 .getxattr = xfs_vn_getxattr, 719 .getxattr = generic_getxattr,
720 .removexattr = generic_removexattr,
882 .listxattr = xfs_vn_listxattr, 721 .listxattr = xfs_vn_listxattr,
883 .removexattr = xfs_vn_removexattr,
884 .fallocate = xfs_vn_fallocate, 722 .fallocate = xfs_vn_fallocate,
885}; 723};
886 724
@@ -891,16 +729,47 @@ const struct inode_operations xfs_dir_inode_operations = {
891 .unlink = xfs_vn_unlink, 729 .unlink = xfs_vn_unlink,
892 .symlink = xfs_vn_symlink, 730 .symlink = xfs_vn_symlink,
893 .mkdir = xfs_vn_mkdir, 731 .mkdir = xfs_vn_mkdir,
894 .rmdir = xfs_vn_rmdir, 732 /*
733 * Yes, XFS uses the same method for rmdir and unlink.
734 *
735 * There are some subtile differences deeper in the code,
736 * but we use S_ISDIR to check for those.
737 */
738 .rmdir = xfs_vn_unlink,
739 .mknod = xfs_vn_mknod,
740 .rename = xfs_vn_rename,
741 .permission = xfs_vn_permission,
742 .getattr = xfs_vn_getattr,
743 .setattr = xfs_vn_setattr,
744 .setxattr = generic_setxattr,
745 .getxattr = generic_getxattr,
746 .removexattr = generic_removexattr,
747 .listxattr = xfs_vn_listxattr,
748};
749
750const struct inode_operations xfs_dir_ci_inode_operations = {
751 .create = xfs_vn_create,
752 .lookup = xfs_vn_ci_lookup,
753 .link = xfs_vn_link,
754 .unlink = xfs_vn_unlink,
755 .symlink = xfs_vn_symlink,
756 .mkdir = xfs_vn_mkdir,
757 /*
758 * Yes, XFS uses the same method for rmdir and unlink.
759 *
760 * There are some subtile differences deeper in the code,
761 * but we use S_ISDIR to check for those.
762 */
763 .rmdir = xfs_vn_unlink,
895 .mknod = xfs_vn_mknod, 764 .mknod = xfs_vn_mknod,
896 .rename = xfs_vn_rename, 765 .rename = xfs_vn_rename,
897 .permission = xfs_vn_permission, 766 .permission = xfs_vn_permission,
898 .getattr = xfs_vn_getattr, 767 .getattr = xfs_vn_getattr,
899 .setattr = xfs_vn_setattr, 768 .setattr = xfs_vn_setattr,
900 .setxattr = xfs_vn_setxattr, 769 .setxattr = generic_setxattr,
901 .getxattr = xfs_vn_getxattr, 770 .getxattr = generic_getxattr,
771 .removexattr = generic_removexattr,
902 .listxattr = xfs_vn_listxattr, 772 .listxattr = xfs_vn_listxattr,
903 .removexattr = xfs_vn_removexattr,
904}; 773};
905 774
906const struct inode_operations xfs_symlink_inode_operations = { 775const struct inode_operations xfs_symlink_inode_operations = {
@@ -910,8 +779,8 @@ const struct inode_operations xfs_symlink_inode_operations = {
910 .permission = xfs_vn_permission, 779 .permission = xfs_vn_permission,
911 .getattr = xfs_vn_getattr, 780 .getattr = xfs_vn_getattr,
912 .setattr = xfs_vn_setattr, 781 .setattr = xfs_vn_setattr,
913 .setxattr = xfs_vn_setxattr, 782 .setxattr = generic_setxattr,
914 .getxattr = xfs_vn_getxattr, 783 .getxattr = generic_getxattr,
784 .removexattr = generic_removexattr,
915 .listxattr = xfs_vn_listxattr, 785 .listxattr = xfs_vn_listxattr,
916 .removexattr = xfs_vn_removexattr,
917}; 786};
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index 14d0deb7afff..d97ba934a2ac 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -20,12 +20,14 @@
20 20
21extern const struct inode_operations xfs_inode_operations; 21extern const struct inode_operations xfs_inode_operations;
22extern const struct inode_operations xfs_dir_inode_operations; 22extern const struct inode_operations xfs_dir_inode_operations;
23extern const struct inode_operations xfs_dir_ci_inode_operations;
23extern const struct inode_operations xfs_symlink_inode_operations; 24extern const struct inode_operations xfs_symlink_inode_operations;
24 25
25extern const struct file_operations xfs_file_operations; 26extern const struct file_operations xfs_file_operations;
26extern const struct file_operations xfs_dir_file_operations; 27extern const struct file_operations xfs_dir_file_operations;
27extern const struct file_operations xfs_invis_file_operations; 28extern const struct file_operations xfs_invis_file_operations;
28 29
30extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
29 31
30struct xfs_inode; 32struct xfs_inode;
31extern void xfs_ichgtime(struct xfs_inode *, int); 33extern void xfs_ichgtime(struct xfs_inode *, int);
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 4edc46915b57..4d45d9351a6c 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -76,6 +76,7 @@
76#include <linux/log2.h> 76#include <linux/log2.h>
77#include <linux/spinlock.h> 77#include <linux/spinlock.h>
78#include <linux/random.h> 78#include <linux/random.h>
79#include <linux/ctype.h>
79 80
80#include <asm/page.h> 81#include <asm/page.h>
81#include <asm/div64.h> 82#include <asm/div64.h>
@@ -299,4 +300,11 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
299 return x; 300 return x;
300} 301}
301 302
303/* ARM old ABI has some weird alignment/padding */
304#if defined(__arm__) && !defined(__ARM_EABI__)
305#define __arch_pack __attribute__((packed))
306#else
307#define __arch_pack
308#endif
309
302#endif /* __XFS_LINUX__ */ 310#endif /* __XFS_LINUX__ */
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c
index e480b6102051..3d5b67c075c7 100644
--- a/fs/xfs/linux-2.6/xfs_stats.c
+++ b/fs/xfs/linux-2.6/xfs_stats.c
@@ -98,12 +98,21 @@ xfs_read_xfsstats(
98 return len; 98 return len;
99} 99}
100 100
101void 101int
102xfs_init_procfs(void) 102xfs_init_procfs(void)
103{ 103{
104 if (!proc_mkdir("fs/xfs", NULL)) 104 if (!proc_mkdir("fs/xfs", NULL))
105 return; 105 goto out;
106 create_proc_read_entry("fs/xfs/stat", 0, NULL, xfs_read_xfsstats, NULL); 106
107 if (!create_proc_read_entry("fs/xfs/stat", 0, NULL,
108 xfs_read_xfsstats, NULL))
109 goto out_remove_entry;
110 return 0;
111
112 out_remove_entry:
113 remove_proc_entry("fs/xfs", NULL);
114 out:
115 return -ENOMEM;
107} 116}
108 117
109void 118void
diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/linux-2.6/xfs_stats.h
index afd0b0d5fdb2..e83820febc9f 100644
--- a/fs/xfs/linux-2.6/xfs_stats.h
+++ b/fs/xfs/linux-2.6/xfs_stats.h
@@ -134,7 +134,7 @@ DECLARE_PER_CPU(struct xfsstats, xfsstats);
134#define XFS_STATS_DEC(v) (per_cpu(xfsstats, current_cpu()).v--) 134#define XFS_STATS_DEC(v) (per_cpu(xfsstats, current_cpu()).v--)
135#define XFS_STATS_ADD(v, inc) (per_cpu(xfsstats, current_cpu()).v += (inc)) 135#define XFS_STATS_ADD(v, inc) (per_cpu(xfsstats, current_cpu()).v += (inc))
136 136
137extern void xfs_init_procfs(void); 137extern int xfs_init_procfs(void);
138extern void xfs_cleanup_procfs(void); 138extern void xfs_cleanup_procfs(void);
139 139
140 140
@@ -144,8 +144,14 @@ extern void xfs_cleanup_procfs(void);
144# define XFS_STATS_DEC(count) 144# define XFS_STATS_DEC(count)
145# define XFS_STATS_ADD(count, inc) 145# define XFS_STATS_ADD(count, inc)
146 146
147static inline void xfs_init_procfs(void) { }; 147static inline int xfs_init_procfs(void)
148static inline void xfs_cleanup_procfs(void) { }; 148{
149 return 0;
150}
151
152static inline void xfs_cleanup_procfs(void)
153{
154}
149 155
150#endif /* !CONFIG_PROC_FS */ 156#endif /* !CONFIG_PROC_FS */
151 157
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 943381284e2e..30ae96397e31 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -52,6 +52,12 @@
52#include "xfs_version.h" 52#include "xfs_version.h"
53#include "xfs_log_priv.h" 53#include "xfs_log_priv.h"
54#include "xfs_trans_priv.h" 54#include "xfs_trans_priv.h"
55#include "xfs_filestream.h"
56#include "xfs_da_btree.h"
57#include "xfs_dir2_trace.h"
58#include "xfs_extfree_item.h"
59#include "xfs_mru_cache.h"
60#include "xfs_inode_item.h"
55 61
56#include <linux/namei.h> 62#include <linux/namei.h>
57#include <linux/init.h> 63#include <linux/init.h>
@@ -60,6 +66,7 @@
60#include <linux/writeback.h> 66#include <linux/writeback.h>
61#include <linux/kthread.h> 67#include <linux/kthread.h>
62#include <linux/freezer.h> 68#include <linux/freezer.h>
69#include <linux/parser.h>
63 70
64static struct quotactl_ops xfs_quotactl_operations; 71static struct quotactl_ops xfs_quotactl_operations;
65static struct super_operations xfs_super_operations; 72static struct super_operations xfs_super_operations;
@@ -74,7 +81,10 @@ xfs_args_allocate(
74{ 81{
75 struct xfs_mount_args *args; 82 struct xfs_mount_args *args;
76 83
77 args = kmem_zalloc(sizeof(struct xfs_mount_args), KM_SLEEP); 84 args = kzalloc(sizeof(struct xfs_mount_args), GFP_KERNEL);
85 if (!args)
86 return NULL;
87
78 args->logbufs = args->logbufsize = -1; 88 args->logbufs = args->logbufsize = -1;
79 strncpy(args->fsname, sb->s_id, MAXNAMELEN); 89 strncpy(args->fsname, sb->s_id, MAXNAMELEN);
80 90
@@ -138,6 +148,23 @@ xfs_args_allocate(
138#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */ 148#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
139#define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */ 149#define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */
140 150
151/*
152 * Table driven mount option parser.
153 *
154 * Currently only used for remount, but it will be used for mount
155 * in the future, too.
156 */
157enum {
158 Opt_barrier, Opt_nobarrier, Opt_err
159};
160
161static match_table_t tokens = {
162 {Opt_barrier, "barrier"},
163 {Opt_nobarrier, "nobarrier"},
164 {Opt_err, NULL}
165};
166
167
141STATIC unsigned long 168STATIC unsigned long
142suffix_strtoul(char *s, char **endp, unsigned int base) 169suffix_strtoul(char *s, char **endp, unsigned int base)
143{ 170{
@@ -314,6 +341,7 @@ xfs_parseargs(
314 args->flags |= XFSMNT_ATTR2; 341 args->flags |= XFSMNT_ATTR2;
315 } else if (!strcmp(this_char, MNTOPT_NOATTR2)) { 342 } else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
316 args->flags &= ~XFSMNT_ATTR2; 343 args->flags &= ~XFSMNT_ATTR2;
344 args->flags |= XFSMNT_NOATTR2;
317 } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) { 345 } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
318 args->flags2 |= XFSMNT2_FILESTREAMS; 346 args->flags2 |= XFSMNT2_FILESTREAMS;
319 } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) { 347 } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
@@ -564,7 +592,10 @@ xfs_set_inodeops(
564 inode->i_mapping->a_ops = &xfs_address_space_operations; 592 inode->i_mapping->a_ops = &xfs_address_space_operations;
565 break; 593 break;
566 case S_IFDIR: 594 case S_IFDIR:
567 inode->i_op = &xfs_dir_inode_operations; 595 if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
596 inode->i_op = &xfs_dir_ci_inode_operations;
597 else
598 inode->i_op = &xfs_dir_inode_operations;
568 inode->i_fop = &xfs_dir_file_operations; 599 inode->i_fop = &xfs_dir_file_operations;
569 break; 600 break;
570 case S_IFLNK: 601 case S_IFLNK:
@@ -733,14 +764,6 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp)
733 return; 764 return;
734 } 765 }
735 766
736 if (mp->m_ddev_targp->bt_bdev->bd_disk->queue->ordered ==
737 QUEUE_ORDERED_NONE) {
738 xfs_fs_cmn_err(CE_NOTE, mp,
739 "Disabling barriers, not supported by the underlying device");
740 mp->m_flags &= ~XFS_MOUNT_BARRIER;
741 return;
742 }
743
744 if (xfs_readonly_buftarg(mp->m_ddev_targp)) { 767 if (xfs_readonly_buftarg(mp->m_ddev_targp)) {
745 xfs_fs_cmn_err(CE_NOTE, mp, 768 xfs_fs_cmn_err(CE_NOTE, mp,
746 "Disabling barriers, underlying device is readonly"); 769 "Disabling barriers, underlying device is readonly");
@@ -764,6 +787,139 @@ xfs_blkdev_issue_flush(
764 blkdev_issue_flush(buftarg->bt_bdev, NULL); 787 blkdev_issue_flush(buftarg->bt_bdev, NULL);
765} 788}
766 789
790STATIC void
791xfs_close_devices(
792 struct xfs_mount *mp)
793{
794 if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
795 struct block_device *logdev = mp->m_logdev_targp->bt_bdev;
796 xfs_free_buftarg(mp->m_logdev_targp);
797 xfs_blkdev_put(logdev);
798 }
799 if (mp->m_rtdev_targp) {
800 struct block_device *rtdev = mp->m_rtdev_targp->bt_bdev;
801 xfs_free_buftarg(mp->m_rtdev_targp);
802 xfs_blkdev_put(rtdev);
803 }
804 xfs_free_buftarg(mp->m_ddev_targp);
805}
806
807/*
808 * The file system configurations are:
809 * (1) device (partition) with data and internal log
810 * (2) logical volume with data and log subvolumes.
811 * (3) logical volume with data, log, and realtime subvolumes.
812 *
813 * We only have to handle opening the log and realtime volumes here if
814 * they are present. The data subvolume has already been opened by
815 * get_sb_bdev() and is stored in sb->s_bdev.
816 */
817STATIC int
818xfs_open_devices(
819 struct xfs_mount *mp,
820 struct xfs_mount_args *args)
821{
822 struct block_device *ddev = mp->m_super->s_bdev;
823 struct block_device *logdev = NULL, *rtdev = NULL;
824 int error;
825
826 /*
827 * Open real time and log devices - order is important.
828 */
829 if (args->logname[0]) {
830 error = xfs_blkdev_get(mp, args->logname, &logdev);
831 if (error)
832 goto out;
833 }
834
835 if (args->rtname[0]) {
836 error = xfs_blkdev_get(mp, args->rtname, &rtdev);
837 if (error)
838 goto out_close_logdev;
839
840 if (rtdev == ddev || rtdev == logdev) {
841 cmn_err(CE_WARN,
842 "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
843 error = EINVAL;
844 goto out_close_rtdev;
845 }
846 }
847
848 /*
849 * Setup xfs_mount buffer target pointers
850 */
851 error = ENOMEM;
852 mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
853 if (!mp->m_ddev_targp)
854 goto out_close_rtdev;
855
856 if (rtdev) {
857 mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
858 if (!mp->m_rtdev_targp)
859 goto out_free_ddev_targ;
860 }
861
862 if (logdev && logdev != ddev) {
863 mp->m_logdev_targp = xfs_alloc_buftarg(logdev, 1);
864 if (!mp->m_logdev_targp)
865 goto out_free_rtdev_targ;
866 } else {
867 mp->m_logdev_targp = mp->m_ddev_targp;
868 }
869
870 return 0;
871
872 out_free_rtdev_targ:
873 if (mp->m_rtdev_targp)
874 xfs_free_buftarg(mp->m_rtdev_targp);
875 out_free_ddev_targ:
876 xfs_free_buftarg(mp->m_ddev_targp);
877 out_close_rtdev:
878 if (rtdev)
879 xfs_blkdev_put(rtdev);
880 out_close_logdev:
881 if (logdev && logdev != ddev)
882 xfs_blkdev_put(logdev);
883 out:
884 return error;
885}
886
887/*
888 * Setup xfs_mount buffer target pointers based on superblock
889 */
890STATIC int
891xfs_setup_devices(
892 struct xfs_mount *mp)
893{
894 int error;
895
896 error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
897 mp->m_sb.sb_sectsize);
898 if (error)
899 return error;
900
901 if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
902 unsigned int log_sector_size = BBSIZE;
903
904 if (xfs_sb_version_hassector(&mp->m_sb))
905 log_sector_size = mp->m_sb.sb_logsectsize;
906 error = xfs_setsize_buftarg(mp->m_logdev_targp,
907 mp->m_sb.sb_blocksize,
908 log_sector_size);
909 if (error)
910 return error;
911 }
912 if (mp->m_rtdev_targp) {
913 error = xfs_setsize_buftarg(mp->m_rtdev_targp,
914 mp->m_sb.sb_blocksize,
915 mp->m_sb.sb_sectsize);
916 if (error)
917 return error;
918 }
919
920 return 0;
921}
922
767/* 923/*
768 * XFS AIL push thread support 924 * XFS AIL push thread support
769 */ 925 */
@@ -848,42 +1004,6 @@ xfs_fs_inode_init_once(
848 inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); 1004 inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
849} 1005}
850 1006
851STATIC int __init
852xfs_init_zones(void)
853{
854 xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode",
855 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
856 KM_ZONE_SPREAD,
857 xfs_fs_inode_init_once);
858 if (!xfs_vnode_zone)
859 goto out;
860
861 xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend");
862 if (!xfs_ioend_zone)
863 goto out_destroy_vnode_zone;
864
865 xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE,
866 xfs_ioend_zone);
867 if (!xfs_ioend_pool)
868 goto out_free_ioend_zone;
869 return 0;
870
871 out_free_ioend_zone:
872 kmem_zone_destroy(xfs_ioend_zone);
873 out_destroy_vnode_zone:
874 kmem_zone_destroy(xfs_vnode_zone);
875 out:
876 return -ENOMEM;
877}
878
879STATIC void
880xfs_destroy_zones(void)
881{
882 mempool_destroy(xfs_ioend_pool);
883 kmem_zone_destroy(xfs_vnode_zone);
884 kmem_zone_destroy(xfs_ioend_zone);
885}
886
887/* 1007/*
888 * Attempt to flush the inode, this will actually fail 1008 * Attempt to flush the inode, this will actually fail
889 * if the inode is pinned, but we dirty the inode again 1009 * if the inode is pinned, but we dirty the inode again
@@ -1073,7 +1193,7 @@ xfssyncd(
1073 list_del(&work->w_list); 1193 list_del(&work->w_list);
1074 if (work == &mp->m_sync_work) 1194 if (work == &mp->m_sync_work)
1075 continue; 1195 continue;
1076 kmem_free(work, sizeof(struct bhv_vfs_sync_work)); 1196 kmem_free(work);
1077 } 1197 }
1078 } 1198 }
1079 1199
@@ -1085,14 +1205,63 @@ xfs_fs_put_super(
1085 struct super_block *sb) 1205 struct super_block *sb)
1086{ 1206{
1087 struct xfs_mount *mp = XFS_M(sb); 1207 struct xfs_mount *mp = XFS_M(sb);
1208 struct xfs_inode *rip = mp->m_rootip;
1209 int unmount_event_flags = 0;
1088 int error; 1210 int error;
1089 1211
1090 kthread_stop(mp->m_sync_task); 1212 kthread_stop(mp->m_sync_task);
1091 1213
1092 xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI); 1214 xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI);
1093 error = xfs_unmount(mp, 0, NULL); 1215
1094 if (error) 1216#ifdef HAVE_DMAPI
1095 printk("XFS: unmount got error=%d\n", error); 1217 if (mp->m_flags & XFS_MOUNT_DMAPI) {
1218 unmount_event_flags =
1219 (mp->m_dmevmask & (1 << DM_EVENT_UNMOUNT)) ?
1220 0 : DM_FLAGS_UNWANTED;
1221 /*
1222 * Ignore error from dmapi here, first unmount is not allowed
1223 * to fail anyway, and second we wouldn't want to fail a
1224 * unmount because of dmapi.
1225 */
1226 XFS_SEND_PREUNMOUNT(mp, rip, DM_RIGHT_NULL, rip, DM_RIGHT_NULL,
1227 NULL, NULL, 0, 0, unmount_event_flags);
1228 }
1229#endif
1230
1231 /*
1232 * Blow away any referenced inode in the filestreams cache.
1233 * This can and will cause log traffic as inodes go inactive
1234 * here.
1235 */
1236 xfs_filestream_unmount(mp);
1237
1238 XFS_bflush(mp->m_ddev_targp);
1239 error = xfs_unmount_flush(mp, 0);
1240 WARN_ON(error);
1241
1242 IRELE(rip);
1243
1244 /*
1245 * If we're forcing a shutdown, typically because of a media error,
1246 * we want to make sure we invalidate dirty pages that belong to
1247 * referenced vnodes as well.
1248 */
1249 if (XFS_FORCED_SHUTDOWN(mp)) {
1250 error = xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE);
1251 ASSERT(error != EFSCORRUPTED);
1252 }
1253
1254 if (mp->m_flags & XFS_MOUNT_DMAPI) {
1255 XFS_SEND_UNMOUNT(mp, rip, DM_RIGHT_NULL, 0, 0,
1256 unmount_event_flags);
1257 }
1258
1259 xfs_unmountfs(mp);
1260 xfs_icsb_destroy_counters(mp);
1261 xfs_close_devices(mp);
1262 xfs_qmops_put(mp);
1263 xfs_dmops_put(mp);
1264 kfree(mp);
1096} 1265}
1097 1266
1098STATIC void 1267STATIC void
@@ -1215,14 +1384,54 @@ xfs_fs_remount(
1215 char *options) 1384 char *options)
1216{ 1385{
1217 struct xfs_mount *mp = XFS_M(sb); 1386 struct xfs_mount *mp = XFS_M(sb);
1218 struct xfs_mount_args *args = xfs_args_allocate(sb, 0); 1387 substring_t args[MAX_OPT_ARGS];
1219 int error; 1388 char *p;
1220 1389
1221 error = xfs_parseargs(mp, options, args, 1); 1390 while ((p = strsep(&options, ",")) != NULL) {
1222 if (!error) 1391 int token;
1223 error = xfs_mntupdate(mp, flags, args); 1392
1224 kmem_free(args, sizeof(*args)); 1393 if (!*p)
1225 return -error; 1394 continue;
1395
1396 token = match_token(p, tokens, args);
1397 switch (token) {
1398 case Opt_barrier:
1399 mp->m_flags |= XFS_MOUNT_BARRIER;
1400
1401 /*
1402 * Test if barriers are actually working if we can,
1403 * else delay this check until the filesystem is
1404 * marked writeable.
1405 */
1406 if (!(mp->m_flags & XFS_MOUNT_RDONLY))
1407 xfs_mountfs_check_barriers(mp);
1408 break;
1409 case Opt_nobarrier:
1410 mp->m_flags &= ~XFS_MOUNT_BARRIER;
1411 break;
1412 default:
1413 printk(KERN_INFO
1414 "XFS: mount option \"%s\" not supported for remount\n", p);
1415 return -EINVAL;
1416 }
1417 }
1418
1419 /* rw/ro -> rw */
1420 if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
1421 mp->m_flags &= ~XFS_MOUNT_RDONLY;
1422 if (mp->m_flags & XFS_MOUNT_BARRIER)
1423 xfs_mountfs_check_barriers(mp);
1424 }
1425
1426 /* rw -> ro */
1427 if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) {
1428 xfs_filestream_flush(mp);
1429 xfs_sync(mp, SYNC_DATA_QUIESCE);
1430 xfs_attr_quiesce(mp);
1431 mp->m_flags |= XFS_MOUNT_RDONLY;
1432 }
1433
1434 return 0;
1226} 1435}
1227 1436
1228/* 1437/*
@@ -1299,6 +1508,225 @@ xfs_fs_setxquota(
1299 Q_XSETPQLIM), id, (caddr_t)fdq); 1508 Q_XSETPQLIM), id, (caddr_t)fdq);
1300} 1509}
1301 1510
1511/*
1512 * This function fills in xfs_mount_t fields based on mount args.
1513 * Note: the superblock has _not_ yet been read in.
1514 */
1515STATIC int
1516xfs_start_flags(
1517 struct xfs_mount_args *ap,
1518 struct xfs_mount *mp)
1519{
1520 /* Values are in BBs */
1521 if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
1522 /*
1523 * At this point the superblock has not been read
1524 * in, therefore we do not know the block size.
1525 * Before the mount call ends we will convert
1526 * these to FSBs.
1527 */
1528 mp->m_dalign = ap->sunit;
1529 mp->m_swidth = ap->swidth;
1530 }
1531
1532 if (ap->logbufs != -1 &&
1533 ap->logbufs != 0 &&
1534 (ap->logbufs < XLOG_MIN_ICLOGS ||
1535 ap->logbufs > XLOG_MAX_ICLOGS)) {
1536 cmn_err(CE_WARN,
1537 "XFS: invalid logbufs value: %d [not %d-%d]",
1538 ap->logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
1539 return XFS_ERROR(EINVAL);
1540 }
1541 mp->m_logbufs = ap->logbufs;
1542 if (ap->logbufsize != -1 &&
1543 ap->logbufsize != 0 &&
1544 (ap->logbufsize < XLOG_MIN_RECORD_BSIZE ||
1545 ap->logbufsize > XLOG_MAX_RECORD_BSIZE ||
1546 !is_power_of_2(ap->logbufsize))) {
1547 cmn_err(CE_WARN,
1548 "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
1549 ap->logbufsize);
1550 return XFS_ERROR(EINVAL);
1551 }
1552 mp->m_logbsize = ap->logbufsize;
1553 mp->m_fsname_len = strlen(ap->fsname) + 1;
1554 mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
1555 strcpy(mp->m_fsname, ap->fsname);
1556 if (ap->rtname[0]) {
1557 mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP);
1558 strcpy(mp->m_rtname, ap->rtname);
1559 }
1560 if (ap->logname[0]) {
1561 mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP);
1562 strcpy(mp->m_logname, ap->logname);
1563 }
1564
1565 if (ap->flags & XFSMNT_WSYNC)
1566 mp->m_flags |= XFS_MOUNT_WSYNC;
1567#if XFS_BIG_INUMS
1568 if (ap->flags & XFSMNT_INO64) {
1569 mp->m_flags |= XFS_MOUNT_INO64;
1570 mp->m_inoadd = XFS_INO64_OFFSET;
1571 }
1572#endif
1573 if (ap->flags & XFSMNT_RETERR)
1574 mp->m_flags |= XFS_MOUNT_RETERR;
1575 if (ap->flags & XFSMNT_NOALIGN)
1576 mp->m_flags |= XFS_MOUNT_NOALIGN;
1577 if (ap->flags & XFSMNT_SWALLOC)
1578 mp->m_flags |= XFS_MOUNT_SWALLOC;
1579 if (ap->flags & XFSMNT_OSYNCISOSYNC)
1580 mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC;
1581 if (ap->flags & XFSMNT_32BITINODES)
1582 mp->m_flags |= XFS_MOUNT_32BITINODES;
1583
1584 if (ap->flags & XFSMNT_IOSIZE) {
1585 if (ap->iosizelog > XFS_MAX_IO_LOG ||
1586 ap->iosizelog < XFS_MIN_IO_LOG) {
1587 cmn_err(CE_WARN,
1588 "XFS: invalid log iosize: %d [not %d-%d]",
1589 ap->iosizelog, XFS_MIN_IO_LOG,
1590 XFS_MAX_IO_LOG);
1591 return XFS_ERROR(EINVAL);
1592 }
1593
1594 mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;
1595 mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
1596 }
1597
1598 if (ap->flags & XFSMNT_IKEEP)
1599 mp->m_flags |= XFS_MOUNT_IKEEP;
1600 if (ap->flags & XFSMNT_DIRSYNC)
1601 mp->m_flags |= XFS_MOUNT_DIRSYNC;
1602 if (ap->flags & XFSMNT_ATTR2)
1603 mp->m_flags |= XFS_MOUNT_ATTR2;
1604 if (ap->flags & XFSMNT_NOATTR2)
1605 mp->m_flags |= XFS_MOUNT_NOATTR2;
1606
1607 if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE)
1608 mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
1609
1610 /*
1611 * no recovery flag requires a read-only mount
1612 */
1613 if (ap->flags & XFSMNT_NORECOVERY) {
1614 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
1615 cmn_err(CE_WARN,
1616 "XFS: tried to mount a FS read-write without recovery!");
1617 return XFS_ERROR(EINVAL);
1618 }
1619 mp->m_flags |= XFS_MOUNT_NORECOVERY;
1620 }
1621
1622 if (ap->flags & XFSMNT_NOUUID)
1623 mp->m_flags |= XFS_MOUNT_NOUUID;
1624 if (ap->flags & XFSMNT_BARRIER)
1625 mp->m_flags |= XFS_MOUNT_BARRIER;
1626 else
1627 mp->m_flags &= ~XFS_MOUNT_BARRIER;
1628
1629 if (ap->flags2 & XFSMNT2_FILESTREAMS)
1630 mp->m_flags |= XFS_MOUNT_FILESTREAMS;
1631
1632 if (ap->flags & XFSMNT_DMAPI)
1633 mp->m_flags |= XFS_MOUNT_DMAPI;
1634 return 0;
1635}
1636
1637/*
1638 * This function fills in xfs_mount_t fields based on mount args.
1639 * Note: the superblock _has_ now been read in.
1640 */
1641STATIC int
1642xfs_finish_flags(
1643 struct xfs_mount_args *ap,
1644 struct xfs_mount *mp)
1645{
1646 int ronly = (mp->m_flags & XFS_MOUNT_RDONLY);
1647
1648 /* Fail a mount where the logbuf is smaller then the log stripe */
1649 if (xfs_sb_version_haslogv2(&mp->m_sb)) {
1650 if ((ap->logbufsize <= 0) &&
1651 (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {
1652 mp->m_logbsize = mp->m_sb.sb_logsunit;
1653 } else if (ap->logbufsize > 0 &&
1654 ap->logbufsize < mp->m_sb.sb_logsunit) {
1655 cmn_err(CE_WARN,
1656 "XFS: logbuf size must be greater than or equal to log stripe size");
1657 return XFS_ERROR(EINVAL);
1658 }
1659 } else {
1660 /* Fail a mount if the logbuf is larger than 32K */
1661 if (ap->logbufsize > XLOG_BIG_RECORD_BSIZE) {
1662 cmn_err(CE_WARN,
1663 "XFS: logbuf size for version 1 logs must be 16K or 32K");
1664 return XFS_ERROR(EINVAL);
1665 }
1666 }
1667
1668 /*
1669 * mkfs'ed attr2 will turn on attr2 mount unless explicitly
1670 * told by noattr2 to turn it off
1671 */
1672 if (xfs_sb_version_hasattr2(&mp->m_sb) &&
1673 !(ap->flags & XFSMNT_NOATTR2))
1674 mp->m_flags |= XFS_MOUNT_ATTR2;
1675
1676 /*
1677 * prohibit r/w mounts of read-only filesystems
1678 */
1679 if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
1680 cmn_err(CE_WARN,
1681 "XFS: cannot mount a read-only filesystem as read-write");
1682 return XFS_ERROR(EROFS);
1683 }
1684
1685 /*
1686 * check for shared mount.
1687 */
1688 if (ap->flags & XFSMNT_SHARED) {
1689 if (!xfs_sb_version_hasshared(&mp->m_sb))
1690 return XFS_ERROR(EINVAL);
1691
1692 /*
1693 * For IRIX 6.5, shared mounts must have the shared
1694 * version bit set, have the persistent readonly
1695 * field set, must be version 0 and can only be mounted
1696 * read-only.
1697 */
1698 if (!ronly || !(mp->m_sb.sb_flags & XFS_SBF_READONLY) ||
1699 (mp->m_sb.sb_shared_vn != 0))
1700 return XFS_ERROR(EINVAL);
1701
1702 mp->m_flags |= XFS_MOUNT_SHARED;
1703
1704 /*
1705 * Shared XFS V0 can't deal with DMI. Return EINVAL.
1706 */
1707 if (mp->m_sb.sb_shared_vn == 0 && (ap->flags & XFSMNT_DMAPI))
1708 return XFS_ERROR(EINVAL);
1709 }
1710
1711 if (ap->flags & XFSMNT_UQUOTA) {
1712 mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
1713 if (ap->flags & XFSMNT_UQUOTAENF)
1714 mp->m_qflags |= XFS_UQUOTA_ENFD;
1715 }
1716
1717 if (ap->flags & XFSMNT_GQUOTA) {
1718 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
1719 if (ap->flags & XFSMNT_GQUOTAENF)
1720 mp->m_qflags |= XFS_OQUOTA_ENFD;
1721 } else if (ap->flags & XFSMNT_PQUOTA) {
1722 mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
1723 if (ap->flags & XFSMNT_PQUOTAENF)
1724 mp->m_qflags |= XFS_OQUOTA_ENFD;
1725 }
1726
1727 return 0;
1728}
1729
1302STATIC int 1730STATIC int
1303xfs_fs_fill_super( 1731xfs_fs_fill_super(
1304 struct super_block *sb, 1732 struct super_block *sb,
@@ -1307,11 +1735,21 @@ xfs_fs_fill_super(
1307{ 1735{
1308 struct inode *root; 1736 struct inode *root;
1309 struct xfs_mount *mp = NULL; 1737 struct xfs_mount *mp = NULL;
1310 struct xfs_mount_args *args = xfs_args_allocate(sb, silent); 1738 struct xfs_mount_args *args;
1311 int error; 1739 int flags = 0, error = ENOMEM;
1740
1741 args = xfs_args_allocate(sb, silent);
1742 if (!args)
1743 return -ENOMEM;
1312 1744
1313 mp = xfs_mount_init(); 1745 mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL);
1746 if (!mp)
1747 goto out_free_args;
1314 1748
1749 spin_lock_init(&mp->m_sb_lock);
1750 mutex_init(&mp->m_ilock);
1751 mutex_init(&mp->m_growlock);
1752 atomic_set(&mp->m_active_trans, 0);
1315 INIT_LIST_HEAD(&mp->m_sync_list); 1753 INIT_LIST_HEAD(&mp->m_sync_list);
1316 spin_lock_init(&mp->m_sync_lock); 1754 spin_lock_init(&mp->m_sync_lock);
1317 init_waitqueue_head(&mp->m_wait_single_sync_task); 1755 init_waitqueue_head(&mp->m_wait_single_sync_task);
@@ -1324,16 +1762,60 @@ xfs_fs_fill_super(
1324 1762
1325 error = xfs_parseargs(mp, (char *)data, args, 0); 1763 error = xfs_parseargs(mp, (char *)data, args, 0);
1326 if (error) 1764 if (error)
1327 goto fail_vfsop; 1765 goto out_free_mp;
1328 1766
1329 sb_min_blocksize(sb, BBSIZE); 1767 sb_min_blocksize(sb, BBSIZE);
1768 sb->s_xattr = xfs_xattr_handlers;
1330 sb->s_export_op = &xfs_export_operations; 1769 sb->s_export_op = &xfs_export_operations;
1331 sb->s_qcop = &xfs_quotactl_operations; 1770 sb->s_qcop = &xfs_quotactl_operations;
1332 sb->s_op = &xfs_super_operations; 1771 sb->s_op = &xfs_super_operations;
1333 1772
1334 error = xfs_mount(mp, args, NULL); 1773 error = xfs_dmops_get(mp, args);
1335 if (error) 1774 if (error)
1336 goto fail_vfsop; 1775 goto out_free_mp;
1776 error = xfs_qmops_get(mp, args);
1777 if (error)
1778 goto out_put_dmops;
1779
1780 if (args->flags & XFSMNT_QUIET)
1781 flags |= XFS_MFSI_QUIET;
1782
1783 error = xfs_open_devices(mp, args);
1784 if (error)
1785 goto out_put_qmops;
1786
1787 if (xfs_icsb_init_counters(mp))
1788 mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB;
1789
1790 /*
1791 * Setup flags based on mount(2) options and then the superblock
1792 */
1793 error = xfs_start_flags(args, mp);
1794 if (error)
1795 goto out_destroy_counters;
1796 error = xfs_readsb(mp, flags);
1797 if (error)
1798 goto out_destroy_counters;
1799 error = xfs_finish_flags(args, mp);
1800 if (error)
1801 goto out_free_sb;
1802
1803 error = xfs_setup_devices(mp);
1804 if (error)
1805 goto out_free_sb;
1806
1807 if (mp->m_flags & XFS_MOUNT_BARRIER)
1808 xfs_mountfs_check_barriers(mp);
1809
1810 error = xfs_filestream_mount(mp);
1811 if (error)
1812 goto out_free_sb;
1813
1814 error = xfs_mountfs(mp, flags);
1815 if (error)
1816 goto out_filestream_unmount;
1817
1818 XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, args->mtpt, args->fsname);
1337 1819
1338 sb->s_dirt = 1; 1820 sb->s_dirt = 1;
1339 sb->s_magic = XFS_SB_MAGIC; 1821 sb->s_magic = XFS_SB_MAGIC;
@@ -1368,10 +1850,27 @@ xfs_fs_fill_super(
1368 1850
1369 xfs_itrace_exit(XFS_I(sb->s_root->d_inode)); 1851 xfs_itrace_exit(XFS_I(sb->s_root->d_inode));
1370 1852
1371 kmem_free(args, sizeof(*args)); 1853 kfree(args);
1372 return 0; 1854 return 0;
1373 1855
1374fail_vnrele: 1856 out_filestream_unmount:
1857 xfs_filestream_unmount(mp);
1858 out_free_sb:
1859 xfs_freesb(mp);
1860 out_destroy_counters:
1861 xfs_icsb_destroy_counters(mp);
1862 xfs_close_devices(mp);
1863 out_put_qmops:
1864 xfs_qmops_put(mp);
1865 out_put_dmops:
1866 xfs_dmops_put(mp);
1867 out_free_mp:
1868 kfree(mp);
1869 out_free_args:
1870 kfree(args);
1871 return -error;
1872
1873 fail_vnrele:
1375 if (sb->s_root) { 1874 if (sb->s_root) {
1376 dput(sb->s_root); 1875 dput(sb->s_root);
1377 sb->s_root = NULL; 1876 sb->s_root = NULL;
@@ -1379,12 +1878,22 @@ fail_vnrele:
1379 iput(root); 1878 iput(root);
1380 } 1879 }
1381 1880
1382fail_unmount: 1881 fail_unmount:
1383 xfs_unmount(mp, 0, NULL); 1882 /*
1883 * Blow away any referenced inode in the filestreams cache.
1884 * This can and will cause log traffic as inodes go inactive
1885 * here.
1886 */
1887 xfs_filestream_unmount(mp);
1384 1888
1385fail_vfsop: 1889 XFS_bflush(mp->m_ddev_targp);
1386 kmem_free(args, sizeof(*args)); 1890 error = xfs_unmount_flush(mp, 0);
1387 return -error; 1891 WARN_ON(error);
1892
1893 IRELE(mp->m_rootip);
1894
1895 xfs_unmountfs(mp);
1896 goto out_destroy_counters;
1388} 1897}
1389 1898
1390STATIC int 1899STATIC int
@@ -1429,9 +1938,235 @@ static struct file_system_type xfs_fs_type = {
1429 .fs_flags = FS_REQUIRES_DEV, 1938 .fs_flags = FS_REQUIRES_DEV,
1430}; 1939};
1431 1940
1941STATIC int __init
1942xfs_alloc_trace_bufs(void)
1943{
1944#ifdef XFS_ALLOC_TRACE
1945 xfs_alloc_trace_buf = ktrace_alloc(XFS_ALLOC_TRACE_SIZE, KM_MAYFAIL);
1946 if (!xfs_alloc_trace_buf)
1947 goto out;
1948#endif
1949#ifdef XFS_BMAP_TRACE
1950 xfs_bmap_trace_buf = ktrace_alloc(XFS_BMAP_TRACE_SIZE, KM_MAYFAIL);
1951 if (!xfs_bmap_trace_buf)
1952 goto out_free_alloc_trace;
1953#endif
1954#ifdef XFS_BMBT_TRACE
1955 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_MAYFAIL);
1956 if (!xfs_bmbt_trace_buf)
1957 goto out_free_bmap_trace;
1958#endif
1959#ifdef XFS_ATTR_TRACE
1960 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_MAYFAIL);
1961 if (!xfs_attr_trace_buf)
1962 goto out_free_bmbt_trace;
1963#endif
1964#ifdef XFS_DIR2_TRACE
1965 xfs_dir2_trace_buf = ktrace_alloc(XFS_DIR2_GTRACE_SIZE, KM_MAYFAIL);
1966 if (!xfs_dir2_trace_buf)
1967 goto out_free_attr_trace;
1968#endif
1969
1970 return 0;
1971
1972#ifdef XFS_DIR2_TRACE
1973 out_free_attr_trace:
1974#endif
1975#ifdef XFS_ATTR_TRACE
1976 ktrace_free(xfs_attr_trace_buf);
1977 out_free_bmbt_trace:
1978#endif
1979#ifdef XFS_BMBT_TRACE
1980 ktrace_free(xfs_bmbt_trace_buf);
1981 out_free_bmap_trace:
1982#endif
1983#ifdef XFS_BMAP_TRACE
1984 ktrace_free(xfs_bmap_trace_buf);
1985 out_free_alloc_trace:
1986#endif
1987#ifdef XFS_ALLOC_TRACE
1988 ktrace_free(xfs_alloc_trace_buf);
1989 out:
1990#endif
1991 return -ENOMEM;
1992}
1993
1994STATIC void
1995xfs_free_trace_bufs(void)
1996{
1997#ifdef XFS_DIR2_TRACE
1998 ktrace_free(xfs_dir2_trace_buf);
1999#endif
2000#ifdef XFS_ATTR_TRACE
2001 ktrace_free(xfs_attr_trace_buf);
2002#endif
2003#ifdef XFS_BMBT_TRACE
2004 ktrace_free(xfs_bmbt_trace_buf);
2005#endif
2006#ifdef XFS_BMAP_TRACE
2007 ktrace_free(xfs_bmap_trace_buf);
2008#endif
2009#ifdef XFS_ALLOC_TRACE
2010 ktrace_free(xfs_alloc_trace_buf);
2011#endif
2012}
1432 2013
1433STATIC int __init 2014STATIC int __init
1434init_xfs_fs( void ) 2015xfs_init_zones(void)
2016{
2017 xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode",
2018 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
2019 KM_ZONE_SPREAD,
2020 xfs_fs_inode_init_once);
2021 if (!xfs_vnode_zone)
2022 goto out;
2023
2024 xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend");
2025 if (!xfs_ioend_zone)
2026 goto out_destroy_vnode_zone;
2027
2028 xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE,
2029 xfs_ioend_zone);
2030 if (!xfs_ioend_pool)
2031 goto out_destroy_ioend_zone;
2032
2033 xfs_log_ticket_zone = kmem_zone_init(sizeof(xlog_ticket_t),
2034 "xfs_log_ticket");
2035 if (!xfs_log_ticket_zone)
2036 goto out_destroy_ioend_pool;
2037
2038 xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
2039 "xfs_bmap_free_item");
2040 if (!xfs_bmap_free_item_zone)
2041 goto out_destroy_log_ticket_zone;
2042 xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
2043 "xfs_btree_cur");
2044 if (!xfs_btree_cur_zone)
2045 goto out_destroy_bmap_free_item_zone;
2046
2047 xfs_da_state_zone = kmem_zone_init(sizeof(xfs_da_state_t),
2048 "xfs_da_state");
2049 if (!xfs_da_state_zone)
2050 goto out_destroy_btree_cur_zone;
2051
2052 xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
2053 if (!xfs_dabuf_zone)
2054 goto out_destroy_da_state_zone;
2055
2056 xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
2057 if (!xfs_ifork_zone)
2058 goto out_destroy_dabuf_zone;
2059
2060 xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
2061 if (!xfs_trans_zone)
2062 goto out_destroy_ifork_zone;
2063
2064 /*
2065 * The size of the zone allocated buf log item is the maximum
2066 * size possible under XFS. This wastes a little bit of memory,
2067 * but it is much faster.
2068 */
2069 xfs_buf_item_zone = kmem_zone_init((sizeof(xfs_buf_log_item_t) +
2070 (((XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK) /
2071 NBWORD) * sizeof(int))), "xfs_buf_item");
2072 if (!xfs_buf_item_zone)
2073 goto out_destroy_trans_zone;
2074
2075 xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) +
2076 ((XFS_EFD_MAX_FAST_EXTENTS - 1) *
2077 sizeof(xfs_extent_t))), "xfs_efd_item");
2078 if (!xfs_efd_zone)
2079 goto out_destroy_buf_item_zone;
2080
2081 xfs_efi_zone = kmem_zone_init((sizeof(xfs_efi_log_item_t) +
2082 ((XFS_EFI_MAX_FAST_EXTENTS - 1) *
2083 sizeof(xfs_extent_t))), "xfs_efi_item");
2084 if (!xfs_efi_zone)
2085 goto out_destroy_efd_zone;
2086
2087 xfs_inode_zone =
2088 kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode",
2089 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
2090 KM_ZONE_SPREAD, NULL);
2091 if (!xfs_inode_zone)
2092 goto out_destroy_efi_zone;
2093
2094 xfs_ili_zone =
2095 kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
2096 KM_ZONE_SPREAD, NULL);
2097 if (!xfs_ili_zone)
2098 goto out_destroy_inode_zone;
2099
2100#ifdef CONFIG_XFS_POSIX_ACL
2101 xfs_acl_zone = kmem_zone_init(sizeof(xfs_acl_t), "xfs_acl");
2102 if (!xfs_acl_zone)
2103 goto out_destroy_ili_zone;
2104#endif
2105
2106 return 0;
2107
2108#ifdef CONFIG_XFS_POSIX_ACL
2109 out_destroy_ili_zone:
2110#endif
2111 kmem_zone_destroy(xfs_ili_zone);
2112 out_destroy_inode_zone:
2113 kmem_zone_destroy(xfs_inode_zone);
2114 out_destroy_efi_zone:
2115 kmem_zone_destroy(xfs_efi_zone);
2116 out_destroy_efd_zone:
2117 kmem_zone_destroy(xfs_efd_zone);
2118 out_destroy_buf_item_zone:
2119 kmem_zone_destroy(xfs_buf_item_zone);
2120 out_destroy_trans_zone:
2121 kmem_zone_destroy(xfs_trans_zone);
2122 out_destroy_ifork_zone:
2123 kmem_zone_destroy(xfs_ifork_zone);
2124 out_destroy_dabuf_zone:
2125 kmem_zone_destroy(xfs_dabuf_zone);
2126 out_destroy_da_state_zone:
2127 kmem_zone_destroy(xfs_da_state_zone);
2128 out_destroy_btree_cur_zone:
2129 kmem_zone_destroy(xfs_btree_cur_zone);
2130 out_destroy_bmap_free_item_zone:
2131 kmem_zone_destroy(xfs_bmap_free_item_zone);
2132 out_destroy_log_ticket_zone:
2133 kmem_zone_destroy(xfs_log_ticket_zone);
2134 out_destroy_ioend_pool:
2135 mempool_destroy(xfs_ioend_pool);
2136 out_destroy_ioend_zone:
2137 kmem_zone_destroy(xfs_ioend_zone);
2138 out_destroy_vnode_zone:
2139 kmem_zone_destroy(xfs_vnode_zone);
2140 out:
2141 return -ENOMEM;
2142}
2143
2144STATIC void
2145xfs_destroy_zones(void)
2146{
2147#ifdef CONFIG_XFS_POSIX_ACL
2148 kmem_zone_destroy(xfs_acl_zone);
2149#endif
2150 kmem_zone_destroy(xfs_ili_zone);
2151 kmem_zone_destroy(xfs_inode_zone);
2152 kmem_zone_destroy(xfs_efi_zone);
2153 kmem_zone_destroy(xfs_efd_zone);
2154 kmem_zone_destroy(xfs_buf_item_zone);
2155 kmem_zone_destroy(xfs_trans_zone);
2156 kmem_zone_destroy(xfs_ifork_zone);
2157 kmem_zone_destroy(xfs_dabuf_zone);
2158 kmem_zone_destroy(xfs_da_state_zone);
2159 kmem_zone_destroy(xfs_btree_cur_zone);
2160 kmem_zone_destroy(xfs_bmap_free_item_zone);
2161 kmem_zone_destroy(xfs_log_ticket_zone);
2162 mempool_destroy(xfs_ioend_pool);
2163 kmem_zone_destroy(xfs_ioend_zone);
2164 kmem_zone_destroy(xfs_vnode_zone);
2165
2166}
2167
2168STATIC int __init
2169init_xfs_fs(void)
1435{ 2170{
1436 int error; 2171 int error;
1437 static char message[] __initdata = KERN_INFO \ 2172 static char message[] __initdata = KERN_INFO \
@@ -1440,42 +2175,73 @@ init_xfs_fs( void )
1440 printk(message); 2175 printk(message);
1441 2176
1442 ktrace_init(64); 2177 ktrace_init(64);
2178 vn_init();
2179 xfs_dir_startup();
1443 2180
1444 error = xfs_init_zones(); 2181 error = xfs_init_zones();
1445 if (error < 0) 2182 if (error)
1446 goto undo_zones; 2183 goto out;
2184
2185 error = xfs_alloc_trace_bufs();
2186 if (error)
2187 goto out_destroy_zones;
2188
2189 error = xfs_mru_cache_init();
2190 if (error)
2191 goto out_free_trace_buffers;
2192
2193 error = xfs_filestream_init();
2194 if (error)
2195 goto out_mru_cache_uninit;
1447 2196
1448 error = xfs_buf_init(); 2197 error = xfs_buf_init();
1449 if (error < 0) 2198 if (error)
1450 goto undo_buffers; 2199 goto out_filestream_uninit;
2200
2201 error = xfs_init_procfs();
2202 if (error)
2203 goto out_buf_terminate;
2204
2205 error = xfs_sysctl_register();
2206 if (error)
2207 goto out_cleanup_procfs;
1451 2208
1452 vn_init();
1453 xfs_init();
1454 uuid_init();
1455 vfs_initquota(); 2209 vfs_initquota();
1456 2210
1457 error = register_filesystem(&xfs_fs_type); 2211 error = register_filesystem(&xfs_fs_type);
1458 if (error) 2212 if (error)
1459 goto undo_register; 2213 goto out_sysctl_unregister;
1460 return 0; 2214 return 0;
1461 2215
1462undo_register: 2216 out_sysctl_unregister:
2217 xfs_sysctl_unregister();
2218 out_cleanup_procfs:
2219 xfs_cleanup_procfs();
2220 out_buf_terminate:
1463 xfs_buf_terminate(); 2221 xfs_buf_terminate();
1464 2222 out_filestream_uninit:
1465undo_buffers: 2223 xfs_filestream_uninit();
2224 out_mru_cache_uninit:
2225 xfs_mru_cache_uninit();
2226 out_free_trace_buffers:
2227 xfs_free_trace_bufs();
2228 out_destroy_zones:
1466 xfs_destroy_zones(); 2229 xfs_destroy_zones();
1467 2230 out:
1468undo_zones:
1469 return error; 2231 return error;
1470} 2232}
1471 2233
1472STATIC void __exit 2234STATIC void __exit
1473exit_xfs_fs( void ) 2235exit_xfs_fs(void)
1474{ 2236{
1475 vfs_exitquota(); 2237 vfs_exitquota();
1476 unregister_filesystem(&xfs_fs_type); 2238 unregister_filesystem(&xfs_fs_type);
1477 xfs_cleanup(); 2239 xfs_sysctl_unregister();
2240 xfs_cleanup_procfs();
1478 xfs_buf_terminate(); 2241 xfs_buf_terminate();
2242 xfs_filestream_uninit();
2243 xfs_mru_cache_uninit();
2244 xfs_free_trace_bufs();
1479 xfs_destroy_zones(); 2245 xfs_destroy_zones();
1480 ktrace_uninit(); 2246 ktrace_uninit();
1481} 2247}
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 3efb7c6d3303..b7d13da01bd6 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -107,12 +107,10 @@ extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp,
107extern void xfs_flush_inode(struct xfs_inode *); 107extern void xfs_flush_inode(struct xfs_inode *);
108extern void xfs_flush_device(struct xfs_inode *); 108extern void xfs_flush_device(struct xfs_inode *);
109 109
110extern int xfs_blkdev_get(struct xfs_mount *, const char *,
111 struct block_device **);
112extern void xfs_blkdev_put(struct block_device *);
113extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); 110extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
114 111
115extern const struct export_operations xfs_export_operations; 112extern const struct export_operations xfs_export_operations;
113extern struct xattr_handler *xfs_xattr_handlers[];
116 114
117#define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) 115#define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info))
118 116
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index bb997d75c05c..7dacb5bbde3f 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -259,15 +259,17 @@ static ctl_table xfs_root_table[] = {
259 {} 259 {}
260}; 260};
261 261
262void 262int
263xfs_sysctl_register(void) 263xfs_sysctl_register(void)
264{ 264{
265 xfs_table_header = register_sysctl_table(xfs_root_table); 265 xfs_table_header = register_sysctl_table(xfs_root_table);
266 if (!xfs_table_header)
267 return -ENOMEM;
268 return 0;
266} 269}
267 270
268void 271void
269xfs_sysctl_unregister(void) 272xfs_sysctl_unregister(void)
270{ 273{
271 if (xfs_table_header) 274 unregister_sysctl_table(xfs_table_header);
272 unregister_sysctl_table(xfs_table_header);
273} 275}
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h
index 98b97e399d6f..4aadb8056c37 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.h
+++ b/fs/xfs/linux-2.6/xfs_sysctl.h
@@ -93,10 +93,10 @@ enum {
93extern xfs_param_t xfs_params; 93extern xfs_param_t xfs_params;
94 94
95#ifdef CONFIG_SYSCTL 95#ifdef CONFIG_SYSCTL
96extern void xfs_sysctl_register(void); 96extern int xfs_sysctl_register(void);
97extern void xfs_sysctl_unregister(void); 97extern void xfs_sysctl_unregister(void);
98#else 98#else
99# define xfs_sysctl_register() do { } while (0) 99# define xfs_sysctl_register() (0)
100# define xfs_sysctl_unregister() do { } while (0) 100# define xfs_sysctl_unregister() do { } while (0)
101#endif /* CONFIG_SYSCTL */ 101#endif /* CONFIG_SYSCTL */
102 102
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index bc7afe007338..25488b6d9881 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -82,56 +82,6 @@ vn_ioerror(
82 xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l); 82 xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l);
83} 83}
84 84
85/*
86 * Revalidate the Linux inode from the XFS inode.
87 * Note: i_size _not_ updated; we must hold the inode
88 * semaphore when doing that - callers responsibility.
89 */
90int
91vn_revalidate(
92 bhv_vnode_t *vp)
93{
94 struct inode *inode = vn_to_inode(vp);
95 struct xfs_inode *ip = XFS_I(inode);
96 struct xfs_mount *mp = ip->i_mount;
97 unsigned long xflags;
98
99 xfs_itrace_entry(ip);
100
101 if (XFS_FORCED_SHUTDOWN(mp))
102 return -EIO;
103
104 xfs_ilock(ip, XFS_ILOCK_SHARED);
105 inode->i_mode = ip->i_d.di_mode;
106 inode->i_uid = ip->i_d.di_uid;
107 inode->i_gid = ip->i_d.di_gid;
108 inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
109 inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
110 inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
111 inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
112
113 xflags = xfs_ip2xflags(ip);
114 if (xflags & XFS_XFLAG_IMMUTABLE)
115 inode->i_flags |= S_IMMUTABLE;
116 else
117 inode->i_flags &= ~S_IMMUTABLE;
118 if (xflags & XFS_XFLAG_APPEND)
119 inode->i_flags |= S_APPEND;
120 else
121 inode->i_flags &= ~S_APPEND;
122 if (xflags & XFS_XFLAG_SYNC)
123 inode->i_flags |= S_SYNC;
124 else
125 inode->i_flags &= ~S_SYNC;
126 if (xflags & XFS_XFLAG_NOATIME)
127 inode->i_flags |= S_NOATIME;
128 else
129 inode->i_flags &= ~S_NOATIME;
130 xfs_iunlock(ip, XFS_ILOCK_SHARED);
131
132 xfs_iflags_clear(ip, XFS_IMODIFIED);
133 return 0;
134}
135 85
136/* 86/*
137 * Add a reference to a referenced vnode. 87 * Add a reference to a referenced vnode.
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 25eb2a9e8d9b..41ca2cec5d31 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -19,7 +19,6 @@
19#define __XFS_VNODE_H__ 19#define __XFS_VNODE_H__
20 20
21struct file; 21struct file;
22struct bhv_vattr;
23struct xfs_iomap; 22struct xfs_iomap;
24struct attrlist_cursor_kern; 23struct attrlist_cursor_kern;
25 24
@@ -66,87 +65,8 @@ static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
66 Prevent VM access to the pages until 65 Prevent VM access to the pages until
67 the operation completes. */ 66 the operation completes. */
68 67
69/*
70 * Vnode attributes. va_mask indicates those attributes the caller
71 * wants to set or extract.
72 */
73typedef struct bhv_vattr {
74 int va_mask; /* bit-mask of attributes present */
75 mode_t va_mode; /* file access mode and type */
76 xfs_nlink_t va_nlink; /* number of references to file */
77 uid_t va_uid; /* owner user id */
78 gid_t va_gid; /* owner group id */
79 xfs_ino_t va_nodeid; /* file id */
80 xfs_off_t va_size; /* file size in bytes */
81 u_long va_blocksize; /* blocksize preferred for i/o */
82 struct timespec va_atime; /* time of last access */
83 struct timespec va_mtime; /* time of last modification */
84 struct timespec va_ctime; /* time file changed */
85 u_int va_gen; /* generation number of file */
86 xfs_dev_t va_rdev; /* device the special file represents */
87 __int64_t va_nblocks; /* number of blocks allocated */
88 u_long va_xflags; /* random extended file flags */
89 u_long va_extsize; /* file extent size */
90 u_long va_nextents; /* number of extents in file */
91 u_long va_anextents; /* number of attr extents in file */
92 prid_t va_projid; /* project id */
93} bhv_vattr_t;
94
95/*
96 * setattr or getattr attributes
97 */
98#define XFS_AT_TYPE 0x00000001
99#define XFS_AT_MODE 0x00000002
100#define XFS_AT_UID 0x00000004
101#define XFS_AT_GID 0x00000008
102#define XFS_AT_FSID 0x00000010
103#define XFS_AT_NODEID 0x00000020
104#define XFS_AT_NLINK 0x00000040
105#define XFS_AT_SIZE 0x00000080
106#define XFS_AT_ATIME 0x00000100
107#define XFS_AT_MTIME 0x00000200
108#define XFS_AT_CTIME 0x00000400
109#define XFS_AT_RDEV 0x00000800
110#define XFS_AT_BLKSIZE 0x00001000
111#define XFS_AT_NBLOCKS 0x00002000
112#define XFS_AT_VCODE 0x00004000
113#define XFS_AT_MAC 0x00008000
114#define XFS_AT_UPDATIME 0x00010000
115#define XFS_AT_UPDMTIME 0x00020000
116#define XFS_AT_UPDCTIME 0x00040000
117#define XFS_AT_ACL 0x00080000
118#define XFS_AT_CAP 0x00100000
119#define XFS_AT_INF 0x00200000
120#define XFS_AT_XFLAGS 0x00400000
121#define XFS_AT_EXTSIZE 0x00800000
122#define XFS_AT_NEXTENTS 0x01000000
123#define XFS_AT_ANEXTENTS 0x02000000
124#define XFS_AT_PROJID 0x04000000
125#define XFS_AT_SIZE_NOPERM 0x08000000
126#define XFS_AT_GENCOUNT 0x10000000
127
128#define XFS_AT_ALL (XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
129 XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
130 XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
131 XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|XFS_AT_MAC|\
132 XFS_AT_ACL|XFS_AT_CAP|XFS_AT_INF|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|\
133 XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_PROJID|XFS_AT_GENCOUNT)
134
135#define XFS_AT_STAT (XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
136 XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
137 XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
138 XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_PROJID)
139
140#define XFS_AT_TIMES (XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME)
141
142#define XFS_AT_UPDTIMES (XFS_AT_UPDATIME|XFS_AT_UPDMTIME|XFS_AT_UPDCTIME)
143
144#define XFS_AT_NOSET (XFS_AT_NLINK|XFS_AT_RDEV|XFS_AT_FSID|XFS_AT_NODEID|\
145 XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
146 XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)
147 68
148extern void vn_init(void); 69extern void vn_init(void);
149extern int vn_revalidate(bhv_vnode_t *);
150 70
151/* 71/*
152 * Yeah, these don't take vnode anymore at all, all this should be 72 * Yeah, these don't take vnode anymore at all, all this should be
@@ -219,15 +139,6 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
219#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ 139#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \
220 PAGECACHE_TAG_DIRTY) 140 PAGECACHE_TAG_DIRTY)
221 141
222/*
223 * Flags to vop_setattr/getattr.
224 */
225#define ATTR_UTIME 0x01 /* non-default utime(2) request */
226#define ATTR_DMI 0x08 /* invocation from a DMI function */
227#define ATTR_LAZY 0x80 /* set/get attributes lazily */
228#define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */
229#define ATTR_NOLOCK 0x200 /* Don't grab any conflicting locks */
230#define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */
231 142
232/* 143/*
233 * Tracking vnode activity. 144 * Tracking vnode activity.
diff --git a/fs/xfs/linux-2.6/xfs_xattr.c b/fs/xfs/linux-2.6/xfs_xattr.c
new file mode 100644
index 000000000000..964621fde6ed
--- /dev/null
+++ b/fs/xfs/linux-2.6/xfs_xattr.c
@@ -0,0 +1,330 @@
1/*
2 * Copyright (C) 2008 Christoph Hellwig.
3 * Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
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
19#include "xfs.h"
20#include "xfs_da_btree.h"
21#include "xfs_bmap_btree.h"
22#include "xfs_inode.h"
23#include "xfs_attr.h"
24#include "xfs_attr_leaf.h"
25#include "xfs_acl.h"
26#include "xfs_vnodeops.h"
27
28#include <linux/posix_acl_xattr.h>
29#include <linux/xattr.h>
30
31
32/*
33 * ACL handling. Should eventually be moved into xfs_acl.c
34 */
35
36static int
37xfs_decode_acl(const char *name)
38{
39 if (strcmp(name, "posix_acl_access") == 0)
40 return _ACL_TYPE_ACCESS;
41 else if (strcmp(name, "posix_acl_default") == 0)
42 return _ACL_TYPE_DEFAULT;
43 return -EINVAL;
44}
45
46/*
47 * Get system extended attributes which at the moment only
48 * includes Posix ACLs.
49 */
50static int
51xfs_xattr_system_get(struct inode *inode, const char *name,
52 void *buffer, size_t size)
53{
54 int acl;
55
56 acl = xfs_decode_acl(name);
57 if (acl < 0)
58 return acl;
59
60 return xfs_acl_vget(inode, buffer, size, acl);
61}
62
63static int
64xfs_xattr_system_set(struct inode *inode, const char *name,
65 const void *value, size_t size, int flags)
66{
67 int acl;
68
69 acl = xfs_decode_acl(name);
70 if (acl < 0)
71 return acl;
72 if (flags & XATTR_CREATE)
73 return -EINVAL;
74
75 if (!value)
76 return xfs_acl_vremove(inode, acl);
77
78 return xfs_acl_vset(inode, (void *)value, size, acl);
79}
80
81static struct xattr_handler xfs_xattr_system_handler = {
82 .prefix = XATTR_SYSTEM_PREFIX,
83 .get = xfs_xattr_system_get,
84 .set = xfs_xattr_system_set,
85};
86
87
88/*
89 * Real xattr handling. The only difference between the namespaces is
90 * a flag passed to the low-level attr code.
91 */
92
93static int
94__xfs_xattr_get(struct inode *inode, const char *name,
95 void *value, size_t size, int xflags)
96{
97 struct xfs_inode *ip = XFS_I(inode);
98 int error, asize = size;
99
100 if (strcmp(name, "") == 0)
101 return -EINVAL;
102
103 /* Convert Linux syscall to XFS internal ATTR flags */
104 if (!size) {
105 xflags |= ATTR_KERNOVAL;
106 value = NULL;
107 }
108
109 error = -xfs_attr_get(ip, name, value, &asize, xflags);
110 if (error)
111 return error;
112 return asize;
113}
114
115static int
116__xfs_xattr_set(struct inode *inode, const char *name, const void *value,
117 size_t size, int flags, int xflags)
118{
119 struct xfs_inode *ip = XFS_I(inode);
120
121 if (strcmp(name, "") == 0)
122 return -EINVAL;
123
124 /* Convert Linux syscall to XFS internal ATTR flags */
125 if (flags & XATTR_CREATE)
126 xflags |= ATTR_CREATE;
127 if (flags & XATTR_REPLACE)
128 xflags |= ATTR_REPLACE;
129
130 if (!value)
131 return -xfs_attr_remove(ip, name, xflags);
132 return -xfs_attr_set(ip, name, (void *)value, size, xflags);
133}
134
135static int
136xfs_xattr_user_get(struct inode *inode, const char *name,
137 void *value, size_t size)
138{
139 return __xfs_xattr_get(inode, name, value, size, 0);
140}
141
142static int
143xfs_xattr_user_set(struct inode *inode, const char *name,
144 const void *value, size_t size, int flags)
145{
146 return __xfs_xattr_set(inode, name, value, size, flags, 0);
147}
148
149static struct xattr_handler xfs_xattr_user_handler = {
150 .prefix = XATTR_USER_PREFIX,
151 .get = xfs_xattr_user_get,
152 .set = xfs_xattr_user_set,
153};
154
155
156static int
157xfs_xattr_trusted_get(struct inode *inode, const char *name,
158 void *value, size_t size)
159{
160 return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT);
161}
162
163static int
164xfs_xattr_trusted_set(struct inode *inode, const char *name,
165 const void *value, size_t size, int flags)
166{
167 return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT);
168}
169
170static struct xattr_handler xfs_xattr_trusted_handler = {
171 .prefix = XATTR_TRUSTED_PREFIX,
172 .get = xfs_xattr_trusted_get,
173 .set = xfs_xattr_trusted_set,
174};
175
176
177static int
178xfs_xattr_secure_get(struct inode *inode, const char *name,
179 void *value, size_t size)
180{
181 return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE);
182}
183
184static int
185xfs_xattr_secure_set(struct inode *inode, const char *name,
186 const void *value, size_t size, int flags)
187{
188 return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE);
189}
190
191static struct xattr_handler xfs_xattr_security_handler = {
192 .prefix = XATTR_SECURITY_PREFIX,
193 .get = xfs_xattr_secure_get,
194 .set = xfs_xattr_secure_set,
195};
196
197
198struct xattr_handler *xfs_xattr_handlers[] = {
199 &xfs_xattr_user_handler,
200 &xfs_xattr_trusted_handler,
201 &xfs_xattr_security_handler,
202 &xfs_xattr_system_handler,
203 NULL
204};
205
206static unsigned int xfs_xattr_prefix_len(int flags)
207{
208 if (flags & XFS_ATTR_SECURE)
209 return sizeof("security");
210 else if (flags & XFS_ATTR_ROOT)
211 return sizeof("trusted");
212 else
213 return sizeof("user");
214}
215
216static const char *xfs_xattr_prefix(int flags)
217{
218 if (flags & XFS_ATTR_SECURE)
219 return xfs_xattr_security_handler.prefix;
220 else if (flags & XFS_ATTR_ROOT)
221 return xfs_xattr_trusted_handler.prefix;
222 else
223 return xfs_xattr_user_handler.prefix;
224}
225
226static int
227xfs_xattr_put_listent(struct xfs_attr_list_context *context, int flags,
228 char *name, int namelen, int valuelen, char *value)
229{
230 unsigned int prefix_len = xfs_xattr_prefix_len(flags);
231 char *offset;
232 int arraytop;
233
234 ASSERT(context->count >= 0);
235
236 /*
237 * Only show root namespace entries if we are actually allowed to
238 * see them.
239 */
240 if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN))
241 return 0;
242
243 arraytop = context->count + prefix_len + namelen + 1;
244 if (arraytop > context->firstu) {
245 context->count = -1; /* insufficient space */
246 return 1;
247 }
248 offset = (char *)context->alist + context->count;
249 strncpy(offset, xfs_xattr_prefix(flags), prefix_len);
250 offset += prefix_len;
251 strncpy(offset, name, namelen); /* real name */
252 offset += namelen;
253 *offset = '\0';
254 context->count += prefix_len + namelen + 1;
255 return 0;
256}
257
258static int
259xfs_xattr_put_listent_sizes(struct xfs_attr_list_context *context, int flags,
260 char *name, int namelen, int valuelen, char *value)
261{
262 context->count += xfs_xattr_prefix_len(flags) + namelen + 1;
263 return 0;
264}
265
266static int
267list_one_attr(const char *name, const size_t len, void *data,
268 size_t size, ssize_t *result)
269{
270 char *p = data + *result;
271
272 *result += len;
273 if (!size)
274 return 0;
275 if (*result > size)
276 return -ERANGE;
277
278 strcpy(p, name);
279 return 0;
280}
281
282ssize_t
283xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
284{
285 struct xfs_attr_list_context context;
286 struct attrlist_cursor_kern cursor = { 0 };
287 struct inode *inode = dentry->d_inode;
288 int error;
289
290 /*
291 * First read the regular on-disk attributes.
292 */
293 memset(&context, 0, sizeof(context));
294 context.dp = XFS_I(inode);
295 context.cursor = &cursor;
296 context.resynch = 1;
297 context.alist = data;
298 context.bufsize = size;
299 context.firstu = context.bufsize;
300
301 if (size)
302 context.put_listent = xfs_xattr_put_listent;
303 else
304 context.put_listent = xfs_xattr_put_listent_sizes;
305
306 xfs_attr_list_int(&context);
307 if (context.count < 0)
308 return -ERANGE;
309
310 /*
311 * Then add the two synthetic ACL attributes.
312 */
313 if (xfs_acl_vhasacl_access(inode)) {
314 error = list_one_attr(POSIX_ACL_XATTR_ACCESS,
315 strlen(POSIX_ACL_XATTR_ACCESS) + 1,
316 data, size, &context.count);
317 if (error)
318 return error;
319 }
320
321 if (xfs_acl_vhasacl_default(inode)) {
322 error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
323 strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
324 data, size, &context.count);
325 if (error)
326 return error;
327 }
328
329 return context.count;
330}
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 85df3288efd5..fc9f3fb39b7b 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -1435,8 +1435,7 @@ xfs_dqlock2(
1435/* ARGSUSED */ 1435/* ARGSUSED */
1436int 1436int
1437xfs_qm_dqpurge( 1437xfs_qm_dqpurge(
1438 xfs_dquot_t *dqp, 1438 xfs_dquot_t *dqp)
1439 uint flags)
1440{ 1439{
1441 xfs_dqhash_t *thishash; 1440 xfs_dqhash_t *thishash;
1442 xfs_mount_t *mp = dqp->q_mount; 1441 xfs_mount_t *mp = dqp->q_mount;
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 5c371a92e3e2..f7393bba4e95 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -164,7 +164,7 @@ extern void xfs_qm_dqprint(xfs_dquot_t *);
164 164
165extern void xfs_qm_dqdestroy(xfs_dquot_t *); 165extern void xfs_qm_dqdestroy(xfs_dquot_t *);
166extern int xfs_qm_dqflush(xfs_dquot_t *, uint); 166extern int xfs_qm_dqflush(xfs_dquot_t *, uint);
167extern int xfs_qm_dqpurge(xfs_dquot_t *, uint); 167extern int xfs_qm_dqpurge(xfs_dquot_t *);
168extern void xfs_qm_dqunpin_wait(xfs_dquot_t *); 168extern void xfs_qm_dqunpin_wait(xfs_dquot_t *);
169extern int xfs_qm_dqlock_nowait(xfs_dquot_t *); 169extern int xfs_qm_dqlock_nowait(xfs_dquot_t *);
170extern int xfs_qm_dqflock_nowait(xfs_dquot_t *); 170extern int xfs_qm_dqflock_nowait(xfs_dquot_t *);
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 36e05ca78412..08d2fc89e6a1 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -576,8 +576,8 @@ xfs_qm_qoffend_logitem_committed(
576 * xfs_trans_delete_ail() drops the AIL lock. 576 * xfs_trans_delete_ail() drops the AIL lock.
577 */ 577 */
578 xfs_trans_delete_ail(qfs->qql_item.li_mountp, (xfs_log_item_t *)qfs); 578 xfs_trans_delete_ail(qfs->qql_item.li_mountp, (xfs_log_item_t *)qfs);
579 kmem_free(qfs, sizeof(xfs_qoff_logitem_t)); 579 kmem_free(qfs);
580 kmem_free(qfe, sizeof(xfs_qoff_logitem_t)); 580 kmem_free(qfe);
581 return (xfs_lsn_t)-1; 581 return (xfs_lsn_t)-1;
582} 582}
583 583
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index d31cce1165c5..021934a3d456 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -192,8 +192,8 @@ xfs_qm_destroy(
192 xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i])); 192 xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
193 xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i])); 193 xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i]));
194 } 194 }
195 kmem_free(xqm->qm_usr_dqhtable, hsize * sizeof(xfs_dqhash_t)); 195 kmem_free(xqm->qm_usr_dqhtable);
196 kmem_free(xqm->qm_grp_dqhtable, hsize * sizeof(xfs_dqhash_t)); 196 kmem_free(xqm->qm_grp_dqhtable);
197 xqm->qm_usr_dqhtable = NULL; 197 xqm->qm_usr_dqhtable = NULL;
198 xqm->qm_grp_dqhtable = NULL; 198 xqm->qm_grp_dqhtable = NULL;
199 xqm->qm_dqhashmask = 0; 199 xqm->qm_dqhashmask = 0;
@@ -201,7 +201,7 @@ xfs_qm_destroy(
201#ifdef DEBUG 201#ifdef DEBUG
202 mutex_destroy(&qcheck_lock); 202 mutex_destroy(&qcheck_lock);
203#endif 203#endif
204 kmem_free(xqm, sizeof(xfs_qm_t)); 204 kmem_free(xqm);
205} 205}
206 206
207/* 207/*
@@ -445,11 +445,11 @@ xfs_qm_unmount_quotas(
445 } 445 }
446 } 446 }
447 if (uqp) { 447 if (uqp) {
448 XFS_PURGE_INODE(uqp); 448 IRELE(uqp);
449 mp->m_quotainfo->qi_uquotaip = NULL; 449 mp->m_quotainfo->qi_uquotaip = NULL;
450 } 450 }
451 if (gqp) { 451 if (gqp) {
452 XFS_PURGE_INODE(gqp); 452 IRELE(gqp);
453 mp->m_quotainfo->qi_gquotaip = NULL; 453 mp->m_quotainfo->qi_gquotaip = NULL;
454 } 454 }
455out: 455out:
@@ -631,7 +631,7 @@ xfs_qm_dqpurge_int(
631 * freelist in INACTIVE state. 631 * freelist in INACTIVE state.
632 */ 632 */
633 nextdqp = dqp->MPL_NEXT; 633 nextdqp = dqp->MPL_NEXT;
634 nmisses += xfs_qm_dqpurge(dqp, flags); 634 nmisses += xfs_qm_dqpurge(dqp);
635 dqp = nextdqp; 635 dqp = nextdqp;
636 } 636 }
637 xfs_qm_mplist_unlock(mp); 637 xfs_qm_mplist_unlock(mp);
@@ -1134,7 +1134,7 @@ xfs_qm_init_quotainfo(
1134 * and change the superblock accordingly. 1134 * and change the superblock accordingly.
1135 */ 1135 */
1136 if ((error = xfs_qm_init_quotainos(mp))) { 1136 if ((error = xfs_qm_init_quotainos(mp))) {
1137 kmem_free(qinf, sizeof(xfs_quotainfo_t)); 1137 kmem_free(qinf);
1138 mp->m_quotainfo = NULL; 1138 mp->m_quotainfo = NULL;
1139 return error; 1139 return error;
1140 } 1140 }
@@ -1240,15 +1240,15 @@ xfs_qm_destroy_quotainfo(
1240 xfs_qm_list_destroy(&qi->qi_dqlist); 1240 xfs_qm_list_destroy(&qi->qi_dqlist);
1241 1241
1242 if (qi->qi_uquotaip) { 1242 if (qi->qi_uquotaip) {
1243 XFS_PURGE_INODE(qi->qi_uquotaip); 1243 IRELE(qi->qi_uquotaip);
1244 qi->qi_uquotaip = NULL; /* paranoia */ 1244 qi->qi_uquotaip = NULL; /* paranoia */
1245 } 1245 }
1246 if (qi->qi_gquotaip) { 1246 if (qi->qi_gquotaip) {
1247 XFS_PURGE_INODE(qi->qi_gquotaip); 1247 IRELE(qi->qi_gquotaip);
1248 qi->qi_gquotaip = NULL; 1248 qi->qi_gquotaip = NULL;
1249 } 1249 }
1250 mutex_destroy(&qi->qi_quotaofflock); 1250 mutex_destroy(&qi->qi_quotaofflock);
1251 kmem_free(qi, sizeof(xfs_quotainfo_t)); 1251 kmem_free(qi);
1252 mp->m_quotainfo = NULL; 1252 mp->m_quotainfo = NULL;
1253} 1253}
1254 1254
@@ -1394,7 +1394,7 @@ xfs_qm_qino_alloc(
1394 * locked exclusively and joined to the transaction already. 1394 * locked exclusively and joined to the transaction already.
1395 */ 1395 */
1396 ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL)); 1396 ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL));
1397 VN_HOLD(XFS_ITOV((*ip))); 1397 IHOLD(*ip);
1398 1398
1399 /* 1399 /*
1400 * Make the changes in the superblock, and log those too. 1400 * Make the changes in the superblock, and log those too.
@@ -1623,7 +1623,7 @@ xfs_qm_dqiterate(
1623 break; 1623 break;
1624 } while (nmaps > 0); 1624 } while (nmaps > 0);
1625 1625
1626 kmem_free(map, XFS_DQITER_MAP_SIZE * sizeof(*map)); 1626 kmem_free(map);
1627 1627
1628 return error; 1628 return error;
1629} 1629}
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 768a3b27d2b6..adfb8723f65a 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -362,11 +362,11 @@ xfs_qm_scall_quotaoff(
362 * if we don't need them anymore. 362 * if we don't need them anymore.
363 */ 363 */
364 if ((dqtype & XFS_QMOPT_UQUOTA) && XFS_QI_UQIP(mp)) { 364 if ((dqtype & XFS_QMOPT_UQUOTA) && XFS_QI_UQIP(mp)) {
365 XFS_PURGE_INODE(XFS_QI_UQIP(mp)); 365 IRELE(XFS_QI_UQIP(mp));
366 XFS_QI_UQIP(mp) = NULL; 366 XFS_QI_UQIP(mp) = NULL;
367 } 367 }
368 if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) { 368 if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) {
369 XFS_PURGE_INODE(XFS_QI_GQIP(mp)); 369 IRELE(XFS_QI_GQIP(mp));
370 XFS_QI_GQIP(mp) = NULL; 370 XFS_QI_GQIP(mp) = NULL;
371 } 371 }
372out_error: 372out_error:
@@ -1449,14 +1449,14 @@ xfs_qm_internalqcheck(
1449 for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) { 1449 for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
1450 xfs_dqtest_cmp(d); 1450 xfs_dqtest_cmp(d);
1451 e = (xfs_dqtest_t *) d->HL_NEXT; 1451 e = (xfs_dqtest_t *) d->HL_NEXT;
1452 kmem_free(d, sizeof(xfs_dqtest_t)); 1452 kmem_free(d);
1453 d = e; 1453 d = e;
1454 } 1454 }
1455 h1 = &qmtest_gdqtab[i]; 1455 h1 = &qmtest_gdqtab[i];
1456 for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) { 1456 for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
1457 xfs_dqtest_cmp(d); 1457 xfs_dqtest_cmp(d);
1458 e = (xfs_dqtest_t *) d->HL_NEXT; 1458 e = (xfs_dqtest_t *) d->HL_NEXT;
1459 kmem_free(d, sizeof(xfs_dqtest_t)); 1459 kmem_free(d);
1460 d = e; 1460 d = e;
1461 } 1461 }
1462 } 1462 }
@@ -1467,8 +1467,8 @@ xfs_qm_internalqcheck(
1467 } else { 1467 } else {
1468 cmn_err(CE_DEBUG, "******** quotacheck successful! ********"); 1468 cmn_err(CE_DEBUG, "******** quotacheck successful! ********");
1469 } 1469 }
1470 kmem_free(qmtest_udqtab, qmtest_hashmask * sizeof(xfs_dqhash_t)); 1470 kmem_free(qmtest_udqtab);
1471 kmem_free(qmtest_gdqtab, qmtest_hashmask * sizeof(xfs_dqhash_t)); 1471 kmem_free(qmtest_gdqtab);
1472 mutex_unlock(&qcheck_lock); 1472 mutex_unlock(&qcheck_lock);
1473 return (qmtest_nfails); 1473 return (qmtest_nfails);
1474} 1474}
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 5e4a40b1c565..c4fcea600bc2 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -158,9 +158,6 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
158#define XFS_IS_SUSER_DQUOT(dqp) \ 158#define XFS_IS_SUSER_DQUOT(dqp) \
159 (!((dqp)->q_core.d_id)) 159 (!((dqp)->q_core.d_id))
160 160
161#define XFS_PURGE_INODE(ip) \
162 IRELE(ip);
163
164#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \ 161#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
165 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \ 162 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
166 (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???"))) 163 (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
index 0b75d302508f..a34ef05489b1 100644
--- a/fs/xfs/support/ktrace.c
+++ b/fs/xfs/support/ktrace.c
@@ -89,7 +89,7 @@ ktrace_alloc(int nentries, unsigned int __nocast sleep)
89 if (sleep & KM_SLEEP) 89 if (sleep & KM_SLEEP)
90 panic("ktrace_alloc: NULL memory on KM_SLEEP request!"); 90 panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
91 91
92 kmem_free(ktp, sizeof(*ktp)); 92 kmem_free(ktp);
93 93
94 return NULL; 94 return NULL;
95 } 95 }
@@ -126,7 +126,7 @@ ktrace_free(ktrace_t *ktp)
126 } else { 126 } else {
127 entries_size = (int)(ktp->kt_nentries * sizeof(ktrace_entry_t)); 127 entries_size = (int)(ktp->kt_nentries * sizeof(ktrace_entry_t));
128 128
129 kmem_free(ktp->kt_entries, entries_size); 129 kmem_free(ktp->kt_entries);
130 } 130 }
131 131
132 kmem_zone_free(ktrace_hdr_zone, ktp); 132 kmem_zone_free(ktrace_hdr_zone, ktp);
diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c
index 493a6ecf8590..5830c040ea7e 100644
--- a/fs/xfs/support/uuid.c
+++ b/fs/xfs/support/uuid.c
@@ -17,7 +17,7 @@
17 */ 17 */
18#include <xfs.h> 18#include <xfs.h>
19 19
20static mutex_t uuid_monitor; 20static DEFINE_MUTEX(uuid_monitor);
21static int uuid_table_size; 21static int uuid_table_size;
22static uuid_t *uuid_table; 22static uuid_t *uuid_table;
23 23
@@ -132,9 +132,3 @@ uuid_table_remove(uuid_t *uuid)
132 ASSERT(i < uuid_table_size); 132 ASSERT(i < uuid_table_size);
133 mutex_unlock(&uuid_monitor); 133 mutex_unlock(&uuid_monitor);
134} 134}
135
136void __init
137uuid_init(void)
138{
139 mutex_init(&uuid_monitor);
140}
diff --git a/fs/xfs/support/uuid.h b/fs/xfs/support/uuid.h
index b6f5922199ba..cff5b607d445 100644
--- a/fs/xfs/support/uuid.h
+++ b/fs/xfs/support/uuid.h
@@ -22,7 +22,6 @@ typedef struct {
22 unsigned char __u_bits[16]; 22 unsigned char __u_bits[16];
23} uuid_t; 23} uuid_t;
24 24
25extern void uuid_init(void);
26extern void uuid_create_nil(uuid_t *uuid); 25extern void uuid_create_nil(uuid_t *uuid);
27extern int uuid_is_nil(uuid_t *uuid); 26extern int uuid_is_nil(uuid_t *uuid);
28extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2); 27extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index ebee3a4f703a..3e4648ad9cfc 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -341,8 +341,7 @@ xfs_acl_iaccess(
341 341
342 /* If the file has no ACL return -1. */ 342 /* If the file has no ACL return -1. */
343 rval = sizeof(xfs_acl_t); 343 rval = sizeof(xfs_acl_t);
344 if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval, 344 if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval, ATTR_ROOT)) {
345 ATTR_ROOT | ATTR_KERNACCESS)) {
346 _ACL_FREE(acl); 345 _ACL_FREE(acl);
347 return -1; 346 return -1;
348 } 347 }
@@ -720,7 +719,7 @@ xfs_acl_setmode(
720 xfs_acl_t *acl, 719 xfs_acl_t *acl,
721 int *basicperms) 720 int *basicperms)
722{ 721{
723 bhv_vattr_t va; 722 struct iattr iattr;
724 xfs_acl_entry_t *ap; 723 xfs_acl_entry_t *ap;
725 xfs_acl_entry_t *gap = NULL; 724 xfs_acl_entry_t *gap = NULL;
726 int i, nomask = 1; 725 int i, nomask = 1;
@@ -734,25 +733,25 @@ xfs_acl_setmode(
734 * Copy the u::, g::, o::, and m:: bits from the ACL into the 733 * Copy the u::, g::, o::, and m:: bits from the ACL into the
735 * mode. The m:: bits take precedence over the g:: bits. 734 * mode. The m:: bits take precedence over the g:: bits.
736 */ 735 */
737 va.va_mask = XFS_AT_MODE; 736 iattr.ia_valid = ATTR_MODE;
738 va.va_mode = xfs_vtoi(vp)->i_d.di_mode; 737 iattr.ia_mode = xfs_vtoi(vp)->i_d.di_mode;
739 va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); 738 iattr.ia_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
740 ap = acl->acl_entry; 739 ap = acl->acl_entry;
741 for (i = 0; i < acl->acl_cnt; ++i) { 740 for (i = 0; i < acl->acl_cnt; ++i) {
742 switch (ap->ae_tag) { 741 switch (ap->ae_tag) {
743 case ACL_USER_OBJ: 742 case ACL_USER_OBJ:
744 va.va_mode |= ap->ae_perm << 6; 743 iattr.ia_mode |= ap->ae_perm << 6;
745 break; 744 break;
746 case ACL_GROUP_OBJ: 745 case ACL_GROUP_OBJ:
747 gap = ap; 746 gap = ap;
748 break; 747 break;
749 case ACL_MASK: /* more than just standard modes */ 748 case ACL_MASK: /* more than just standard modes */
750 nomask = 0; 749 nomask = 0;
751 va.va_mode |= ap->ae_perm << 3; 750 iattr.ia_mode |= ap->ae_perm << 3;
752 *basicperms = 0; 751 *basicperms = 0;
753 break; 752 break;
754 case ACL_OTHER: 753 case ACL_OTHER:
755 va.va_mode |= ap->ae_perm; 754 iattr.ia_mode |= ap->ae_perm;
756 break; 755 break;
757 default: /* more than just standard modes */ 756 default: /* more than just standard modes */
758 *basicperms = 0; 757 *basicperms = 0;
@@ -763,9 +762,9 @@ xfs_acl_setmode(
763 762
764 /* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */ 763 /* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */
765 if (gap && nomask) 764 if (gap && nomask)
766 va.va_mode |= gap->ae_perm << 3; 765 iattr.ia_mode |= gap->ae_perm << 3;
767 766
768 return xfs_setattr(xfs_vtoi(vp), &va, 0, sys_cred); 767 return xfs_setattr(xfs_vtoi(vp), &iattr, 0, sys_cred);
769} 768}
770 769
771/* 770/*
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 332a772461c4..323ee94cf831 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -46,6 +46,8 @@ typedef struct xfs_acl {
46#define SGI_ACL_FILE_SIZE (sizeof(SGI_ACL_FILE)-1) 46#define SGI_ACL_FILE_SIZE (sizeof(SGI_ACL_FILE)-1)
47#define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1) 47#define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1)
48 48
49#define _ACL_TYPE_ACCESS 1
50#define _ACL_TYPE_DEFAULT 2
49 51
50#ifdef CONFIG_XFS_POSIX_ACL 52#ifdef CONFIG_XFS_POSIX_ACL
51 53
@@ -66,8 +68,6 @@ extern int xfs_acl_vset(bhv_vnode_t *, void *, size_t, int);
66extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int); 68extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int);
67extern int xfs_acl_vremove(bhv_vnode_t *, int); 69extern int xfs_acl_vremove(bhv_vnode_t *, int);
68 70
69#define _ACL_TYPE_ACCESS 1
70#define _ACL_TYPE_DEFAULT 2
71#define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE)) 71#define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
72 72
73#define _ACL_INHERIT(c,m,d) (xfs_acl_inherit(c,m,d)) 73#define _ACL_INHERIT(c,m,d) (xfs_acl_inherit(c,m,d))
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index df151a859186..78de80e3caa2 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -16,8 +16,6 @@
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 18
19#include <linux/capability.h>
20
21#include "xfs.h" 19#include "xfs.h"
22#include "xfs_fs.h" 20#include "xfs_fs.h"
23#include "xfs_types.h" 21#include "xfs_types.h"
@@ -57,11 +55,6 @@
57 * Provide the external interfaces to manage attribute lists. 55 * Provide the external interfaces to manage attribute lists.
58 */ 56 */
59 57
60#define ATTR_SYSCOUNT 2
61static struct attrnames posix_acl_access;
62static struct attrnames posix_acl_default;
63static struct attrnames *attr_system_names[ATTR_SYSCOUNT];
64
65/*======================================================================== 58/*========================================================================
66 * Function prototypes for the kernel. 59 * Function prototypes for the kernel.
67 *========================================================================*/ 60 *========================================================================*/
@@ -116,6 +109,17 @@ xfs_attr_name_to_xname(
116 return 0; 109 return 0;
117} 110}
118 111
112STATIC int
113xfs_inode_hasattr(
114 struct xfs_inode *ip)
115{
116 if (!XFS_IFORK_Q(ip) ||
117 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
118 ip->i_d.di_anextents == 0))
119 return 0;
120 return 1;
121}
122
119/*======================================================================== 123/*========================================================================
120 * Overall external interface routines. 124 * Overall external interface routines.
121 *========================================================================*/ 125 *========================================================================*/
@@ -127,10 +131,8 @@ xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name,
127 xfs_da_args_t args; 131 xfs_da_args_t args;
128 int error; 132 int error;
129 133
130 if ((XFS_IFORK_Q(ip) == 0) || 134 if (!xfs_inode_hasattr(ip))
131 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 135 return ENOATTR;
132 ip->i_d.di_anextents == 0))
133 return(ENOATTR);
134 136
135 /* 137 /*
136 * Fill in the arg structure for this request. 138 * Fill in the arg structure for this request.
@@ -148,11 +150,7 @@ xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name,
148 /* 150 /*
149 * Decide on what work routines to call based on the inode size. 151 * Decide on what work routines to call based on the inode size.
150 */ 152 */
151 if (XFS_IFORK_Q(ip) == 0 || 153 if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
152 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
153 ip->i_d.di_anextents == 0)) {
154 error = XFS_ERROR(ENOATTR);
155 } else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
156 error = xfs_attr_shortform_getvalue(&args); 154 error = xfs_attr_shortform_getvalue(&args);
157 } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { 155 } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) {
158 error = xfs_attr_leaf_get(&args); 156 error = xfs_attr_leaf_get(&args);
@@ -241,8 +239,7 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
241 args.firstblock = &firstblock; 239 args.firstblock = &firstblock;
242 args.flist = &flist; 240 args.flist = &flist;
243 args.whichfork = XFS_ATTR_FORK; 241 args.whichfork = XFS_ATTR_FORK;
244 args.addname = 1; 242 args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
245 args.oknoent = 1;
246 243
247 /* 244 /*
248 * Determine space new attribute will use, and if it would be 245 * Determine space new attribute will use, and if it would be
@@ -529,9 +526,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
529 /* 526 /*
530 * Decide on what work routines to call based on the inode size. 527 * Decide on what work routines to call based on the inode size.
531 */ 528 */
532 if (XFS_IFORK_Q(dp) == 0 || 529 if (!xfs_inode_hasattr(dp)) {
533 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
534 dp->i_d.di_anextents == 0)) {
535 error = XFS_ERROR(ENOATTR); 530 error = XFS_ERROR(ENOATTR);
536 goto out; 531 goto out;
537 } 532 }
@@ -601,29 +596,33 @@ xfs_attr_remove(
601 return error; 596 return error;
602 597
603 xfs_ilock(dp, XFS_ILOCK_SHARED); 598 xfs_ilock(dp, XFS_ILOCK_SHARED);
604 if (XFS_IFORK_Q(dp) == 0 || 599 if (!xfs_inode_hasattr(dp)) {
605 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
606 dp->i_d.di_anextents == 0)) {
607 xfs_iunlock(dp, XFS_ILOCK_SHARED); 600 xfs_iunlock(dp, XFS_ILOCK_SHARED);
608 return(XFS_ERROR(ENOATTR)); 601 return XFS_ERROR(ENOATTR);
609 } 602 }
610 xfs_iunlock(dp, XFS_ILOCK_SHARED); 603 xfs_iunlock(dp, XFS_ILOCK_SHARED);
611 604
612 return xfs_attr_remove_int(dp, &xname, flags); 605 return xfs_attr_remove_int(dp, &xname, flags);
613} 606}
614 607
615STATIC int 608int
616xfs_attr_list_int(xfs_attr_list_context_t *context) 609xfs_attr_list_int(xfs_attr_list_context_t *context)
617{ 610{
618 int error; 611 int error;
619 xfs_inode_t *dp = context->dp; 612 xfs_inode_t *dp = context->dp;
620 613
614 XFS_STATS_INC(xs_attr_list);
615
616 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
617 return EIO;
618
619 xfs_ilock(dp, XFS_ILOCK_SHARED);
620 xfs_attr_trace_l_c("syscall start", context);
621
621 /* 622 /*
622 * Decide on what work routines to call based on the inode size. 623 * Decide on what work routines to call based on the inode size.
623 */ 624 */
624 if (XFS_IFORK_Q(dp) == 0 || 625 if (!xfs_inode_hasattr(dp)) {
625 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
626 dp->i_d.di_anextents == 0)) {
627 error = 0; 626 error = 0;
628 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 627 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
629 error = xfs_attr_shortform_list(context); 628 error = xfs_attr_shortform_list(context);
@@ -632,6 +631,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
632 } else { 631 } else {
633 error = xfs_attr_node_list(context); 632 error = xfs_attr_node_list(context);
634 } 633 }
634
635 xfs_iunlock(dp, XFS_ILOCK_SHARED);
636 xfs_attr_trace_l_c("syscall end", context);
637
635 return error; 638 return error;
636} 639}
637 640
@@ -648,74 +651,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
648 */ 651 */
649/*ARGSUSED*/ 652/*ARGSUSED*/
650STATIC int 653STATIC int
651xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp, 654xfs_attr_put_listent(xfs_attr_list_context_t *context, int flags,
652 char *name, int namelen, 655 char *name, int namelen,
653 int valuelen, char *value) 656 int valuelen, char *value)
654{ 657{
658 struct attrlist *alist = (struct attrlist *)context->alist;
655 attrlist_ent_t *aep; 659 attrlist_ent_t *aep;
656 int arraytop; 660 int arraytop;
657 661
658 ASSERT(!(context->flags & ATTR_KERNOVAL)); 662 ASSERT(!(context->flags & ATTR_KERNOVAL));
659 ASSERT(context->count >= 0); 663 ASSERT(context->count >= 0);
660 ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); 664 ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
661 ASSERT(context->firstu >= sizeof(*context->alist)); 665 ASSERT(context->firstu >= sizeof(*alist));
662 ASSERT(context->firstu <= context->bufsize); 666 ASSERT(context->firstu <= context->bufsize);
663 667
664 arraytop = sizeof(*context->alist) + 668 /*
665 context->count * sizeof(context->alist->al_offset[0]); 669 * Only list entries in the right namespace.
670 */
671 if (((context->flags & ATTR_SECURE) == 0) !=
672 ((flags & XFS_ATTR_SECURE) == 0))
673 return 0;
674 if (((context->flags & ATTR_ROOT) == 0) !=
675 ((flags & XFS_ATTR_ROOT) == 0))
676 return 0;
677
678 arraytop = sizeof(*alist) +
679 context->count * sizeof(alist->al_offset[0]);
666 context->firstu -= ATTR_ENTSIZE(namelen); 680 context->firstu -= ATTR_ENTSIZE(namelen);
667 if (context->firstu < arraytop) { 681 if (context->firstu < arraytop) {
668 xfs_attr_trace_l_c("buffer full", context); 682 xfs_attr_trace_l_c("buffer full", context);
669 context->alist->al_more = 1; 683 alist->al_more = 1;
670 context->seen_enough = 1; 684 context->seen_enough = 1;
671 return 1; 685 return 1;
672 } 686 }
673 687
674 aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]); 688 aep = (attrlist_ent_t *)&context->alist[context->firstu];
675 aep->a_valuelen = valuelen; 689 aep->a_valuelen = valuelen;
676 memcpy(aep->a_name, name, namelen); 690 memcpy(aep->a_name, name, namelen);
677 aep->a_name[ namelen ] = 0; 691 aep->a_name[namelen] = 0;
678 context->alist->al_offset[ context->count++ ] = context->firstu; 692 alist->al_offset[context->count++] = context->firstu;
679 context->alist->al_count = context->count; 693 alist->al_count = context->count;
680 xfs_attr_trace_l_c("add", context); 694 xfs_attr_trace_l_c("add", context);
681 return 0; 695 return 0;
682} 696}
683 697
684STATIC int
685xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp,
686 char *name, int namelen,
687 int valuelen, char *value)
688{
689 char *offset;
690 int arraytop;
691
692 ASSERT(context->count >= 0);
693
694 arraytop = context->count + namesp->attr_namelen + namelen + 1;
695 if (arraytop > context->firstu) {
696 context->count = -1; /* insufficient space */
697 return 1;
698 }
699 offset = (char *)context->alist + context->count;
700 strncpy(offset, namesp->attr_name, namesp->attr_namelen);
701 offset += namesp->attr_namelen;
702 strncpy(offset, name, namelen); /* real name */
703 offset += namelen;
704 *offset = '\0';
705 context->count += namesp->attr_namelen + namelen + 1;
706 return 0;
707}
708
709/*ARGSUSED*/
710STATIC int
711xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
712 char *name, int namelen,
713 int valuelen, char *value)
714{
715 context->count += namesp->attr_namelen + namelen + 1;
716 return 0;
717}
718
719/* 698/*
720 * Generate a list of extended attribute names and optionally 699 * Generate a list of extended attribute names and optionally
721 * also value lengths. Positive return value follows the XFS 700 * also value lengths. Positive return value follows the XFS
@@ -732,10 +711,9 @@ xfs_attr_list(
732 attrlist_cursor_kern_t *cursor) 711 attrlist_cursor_kern_t *cursor)
733{ 712{
734 xfs_attr_list_context_t context; 713 xfs_attr_list_context_t context;
714 struct attrlist *alist;
735 int error; 715 int error;
736 716
737 XFS_STATS_INC(xs_attr_list);
738
739 /* 717 /*
740 * Validate the cursor. 718 * Validate the cursor.
741 */ 719 */
@@ -756,52 +734,23 @@ xfs_attr_list(
756 /* 734 /*
757 * Initialize the output buffer. 735 * Initialize the output buffer.
758 */ 736 */
737 memset(&context, 0, sizeof(context));
759 context.dp = dp; 738 context.dp = dp;
760 context.cursor = cursor; 739 context.cursor = cursor;
761 context.count = 0;
762 context.dupcnt = 0;
763 context.resynch = 1; 740 context.resynch = 1;
764 context.flags = flags; 741 context.flags = flags;
765 context.seen_enough = 0; 742 context.alist = buffer;
766 context.alist = (attrlist_t *)buffer; 743 context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
767 context.put_value = 0; 744 context.firstu = context.bufsize;
768 745 context.put_listent = xfs_attr_put_listent;
769 if (flags & ATTR_KERNAMELS) {
770 context.bufsize = bufsize;
771 context.firstu = context.bufsize;
772 if (flags & ATTR_KERNOVAL)
773 context.put_listent = xfs_attr_kern_list_sizes;
774 else
775 context.put_listent = xfs_attr_kern_list;
776 } else {
777 context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
778 context.firstu = context.bufsize;
779 context.alist->al_count = 0;
780 context.alist->al_more = 0;
781 context.alist->al_offset[0] = context.bufsize;
782 context.put_listent = xfs_attr_put_listent;
783 }
784 746
785 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 747 alist = (struct attrlist *)context.alist;
786 return EIO; 748 alist->al_count = 0;
787 749 alist->al_more = 0;
788 xfs_ilock(dp, XFS_ILOCK_SHARED); 750 alist->al_offset[0] = context.bufsize;
789 xfs_attr_trace_l_c("syscall start", &context);
790 751
791 error = xfs_attr_list_int(&context); 752 error = xfs_attr_list_int(&context);
792 753 ASSERT(error >= 0);
793 xfs_iunlock(dp, XFS_ILOCK_SHARED);
794 xfs_attr_trace_l_c("syscall end", &context);
795
796 if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) {
797 /* must return negated buffer size or the error */
798 if (context.count < 0)
799 error = XFS_ERROR(ERANGE);
800 else
801 error = -context.count;
802 } else
803 ASSERT(error >= 0);
804
805 return error; 754 return error;
806} 755}
807 756
@@ -816,12 +765,10 @@ xfs_attr_inactive(xfs_inode_t *dp)
816 ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); 765 ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
817 766
818 xfs_ilock(dp, XFS_ILOCK_SHARED); 767 xfs_ilock(dp, XFS_ILOCK_SHARED);
819 if ((XFS_IFORK_Q(dp) == 0) || 768 if (!xfs_inode_hasattr(dp) ||
820 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 769 dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
821 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
822 dp->i_d.di_anextents == 0)) {
823 xfs_iunlock(dp, XFS_ILOCK_SHARED); 770 xfs_iunlock(dp, XFS_ILOCK_SHARED);
824 return(0); 771 return 0;
825 } 772 }
826 xfs_iunlock(dp, XFS_ILOCK_SHARED); 773 xfs_iunlock(dp, XFS_ILOCK_SHARED);
827 774
@@ -854,10 +801,8 @@ xfs_attr_inactive(xfs_inode_t *dp)
854 /* 801 /*
855 * Decide on what work routines to call based on the inode size. 802 * Decide on what work routines to call based on the inode size.
856 */ 803 */
857 if ((XFS_IFORK_Q(dp) == 0) || 804 if (!xfs_inode_hasattr(dp) ||
858 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 805 dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
859 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
860 dp->i_d.di_anextents == 0)) {
861 error = 0; 806 error = 0;
862 goto out; 807 goto out;
863 } 808 }
@@ -974,7 +919,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
974 xfs_da_brelse(args->trans, bp); 919 xfs_da_brelse(args->trans, bp);
975 return(retval); 920 return(retval);
976 } 921 }
977 args->rename = 1; /* an atomic rename */ 922 args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */
978 args->blkno2 = args->blkno; /* set 2nd entry info*/ 923 args->blkno2 = args->blkno; /* set 2nd entry info*/
979 args->index2 = args->index; 924 args->index2 = args->index;
980 args->rmtblkno2 = args->rmtblkno; 925 args->rmtblkno2 = args->rmtblkno;
@@ -1054,7 +999,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
1054 * so that one disappears and one appears atomically. Then we 999 * so that one disappears and one appears atomically. Then we
1055 * must remove the "old" attribute/value pair. 1000 * must remove the "old" attribute/value pair.
1056 */ 1001 */
1057 if (args->rename) { 1002 if (args->op_flags & XFS_DA_OP_RENAME) {
1058 /* 1003 /*
1059 * In a separate transaction, set the incomplete flag on the 1004 * In a separate transaction, set the incomplete flag on the
1060 * "old" attr and clear the incomplete flag on the "new" attr. 1005 * "old" attr and clear the incomplete flag on the "new" attr.
@@ -1307,7 +1252,7 @@ restart:
1307 } else if (retval == EEXIST) { 1252 } else if (retval == EEXIST) {
1308 if (args->flags & ATTR_CREATE) 1253 if (args->flags & ATTR_CREATE)
1309 goto out; 1254 goto out;
1310 args->rename = 1; /* atomic rename op */ 1255 args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */
1311 args->blkno2 = args->blkno; /* set 2nd entry info*/ 1256 args->blkno2 = args->blkno; /* set 2nd entry info*/
1312 args->index2 = args->index; 1257 args->index2 = args->index;
1313 args->rmtblkno2 = args->rmtblkno; 1258 args->rmtblkno2 = args->rmtblkno;
@@ -1425,7 +1370,7 @@ restart:
1425 * so that one disappears and one appears atomically. Then we 1370 * so that one disappears and one appears atomically. Then we
1426 * must remove the "old" attribute/value pair. 1371 * must remove the "old" attribute/value pair.
1427 */ 1372 */
1428 if (args->rename) { 1373 if (args->op_flags & XFS_DA_OP_RENAME) {
1429 /* 1374 /*
1430 * In a separate transaction, set the incomplete flag on the 1375 * In a separate transaction, set the incomplete flag on the
1431 * "old" attr and clear the incomplete flag on the "new" attr. 1376 * "old" attr and clear the incomplete flag on the "new" attr.
@@ -2300,23 +2245,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
2300void 2245void
2301xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context) 2246xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context)
2302{ 2247{
2303 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, 2248 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, context,
2304 (__psunsigned_t)context->dp,
2305 (__psunsigned_t)context->cursor->hashval,
2306 (__psunsigned_t)context->cursor->blkno,
2307 (__psunsigned_t)context->cursor->offset,
2308 (__psunsigned_t)context->alist,
2309 (__psunsigned_t)context->bufsize,
2310 (__psunsigned_t)context->count,
2311 (__psunsigned_t)context->firstu,
2312 (__psunsigned_t)
2313 ((context->count > 0) &&
2314 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2315 ? (ATTR_ENTRY(context->alist,
2316 context->count-1)->a_valuelen)
2317 : 0,
2318 (__psunsigned_t)context->dupcnt,
2319 (__psunsigned_t)context->flags,
2320 (__psunsigned_t)NULL, 2249 (__psunsigned_t)NULL,
2321 (__psunsigned_t)NULL, 2250 (__psunsigned_t)NULL,
2322 (__psunsigned_t)NULL); 2251 (__psunsigned_t)NULL);
@@ -2329,23 +2258,7 @@ void
2329xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context, 2258xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,
2330 struct xfs_da_intnode *node) 2259 struct xfs_da_intnode *node)
2331{ 2260{
2332 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, 2261 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, context,
2333 (__psunsigned_t)context->dp,
2334 (__psunsigned_t)context->cursor->hashval,
2335 (__psunsigned_t)context->cursor->blkno,
2336 (__psunsigned_t)context->cursor->offset,
2337 (__psunsigned_t)context->alist,
2338 (__psunsigned_t)context->bufsize,
2339 (__psunsigned_t)context->count,
2340 (__psunsigned_t)context->firstu,
2341 (__psunsigned_t)
2342 ((context->count > 0) &&
2343 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2344 ? (ATTR_ENTRY(context->alist,
2345 context->count-1)->a_valuelen)
2346 : 0,
2347 (__psunsigned_t)context->dupcnt,
2348 (__psunsigned_t)context->flags,
2349 (__psunsigned_t)be16_to_cpu(node->hdr.count), 2262 (__psunsigned_t)be16_to_cpu(node->hdr.count),
2350 (__psunsigned_t)be32_to_cpu(node->btree[0].hashval), 2263 (__psunsigned_t)be32_to_cpu(node->btree[0].hashval),
2351 (__psunsigned_t)be32_to_cpu(node->btree[ 2264 (__psunsigned_t)be32_to_cpu(node->btree[
@@ -2359,23 +2272,7 @@ void
2359xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context, 2272xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,
2360 struct xfs_da_node_entry *btree) 2273 struct xfs_da_node_entry *btree)
2361{ 2274{
2362 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, 2275 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, context,
2363 (__psunsigned_t)context->dp,
2364 (__psunsigned_t)context->cursor->hashval,
2365 (__psunsigned_t)context->cursor->blkno,
2366 (__psunsigned_t)context->cursor->offset,
2367 (__psunsigned_t)context->alist,
2368 (__psunsigned_t)context->bufsize,
2369 (__psunsigned_t)context->count,
2370 (__psunsigned_t)context->firstu,
2371 (__psunsigned_t)
2372 ((context->count > 0) &&
2373 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2374 ? (ATTR_ENTRY(context->alist,
2375 context->count-1)->a_valuelen)
2376 : 0,
2377 (__psunsigned_t)context->dupcnt,
2378 (__psunsigned_t)context->flags,
2379 (__psunsigned_t)be32_to_cpu(btree->hashval), 2276 (__psunsigned_t)be32_to_cpu(btree->hashval),
2380 (__psunsigned_t)be32_to_cpu(btree->before), 2277 (__psunsigned_t)be32_to_cpu(btree->before),
2381 (__psunsigned_t)NULL); 2278 (__psunsigned_t)NULL);
@@ -2388,23 +2285,7 @@ void
2388xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, 2285xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
2389 struct xfs_attr_leafblock *leaf) 2286 struct xfs_attr_leafblock *leaf)
2390{ 2287{
2391 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, 2288 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, context,
2392 (__psunsigned_t)context->dp,
2393 (__psunsigned_t)context->cursor->hashval,
2394 (__psunsigned_t)context->cursor->blkno,
2395 (__psunsigned_t)context->cursor->offset,
2396 (__psunsigned_t)context->alist,
2397 (__psunsigned_t)context->bufsize,
2398 (__psunsigned_t)context->count,
2399 (__psunsigned_t)context->firstu,
2400 (__psunsigned_t)
2401 ((context->count > 0) &&
2402 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
2403 ? (ATTR_ENTRY(context->alist,
2404 context->count-1)->a_valuelen)
2405 : 0,
2406 (__psunsigned_t)context->dupcnt,
2407 (__psunsigned_t)context->flags,
2408 (__psunsigned_t)be16_to_cpu(leaf->hdr.count), 2289 (__psunsigned_t)be16_to_cpu(leaf->hdr.count),
2409 (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval), 2290 (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval),
2410 (__psunsigned_t)be32_to_cpu(leaf->entries[ 2291 (__psunsigned_t)be32_to_cpu(leaf->entries[
@@ -2417,329 +2298,24 @@ xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
2417 */ 2298 */
2418void 2299void
2419xfs_attr_trace_enter(int type, char *where, 2300xfs_attr_trace_enter(int type, char *where,
2420 __psunsigned_t a2, __psunsigned_t a3, 2301 struct xfs_attr_list_context *context,
2421 __psunsigned_t a4, __psunsigned_t a5, 2302 __psunsigned_t a13, __psunsigned_t a14,
2422 __psunsigned_t a6, __psunsigned_t a7, 2303 __psunsigned_t a15)
2423 __psunsigned_t a8, __psunsigned_t a9,
2424 __psunsigned_t a10, __psunsigned_t a11,
2425 __psunsigned_t a12, __psunsigned_t a13,
2426 __psunsigned_t a14, __psunsigned_t a15)
2427{ 2304{
2428 ASSERT(xfs_attr_trace_buf); 2305 ASSERT(xfs_attr_trace_buf);
2429 ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type), 2306 ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type),
2430 (void *)where, 2307 (void *)((__psunsigned_t)where),
2431 (void *)a2, (void *)a3, (void *)a4, 2308 (void *)((__psunsigned_t)context->dp),
2432 (void *)a5, (void *)a6, (void *)a7, 2309 (void *)((__psunsigned_t)context->cursor->hashval),
2433 (void *)a8, (void *)a9, (void *)a10, 2310 (void *)((__psunsigned_t)context->cursor->blkno),
2434 (void *)a11, (void *)a12, (void *)a13, 2311 (void *)((__psunsigned_t)context->cursor->offset),
2435 (void *)a14, (void *)a15); 2312 (void *)((__psunsigned_t)context->alist),
2313 (void *)((__psunsigned_t)context->bufsize),
2314 (void *)((__psunsigned_t)context->count),
2315 (void *)((__psunsigned_t)context->firstu),
2316 NULL,
2317 (void *)((__psunsigned_t)context->dupcnt),
2318 (void *)((__psunsigned_t)context->flags),
2319 (void *)a13, (void *)a14, (void *)a15);
2436} 2320}
2437#endif /* XFS_ATTR_TRACE */ 2321#endif /* XFS_ATTR_TRACE */
2438
2439
2440/*========================================================================
2441 * System (pseudo) namespace attribute interface routines.
2442 *========================================================================*/
2443
2444STATIC int
2445posix_acl_access_set(
2446 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2447{
2448 return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
2449}
2450
2451STATIC int
2452posix_acl_access_remove(
2453 bhv_vnode_t *vp, char *name, int xflags)
2454{
2455 return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
2456}
2457
2458STATIC int
2459posix_acl_access_get(
2460 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2461{
2462 return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
2463}
2464
2465STATIC int
2466posix_acl_access_exists(
2467 bhv_vnode_t *vp)
2468{
2469 return xfs_acl_vhasacl_access(vp);
2470}
2471
2472STATIC int
2473posix_acl_default_set(
2474 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2475{
2476 return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
2477}
2478
2479STATIC int
2480posix_acl_default_get(
2481 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2482{
2483 return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
2484}
2485
2486STATIC int
2487posix_acl_default_remove(
2488 bhv_vnode_t *vp, char *name, int xflags)
2489{
2490 return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
2491}
2492
2493STATIC int
2494posix_acl_default_exists(
2495 bhv_vnode_t *vp)
2496{
2497 return xfs_acl_vhasacl_default(vp);
2498}
2499
2500static struct attrnames posix_acl_access = {
2501 .attr_name = "posix_acl_access",
2502 .attr_namelen = sizeof("posix_acl_access") - 1,
2503 .attr_get = posix_acl_access_get,
2504 .attr_set = posix_acl_access_set,
2505 .attr_remove = posix_acl_access_remove,
2506 .attr_exists = posix_acl_access_exists,
2507};
2508
2509static struct attrnames posix_acl_default = {
2510 .attr_name = "posix_acl_default",
2511 .attr_namelen = sizeof("posix_acl_default") - 1,
2512 .attr_get = posix_acl_default_get,
2513 .attr_set = posix_acl_default_set,
2514 .attr_remove = posix_acl_default_remove,
2515 .attr_exists = posix_acl_default_exists,
2516};
2517
2518static struct attrnames *attr_system_names[] =
2519 { &posix_acl_access, &posix_acl_default };
2520
2521
2522/*========================================================================
2523 * Namespace-prefix-style attribute name interface routines.
2524 *========================================================================*/
2525
2526STATIC int
2527attr_generic_set(
2528 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2529{
2530 return -xfs_attr_set(xfs_vtoi(vp), name, data, size, xflags);
2531}
2532
2533STATIC int
2534attr_generic_get(
2535 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2536{
2537 int error, asize = size;
2538
2539 error = xfs_attr_get(xfs_vtoi(vp), name, data, &asize, xflags);
2540 if (!error)
2541 return asize;
2542 return -error;
2543}
2544
2545STATIC int
2546attr_generic_remove(
2547 bhv_vnode_t *vp, char *name, int xflags)
2548{
2549 return -xfs_attr_remove(xfs_vtoi(vp), name, xflags);
2550}
2551
2552STATIC int
2553attr_generic_listadd(
2554 attrnames_t *prefix,
2555 attrnames_t *namesp,
2556 void *data,
2557 size_t size,
2558 ssize_t *result)
2559{
2560 char *p = data + *result;
2561
2562 *result += prefix->attr_namelen;
2563 *result += namesp->attr_namelen + 1;
2564 if (!size)
2565 return 0;
2566 if (*result > size)
2567 return -ERANGE;
2568 strcpy(p, prefix->attr_name);
2569 p += prefix->attr_namelen;
2570 strcpy(p, namesp->attr_name);
2571 p += namesp->attr_namelen + 1;
2572 return 0;
2573}
2574
2575STATIC int
2576attr_system_list(
2577 bhv_vnode_t *vp,
2578 void *data,
2579 size_t size,
2580 ssize_t *result)
2581{
2582 attrnames_t *namesp;
2583 int i, error = 0;
2584
2585 for (i = 0; i < ATTR_SYSCOUNT; i++) {
2586 namesp = attr_system_names[i];
2587 if (!namesp->attr_exists || !namesp->attr_exists(vp))
2588 continue;
2589 error = attr_generic_listadd(&attr_system, namesp,
2590 data, size, result);
2591 if (error)
2592 break;
2593 }
2594 return error;
2595}
2596
2597int
2598attr_generic_list(
2599 bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result)
2600{
2601 attrlist_cursor_kern_t cursor = { 0 };
2602 int error;
2603
2604 error = xfs_attr_list(xfs_vtoi(vp), data, size, xflags, &cursor);
2605 if (error > 0)
2606 return -error;
2607 *result = -error;
2608 return attr_system_list(vp, data, size, result);
2609}
2610
2611attrnames_t *
2612attr_lookup_namespace(
2613 char *name,
2614 struct attrnames **names,
2615 int nnames)
2616{
2617 int i;
2618
2619 for (i = 0; i < nnames; i++)
2620 if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen))
2621 return names[i];
2622 return NULL;
2623}
2624
2625/*
2626 * Some checks to prevent people abusing EAs to get over quota:
2627 * - Don't allow modifying user EAs on devices/symlinks;
2628 * - Don't allow modifying user EAs if sticky bit set;
2629 */
2630STATIC int
2631attr_user_capable(
2632 bhv_vnode_t *vp,
2633 cred_t *cred)
2634{
2635 struct inode *inode = vn_to_inode(vp);
2636
2637 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
2638 return -EPERM;
2639 if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
2640 !capable(CAP_SYS_ADMIN))
2641 return -EPERM;
2642 if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
2643 (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
2644 return -EPERM;
2645 return 0;
2646}
2647
2648STATIC int
2649attr_trusted_capable(
2650 bhv_vnode_t *vp,
2651 cred_t *cred)
2652{
2653 struct inode *inode = vn_to_inode(vp);
2654
2655 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
2656 return -EPERM;
2657 if (!capable(CAP_SYS_ADMIN))
2658 return -EPERM;
2659 return 0;
2660}
2661
2662STATIC int
2663attr_system_set(
2664 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2665{
2666 attrnames_t *namesp;
2667 int error;
2668
2669 if (xflags & ATTR_CREATE)
2670 return -EINVAL;
2671
2672 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
2673 if (!namesp)
2674 return -EOPNOTSUPP;
2675 error = namesp->attr_set(vp, name, data, size, xflags);
2676 if (!error)
2677 error = vn_revalidate(vp);
2678 return error;
2679}
2680
2681STATIC int
2682attr_system_get(
2683 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2684{
2685 attrnames_t *namesp;
2686
2687 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
2688 if (!namesp)
2689 return -EOPNOTSUPP;
2690 return namesp->attr_get(vp, name, data, size, xflags);
2691}
2692
2693STATIC int
2694attr_system_remove(
2695 bhv_vnode_t *vp, char *name, int xflags)
2696{
2697 attrnames_t *namesp;
2698
2699 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
2700 if (!namesp)
2701 return -EOPNOTSUPP;
2702 return namesp->attr_remove(vp, name, xflags);
2703}
2704
2705struct attrnames attr_system = {
2706 .attr_name = "system.",
2707 .attr_namelen = sizeof("system.") - 1,
2708 .attr_flag = ATTR_SYSTEM,
2709 .attr_get = attr_system_get,
2710 .attr_set = attr_system_set,
2711 .attr_remove = attr_system_remove,
2712 .attr_capable = (attrcapable_t)fs_noerr,
2713};
2714
2715struct attrnames attr_trusted = {
2716 .attr_name = "trusted.",
2717 .attr_namelen = sizeof("trusted.") - 1,
2718 .attr_flag = ATTR_ROOT,
2719 .attr_get = attr_generic_get,
2720 .attr_set = attr_generic_set,
2721 .attr_remove = attr_generic_remove,
2722 .attr_capable = attr_trusted_capable,
2723};
2724
2725struct attrnames attr_secure = {
2726 .attr_name = "security.",
2727 .attr_namelen = sizeof("security.") - 1,
2728 .attr_flag = ATTR_SECURE,
2729 .attr_get = attr_generic_get,
2730 .attr_set = attr_generic_set,
2731 .attr_remove = attr_generic_remove,
2732 .attr_capable = (attrcapable_t)fs_noerr,
2733};
2734
2735struct attrnames attr_user = {
2736 .attr_name = "user.",
2737 .attr_namelen = sizeof("user.") - 1,
2738 .attr_get = attr_generic_get,
2739 .attr_set = attr_generic_set,
2740 .attr_remove = attr_generic_remove,
2741 .attr_capable = attr_user_capable,
2742};
2743
2744struct attrnames *attr_namespaces[] =
2745 { &attr_system, &attr_trusted, &attr_secure, &attr_user };
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index 6cfc9384fe35..8b2d31c19e4d 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -18,9 +18,11 @@
18#ifndef __XFS_ATTR_H__ 18#ifndef __XFS_ATTR_H__
19#define __XFS_ATTR_H__ 19#define __XFS_ATTR_H__
20 20
21struct xfs_inode;
22struct xfs_da_args;
23struct xfs_attr_list_context;
24
21/* 25/*
22 * xfs_attr.h
23 *
24 * Large attribute lists are structured around Btrees where all the data 26 * Large attribute lists are structured around Btrees where all the data
25 * elements are in the leaf nodes. Attribute names are hashed into an int, 27 * elements are in the leaf nodes. Attribute names are hashed into an int,
26 * then that int is used as the index into the Btree. Since the hashval 28 * then that int is used as the index into the Btree. Since the hashval
@@ -35,35 +37,6 @@
35 * External interfaces 37 * External interfaces
36 *========================================================================*/ 38 *========================================================================*/
37 39
38struct cred;
39struct xfs_attr_list_context;
40
41typedef int (*attrset_t)(bhv_vnode_t *, char *, void *, size_t, int);
42typedef int (*attrget_t)(bhv_vnode_t *, char *, void *, size_t, int);
43typedef int (*attrremove_t)(bhv_vnode_t *, char *, int);
44typedef int (*attrexists_t)(bhv_vnode_t *);
45typedef int (*attrcapable_t)(bhv_vnode_t *, struct cred *);
46
47typedef struct attrnames {
48 char * attr_name;
49 unsigned int attr_namelen;
50 unsigned int attr_flag;
51 attrget_t attr_get;
52 attrset_t attr_set;
53 attrremove_t attr_remove;
54 attrexists_t attr_exists;
55 attrcapable_t attr_capable;
56} attrnames_t;
57
58#define ATTR_NAMECOUNT 4
59extern struct attrnames attr_user;
60extern struct attrnames attr_secure;
61extern struct attrnames attr_system;
62extern struct attrnames attr_trusted;
63extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
64
65extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
66extern int attr_generic_list(bhv_vnode_t *, void *, size_t, int, ssize_t *);
67 40
68#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ 41#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
69#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ 42#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
@@ -71,16 +44,9 @@ extern int attr_generic_list(bhv_vnode_t *, void *, size_t, int, ssize_t *);
71#define ATTR_SECURE 0x0008 /* use attrs in security namespace */ 44#define ATTR_SECURE 0x0008 /* use attrs in security namespace */
72#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ 45#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */
73#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */ 46#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */
74#define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */
75 47
76#define ATTR_KERNACCESS 0x0400 /* [kernel] iaccess, inode held io-locked */
77#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */ 48#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
78#define ATTR_KERNOVAL 0x2000 /* [kernel] get attr size only, not value */ 49#define ATTR_KERNOVAL 0x2000 /* [kernel] get attr size only, not value */
79#define ATTR_KERNAMELS 0x4000 /* [kernel] list attr names (simple list) */
80
81#define ATTR_KERNORMALS 0x0800 /* [kernel] normal attr list: user+secure */
82#define ATTR_KERNROOTLS 0x8000 /* [kernel] include root in the attr list */
83#define ATTR_KERNFULLS (ATTR_KERNORMALS|ATTR_KERNROOTLS)
84 50
85/* 51/*
86 * The maximum size (into the kernel or returned from the kernel) of an 52 * The maximum size (into the kernel or returned from the kernel) of an
@@ -119,22 +85,6 @@ typedef struct attrlist_ent { /* data from attr_list() */
119 &((char *)buffer)[ ((attrlist_t *)(buffer))->al_offset[index] ]) 85 &((char *)buffer)[ ((attrlist_t *)(buffer))->al_offset[index] ])
120 86
121/* 87/*
122 * Multi-attribute operation vector.
123 */
124typedef struct attr_multiop {
125 int am_opcode; /* operation to perform (ATTR_OP_GET, etc.) */
126 int am_error; /* [out arg] result of this sub-op (an errno) */
127 char *am_attrname; /* attribute name to work with */
128 char *am_attrvalue; /* [in/out arg] attribute value (raw bytes) */
129 int am_length; /* [in/out arg] length of value */
130 int am_flags; /* bitwise OR of attr API flags defined above */
131} attr_multiop_t;
132
133#define ATTR_OP_GET 1 /* return the indicated attr's value */
134#define ATTR_OP_SET 2 /* set/create the indicated attr/value pair */
135#define ATTR_OP_REMOVE 3 /* remove the indicated attr */
136
137/*
138 * Kernel-internal version of the attrlist cursor. 88 * Kernel-internal version of the attrlist cursor.
139 */ 89 */
140typedef struct attrlist_cursor_kern { 90typedef struct attrlist_cursor_kern {
@@ -148,20 +98,40 @@ typedef struct attrlist_cursor_kern {
148 98
149 99
150/*======================================================================== 100/*========================================================================
151 * Function prototypes for the kernel. 101 * Structure used to pass context around among the routines.
152 *========================================================================*/ 102 *========================================================================*/
153 103
154struct xfs_inode; 104
155struct attrlist_cursor_kern; 105typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, int,
156struct xfs_da_args; 106 char *, int, int, char *);
107
108typedef struct xfs_attr_list_context {
109 struct xfs_inode *dp; /* inode */
110 struct attrlist_cursor_kern *cursor; /* position in list */
111 char *alist; /* output buffer */
112 int seen_enough; /* T/F: seen enough of list? */
113 ssize_t count; /* num used entries */
114 int dupcnt; /* count dup hashvals seen */
115 int bufsize; /* total buffer size */
116 int firstu; /* first used byte in buffer */
117 int flags; /* from VOP call */
118 int resynch; /* T/F: resynch with cursor */
119 int put_value; /* T/F: need value for listent */
120 put_listent_func_t put_listent; /* list output fmt function */
121 int index; /* index into output buffer */
122} xfs_attr_list_context_t;
123
124
125/*========================================================================
126 * Function prototypes for the kernel.
127 *========================================================================*/
157 128
158/* 129/*
159 * Overall external interface routines. 130 * Overall external interface routines.
160 */ 131 */
161int xfs_attr_inactive(struct xfs_inode *dp); 132int xfs_attr_inactive(struct xfs_inode *dp);
162
163int xfs_attr_shortform_getvalue(struct xfs_da_args *);
164int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int); 133int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int);
165int xfs_attr_rmtval_get(struct xfs_da_args *args); 134int xfs_attr_rmtval_get(struct xfs_da_args *args);
135int xfs_attr_list_int(struct xfs_attr_list_context *);
166 136
167#endif /* __XFS_ATTR_H__ */ 137#endif /* __XFS_ATTR_H__ */
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 303d41e4217b..23ef5d7c87e1 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -94,13 +94,6 @@ STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
94 * Namespace helper routines 94 * Namespace helper routines
95 *========================================================================*/ 95 *========================================================================*/
96 96
97STATIC_INLINE attrnames_t *
98xfs_attr_flags_namesp(int flags)
99{
100 return ((flags & XFS_ATTR_SECURE) ? &attr_secure:
101 ((flags & XFS_ATTR_ROOT) ? &attr_trusted : &attr_user));
102}
103
104/* 97/*
105 * If namespace bits don't match return 0. 98 * If namespace bits don't match return 0.
106 * If all match then return 1. 99 * If all match then return 1.
@@ -111,25 +104,6 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
111 return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); 104 return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
112} 105}
113 106
114/*
115 * If namespace bits don't match and we don't have an override for it
116 * then return 0.
117 * If all match or are overridable then return 1.
118 */
119STATIC_INLINE int
120xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags)
121{
122 if (((arg_flags & ATTR_SECURE) == 0) !=
123 ((ondisk_flags & XFS_ATTR_SECURE) == 0) &&
124 !(arg_flags & ATTR_KERNORMALS))
125 return 0;
126 if (((arg_flags & ATTR_ROOT) == 0) !=
127 ((ondisk_flags & XFS_ATTR_ROOT) == 0) &&
128 !(arg_flags & ATTR_KERNROOTLS))
129 return 0;
130 return 1;
131}
132
133 107
134/*======================================================================== 108/*========================================================================
135 * External routines when attribute fork size < XFS_LITINO(mp). 109 * External routines when attribute fork size < XFS_LITINO(mp).
@@ -369,9 +343,10 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
369 * Fix up the start offset of the attribute fork 343 * Fix up the start offset of the attribute fork
370 */ 344 */
371 totsize -= size; 345 totsize -= size;
372 if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname && 346 if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
373 (mp->m_flags & XFS_MOUNT_ATTR2) && 347 !(args->op_flags & XFS_DA_OP_ADDNAME) &&
374 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) { 348 (mp->m_flags & XFS_MOUNT_ATTR2) &&
349 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) {
375 /* 350 /*
376 * Last attribute now removed, revert to original 351 * Last attribute now removed, revert to original
377 * inode format making all literal area available 352 * inode format making all literal area available
@@ -389,9 +364,10 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
389 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); 364 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
390 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); 365 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
391 ASSERT(dp->i_d.di_forkoff); 366 ASSERT(dp->i_d.di_forkoff);
392 ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname || 367 ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) ||
393 !(mp->m_flags & XFS_MOUNT_ATTR2) || 368 (args->op_flags & XFS_DA_OP_ADDNAME) ||
394 dp->i_d.di_format == XFS_DINODE_FMT_BTREE); 369 !(mp->m_flags & XFS_MOUNT_ATTR2) ||
370 dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
395 dp->i_afp->if_ext_max = 371 dp->i_afp->if_ext_max =
396 XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); 372 XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
397 dp->i_df.if_ext_max = 373 dp->i_df.if_ext_max =
@@ -531,7 +507,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
531 nargs.total = args->total; 507 nargs.total = args->total;
532 nargs.whichfork = XFS_ATTR_FORK; 508 nargs.whichfork = XFS_ATTR_FORK;
533 nargs.trans = args->trans; 509 nargs.trans = args->trans;
534 nargs.oknoent = 1; 510 nargs.op_flags = XFS_DA_OP_OKNOENT;
535 511
536 sfe = &sf->list[0]; 512 sfe = &sf->list[0];
537 for (i = 0; i < sf->hdr.count; i++) { 513 for (i = 0; i < sf->hdr.count; i++) {
@@ -555,7 +531,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
555out: 531out:
556 if(bp) 532 if(bp)
557 xfs_da_buf_done(bp); 533 xfs_da_buf_done(bp);
558 kmem_free(tmpbuffer, size); 534 kmem_free(tmpbuffer);
559 return(error); 535 return(error);
560} 536}
561 537
@@ -624,15 +600,8 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
624 (XFS_ISRESET_CURSOR(cursor) && 600 (XFS_ISRESET_CURSOR(cursor) &&
625 (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) { 601 (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
626 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { 602 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
627 attrnames_t *namesp;
628
629 if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {
630 sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
631 continue;
632 }
633 namesp = xfs_attr_flags_namesp(sfe->flags);
634 error = context->put_listent(context, 603 error = context->put_listent(context,
635 namesp, 604 sfe->flags,
636 (char *)sfe->nameval, 605 (char *)sfe->nameval,
637 (int)sfe->namelen, 606 (int)sfe->namelen,
638 (int)sfe->valuelen, 607 (int)sfe->valuelen,
@@ -676,13 +645,10 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
676 XFS_ERRLEVEL_LOW, 645 XFS_ERRLEVEL_LOW,
677 context->dp->i_mount, sfe); 646 context->dp->i_mount, sfe);
678 xfs_attr_trace_l_c("sf corrupted", context); 647 xfs_attr_trace_l_c("sf corrupted", context);
679 kmem_free(sbuf, sbsize); 648 kmem_free(sbuf);
680 return XFS_ERROR(EFSCORRUPTED); 649 return XFS_ERROR(EFSCORRUPTED);
681 } 650 }
682 if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) { 651
683 sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
684 continue;
685 }
686 sbp->entno = i; 652 sbp->entno = i;
687 sbp->hash = xfs_da_hashname((char *)sfe->nameval, sfe->namelen); 653 sbp->hash = xfs_da_hashname((char *)sfe->nameval, sfe->namelen);
688 sbp->name = (char *)sfe->nameval; 654 sbp->name = (char *)sfe->nameval;
@@ -717,7 +683,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
717 } 683 }
718 } 684 }
719 if (i == nsbuf) { 685 if (i == nsbuf) {
720 kmem_free(sbuf, sbsize); 686 kmem_free(sbuf);
721 xfs_attr_trace_l_c("blk end", context); 687 xfs_attr_trace_l_c("blk end", context);
722 return(0); 688 return(0);
723 } 689 }
@@ -726,16 +692,12 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
726 * Loop putting entries into the user buffer. 692 * Loop putting entries into the user buffer.
727 */ 693 */
728 for ( ; i < nsbuf; i++, sbp++) { 694 for ( ; i < nsbuf; i++, sbp++) {
729 attrnames_t *namesp;
730
731 namesp = xfs_attr_flags_namesp(sbp->flags);
732
733 if (cursor->hashval != sbp->hash) { 695 if (cursor->hashval != sbp->hash) {
734 cursor->hashval = sbp->hash; 696 cursor->hashval = sbp->hash;
735 cursor->offset = 0; 697 cursor->offset = 0;
736 } 698 }
737 error = context->put_listent(context, 699 error = context->put_listent(context,
738 namesp, 700 sbp->flags,
739 sbp->name, 701 sbp->name,
740 sbp->namelen, 702 sbp->namelen,
741 sbp->valuelen, 703 sbp->valuelen,
@@ -747,7 +709,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
747 cursor->offset++; 709 cursor->offset++;
748 } 710 }
749 711
750 kmem_free(sbuf, sbsize); 712 kmem_free(sbuf);
751 xfs_attr_trace_l_c("sf E-O-F", context); 713 xfs_attr_trace_l_c("sf E-O-F", context);
752 return(0); 714 return(0);
753} 715}
@@ -853,7 +815,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
853 nargs.total = args->total; 815 nargs.total = args->total;
854 nargs.whichfork = XFS_ATTR_FORK; 816 nargs.whichfork = XFS_ATTR_FORK;
855 nargs.trans = args->trans; 817 nargs.trans = args->trans;
856 nargs.oknoent = 1; 818 nargs.op_flags = XFS_DA_OP_OKNOENT;
857 entry = &leaf->entries[0]; 819 entry = &leaf->entries[0];
858 for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { 820 for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
859 if (entry->flags & XFS_ATTR_INCOMPLETE) 821 if (entry->flags & XFS_ATTR_INCOMPLETE)
@@ -873,7 +835,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
873 error = 0; 835 error = 0;
874 836
875out: 837out:
876 kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount)); 838 kmem_free(tmpbuffer);
877 return(error); 839 return(error);
878} 840}
879 841
@@ -1155,7 +1117,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
1155 entry->hashval = cpu_to_be32(args->hashval); 1117 entry->hashval = cpu_to_be32(args->hashval);
1156 entry->flags = tmp ? XFS_ATTR_LOCAL : 0; 1118 entry->flags = tmp ? XFS_ATTR_LOCAL : 0;
1157 entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); 1119 entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);
1158 if (args->rename) { 1120 if (args->op_flags & XFS_DA_OP_RENAME) {
1159 entry->flags |= XFS_ATTR_INCOMPLETE; 1121 entry->flags |= XFS_ATTR_INCOMPLETE;
1160 if ((args->blkno2 == args->blkno) && 1122 if ((args->blkno2 == args->blkno) &&
1161 (args->index2 <= args->index)) { 1123 (args->index2 <= args->index)) {
@@ -1271,7 +1233,7 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp)
1271 be16_to_cpu(hdr_s->count), mp); 1233 be16_to_cpu(hdr_s->count), mp);
1272 xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); 1234 xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1);
1273 1235
1274 kmem_free(tmpbuffer, XFS_LBSIZE(mp)); 1236 kmem_free(tmpbuffer);
1275} 1237}
1276 1238
1277/* 1239/*
@@ -1921,7 +1883,7 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1921 be16_to_cpu(drop_hdr->count), mp); 1883 be16_to_cpu(drop_hdr->count), mp);
1922 } 1884 }
1923 memcpy((char *)save_leaf, (char *)tmp_leaf, state->blocksize); 1885 memcpy((char *)save_leaf, (char *)tmp_leaf, state->blocksize);
1924 kmem_free(tmpbuffer, state->blocksize); 1886 kmem_free(tmpbuffer);
1925 } 1887 }
1926 1888
1927 xfs_da_log_buf(state->args->trans, save_blk->bp, 0, 1889 xfs_da_log_buf(state->args->trans, save_blk->bp, 0,
@@ -2400,8 +2362,6 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
2400 */ 2362 */
2401 retval = 0; 2363 retval = 0;
2402 for ( ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) { 2364 for ( ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) {
2403 attrnames_t *namesp;
2404
2405 if (be32_to_cpu(entry->hashval) != cursor->hashval) { 2365 if (be32_to_cpu(entry->hashval) != cursor->hashval) {
2406 cursor->hashval = be32_to_cpu(entry->hashval); 2366 cursor->hashval = be32_to_cpu(entry->hashval);
2407 cursor->offset = 0; 2367 cursor->offset = 0;
@@ -2409,17 +2369,13 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
2409 2369
2410 if (entry->flags & XFS_ATTR_INCOMPLETE) 2370 if (entry->flags & XFS_ATTR_INCOMPLETE)
2411 continue; /* skip incomplete entries */ 2371 continue; /* skip incomplete entries */
2412 if (!xfs_attr_namesp_match_overrides(context->flags, entry->flags))
2413 continue;
2414
2415 namesp = xfs_attr_flags_namesp(entry->flags);
2416 2372
2417 if (entry->flags & XFS_ATTR_LOCAL) { 2373 if (entry->flags & XFS_ATTR_LOCAL) {
2418 xfs_attr_leaf_name_local_t *name_loc = 2374 xfs_attr_leaf_name_local_t *name_loc =
2419 XFS_ATTR_LEAF_NAME_LOCAL(leaf, i); 2375 XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
2420 2376
2421 retval = context->put_listent(context, 2377 retval = context->put_listent(context,
2422 namesp, 2378 entry->flags,
2423 (char *)name_loc->nameval, 2379 (char *)name_loc->nameval,
2424 (int)name_loc->namelen, 2380 (int)name_loc->namelen,
2425 be16_to_cpu(name_loc->valuelen), 2381 be16_to_cpu(name_loc->valuelen),
@@ -2446,16 +2402,15 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
2446 if (retval) 2402 if (retval)
2447 return retval; 2403 return retval;
2448 retval = context->put_listent(context, 2404 retval = context->put_listent(context,
2449 namesp, 2405 entry->flags,
2450 (char *)name_rmt->name, 2406 (char *)name_rmt->name,
2451 (int)name_rmt->namelen, 2407 (int)name_rmt->namelen,
2452 valuelen, 2408 valuelen,
2453 (char*)args.value); 2409 (char*)args.value);
2454 kmem_free(args.value, valuelen); 2410 kmem_free(args.value);
2455 } 2411 } else {
2456 else {
2457 retval = context->put_listent(context, 2412 retval = context->put_listent(context,
2458 namesp, 2413 entry->flags,
2459 (char *)name_rmt->name, 2414 (char *)name_rmt->name,
2460 (int)name_rmt->namelen, 2415 (int)name_rmt->namelen,
2461 valuelen, 2416 valuelen,
@@ -2954,7 +2909,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
2954 error = tmp; /* save only the 1st errno */ 2909 error = tmp; /* save only the 1st errno */
2955 } 2910 }
2956 2911
2957 kmem_free((xfs_caddr_t)list, size); 2912 kmem_free((xfs_caddr_t)list);
2958 return(error); 2913 return(error);
2959} 2914}
2960 2915
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index 040f732ce1e2..5ecf437b7825 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -30,7 +30,7 @@
30 30
31struct attrlist; 31struct attrlist;
32struct attrlist_cursor_kern; 32struct attrlist_cursor_kern;
33struct attrnames; 33struct xfs_attr_list_context;
34struct xfs_dabuf; 34struct xfs_dabuf;
35struct xfs_da_args; 35struct xfs_da_args;
36struct xfs_da_state; 36struct xfs_da_state;
@@ -204,33 +204,6 @@ static inline int xfs_attr_leaf_entsize_local_max(int bsize)
204 return (((bsize) >> 1) + ((bsize) >> 2)); 204 return (((bsize) >> 1) + ((bsize) >> 2));
205} 205}
206 206
207
208/*========================================================================
209 * Structure used to pass context around among the routines.
210 *========================================================================*/
211
212
213struct xfs_attr_list_context;
214
215typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, struct attrnames *,
216 char *, int, int, char *);
217
218typedef struct xfs_attr_list_context {
219 struct xfs_inode *dp; /* inode */
220 struct attrlist_cursor_kern *cursor; /* position in list */
221 struct attrlist *alist; /* output buffer */
222 int seen_enough; /* T/F: seen enough of list? */
223 int count; /* num used entries */
224 int dupcnt; /* count dup hashvals seen */
225 int bufsize; /* total buffer size */
226 int firstu; /* first used byte in buffer */
227 int flags; /* from VOP call */
228 int resynch; /* T/F: resynch with cursor */
229 int put_value; /* T/F: need value for listent */
230 put_listent_func_t put_listent; /* list output fmt function */
231 int index; /* index into output buffer */
232} xfs_attr_list_context_t;
233
234/* 207/*
235 * Used to keep a list of "remote value" extents when unlinking an inode. 208 * Used to keep a list of "remote value" extents when unlinking an inode.
236 */ 209 */
diff --git a/fs/xfs/xfs_attr_sf.h b/fs/xfs/xfs_attr_sf.h
index f67f917803b1..ea22839caed2 100644
--- a/fs/xfs/xfs_attr_sf.h
+++ b/fs/xfs/xfs_attr_sf.h
@@ -97,13 +97,9 @@ void xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,
97void xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, 97void xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
98 struct xfs_attr_leafblock *leaf); 98 struct xfs_attr_leafblock *leaf);
99void xfs_attr_trace_enter(int type, char *where, 99void xfs_attr_trace_enter(int type, char *where,
100 __psunsigned_t a2, __psunsigned_t a3, 100 struct xfs_attr_list_context *context,
101 __psunsigned_t a4, __psunsigned_t a5, 101 __psunsigned_t a13, __psunsigned_t a14,
102 __psunsigned_t a6, __psunsigned_t a7, 102 __psunsigned_t a15);
103 __psunsigned_t a8, __psunsigned_t a9,
104 __psunsigned_t a10, __psunsigned_t a11,
105 __psunsigned_t a12, __psunsigned_t a13,
106 __psunsigned_t a14, __psunsigned_t a15);
107#else 103#else
108#define xfs_attr_trace_l_c(w,c) 104#define xfs_attr_trace_l_c(w,c)
109#define xfs_attr_trace_l_cn(w,c,n) 105#define xfs_attr_trace_l_cn(w,c,n)
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 53c259f5a5af..3c4beb3a4326 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -428,7 +428,8 @@ xfs_bmap_add_attrfork_btree(
428 cur->bc_private.b.firstblock = *firstblock; 428 cur->bc_private.b.firstblock = *firstblock;
429 if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat))) 429 if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
430 goto error0; 430 goto error0;
431 ASSERT(stat == 1); /* must be at least one entry */ 431 /* must be at least one entry */
432 XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
432 if ((error = xfs_bmbt_newroot(cur, flags, &stat))) 433 if ((error = xfs_bmbt_newroot(cur, flags, &stat)))
433 goto error0; 434 goto error0;
434 if (stat == 0) { 435 if (stat == 0) {
@@ -816,13 +817,13 @@ xfs_bmap_add_extent_delay_real(
816 RIGHT.br_startblock, 817 RIGHT.br_startblock,
817 RIGHT.br_blockcount, &i))) 818 RIGHT.br_blockcount, &i)))
818 goto done; 819 goto done;
819 ASSERT(i == 1); 820 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
820 if ((error = xfs_bmbt_delete(cur, &i))) 821 if ((error = xfs_bmbt_delete(cur, &i)))
821 goto done; 822 goto done;
822 ASSERT(i == 1); 823 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
823 if ((error = xfs_bmbt_decrement(cur, 0, &i))) 824 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
824 goto done; 825 goto done;
825 ASSERT(i == 1); 826 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
826 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, 827 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
827 LEFT.br_startblock, 828 LEFT.br_startblock,
828 LEFT.br_blockcount + 829 LEFT.br_blockcount +
@@ -860,7 +861,7 @@ xfs_bmap_add_extent_delay_real(
860 LEFT.br_startblock, LEFT.br_blockcount, 861 LEFT.br_startblock, LEFT.br_blockcount,
861 &i))) 862 &i)))
862 goto done; 863 goto done;
863 ASSERT(i == 1); 864 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
864 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, 865 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
865 LEFT.br_startblock, 866 LEFT.br_startblock,
866 LEFT.br_blockcount + 867 LEFT.br_blockcount +
@@ -895,7 +896,7 @@ xfs_bmap_add_extent_delay_real(
895 RIGHT.br_startblock, 896 RIGHT.br_startblock,
896 RIGHT.br_blockcount, &i))) 897 RIGHT.br_blockcount, &i)))
897 goto done; 898 goto done;
898 ASSERT(i == 1); 899 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
899 if ((error = xfs_bmbt_update(cur, PREV.br_startoff, 900 if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
900 new->br_startblock, 901 new->br_startblock,
901 PREV.br_blockcount + 902 PREV.br_blockcount +
@@ -928,11 +929,11 @@ xfs_bmap_add_extent_delay_real(
928 new->br_startblock, new->br_blockcount, 929 new->br_startblock, new->br_blockcount,
929 &i))) 930 &i)))
930 goto done; 931 goto done;
931 ASSERT(i == 0); 932 XFS_WANT_CORRUPTED_GOTO(i == 0, done);
932 cur->bc_rec.b.br_state = XFS_EXT_NORM; 933 cur->bc_rec.b.br_state = XFS_EXT_NORM;
933 if ((error = xfs_bmbt_insert(cur, &i))) 934 if ((error = xfs_bmbt_insert(cur, &i)))
934 goto done; 935 goto done;
935 ASSERT(i == 1); 936 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
936 } 937 }
937 *dnew = 0; 938 *dnew = 0;
938 /* DELTA: The in-core extent described by new changed type. */ 939 /* DELTA: The in-core extent described by new changed type. */
@@ -963,7 +964,7 @@ xfs_bmap_add_extent_delay_real(
963 LEFT.br_startblock, LEFT.br_blockcount, 964 LEFT.br_startblock, LEFT.br_blockcount,
964 &i))) 965 &i)))
965 goto done; 966 goto done;
966 ASSERT(i == 1); 967 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
967 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, 968 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
968 LEFT.br_startblock, 969 LEFT.br_startblock,
969 LEFT.br_blockcount + 970 LEFT.br_blockcount +
@@ -1004,11 +1005,11 @@ xfs_bmap_add_extent_delay_real(
1004 new->br_startblock, new->br_blockcount, 1005 new->br_startblock, new->br_blockcount,
1005 &i))) 1006 &i)))
1006 goto done; 1007 goto done;
1007 ASSERT(i == 0); 1008 XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1008 cur->bc_rec.b.br_state = XFS_EXT_NORM; 1009 cur->bc_rec.b.br_state = XFS_EXT_NORM;
1009 if ((error = xfs_bmbt_insert(cur, &i))) 1010 if ((error = xfs_bmbt_insert(cur, &i)))
1010 goto done; 1011 goto done;
1011 ASSERT(i == 1); 1012 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1012 } 1013 }
1013 if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && 1014 if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1014 ip->i_d.di_nextents > ip->i_df.if_ext_max) { 1015 ip->i_d.di_nextents > ip->i_df.if_ext_max) {
@@ -1054,7 +1055,7 @@ xfs_bmap_add_extent_delay_real(
1054 RIGHT.br_startblock, 1055 RIGHT.br_startblock,
1055 RIGHT.br_blockcount, &i))) 1056 RIGHT.br_blockcount, &i)))
1056 goto done; 1057 goto done;
1057 ASSERT(i == 1); 1058 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1058 if ((error = xfs_bmbt_update(cur, new->br_startoff, 1059 if ((error = xfs_bmbt_update(cur, new->br_startoff,
1059 new->br_startblock, 1060 new->br_startblock,
1060 new->br_blockcount + 1061 new->br_blockcount +
@@ -1094,11 +1095,11 @@ xfs_bmap_add_extent_delay_real(
1094 new->br_startblock, new->br_blockcount, 1095 new->br_startblock, new->br_blockcount,
1095 &i))) 1096 &i)))
1096 goto done; 1097 goto done;
1097 ASSERT(i == 0); 1098 XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1098 cur->bc_rec.b.br_state = XFS_EXT_NORM; 1099 cur->bc_rec.b.br_state = XFS_EXT_NORM;
1099 if ((error = xfs_bmbt_insert(cur, &i))) 1100 if ((error = xfs_bmbt_insert(cur, &i)))
1100 goto done; 1101 goto done;
1101 ASSERT(i == 1); 1102 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1102 } 1103 }
1103 if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && 1104 if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1104 ip->i_d.di_nextents > ip->i_df.if_ext_max) { 1105 ip->i_d.di_nextents > ip->i_df.if_ext_max) {
@@ -1149,11 +1150,11 @@ xfs_bmap_add_extent_delay_real(
1149 new->br_startblock, new->br_blockcount, 1150 new->br_startblock, new->br_blockcount,
1150 &i))) 1151 &i)))
1151 goto done; 1152 goto done;
1152 ASSERT(i == 0); 1153 XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1153 cur->bc_rec.b.br_state = XFS_EXT_NORM; 1154 cur->bc_rec.b.br_state = XFS_EXT_NORM;
1154 if ((error = xfs_bmbt_insert(cur, &i))) 1155 if ((error = xfs_bmbt_insert(cur, &i)))
1155 goto done; 1156 goto done;
1156 ASSERT(i == 1); 1157 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1157 } 1158 }
1158 if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && 1159 if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1159 ip->i_d.di_nextents > ip->i_df.if_ext_max) { 1160 ip->i_d.di_nextents > ip->i_df.if_ext_max) {
@@ -1377,19 +1378,19 @@ xfs_bmap_add_extent_unwritten_real(
1377 RIGHT.br_startblock, 1378 RIGHT.br_startblock,
1378 RIGHT.br_blockcount, &i))) 1379 RIGHT.br_blockcount, &i)))
1379 goto done; 1380 goto done;
1380 ASSERT(i == 1); 1381 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1381 if ((error = xfs_bmbt_delete(cur, &i))) 1382 if ((error = xfs_bmbt_delete(cur, &i)))
1382 goto done; 1383 goto done;
1383 ASSERT(i == 1); 1384 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1384 if ((error = xfs_bmbt_decrement(cur, 0, &i))) 1385 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1385 goto done; 1386 goto done;
1386 ASSERT(i == 1); 1387 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1387 if ((error = xfs_bmbt_delete(cur, &i))) 1388 if ((error = xfs_bmbt_delete(cur, &i)))
1388 goto done; 1389 goto done;
1389 ASSERT(i == 1); 1390 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1390 if ((error = xfs_bmbt_decrement(cur, 0, &i))) 1391 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1391 goto done; 1392 goto done;
1392 ASSERT(i == 1); 1393 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1393 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, 1394 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1394 LEFT.br_startblock, 1395 LEFT.br_startblock,
1395 LEFT.br_blockcount + PREV.br_blockcount + 1396 LEFT.br_blockcount + PREV.br_blockcount +
@@ -1426,13 +1427,13 @@ xfs_bmap_add_extent_unwritten_real(
1426 PREV.br_startblock, PREV.br_blockcount, 1427 PREV.br_startblock, PREV.br_blockcount,
1427 &i))) 1428 &i)))
1428 goto done; 1429 goto done;
1429 ASSERT(i == 1); 1430 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1430 if ((error = xfs_bmbt_delete(cur, &i))) 1431 if ((error = xfs_bmbt_delete(cur, &i)))
1431 goto done; 1432 goto done;
1432 ASSERT(i == 1); 1433 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1433 if ((error = xfs_bmbt_decrement(cur, 0, &i))) 1434 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1434 goto done; 1435 goto done;
1435 ASSERT(i == 1); 1436 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1436 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, 1437 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1437 LEFT.br_startblock, 1438 LEFT.br_startblock,
1438 LEFT.br_blockcount + PREV.br_blockcount, 1439 LEFT.br_blockcount + PREV.br_blockcount,
@@ -1469,13 +1470,13 @@ xfs_bmap_add_extent_unwritten_real(
1469 RIGHT.br_startblock, 1470 RIGHT.br_startblock,
1470 RIGHT.br_blockcount, &i))) 1471 RIGHT.br_blockcount, &i)))
1471 goto done; 1472 goto done;
1472 ASSERT(i == 1); 1473 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1473 if ((error = xfs_bmbt_delete(cur, &i))) 1474 if ((error = xfs_bmbt_delete(cur, &i)))
1474 goto done; 1475 goto done;
1475 ASSERT(i == 1); 1476 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1476 if ((error = xfs_bmbt_decrement(cur, 0, &i))) 1477 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1477 goto done; 1478 goto done;
1478 ASSERT(i == 1); 1479 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1479 if ((error = xfs_bmbt_update(cur, new->br_startoff, 1480 if ((error = xfs_bmbt_update(cur, new->br_startoff,
1480 new->br_startblock, 1481 new->br_startblock,
1481 new->br_blockcount + RIGHT.br_blockcount, 1482 new->br_blockcount + RIGHT.br_blockcount,
@@ -1508,7 +1509,7 @@ xfs_bmap_add_extent_unwritten_real(
1508 new->br_startblock, new->br_blockcount, 1509 new->br_startblock, new->br_blockcount,
1509 &i))) 1510 &i)))
1510 goto done; 1511 goto done;
1511 ASSERT(i == 1); 1512 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1512 if ((error = xfs_bmbt_update(cur, new->br_startoff, 1513 if ((error = xfs_bmbt_update(cur, new->br_startoff,
1513 new->br_startblock, new->br_blockcount, 1514 new->br_startblock, new->br_blockcount,
1514 newext))) 1515 newext)))
@@ -1549,7 +1550,7 @@ xfs_bmap_add_extent_unwritten_real(
1549 PREV.br_startblock, PREV.br_blockcount, 1550 PREV.br_startblock, PREV.br_blockcount,
1550 &i))) 1551 &i)))
1551 goto done; 1552 goto done;
1552 ASSERT(i == 1); 1553 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1553 if ((error = xfs_bmbt_update(cur, 1554 if ((error = xfs_bmbt_update(cur,
1554 PREV.br_startoff + new->br_blockcount, 1555 PREV.br_startoff + new->br_blockcount,
1555 PREV.br_startblock + new->br_blockcount, 1556 PREV.br_startblock + new->br_blockcount,
@@ -1596,7 +1597,7 @@ xfs_bmap_add_extent_unwritten_real(
1596 PREV.br_startblock, PREV.br_blockcount, 1597 PREV.br_startblock, PREV.br_blockcount,
1597 &i))) 1598 &i)))
1598 goto done; 1599 goto done;
1599 ASSERT(i == 1); 1600 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1600 if ((error = xfs_bmbt_update(cur, 1601 if ((error = xfs_bmbt_update(cur,
1601 PREV.br_startoff + new->br_blockcount, 1602 PREV.br_startoff + new->br_blockcount,
1602 PREV.br_startblock + new->br_blockcount, 1603 PREV.br_startblock + new->br_blockcount,
@@ -1606,7 +1607,7 @@ xfs_bmap_add_extent_unwritten_real(
1606 cur->bc_rec.b = *new; 1607 cur->bc_rec.b = *new;
1607 if ((error = xfs_bmbt_insert(cur, &i))) 1608 if ((error = xfs_bmbt_insert(cur, &i)))
1608 goto done; 1609 goto done;
1609 ASSERT(i == 1); 1610 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1610 } 1611 }
1611 /* DELTA: One in-core extent is split in two. */ 1612 /* DELTA: One in-core extent is split in two. */
1612 temp = PREV.br_startoff; 1613 temp = PREV.br_startoff;
@@ -1640,7 +1641,7 @@ xfs_bmap_add_extent_unwritten_real(
1640 PREV.br_startblock, 1641 PREV.br_startblock,
1641 PREV.br_blockcount, &i))) 1642 PREV.br_blockcount, &i)))
1642 goto done; 1643 goto done;
1643 ASSERT(i == 1); 1644 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1644 if ((error = xfs_bmbt_update(cur, PREV.br_startoff, 1645 if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1645 PREV.br_startblock, 1646 PREV.br_startblock,
1646 PREV.br_blockcount - new->br_blockcount, 1647 PREV.br_blockcount - new->br_blockcount,
@@ -1682,7 +1683,7 @@ xfs_bmap_add_extent_unwritten_real(
1682 PREV.br_startblock, PREV.br_blockcount, 1683 PREV.br_startblock, PREV.br_blockcount,
1683 &i))) 1684 &i)))
1684 goto done; 1685 goto done;
1685 ASSERT(i == 1); 1686 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1686 if ((error = xfs_bmbt_update(cur, PREV.br_startoff, 1687 if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1687 PREV.br_startblock, 1688 PREV.br_startblock,
1688 PREV.br_blockcount - new->br_blockcount, 1689 PREV.br_blockcount - new->br_blockcount,
@@ -1692,11 +1693,11 @@ xfs_bmap_add_extent_unwritten_real(
1692 new->br_startblock, new->br_blockcount, 1693 new->br_startblock, new->br_blockcount,
1693 &i))) 1694 &i)))
1694 goto done; 1695 goto done;
1695 ASSERT(i == 0); 1696 XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1696 cur->bc_rec.b.br_state = XFS_EXT_NORM; 1697 cur->bc_rec.b.br_state = XFS_EXT_NORM;
1697 if ((error = xfs_bmbt_insert(cur, &i))) 1698 if ((error = xfs_bmbt_insert(cur, &i)))
1698 goto done; 1699 goto done;
1699 ASSERT(i == 1); 1700 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1700 } 1701 }
1701 /* DELTA: One in-core extent is split in two. */ 1702 /* DELTA: One in-core extent is split in two. */
1702 temp = PREV.br_startoff; 1703 temp = PREV.br_startoff;
@@ -1732,27 +1733,34 @@ xfs_bmap_add_extent_unwritten_real(
1732 PREV.br_startblock, PREV.br_blockcount, 1733 PREV.br_startblock, PREV.br_blockcount,
1733 &i))) 1734 &i)))
1734 goto done; 1735 goto done;
1735 ASSERT(i == 1); 1736 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1736 /* new right extent - oldext */ 1737 /* new right extent - oldext */
1737 if ((error = xfs_bmbt_update(cur, r[1].br_startoff, 1738 if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
1738 r[1].br_startblock, r[1].br_blockcount, 1739 r[1].br_startblock, r[1].br_blockcount,
1739 r[1].br_state))) 1740 r[1].br_state)))
1740 goto done; 1741 goto done;
1741 /* new left extent - oldext */ 1742 /* new left extent - oldext */
1742 PREV.br_blockcount =
1743 new->br_startoff - PREV.br_startoff;
1744 cur->bc_rec.b = PREV; 1743 cur->bc_rec.b = PREV;
1744 cur->bc_rec.b.br_blockcount =
1745 new->br_startoff - PREV.br_startoff;
1745 if ((error = xfs_bmbt_insert(cur, &i))) 1746 if ((error = xfs_bmbt_insert(cur, &i)))
1746 goto done; 1747 goto done;
1747 ASSERT(i == 1); 1748 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1748 if ((error = xfs_bmbt_increment(cur, 0, &i))) 1749 /*
1750 * Reset the cursor to the position of the new extent
1751 * we are about to insert as we can't trust it after
1752 * the previous insert.
1753 */
1754 if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1755 new->br_startblock, new->br_blockcount,
1756 &i)))
1749 goto done; 1757 goto done;
1750 ASSERT(i == 1); 1758 XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1751 /* new middle extent - newext */ 1759 /* new middle extent - newext */
1752 cur->bc_rec.b = *new; 1760 cur->bc_rec.b.br_state = new->br_state;
1753 if ((error = xfs_bmbt_insert(cur, &i))) 1761 if ((error = xfs_bmbt_insert(cur, &i)))
1754 goto done; 1762 goto done;
1755 ASSERT(i == 1); 1763 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1756 } 1764 }
1757 /* DELTA: One in-core extent is split in three. */ 1765 /* DELTA: One in-core extent is split in three. */
1758 temp = PREV.br_startoff; 1766 temp = PREV.br_startoff;
@@ -2097,13 +2105,13 @@ xfs_bmap_add_extent_hole_real(
2097 right.br_startblock, 2105 right.br_startblock,
2098 right.br_blockcount, &i))) 2106 right.br_blockcount, &i)))
2099 goto done; 2107 goto done;
2100 ASSERT(i == 1); 2108 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2101 if ((error = xfs_bmbt_delete(cur, &i))) 2109 if ((error = xfs_bmbt_delete(cur, &i)))
2102 goto done; 2110 goto done;
2103 ASSERT(i == 1); 2111 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2104 if ((error = xfs_bmbt_decrement(cur, 0, &i))) 2112 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
2105 goto done; 2113 goto done;
2106 ASSERT(i == 1); 2114 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2107 if ((error = xfs_bmbt_update(cur, left.br_startoff, 2115 if ((error = xfs_bmbt_update(cur, left.br_startoff,
2108 left.br_startblock, 2116 left.br_startblock,
2109 left.br_blockcount + 2117 left.br_blockcount +
@@ -2139,7 +2147,7 @@ xfs_bmap_add_extent_hole_real(
2139 left.br_startblock, 2147 left.br_startblock,
2140 left.br_blockcount, &i))) 2148 left.br_blockcount, &i)))
2141 goto done; 2149 goto done;
2142 ASSERT(i == 1); 2150 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2143 if ((error = xfs_bmbt_update(cur, left.br_startoff, 2151 if ((error = xfs_bmbt_update(cur, left.br_startoff,
2144 left.br_startblock, 2152 left.br_startblock,
2145 left.br_blockcount + 2153 left.br_blockcount +
@@ -2174,7 +2182,7 @@ xfs_bmap_add_extent_hole_real(
2174 right.br_startblock, 2182 right.br_startblock,
2175 right.br_blockcount, &i))) 2183 right.br_blockcount, &i)))
2176 goto done; 2184 goto done;
2177 ASSERT(i == 1); 2185 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2178 if ((error = xfs_bmbt_update(cur, new->br_startoff, 2186 if ((error = xfs_bmbt_update(cur, new->br_startoff,
2179 new->br_startblock, 2187 new->br_startblock,
2180 new->br_blockcount + 2188 new->br_blockcount +
@@ -2208,11 +2216,11 @@ xfs_bmap_add_extent_hole_real(
2208 new->br_startblock, 2216 new->br_startblock,
2209 new->br_blockcount, &i))) 2217 new->br_blockcount, &i)))
2210 goto done; 2218 goto done;
2211 ASSERT(i == 0); 2219 XFS_WANT_CORRUPTED_GOTO(i == 0, done);
2212 cur->bc_rec.b.br_state = new->br_state; 2220 cur->bc_rec.b.br_state = new->br_state;
2213 if ((error = xfs_bmbt_insert(cur, &i))) 2221 if ((error = xfs_bmbt_insert(cur, &i)))
2214 goto done; 2222 goto done;
2215 ASSERT(i == 1); 2223 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2216 } 2224 }
2217 /* DELTA: A new extent was added in a hole. */ 2225 /* DELTA: A new extent was added in a hole. */
2218 temp = new->br_startoff; 2226 temp = new->br_startoff;
@@ -3131,7 +3139,7 @@ xfs_bmap_del_extent(
3131 got.br_startblock, got.br_blockcount, 3139 got.br_startblock, got.br_blockcount,
3132 &i))) 3140 &i)))
3133 goto done; 3141 goto done;
3134 ASSERT(i == 1); 3142 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3135 } 3143 }
3136 da_old = da_new = 0; 3144 da_old = da_new = 0;
3137 } else { 3145 } else {
@@ -3164,7 +3172,7 @@ xfs_bmap_del_extent(
3164 } 3172 }
3165 if ((error = xfs_bmbt_delete(cur, &i))) 3173 if ((error = xfs_bmbt_delete(cur, &i)))
3166 goto done; 3174 goto done;
3167 ASSERT(i == 1); 3175 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3168 break; 3176 break;
3169 3177
3170 case 2: 3178 case 2:
@@ -3268,7 +3276,7 @@ xfs_bmap_del_extent(
3268 got.br_startblock, 3276 got.br_startblock,
3269 temp, &i))) 3277 temp, &i)))
3270 goto done; 3278 goto done;
3271 ASSERT(i == 1); 3279 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3272 /* 3280 /*
3273 * Update the btree record back 3281 * Update the btree record back
3274 * to the original value. 3282 * to the original value.
@@ -3289,7 +3297,7 @@ xfs_bmap_del_extent(
3289 error = XFS_ERROR(ENOSPC); 3297 error = XFS_ERROR(ENOSPC);
3290 goto done; 3298 goto done;
3291 } 3299 }
3292 ASSERT(i == 1); 3300 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3293 } else 3301 } else
3294 flags |= XFS_ILOG_FEXT(whichfork); 3302 flags |= XFS_ILOG_FEXT(whichfork);
3295 XFS_IFORK_NEXT_SET(ip, whichfork, 3303 XFS_IFORK_NEXT_SET(ip, whichfork,
@@ -5970,7 +5978,7 @@ unlock_and_return:
5970 xfs_iunlock_map_shared(ip, lock); 5978 xfs_iunlock_map_shared(ip, lock);
5971 xfs_iunlock(ip, XFS_IOLOCK_SHARED); 5979 xfs_iunlock(ip, XFS_IOLOCK_SHARED);
5972 5980
5973 kmem_free(map, subnex * sizeof(*map)); 5981 kmem_free(map);
5974 5982
5975 return error; 5983 return error;
5976} 5984}
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 6ff70cda451c..9f3e3a836d15 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -54,12 +54,23 @@ typedef struct xfs_bmap_free_item
54 54
55/* 55/*
56 * Header for free extent list. 56 * Header for free extent list.
57 *
58 * xbf_low is used by the allocator to activate the lowspace algorithm -
59 * when free space is running low the extent allocator may choose to
60 * allocate an extent from an AG without leaving sufficient space for
61 * a btree split when inserting the new extent. In this case the allocator
62 * will enable the lowspace algorithm which is supposed to allow further
63 * allocations (such as btree splits and newroots) to allocate from
64 * sequential AGs. In order to avoid locking AGs out of order the lowspace
65 * algorithm will start searching for free space from AG 0. If the correct
66 * transaction reservations have been made then this algorithm will eventually
67 * find all the space it needs.
57 */ 68 */
58typedef struct xfs_bmap_free 69typedef struct xfs_bmap_free
59{ 70{
60 xfs_bmap_free_item_t *xbf_first; /* list of to-be-free extents */ 71 xfs_bmap_free_item_t *xbf_first; /* list of to-be-free extents */
61 int xbf_count; /* count of items on list */ 72 int xbf_count; /* count of items on list */
62 int xbf_low; /* kludge: alloc in low mode */ 73 int xbf_low; /* alloc in low mode */
63} xfs_bmap_free_t; 74} xfs_bmap_free_t;
64 75
65#define XFS_BMAP_MAX_NMAP 4 76#define XFS_BMAP_MAX_NMAP 4
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 4f0e849d973e..23efad29a5cd 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -1493,12 +1493,27 @@ xfs_bmbt_split(
1493 left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1493 left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1494 args.fsbno = cur->bc_private.b.firstblock; 1494 args.fsbno = cur->bc_private.b.firstblock;
1495 args.firstblock = args.fsbno; 1495 args.firstblock = args.fsbno;
1496 args.minleft = 0;
1496 if (args.fsbno == NULLFSBLOCK) { 1497 if (args.fsbno == NULLFSBLOCK) {
1497 args.fsbno = lbno; 1498 args.fsbno = lbno;
1498 args.type = XFS_ALLOCTYPE_START_BNO; 1499 args.type = XFS_ALLOCTYPE_START_BNO;
1499 } else 1500 /*
1501 * Make sure there is sufficient room left in the AG to
1502 * complete a full tree split for an extent insert. If
1503 * we are converting the middle part of an extent then
1504 * we may need space for two tree splits.
1505 *
1506 * We are relying on the caller to make the correct block
1507 * reservation for this operation to succeed. If the
1508 * reservation amount is insufficient then we may fail a
1509 * block allocation here and corrupt the filesystem.
1510 */
1511 args.minleft = xfs_trans_get_block_res(args.tp);
1512 } else if (cur->bc_private.b.flist->xbf_low)
1513 args.type = XFS_ALLOCTYPE_START_BNO;
1514 else
1500 args.type = XFS_ALLOCTYPE_NEAR_BNO; 1515 args.type = XFS_ALLOCTYPE_NEAR_BNO;
1501 args.mod = args.minleft = args.alignment = args.total = args.isfl = 1516 args.mod = args.alignment = args.total = args.isfl =
1502 args.userdata = args.minalignslop = 0; 1517 args.userdata = args.minalignslop = 0;
1503 args.minlen = args.maxlen = args.prod = 1; 1518 args.minlen = args.maxlen = args.prod = 1;
1504 args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; 1519 args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
@@ -1510,6 +1525,21 @@ xfs_bmbt_split(
1510 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1525 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1511 return error; 1526 return error;
1512 } 1527 }
1528 if (args.fsbno == NULLFSBLOCK && args.minleft) {
1529 /*
1530 * Could not find an AG with enough free space to satisfy
1531 * a full btree split. Try again without minleft and if
1532 * successful activate the lowspace algorithm.
1533 */
1534 args.fsbno = 0;
1535 args.type = XFS_ALLOCTYPE_FIRST_AG;
1536 args.minleft = 0;
1537 if ((error = xfs_alloc_vextent(&args))) {
1538 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1539 return error;
1540 }
1541 cur->bc_private.b.flist->xbf_low = 1;
1542 }
1513 if (args.fsbno == NULLFSBLOCK) { 1543 if (args.fsbno == NULLFSBLOCK) {
1514 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1544 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1515 *stat = 0; 1545 *stat = 0;
@@ -2029,22 +2059,8 @@ xfs_bmbt_increment(
2029 * Insert the current record at the point referenced by cur. 2059 * Insert the current record at the point referenced by cur.
2030 * 2060 *
2031 * A multi-level split of the tree on insert will invalidate the original 2061 * A multi-level split of the tree on insert will invalidate the original
2032 * cursor. It appears, however, that some callers assume that the cursor is 2062 * cursor. All callers of this function should assume that the cursor is
2033 * always valid. Hence if we do a multi-level split we need to revalidate the 2063 * no longer valid and revalidate it.
2034 * cursor.
2035 *
2036 * When a split occurs, we will see a new cursor returned. Use that as a
2037 * trigger to determine if we need to revalidate the original cursor. If we get
2038 * a split, then use the original irec to lookup up the path of the record we
2039 * just inserted.
2040 *
2041 * Note that the fact that the btree root is in the inode means that we can
2042 * have the level of the tree change without a "split" occurring at the root
2043 * level. What happens is that the root is migrated to an allocated block and
2044 * the inode root is pointed to it. This means a single split can change the
2045 * level of the tree (level 2 -> level 3) and invalidate the old cursor. Hence
2046 * the level change should be accounted as a split so as to correctly trigger a
2047 * revalidation of the old cursor.
2048 */ 2064 */
2049int /* error */ 2065int /* error */
2050xfs_bmbt_insert( 2066xfs_bmbt_insert(
@@ -2057,14 +2073,11 @@ xfs_bmbt_insert(
2057 xfs_fsblock_t nbno; 2073 xfs_fsblock_t nbno;
2058 xfs_btree_cur_t *ncur; 2074 xfs_btree_cur_t *ncur;
2059 xfs_bmbt_rec_t nrec; 2075 xfs_bmbt_rec_t nrec;
2060 xfs_bmbt_irec_t oirec; /* original irec */
2061 xfs_btree_cur_t *pcur; 2076 xfs_btree_cur_t *pcur;
2062 int splits = 0;
2063 2077
2064 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2078 XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2065 level = 0; 2079 level = 0;
2066 nbno = NULLFSBLOCK; 2080 nbno = NULLFSBLOCK;
2067 oirec = cur->bc_rec.b;
2068 xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); 2081 xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
2069 ncur = NULL; 2082 ncur = NULL;
2070 pcur = cur; 2083 pcur = cur;
@@ -2073,13 +2086,11 @@ xfs_bmbt_insert(
2073 &i))) { 2086 &i))) {
2074 if (pcur != cur) 2087 if (pcur != cur)
2075 xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); 2088 xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
2076 goto error0; 2089 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2090 return error;
2077 } 2091 }
2078 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 2092 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2079 if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { 2093 if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
2080 /* allocating a new root is effectively a split */
2081 if (cur->bc_nlevels != pcur->bc_nlevels)
2082 splits++;
2083 cur->bc_nlevels = pcur->bc_nlevels; 2094 cur->bc_nlevels = pcur->bc_nlevels;
2084 cur->bc_private.b.allocated += 2095 cur->bc_private.b.allocated +=
2085 pcur->bc_private.b.allocated; 2096 pcur->bc_private.b.allocated;
@@ -2093,21 +2104,10 @@ xfs_bmbt_insert(
2093 xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); 2104 xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
2094 } 2105 }
2095 if (ncur) { 2106 if (ncur) {
2096 splits++;
2097 pcur = ncur; 2107 pcur = ncur;
2098 ncur = NULL; 2108 ncur = NULL;
2099 } 2109 }
2100 } while (nbno != NULLFSBLOCK); 2110 } while (nbno != NULLFSBLOCK);
2101
2102 if (splits > 1) {
2103 /* revalidate the old cursor as we had a multi-level split */
2104 error = xfs_bmbt_lookup_eq(cur, oirec.br_startoff,
2105 oirec.br_startblock, oirec.br_blockcount, &i);
2106 if (error)
2107 goto error0;
2108 ASSERT(i == 1);
2109 }
2110
2111 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2111 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2112 *stat = i; 2112 *stat = i;
2113 return 0; 2113 return 0;
@@ -2254,7 +2254,9 @@ xfs_bmbt_newroot(
2254#endif 2254#endif
2255 args.fsbno = be64_to_cpu(*pp); 2255 args.fsbno = be64_to_cpu(*pp);
2256 args.type = XFS_ALLOCTYPE_START_BNO; 2256 args.type = XFS_ALLOCTYPE_START_BNO;
2257 } else 2257 } else if (cur->bc_private.b.flist->xbf_low)
2258 args.type = XFS_ALLOCTYPE_START_BNO;
2259 else
2258 args.type = XFS_ALLOCTYPE_NEAR_BNO; 2260 args.type = XFS_ALLOCTYPE_NEAR_BNO;
2259 if ((error = xfs_alloc_vextent(&args))) { 2261 if ((error = xfs_alloc_vextent(&args))) {
2260 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2262 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 53a71c62025d..d86ca2c03a70 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -889,9 +889,9 @@ xfs_buf_item_relse(
889 } 889 }
890 890
891#ifdef XFS_TRANS_DEBUG 891#ifdef XFS_TRANS_DEBUG
892 kmem_free(bip->bli_orig, XFS_BUF_COUNT(bp)); 892 kmem_free(bip->bli_orig);
893 bip->bli_orig = NULL; 893 bip->bli_orig = NULL;
894 kmem_free(bip->bli_logged, XFS_BUF_COUNT(bp) / NBBY); 894 kmem_free(bip->bli_logged);
895 bip->bli_logged = NULL; 895 bip->bli_logged = NULL;
896#endif /* XFS_TRANS_DEBUG */ 896#endif /* XFS_TRANS_DEBUG */
897 897
@@ -1138,9 +1138,9 @@ xfs_buf_iodone(
1138 xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip); 1138 xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip);
1139 1139
1140#ifdef XFS_TRANS_DEBUG 1140#ifdef XFS_TRANS_DEBUG
1141 kmem_free(bip->bli_orig, XFS_BUF_COUNT(bp)); 1141 kmem_free(bip->bli_orig);
1142 bip->bli_orig = NULL; 1142 bip->bli_orig = NULL;
1143 kmem_free(bip->bli_logged, XFS_BUF_COUNT(bp) / NBBY); 1143 kmem_free(bip->bli_logged);
1144 bip->bli_logged = NULL; 1144 bip->bli_logged = NULL;
1145#endif /* XFS_TRANS_DEBUG */ 1145#endif /* XFS_TRANS_DEBUG */
1146 1146
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index d5d1e60ee224..d2ce5dd70d87 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -78,6 +78,7 @@ struct xfs_mount_args {
78#define XFSMNT_IOSIZE 0x00002000 /* optimize for I/O size */ 78#define XFSMNT_IOSIZE 0x00002000 /* optimize for I/O size */
79#define XFSMNT_OSYNCISOSYNC 0x00004000 /* o_sync is REALLY o_sync */ 79#define XFSMNT_OSYNCISOSYNC 0x00004000 /* o_sync is REALLY o_sync */
80 /* (osyncisdsync is default) */ 80 /* (osyncisdsync is default) */
81#define XFSMNT_NOATTR2 0x00008000 /* turn off ATTR2 EA format */
81#define XFSMNT_32BITINODES 0x00200000 /* restrict inodes to 32 82#define XFSMNT_32BITINODES 0x00200000 /* restrict inodes to 32
82 * bits of address space */ 83 * bits of address space */
83#define XFSMNT_GQUOTA 0x00400000 /* group quota accounting */ 84#define XFSMNT_GQUOTA 0x00400000 /* group quota accounting */
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 021a8f7e563f..9e561a9cefca 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -1431,7 +1431,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
1431 } 1431 }
1432 if (level < 0) { 1432 if (level < 0) {
1433 *result = XFS_ERROR(ENOENT); /* we're out of our tree */ 1433 *result = XFS_ERROR(ENOENT); /* we're out of our tree */
1434 ASSERT(args->oknoent); 1434 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
1435 return(0); 1435 return(0);
1436 } 1436 }
1437 1437
@@ -1530,6 +1530,28 @@ xfs_da_hashname(const uchar_t *name, int namelen)
1530 } 1530 }
1531} 1531}
1532 1532
1533enum xfs_dacmp
1534xfs_da_compname(
1535 struct xfs_da_args *args,
1536 const char *name,
1537 int len)
1538{
1539 return (args->namelen == len && memcmp(args->name, name, len) == 0) ?
1540 XFS_CMP_EXACT : XFS_CMP_DIFFERENT;
1541}
1542
1543static xfs_dahash_t
1544xfs_default_hashname(
1545 struct xfs_name *name)
1546{
1547 return xfs_da_hashname(name->name, name->len);
1548}
1549
1550const struct xfs_nameops xfs_default_nameops = {
1551 .hashname = xfs_default_hashname,
1552 .compname = xfs_da_compname
1553};
1554
1533/* 1555/*
1534 * Add a block to the btree ahead of the file. 1556 * Add a block to the btree ahead of the file.
1535 * Return the new block number to the caller. 1557 * Return the new block number to the caller.
@@ -1598,7 +1620,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1598 args->firstblock, args->total, 1620 args->firstblock, args->total,
1599 &mapp[mapi], &nmap, args->flist, 1621 &mapp[mapi], &nmap, args->flist,
1600 NULL))) { 1622 NULL))) {
1601 kmem_free(mapp, sizeof(*mapp) * count); 1623 kmem_free(mapp);
1602 return error; 1624 return error;
1603 } 1625 }
1604 if (nmap < 1) 1626 if (nmap < 1)
@@ -1620,11 +1642,11 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1620 mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != 1642 mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
1621 bno + count) { 1643 bno + count) {
1622 if (mapp != &map) 1644 if (mapp != &map)
1623 kmem_free(mapp, sizeof(*mapp) * count); 1645 kmem_free(mapp);
1624 return XFS_ERROR(ENOSPC); 1646 return XFS_ERROR(ENOSPC);
1625 } 1647 }
1626 if (mapp != &map) 1648 if (mapp != &map)
1627 kmem_free(mapp, sizeof(*mapp) * count); 1649 kmem_free(mapp);
1628 *new_blkno = (xfs_dablk_t)bno; 1650 *new_blkno = (xfs_dablk_t)bno;
1629 return 0; 1651 return 0;
1630} 1652}
@@ -2090,10 +2112,10 @@ xfs_da_do_buf(
2090 } 2112 }
2091 } 2113 }
2092 if (bplist) { 2114 if (bplist) {
2093 kmem_free(bplist, sizeof(*bplist) * nmap); 2115 kmem_free(bplist);
2094 } 2116 }
2095 if (mapp != &map) { 2117 if (mapp != &map) {
2096 kmem_free(mapp, sizeof(*mapp) * nfsb); 2118 kmem_free(mapp);
2097 } 2119 }
2098 if (bpp) 2120 if (bpp)
2099 *bpp = rbp; 2121 *bpp = rbp;
@@ -2102,11 +2124,11 @@ exit1:
2102 if (bplist) { 2124 if (bplist) {
2103 for (i = 0; i < nbplist; i++) 2125 for (i = 0; i < nbplist; i++)
2104 xfs_trans_brelse(trans, bplist[i]); 2126 xfs_trans_brelse(trans, bplist[i]);
2105 kmem_free(bplist, sizeof(*bplist) * nmap); 2127 kmem_free(bplist);
2106 } 2128 }
2107exit0: 2129exit0:
2108 if (mapp != &map) 2130 if (mapp != &map)
2109 kmem_free(mapp, sizeof(*mapp) * nfsb); 2131 kmem_free(mapp);
2110 if (bpp) 2132 if (bpp)
2111 *bpp = NULL; 2133 *bpp = NULL;
2112 return error; 2134 return error;
@@ -2218,7 +2240,7 @@ xfs_da_state_free(xfs_da_state_t *state)
2218 2240
2219#ifdef XFS_DABUF_DEBUG 2241#ifdef XFS_DABUF_DEBUG
2220xfs_dabuf_t *xfs_dabuf_global_list; 2242xfs_dabuf_t *xfs_dabuf_global_list;
2221spinlock_t xfs_dabuf_global_lock; 2243static DEFINE_SPINLOCK(xfs_dabuf_global_lock);
2222#endif 2244#endif
2223 2245
2224/* 2246/*
@@ -2315,7 +2337,7 @@ xfs_da_buf_done(xfs_dabuf_t *dabuf)
2315 if (dabuf->dirty) 2337 if (dabuf->dirty)
2316 xfs_da_buf_clean(dabuf); 2338 xfs_da_buf_clean(dabuf);
2317 if (dabuf->nbuf > 1) 2339 if (dabuf->nbuf > 1)
2318 kmem_free(dabuf->data, BBTOB(dabuf->bbcount)); 2340 kmem_free(dabuf->data);
2319#ifdef XFS_DABUF_DEBUG 2341#ifdef XFS_DABUF_DEBUG
2320 { 2342 {
2321 spin_lock(&xfs_dabuf_global_lock); 2343 spin_lock(&xfs_dabuf_global_lock);
@@ -2332,7 +2354,7 @@ xfs_da_buf_done(xfs_dabuf_t *dabuf)
2332 if (dabuf->nbuf == 1) 2354 if (dabuf->nbuf == 1)
2333 kmem_zone_free(xfs_dabuf_zone, dabuf); 2355 kmem_zone_free(xfs_dabuf_zone, dabuf);
2334 else 2356 else
2335 kmem_free(dabuf, XFS_DA_BUF_SIZE(dabuf->nbuf)); 2357 kmem_free(dabuf);
2336} 2358}
2337 2359
2338/* 2360/*
@@ -2403,7 +2425,7 @@ xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf)
2403 for (i = 0; i < nbuf; i++) 2425 for (i = 0; i < nbuf; i++)
2404 xfs_trans_brelse(tp, bplist[i]); 2426 xfs_trans_brelse(tp, bplist[i]);
2405 if (bplist != &bp) 2427 if (bplist != &bp)
2406 kmem_free(bplist, nbuf * sizeof(*bplist)); 2428 kmem_free(bplist);
2407} 2429}
2408 2430
2409/* 2431/*
@@ -2429,7 +2451,7 @@ xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf)
2429 for (i = 0; i < nbuf; i++) 2451 for (i = 0; i < nbuf; i++)
2430 xfs_trans_binval(tp, bplist[i]); 2452 xfs_trans_binval(tp, bplist[i]);
2431 if (bplist != &bp) 2453 if (bplist != &bp)
2432 kmem_free(bplist, nbuf * sizeof(*bplist)); 2454 kmem_free(bplist);
2433} 2455}
2434 2456
2435/* 2457/*
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 7facf86f74f9..8be0b00ede9a 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -99,6 +99,15 @@ typedef struct xfs_da_node_entry xfs_da_node_entry_t;
99 *========================================================================*/ 99 *========================================================================*/
100 100
101/* 101/*
102 * Search comparison results
103 */
104enum xfs_dacmp {
105 XFS_CMP_DIFFERENT, /* names are completely different */
106 XFS_CMP_EXACT, /* names are exactly the same */
107 XFS_CMP_CASE /* names are same but differ in case */
108};
109
110/*
102 * Structure to ease passing around component names. 111 * Structure to ease passing around component names.
103 */ 112 */
104typedef struct xfs_da_args { 113typedef struct xfs_da_args {
@@ -123,13 +132,20 @@ typedef struct xfs_da_args {
123 int index2; /* index of 2nd attr in blk */ 132 int index2; /* index of 2nd attr in blk */
124 xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */ 133 xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */
125 int rmtblkcnt2; /* remote attr value block count */ 134 int rmtblkcnt2; /* remote attr value block count */
126 unsigned char justcheck; /* T/F: check for ok with no space */ 135 int op_flags; /* operation flags */
127 unsigned char rename; /* T/F: this is an atomic rename op */ 136 enum xfs_dacmp cmpresult; /* name compare result for lookups */
128 unsigned char addname; /* T/F: this is an add operation */
129 unsigned char oknoent; /* T/F: ok to return ENOENT, else die */
130} xfs_da_args_t; 137} xfs_da_args_t;
131 138
132/* 139/*
140 * Operation flags:
141 */
142#define XFS_DA_OP_JUSTCHECK 0x0001 /* check for ok with no space */
143#define XFS_DA_OP_RENAME 0x0002 /* this is an atomic rename op */
144#define XFS_DA_OP_ADDNAME 0x0004 /* this is an add operation */
145#define XFS_DA_OP_OKNOENT 0x0008 /* lookup/add op, ENOENT ok, else die */
146#define XFS_DA_OP_CILOOKUP 0x0010 /* lookup to return CI name if found */
147
148/*
133 * Structure to describe buffer(s) for a block. 149 * Structure to describe buffer(s) for a block.
134 * This is needed in the directory version 2 format case, when 150 * This is needed in the directory version 2 format case, when
135 * multiple non-contiguous fsblocks might be needed to cover one 151 * multiple non-contiguous fsblocks might be needed to cover one
@@ -201,6 +217,14 @@ typedef struct xfs_da_state {
201 (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \ 217 (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \
202 (uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1) 218 (uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1)
203 219
220/*
221 * Name ops for directory and/or attr name operations
222 */
223struct xfs_nameops {
224 xfs_dahash_t (*hashname)(struct xfs_name *);
225 enum xfs_dacmp (*compname)(struct xfs_da_args *, const char *, int);
226};
227
204 228
205#ifdef __KERNEL__ 229#ifdef __KERNEL__
206/*======================================================================== 230/*========================================================================
@@ -249,6 +273,10 @@ int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
249 xfs_dabuf_t *dead_buf); 273 xfs_dabuf_t *dead_buf);
250 274
251uint xfs_da_hashname(const uchar_t *name_string, int name_length); 275uint xfs_da_hashname(const uchar_t *name_string, int name_length);
276enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args,
277 const char *name, int len);
278
279
252xfs_da_state_t *xfs_da_state_alloc(void); 280xfs_da_state_t *xfs_da_state_alloc(void);
253void xfs_da_state_free(xfs_da_state_t *state); 281void xfs_da_state_free(xfs_da_state_t *state);
254 282
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 5f3647cb9885..2211e885ef24 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -116,7 +116,7 @@ xfs_swapext(
116 out_put_file: 116 out_put_file:
117 fput(file); 117 fput(file);
118 out_free_sxp: 118 out_free_sxp:
119 kmem_free(sxp, sizeof(xfs_swapext_t)); 119 kmem_free(sxp);
120 out: 120 out:
121 return error; 121 return error;
122} 122}
@@ -381,6 +381,6 @@ xfs_swap_extents(
381 xfs_iunlock(tip, lock_flags); 381 xfs_iunlock(tip, lock_flags);
382 } 382 }
383 if (tempifp != NULL) 383 if (tempifp != NULL)
384 kmem_free(tempifp, sizeof(xfs_ifork_t)); 384 kmem_free(tempifp);
385 return error; 385 return error;
386} 386}
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 7cb26529766b..80e0dc51361c 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -46,6 +46,54 @@
46 46
47struct xfs_name xfs_name_dotdot = {"..", 2}; 47struct xfs_name xfs_name_dotdot = {"..", 2};
48 48
49extern const struct xfs_nameops xfs_default_nameops;
50
51/*
52 * ASCII case-insensitive (ie. A-Z) support for directories that was
53 * used in IRIX.
54 */
55STATIC xfs_dahash_t
56xfs_ascii_ci_hashname(
57 struct xfs_name *name)
58{
59 xfs_dahash_t hash;
60 int i;
61
62 for (i = 0, hash = 0; i < name->len; i++)
63 hash = tolower(name->name[i]) ^ rol32(hash, 7);
64
65 return hash;
66}
67
68STATIC enum xfs_dacmp
69xfs_ascii_ci_compname(
70 struct xfs_da_args *args,
71 const char *name,
72 int len)
73{
74 enum xfs_dacmp result;
75 int i;
76
77 if (args->namelen != len)
78 return XFS_CMP_DIFFERENT;
79
80 result = XFS_CMP_EXACT;
81 for (i = 0; i < len; i++) {
82 if (args->name[i] == name[i])
83 continue;
84 if (tolower(args->name[i]) != tolower(name[i]))
85 return XFS_CMP_DIFFERENT;
86 result = XFS_CMP_CASE;
87 }
88
89 return result;
90}
91
92static struct xfs_nameops xfs_ascii_ci_nameops = {
93 .hashname = xfs_ascii_ci_hashname,
94 .compname = xfs_ascii_ci_compname,
95};
96
49void 97void
50xfs_dir_mount( 98xfs_dir_mount(
51 xfs_mount_t *mp) 99 xfs_mount_t *mp)
@@ -65,6 +113,10 @@ xfs_dir_mount(
65 (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / 113 (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) /
66 (uint)sizeof(xfs_da_node_entry_t); 114 (uint)sizeof(xfs_da_node_entry_t);
67 mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; 115 mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
116 if (xfs_sb_version_hasasciici(&mp->m_sb))
117 mp->m_dirnameops = &xfs_ascii_ci_nameops;
118 else
119 mp->m_dirnameops = &xfs_default_nameops;
68} 120}
69 121
70/* 122/*
@@ -162,9 +214,10 @@ xfs_dir_createname(
162 return rval; 214 return rval;
163 XFS_STATS_INC(xs_dir_create); 215 XFS_STATS_INC(xs_dir_create);
164 216
217 memset(&args, 0, sizeof(xfs_da_args_t));
165 args.name = name->name; 218 args.name = name->name;
166 args.namelen = name->len; 219 args.namelen = name->len;
167 args.hashval = xfs_da_hashname(name->name, name->len); 220 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
168 args.inumber = inum; 221 args.inumber = inum;
169 args.dp = dp; 222 args.dp = dp;
170 args.firstblock = first; 223 args.firstblock = first;
@@ -172,8 +225,7 @@ xfs_dir_createname(
172 args.total = total; 225 args.total = total;
173 args.whichfork = XFS_DATA_FORK; 226 args.whichfork = XFS_DATA_FORK;
174 args.trans = tp; 227 args.trans = tp;
175 args.justcheck = 0; 228 args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
176 args.addname = args.oknoent = 1;
177 229
178 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 230 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
179 rval = xfs_dir2_sf_addname(&args); 231 rval = xfs_dir2_sf_addname(&args);
@@ -191,14 +243,43 @@ xfs_dir_createname(
191} 243}
192 244
193/* 245/*
246 * If doing a CI lookup and case-insensitive match, dup actual name into
247 * args.value. Return EEXIST for success (ie. name found) or an error.
248 */
249int
250xfs_dir_cilookup_result(
251 struct xfs_da_args *args,
252 const char *name,
253 int len)
254{
255 if (args->cmpresult == XFS_CMP_DIFFERENT)
256 return ENOENT;
257 if (args->cmpresult != XFS_CMP_CASE ||
258 !(args->op_flags & XFS_DA_OP_CILOOKUP))
259 return EEXIST;
260
261 args->value = kmem_alloc(len, KM_MAYFAIL);
262 if (!args->value)
263 return ENOMEM;
264
265 memcpy(args->value, name, len);
266 args->valuelen = len;
267 return EEXIST;
268}
269
270/*
194 * Lookup a name in a directory, give back the inode number. 271 * Lookup a name in a directory, give back the inode number.
272 * If ci_name is not NULL, returns the actual name in ci_name if it differs
273 * to name, or ci_name->name is set to NULL for an exact match.
195 */ 274 */
275
196int 276int
197xfs_dir_lookup( 277xfs_dir_lookup(
198 xfs_trans_t *tp, 278 xfs_trans_t *tp,
199 xfs_inode_t *dp, 279 xfs_inode_t *dp,
200 struct xfs_name *name, 280 struct xfs_name *name,
201 xfs_ino_t *inum) /* out: inode number */ 281 xfs_ino_t *inum, /* out: inode number */
282 struct xfs_name *ci_name) /* out: actual name if CI match */
202{ 283{
203 xfs_da_args_t args; 284 xfs_da_args_t args;
204 int rval; 285 int rval;
@@ -206,15 +287,17 @@ xfs_dir_lookup(
206 287
207 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 288 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
208 XFS_STATS_INC(xs_dir_lookup); 289 XFS_STATS_INC(xs_dir_lookup);
209 memset(&args, 0, sizeof(xfs_da_args_t));
210 290
291 memset(&args, 0, sizeof(xfs_da_args_t));
211 args.name = name->name; 292 args.name = name->name;
212 args.namelen = name->len; 293 args.namelen = name->len;
213 args.hashval = xfs_da_hashname(name->name, name->len); 294 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
214 args.dp = dp; 295 args.dp = dp;
215 args.whichfork = XFS_DATA_FORK; 296 args.whichfork = XFS_DATA_FORK;
216 args.trans = tp; 297 args.trans = tp;
217 args.oknoent = 1; 298 args.op_flags = XFS_DA_OP_OKNOENT;
299 if (ci_name)
300 args.op_flags |= XFS_DA_OP_CILOOKUP;
218 301
219 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 302 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
220 rval = xfs_dir2_sf_lookup(&args); 303 rval = xfs_dir2_sf_lookup(&args);
@@ -230,8 +313,13 @@ xfs_dir_lookup(
230 rval = xfs_dir2_node_lookup(&args); 313 rval = xfs_dir2_node_lookup(&args);
231 if (rval == EEXIST) 314 if (rval == EEXIST)
232 rval = 0; 315 rval = 0;
233 if (rval == 0) 316 if (!rval) {
234 *inum = args.inumber; 317 *inum = args.inumber;
318 if (ci_name) {
319 ci_name->name = args.value;
320 ci_name->len = args.valuelen;
321 }
322 }
235 return rval; 323 return rval;
236} 324}
237 325
@@ -255,9 +343,10 @@ xfs_dir_removename(
255 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 343 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
256 XFS_STATS_INC(xs_dir_remove); 344 XFS_STATS_INC(xs_dir_remove);
257 345
346 memset(&args, 0, sizeof(xfs_da_args_t));
258 args.name = name->name; 347 args.name = name->name;
259 args.namelen = name->len; 348 args.namelen = name->len;
260 args.hashval = xfs_da_hashname(name->name, name->len); 349 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
261 args.inumber = ino; 350 args.inumber = ino;
262 args.dp = dp; 351 args.dp = dp;
263 args.firstblock = first; 352 args.firstblock = first;
@@ -265,7 +354,6 @@ xfs_dir_removename(
265 args.total = total; 354 args.total = total;
266 args.whichfork = XFS_DATA_FORK; 355 args.whichfork = XFS_DATA_FORK;
267 args.trans = tp; 356 args.trans = tp;
268 args.justcheck = args.addname = args.oknoent = 0;
269 357
270 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 358 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
271 rval = xfs_dir2_sf_removename(&args); 359 rval = xfs_dir2_sf_removename(&args);
@@ -338,9 +426,10 @@ xfs_dir_replace(
338 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) 426 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
339 return rval; 427 return rval;
340 428
429 memset(&args, 0, sizeof(xfs_da_args_t));
341 args.name = name->name; 430 args.name = name->name;
342 args.namelen = name->len; 431 args.namelen = name->len;
343 args.hashval = xfs_da_hashname(name->name, name->len); 432 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
344 args.inumber = inum; 433 args.inumber = inum;
345 args.dp = dp; 434 args.dp = dp;
346 args.firstblock = first; 435 args.firstblock = first;
@@ -348,7 +437,6 @@ xfs_dir_replace(
348 args.total = total; 437 args.total = total;
349 args.whichfork = XFS_DATA_FORK; 438 args.whichfork = XFS_DATA_FORK;
350 args.trans = tp; 439 args.trans = tp;
351 args.justcheck = args.addname = args.oknoent = 0;
352 440
353 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 441 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
354 rval = xfs_dir2_sf_replace(&args); 442 rval = xfs_dir2_sf_replace(&args);
@@ -384,15 +472,16 @@ xfs_dir_canenter(
384 return 0; 472 return 0;
385 473
386 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 474 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
387 memset(&args, 0, sizeof(xfs_da_args_t));
388 475
476 memset(&args, 0, sizeof(xfs_da_args_t));
389 args.name = name->name; 477 args.name = name->name;
390 args.namelen = name->len; 478 args.namelen = name->len;
391 args.hashval = xfs_da_hashname(name->name, name->len); 479 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
392 args.dp = dp; 480 args.dp = dp;
393 args.whichfork = XFS_DATA_FORK; 481 args.whichfork = XFS_DATA_FORK;
394 args.trans = tp; 482 args.trans = tp;
395 args.justcheck = args.addname = args.oknoent = 1; 483 args.op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME |
484 XFS_DA_OP_OKNOENT;
396 485
397 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 486 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
398 rval = xfs_dir2_sf_addname(&args); 487 rval = xfs_dir2_sf_addname(&args);
@@ -493,7 +582,7 @@ xfs_dir2_grow_inode(
493 args->firstblock, args->total, 582 args->firstblock, args->total,
494 &mapp[mapi], &nmap, args->flist, 583 &mapp[mapi], &nmap, args->flist,
495 NULL))) { 584 NULL))) {
496 kmem_free(mapp, sizeof(*mapp) * count); 585 kmem_free(mapp);
497 return error; 586 return error;
498 } 587 }
499 if (nmap < 1) 588 if (nmap < 1)
@@ -525,14 +614,14 @@ xfs_dir2_grow_inode(
525 mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != 614 mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
526 bno + count) { 615 bno + count) {
527 if (mapp != &map) 616 if (mapp != &map)
528 kmem_free(mapp, sizeof(*mapp) * count); 617 kmem_free(mapp);
529 return XFS_ERROR(ENOSPC); 618 return XFS_ERROR(ENOSPC);
530 } 619 }
531 /* 620 /*
532 * Done with the temporary mapping table. 621 * Done with the temporary mapping table.
533 */ 622 */
534 if (mapp != &map) 623 if (mapp != &map)
535 kmem_free(mapp, sizeof(*mapp) * count); 624 kmem_free(mapp);
536 *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); 625 *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
537 /* 626 /*
538 * Update file's size if this is the data space and it grew. 627 * Update file's size if this is the data space and it grew.
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 6392f939029f..1d9ef96f33aa 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -74,7 +74,8 @@ extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
74 xfs_fsblock_t *first, 74 xfs_fsblock_t *first,
75 struct xfs_bmap_free *flist, xfs_extlen_t tot); 75 struct xfs_bmap_free *flist, xfs_extlen_t tot);
76extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, 76extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
77 struct xfs_name *name, xfs_ino_t *inum); 77 struct xfs_name *name, xfs_ino_t *inum,
78 struct xfs_name *ci_name);
78extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, 79extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
79 struct xfs_name *name, xfs_ino_t ino, 80 struct xfs_name *name, xfs_ino_t ino,
80 xfs_fsblock_t *first, 81 xfs_fsblock_t *first,
@@ -99,4 +100,7 @@ extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp,
99extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, 100extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
100 struct xfs_dabuf *bp); 101 struct xfs_dabuf *bp);
101 102
103extern int xfs_dir_cilookup_result(struct xfs_da_args *args, const char *name,
104 int len);
105
102#endif /* __XFS_DIR2_H__ */ 106#endif /* __XFS_DIR2_H__ */
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index fb5a556725b3..e2fa0a1d8e96 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -215,7 +215,7 @@ xfs_dir2_block_addname(
215 /* 215 /*
216 * If this isn't a real add, we're done with the buffer. 216 * If this isn't a real add, we're done with the buffer.
217 */ 217 */
218 if (args->justcheck) 218 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
219 xfs_da_brelse(tp, bp); 219 xfs_da_brelse(tp, bp);
220 /* 220 /*
221 * If we don't have space for the new entry & leaf ... 221 * If we don't have space for the new entry & leaf ...
@@ -225,7 +225,7 @@ xfs_dir2_block_addname(
225 * Not trying to actually do anything, or don't have 225 * Not trying to actually do anything, or don't have
226 * a space reservation: return no-space. 226 * a space reservation: return no-space.
227 */ 227 */
228 if (args->justcheck || args->total == 0) 228 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
229 return XFS_ERROR(ENOSPC); 229 return XFS_ERROR(ENOSPC);
230 /* 230 /*
231 * Convert to the next larger format. 231 * Convert to the next larger format.
@@ -240,7 +240,7 @@ xfs_dir2_block_addname(
240 /* 240 /*
241 * Just checking, and it would work, so say so. 241 * Just checking, and it would work, so say so.
242 */ 242 */
243 if (args->justcheck) 243 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
244 return 0; 244 return 0;
245 needlog = needscan = 0; 245 needlog = needscan = 0;
246 /* 246 /*
@@ -610,14 +610,15 @@ xfs_dir2_block_lookup(
610 /* 610 /*
611 * Get the offset from the leaf entry, to point to the data. 611 * Get the offset from the leaf entry, to point to the data.
612 */ 612 */
613 dep = (xfs_dir2_data_entry_t *) 613 dep = (xfs_dir2_data_entry_t *)((char *)block +
614 ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); 614 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
615 /* 615 /*
616 * Fill in inode number, release the block. 616 * Fill in inode number, CI name if appropriate, release the block.
617 */ 617 */
618 args->inumber = be64_to_cpu(dep->inumber); 618 args->inumber = be64_to_cpu(dep->inumber);
619 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
619 xfs_da_brelse(args->trans, bp); 620 xfs_da_brelse(args->trans, bp);
620 return XFS_ERROR(EEXIST); 621 return XFS_ERROR(error);
621} 622}
622 623
623/* 624/*
@@ -643,6 +644,7 @@ xfs_dir2_block_lookup_int(
643 int mid; /* binary search current idx */ 644 int mid; /* binary search current idx */
644 xfs_mount_t *mp; /* filesystem mount point */ 645 xfs_mount_t *mp; /* filesystem mount point */
645 xfs_trans_t *tp; /* transaction pointer */ 646 xfs_trans_t *tp; /* transaction pointer */
647 enum xfs_dacmp cmp; /* comparison result */
646 648
647 dp = args->dp; 649 dp = args->dp;
648 tp = args->trans; 650 tp = args->trans;
@@ -673,7 +675,7 @@ xfs_dir2_block_lookup_int(
673 else 675 else
674 high = mid - 1; 676 high = mid - 1;
675 if (low > high) { 677 if (low > high) {
676 ASSERT(args->oknoent); 678 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
677 xfs_da_brelse(tp, bp); 679 xfs_da_brelse(tp, bp);
678 return XFS_ERROR(ENOENT); 680 return XFS_ERROR(ENOENT);
679 } 681 }
@@ -697,20 +699,31 @@ xfs_dir2_block_lookup_int(
697 dep = (xfs_dir2_data_entry_t *) 699 dep = (xfs_dir2_data_entry_t *)
698 ((char *)block + xfs_dir2_dataptr_to_off(mp, addr)); 700 ((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
699 /* 701 /*
700 * Compare, if it's right give back buffer & entry number. 702 * Compare name and if it's an exact match, return the index
703 * and buffer. If it's the first case-insensitive match, store
704 * the index and buffer and continue looking for an exact match.
701 */ 705 */
702 if (dep->namelen == args->namelen && 706 cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
703 dep->name[0] == args->name[0] && 707 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
704 memcmp(dep->name, args->name, args->namelen) == 0) { 708 args->cmpresult = cmp;
705 *bpp = bp; 709 *bpp = bp;
706 *entno = mid; 710 *entno = mid;
707 return 0; 711 if (cmp == XFS_CMP_EXACT)
712 return 0;
708 } 713 }
709 } while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash); 714 } while (++mid < be32_to_cpu(btp->count) &&
715 be32_to_cpu(blp[mid].hashval) == hash);
716
717 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
718 /*
719 * Here, we can only be doing a lookup (not a rename or replace).
720 * If a case-insensitive match was found earlier, return success.
721 */
722 if (args->cmpresult == XFS_CMP_CASE)
723 return 0;
710 /* 724 /*
711 * No match, release the buffer and return ENOENT. 725 * No match, release the buffer and return ENOENT.
712 */ 726 */
713 ASSERT(args->oknoent);
714 xfs_da_brelse(tp, bp); 727 xfs_da_brelse(tp, bp);
715 return XFS_ERROR(ENOENT); 728 return XFS_ERROR(ENOENT);
716} 729}
@@ -1033,6 +1046,7 @@ xfs_dir2_sf_to_block(
1033 xfs_dir2_sf_t *sfp; /* shortform structure */ 1046 xfs_dir2_sf_t *sfp; /* shortform structure */
1034 __be16 *tagp; /* end of data entry */ 1047 __be16 *tagp; /* end of data entry */
1035 xfs_trans_t *tp; /* transaction pointer */ 1048 xfs_trans_t *tp; /* transaction pointer */
1049 struct xfs_name name;
1036 1050
1037 xfs_dir2_trace_args("sf_to_block", args); 1051 xfs_dir2_trace_args("sf_to_block", args);
1038 dp = args->dp; 1052 dp = args->dp;
@@ -1071,7 +1085,7 @@ xfs_dir2_sf_to_block(
1071 */ 1085 */
1072 error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno); 1086 error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
1073 if (error) { 1087 if (error) {
1074 kmem_free(buf, buf_len); 1088 kmem_free(buf);
1075 return error; 1089 return error;
1076 } 1090 }
1077 /* 1091 /*
@@ -1079,7 +1093,7 @@ xfs_dir2_sf_to_block(
1079 */ 1093 */
1080 error = xfs_dir2_data_init(args, blkno, &bp); 1094 error = xfs_dir2_data_init(args, blkno, &bp);
1081 if (error) { 1095 if (error) {
1082 kmem_free(buf, buf_len); 1096 kmem_free(buf);
1083 return error; 1097 return error;
1084 } 1098 }
1085 block = bp->data; 1099 block = bp->data;
@@ -1187,8 +1201,10 @@ xfs_dir2_sf_to_block(
1187 tagp = xfs_dir2_data_entry_tag_p(dep); 1201 tagp = xfs_dir2_data_entry_tag_p(dep);
1188 *tagp = cpu_to_be16((char *)dep - (char *)block); 1202 *tagp = cpu_to_be16((char *)dep - (char *)block);
1189 xfs_dir2_data_log_entry(tp, bp, dep); 1203 xfs_dir2_data_log_entry(tp, bp, dep);
1190 blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname( 1204 name.name = sfep->name;
1191 (char *)sfep->name, sfep->namelen)); 1205 name.len = sfep->namelen;
1206 blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
1207 hashname(&name));
1192 blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, 1208 blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
1193 (char *)dep - (char *)block)); 1209 (char *)dep - (char *)block));
1194 offset = (int)((char *)(tagp + 1) - (char *)block); 1210 offset = (int)((char *)(tagp + 1) - (char *)block);
@@ -1198,7 +1214,7 @@ xfs_dir2_sf_to_block(
1198 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 1214 sfep = xfs_dir2_sf_nextentry(sfp, sfep);
1199 } 1215 }
1200 /* Done with the temporary buffer */ 1216 /* Done with the temporary buffer */
1201 kmem_free(buf, buf_len); 1217 kmem_free(buf);
1202 /* 1218 /*
1203 * Sort the leaf entries by hash value. 1219 * Sort the leaf entries by hash value.
1204 */ 1220 */
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index fb8c9e08b23d..498f8d694330 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -65,6 +65,7 @@ xfs_dir2_data_check(
65 xfs_mount_t *mp; /* filesystem mount point */ 65 xfs_mount_t *mp; /* filesystem mount point */
66 char *p; /* current data position */ 66 char *p; /* current data position */
67 int stale; /* count of stale leaves */ 67 int stale; /* count of stale leaves */
68 struct xfs_name name;
68 69
69 mp = dp->i_mount; 70 mp = dp->i_mount;
70 d = bp->data; 71 d = bp->data;
@@ -140,7 +141,9 @@ xfs_dir2_data_check(
140 addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 141 addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
141 (xfs_dir2_data_aoff_t) 142 (xfs_dir2_data_aoff_t)
142 ((char *)dep - (char *)d)); 143 ((char *)dep - (char *)d));
143 hash = xfs_da_hashname((char *)dep->name, dep->namelen); 144 name.name = dep->name;
145 name.len = dep->namelen;
146 hash = mp->m_dirnameops->hashname(&name);
144 for (i = 0; i < be32_to_cpu(btp->count); i++) { 147 for (i = 0; i < be32_to_cpu(btp->count); i++) {
145 if (be32_to_cpu(lep[i].address) == addr && 148 if (be32_to_cpu(lep[i].address) == addr &&
146 be32_to_cpu(lep[i].hashval) == hash) 149 be32_to_cpu(lep[i].hashval) == hash)
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index bc52b803d79b..93535992cb60 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -263,20 +263,21 @@ xfs_dir2_leaf_addname(
263 * If we don't have enough free bytes but we can make enough 263 * If we don't have enough free bytes but we can make enough
264 * by compacting out stale entries, we'll do that. 264 * by compacting out stale entries, we'll do that.
265 */ 265 */
266 if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < needbytes && 266 if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <
267 be16_to_cpu(leaf->hdr.stale) > 1) { 267 needbytes && be16_to_cpu(leaf->hdr.stale) > 1) {
268 compact = 1; 268 compact = 1;
269 } 269 }
270 /* 270 /*
271 * Otherwise if we don't have enough free bytes we need to 271 * Otherwise if we don't have enough free bytes we need to
272 * convert to node form. 272 * convert to node form.
273 */ 273 */
274 else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < 274 else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(
275 needbytes) { 275 leaf->hdr.count)] < needbytes) {
276 /* 276 /*
277 * Just checking or no space reservation, give up. 277 * Just checking or no space reservation, give up.
278 */ 278 */
279 if (args->justcheck || args->total == 0) { 279 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) ||
280 args->total == 0) {
280 xfs_da_brelse(tp, lbp); 281 xfs_da_brelse(tp, lbp);
281 return XFS_ERROR(ENOSPC); 282 return XFS_ERROR(ENOSPC);
282 } 283 }
@@ -301,7 +302,7 @@ xfs_dir2_leaf_addname(
301 * If just checking, then it will fit unless we needed to allocate 302 * If just checking, then it will fit unless we needed to allocate
302 * a new data block. 303 * a new data block.
303 */ 304 */
304 if (args->justcheck) { 305 if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
305 xfs_da_brelse(tp, lbp); 306 xfs_da_brelse(tp, lbp);
306 return use_block == -1 ? XFS_ERROR(ENOSPC) : 0; 307 return use_block == -1 ? XFS_ERROR(ENOSPC) : 0;
307 } 308 }
@@ -1110,7 +1111,7 @@ xfs_dir2_leaf_getdents(
1110 *offset = XFS_DIR2_MAX_DATAPTR; 1111 *offset = XFS_DIR2_MAX_DATAPTR;
1111 else 1112 else
1112 *offset = xfs_dir2_byte_to_dataptr(mp, curoff); 1113 *offset = xfs_dir2_byte_to_dataptr(mp, curoff);
1113 kmem_free(map, map_size * sizeof(*map)); 1114 kmem_free(map);
1114 if (bp) 1115 if (bp)
1115 xfs_da_brelse(NULL, bp); 1116 xfs_da_brelse(NULL, bp);
1116 return error; 1117 return error;
@@ -1298,12 +1299,13 @@ xfs_dir2_leaf_lookup(
1298 ((char *)dbp->data + 1299 ((char *)dbp->data +
1299 xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address))); 1300 xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
1300 /* 1301 /*
1301 * Return the found inode number. 1302 * Return the found inode number & CI name if appropriate
1302 */ 1303 */
1303 args->inumber = be64_to_cpu(dep->inumber); 1304 args->inumber = be64_to_cpu(dep->inumber);
1305 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
1304 xfs_da_brelse(tp, dbp); 1306 xfs_da_brelse(tp, dbp);
1305 xfs_da_brelse(tp, lbp); 1307 xfs_da_brelse(tp, lbp);
1306 return XFS_ERROR(EEXIST); 1308 return XFS_ERROR(error);
1307} 1309}
1308 1310
1309/* 1311/*
@@ -1319,8 +1321,8 @@ xfs_dir2_leaf_lookup_int(
1319 int *indexp, /* out: index in leaf block */ 1321 int *indexp, /* out: index in leaf block */
1320 xfs_dabuf_t **dbpp) /* out: data buffer */ 1322 xfs_dabuf_t **dbpp) /* out: data buffer */
1321{ 1323{
1322 xfs_dir2_db_t curdb; /* current data block number */ 1324 xfs_dir2_db_t curdb = -1; /* current data block number */
1323 xfs_dabuf_t *dbp; /* data buffer */ 1325 xfs_dabuf_t *dbp = NULL; /* data buffer */
1324 xfs_dir2_data_entry_t *dep; /* data entry */ 1326 xfs_dir2_data_entry_t *dep; /* data entry */
1325 xfs_inode_t *dp; /* incore directory inode */ 1327 xfs_inode_t *dp; /* incore directory inode */
1326 int error; /* error return code */ 1328 int error; /* error return code */
@@ -1331,6 +1333,8 @@ xfs_dir2_leaf_lookup_int(
1331 xfs_mount_t *mp; /* filesystem mount point */ 1333 xfs_mount_t *mp; /* filesystem mount point */
1332 xfs_dir2_db_t newdb; /* new data block number */ 1334 xfs_dir2_db_t newdb; /* new data block number */
1333 xfs_trans_t *tp; /* transaction pointer */ 1335 xfs_trans_t *tp; /* transaction pointer */
1336 xfs_dir2_db_t cidb = -1; /* case match data block no. */
1337 enum xfs_dacmp cmp; /* name compare result */
1334 1338
1335 dp = args->dp; 1339 dp = args->dp;
1336 tp = args->trans; 1340 tp = args->trans;
@@ -1338,11 +1342,10 @@ xfs_dir2_leaf_lookup_int(
1338 /* 1342 /*
1339 * Read the leaf block into the buffer. 1343 * Read the leaf block into the buffer.
1340 */ 1344 */
1341 if ((error = 1345 error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
1342 xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp, 1346 XFS_DATA_FORK);
1343 XFS_DATA_FORK))) { 1347 if (error)
1344 return error; 1348 return error;
1345 }
1346 *lbpp = lbp; 1349 *lbpp = lbp;
1347 leaf = lbp->data; 1350 leaf = lbp->data;
1348 xfs_dir2_leaf_check(dp, lbp); 1351 xfs_dir2_leaf_check(dp, lbp);
@@ -1354,9 +1357,9 @@ xfs_dir2_leaf_lookup_int(
1354 * Loop over all the entries with the right hash value 1357 * Loop over all the entries with the right hash value
1355 * looking to match the name. 1358 * looking to match the name.
1356 */ 1359 */
1357 for (lep = &leaf->ents[index], dbp = NULL, curdb = -1; 1360 for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
1358 index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; 1361 be32_to_cpu(lep->hashval) == args->hashval;
1359 lep++, index++) { 1362 lep++, index++) {
1360 /* 1363 /*
1361 * Skip over stale leaf entries. 1364 * Skip over stale leaf entries.
1362 */ 1365 */
@@ -1373,10 +1376,10 @@ xfs_dir2_leaf_lookup_int(
1373 if (newdb != curdb) { 1376 if (newdb != curdb) {
1374 if (dbp) 1377 if (dbp)
1375 xfs_da_brelse(tp, dbp); 1378 xfs_da_brelse(tp, dbp);
1376 if ((error = 1379 error = xfs_da_read_buf(tp, dp,
1377 xfs_da_read_buf(tp, dp, 1380 xfs_dir2_db_to_da(mp, newdb),
1378 xfs_dir2_db_to_da(mp, newdb), -1, &dbp, 1381 -1, &dbp, XFS_DATA_FORK);
1379 XFS_DATA_FORK))) { 1382 if (error) {
1380 xfs_da_brelse(tp, lbp); 1383 xfs_da_brelse(tp, lbp);
1381 return error; 1384 return error;
1382 } 1385 }
@@ -1386,24 +1389,50 @@ xfs_dir2_leaf_lookup_int(
1386 /* 1389 /*
1387 * Point to the data entry. 1390 * Point to the data entry.
1388 */ 1391 */
1389 dep = (xfs_dir2_data_entry_t *) 1392 dep = (xfs_dir2_data_entry_t *)((char *)dbp->data +
1390 ((char *)dbp->data + 1393 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
1391 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
1392 /* 1394 /*
1393 * If it matches then return it. 1395 * Compare name and if it's an exact match, return the index
1396 * and buffer. If it's the first case-insensitive match, store
1397 * the index and buffer and continue looking for an exact match.
1394 */ 1398 */
1395 if (dep->namelen == args->namelen && 1399 cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
1396 dep->name[0] == args->name[0] && 1400 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
1397 memcmp(dep->name, args->name, args->namelen) == 0) { 1401 args->cmpresult = cmp;
1398 *dbpp = dbp;
1399 *indexp = index; 1402 *indexp = index;
1400 return 0; 1403 /* case exact match: return the current buffer. */
1404 if (cmp == XFS_CMP_EXACT) {
1405 *dbpp = dbp;
1406 return 0;
1407 }
1408 cidb = curdb;
1401 } 1409 }
1402 } 1410 }
1411 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
1412 /*
1413 * Here, we can only be doing a lookup (not a rename or remove).
1414 * If a case-insensitive match was found earlier, re-read the
1415 * appropriate data block if required and return it.
1416 */
1417 if (args->cmpresult == XFS_CMP_CASE) {
1418 ASSERT(cidb != -1);
1419 if (cidb != curdb) {
1420 xfs_da_brelse(tp, dbp);
1421 error = xfs_da_read_buf(tp, dp,
1422 xfs_dir2_db_to_da(mp, cidb),
1423 -1, &dbp, XFS_DATA_FORK);
1424 if (error) {
1425 xfs_da_brelse(tp, lbp);
1426 return error;
1427 }
1428 }
1429 *dbpp = dbp;
1430 return 0;
1431 }
1403 /* 1432 /*
1404 * No match found, return ENOENT. 1433 * No match found, return ENOENT.
1405 */ 1434 */
1406 ASSERT(args->oknoent); 1435 ASSERT(cidb == -1);
1407 if (dbp) 1436 if (dbp)
1408 xfs_da_brelse(tp, dbp); 1437 xfs_da_brelse(tp, dbp);
1409 xfs_da_brelse(tp, lbp); 1438 xfs_da_brelse(tp, lbp);
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 8dade711f099..fa6c3a5ddbc6 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -226,7 +226,7 @@ xfs_dir2_leafn_add(
226 ASSERT(index == be16_to_cpu(leaf->hdr.count) || 226 ASSERT(index == be16_to_cpu(leaf->hdr.count) ||
227 be32_to_cpu(leaf->ents[index].hashval) >= args->hashval); 227 be32_to_cpu(leaf->ents[index].hashval) >= args->hashval);
228 228
229 if (args->justcheck) 229 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
230 return 0; 230 return 0;
231 231
232 /* 232 /*
@@ -387,28 +387,26 @@ xfs_dir2_leafn_lasthash(
387} 387}
388 388
389/* 389/*
390 * Look up a leaf entry in a node-format leaf block. 390 * Look up a leaf entry for space to add a name in a node-format leaf block.
391 * If this is an addname then the extrablk in state is a freespace block, 391 * The extrablk in state is a freespace block.
392 * otherwise it's a data block.
393 */ 392 */
394int 393STATIC int
395xfs_dir2_leafn_lookup_int( 394xfs_dir2_leafn_lookup_for_addname(
396 xfs_dabuf_t *bp, /* leaf buffer */ 395 xfs_dabuf_t *bp, /* leaf buffer */
397 xfs_da_args_t *args, /* operation arguments */ 396 xfs_da_args_t *args, /* operation arguments */
398 int *indexp, /* out: leaf entry index */ 397 int *indexp, /* out: leaf entry index */
399 xfs_da_state_t *state) /* state to fill in */ 398 xfs_da_state_t *state) /* state to fill in */
400{ 399{
401 xfs_dabuf_t *curbp; /* current data/free buffer */ 400 xfs_dabuf_t *curbp = NULL; /* current data/free buffer */
402 xfs_dir2_db_t curdb; /* current data block number */ 401 xfs_dir2_db_t curdb = -1; /* current data block number */
403 xfs_dir2_db_t curfdb; /* current free block number */ 402 xfs_dir2_db_t curfdb = -1; /* current free block number */
404 xfs_dir2_data_entry_t *dep; /* data block entry */
405 xfs_inode_t *dp; /* incore directory inode */ 403 xfs_inode_t *dp; /* incore directory inode */
406 int error; /* error return value */ 404 int error; /* error return value */
407 int fi; /* free entry index */ 405 int fi; /* free entry index */
408 xfs_dir2_free_t *free=NULL; /* free block structure */ 406 xfs_dir2_free_t *free = NULL; /* free block structure */
409 int index; /* leaf entry index */ 407 int index; /* leaf entry index */
410 xfs_dir2_leaf_t *leaf; /* leaf structure */ 408 xfs_dir2_leaf_t *leaf; /* leaf structure */
411 int length=0; /* length of new data entry */ 409 int length; /* length of new data entry */
412 xfs_dir2_leaf_entry_t *lep; /* leaf entry */ 410 xfs_dir2_leaf_entry_t *lep; /* leaf entry */
413 xfs_mount_t *mp; /* filesystem mount point */ 411 xfs_mount_t *mp; /* filesystem mount point */
414 xfs_dir2_db_t newdb; /* new data block number */ 412 xfs_dir2_db_t newdb; /* new data block number */
@@ -431,33 +429,20 @@ xfs_dir2_leafn_lookup_int(
431 /* 429 /*
432 * Do we have a buffer coming in? 430 * Do we have a buffer coming in?
433 */ 431 */
434 if (state->extravalid) 432 if (state->extravalid) {
433 /* If so, it's a free block buffer, get the block number. */
435 curbp = state->extrablk.bp; 434 curbp = state->extrablk.bp;
436 else 435 curfdb = state->extrablk.blkno;
437 curbp = NULL; 436 free = curbp->data;
438 /* 437 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
439 * For addname, it's a free block buffer, get the block number.
440 */
441 if (args->addname) {
442 curfdb = curbp ? state->extrablk.blkno : -1;
443 curdb = -1;
444 length = xfs_dir2_data_entsize(args->namelen);
445 if ((free = (curbp ? curbp->data : NULL)))
446 ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
447 }
448 /*
449 * For others, it's a data block buffer, get the block number.
450 */
451 else {
452 curfdb = -1;
453 curdb = curbp ? state->extrablk.blkno : -1;
454 } 438 }
439 length = xfs_dir2_data_entsize(args->namelen);
455 /* 440 /*
456 * Loop over leaf entries with the right hash value. 441 * Loop over leaf entries with the right hash value.
457 */ 442 */
458 for (lep = &leaf->ents[index]; 443 for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
459 index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; 444 be32_to_cpu(lep->hashval) == args->hashval;
460 lep++, index++) { 445 lep++, index++) {
461 /* 446 /*
462 * Skip stale leaf entries. 447 * Skip stale leaf entries.
463 */ 448 */
@@ -471,161 +456,244 @@ xfs_dir2_leafn_lookup_int(
471 * For addname, we're looking for a place to put the new entry. 456 * For addname, we're looking for a place to put the new entry.
472 * We want to use a data block with an entry of equal 457 * We want to use a data block with an entry of equal
473 * hash value to ours if there is one with room. 458 * hash value to ours if there is one with room.
459 *
460 * If this block isn't the data block we already have
461 * in hand, take a look at it.
474 */ 462 */
475 if (args->addname) { 463 if (newdb != curdb) {
464 curdb = newdb;
476 /* 465 /*
477 * If this block isn't the data block we already have 466 * Convert the data block to the free block
478 * in hand, take a look at it. 467 * holding its freespace information.
479 */ 468 */
480 if (newdb != curdb) { 469 newfdb = xfs_dir2_db_to_fdb(mp, newdb);
481 curdb = newdb;
482 /*
483 * Convert the data block to the free block
484 * holding its freespace information.
485 */
486 newfdb = xfs_dir2_db_to_fdb(mp, newdb);
487 /*
488 * If it's not the one we have in hand,
489 * read it in.
490 */
491 if (newfdb != curfdb) {
492 /*
493 * If we had one before, drop it.
494 */
495 if (curbp)
496 xfs_da_brelse(tp, curbp);
497 /*
498 * Read the free block.
499 */
500 if ((error = xfs_da_read_buf(tp, dp,
501 xfs_dir2_db_to_da(mp,
502 newfdb),
503 -1, &curbp,
504 XFS_DATA_FORK))) {
505 return error;
506 }
507 free = curbp->data;
508 ASSERT(be32_to_cpu(free->hdr.magic) ==
509 XFS_DIR2_FREE_MAGIC);
510 ASSERT((be32_to_cpu(free->hdr.firstdb) %
511 XFS_DIR2_MAX_FREE_BESTS(mp)) ==
512 0);
513 ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
514 ASSERT(curdb <
515 be32_to_cpu(free->hdr.firstdb) +
516 be32_to_cpu(free->hdr.nvalid));
517 }
518 /*
519 * Get the index for our entry.
520 */
521 fi = xfs_dir2_db_to_fdindex(mp, curdb);
522 /*
523 * If it has room, return it.
524 */
525 if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
526 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
527 XFS_ERRLEVEL_LOW, mp);
528 if (curfdb != newfdb)
529 xfs_da_brelse(tp, curbp);
530 return XFS_ERROR(EFSCORRUPTED);
531 }
532 curfdb = newfdb;
533 if (be16_to_cpu(free->bests[fi]) >= length) {
534 *indexp = index;
535 state->extravalid = 1;
536 state->extrablk.bp = curbp;
537 state->extrablk.blkno = curfdb;
538 state->extrablk.index = fi;
539 state->extrablk.magic =
540 XFS_DIR2_FREE_MAGIC;
541 ASSERT(args->oknoent);
542 return XFS_ERROR(ENOENT);
543 }
544 }
545 }
546 /*
547 * Not adding a new entry, so we really want to find
548 * the name given to us.
549 */
550 else {
551 /* 470 /*
552 * If it's a different data block, go get it. 471 * If it's not the one we have in hand, read it in.
553 */ 472 */
554 if (newdb != curdb) { 473 if (newfdb != curfdb) {
555 /* 474 /*
556 * If we had a block before, drop it. 475 * If we had one before, drop it.
557 */ 476 */
558 if (curbp) 477 if (curbp)
559 xfs_da_brelse(tp, curbp); 478 xfs_da_brelse(tp, curbp);
560 /* 479 /*
561 * Read the data block. 480 * Read the free block.
562 */ 481 */
563 if ((error = 482 error = xfs_da_read_buf(tp, dp,
564 xfs_da_read_buf(tp, dp, 483 xfs_dir2_db_to_da(mp, newfdb),
565 xfs_dir2_db_to_da(mp, newdb), -1, 484 -1, &curbp, XFS_DATA_FORK);
566 &curbp, XFS_DATA_FORK))) { 485 if (error)
567 return error; 486 return error;
568 } 487 free = curbp->data;
569 xfs_dir2_data_check(dp, curbp); 488 ASSERT(be32_to_cpu(free->hdr.magic) ==
570 curdb = newdb; 489 XFS_DIR2_FREE_MAGIC);
490 ASSERT((be32_to_cpu(free->hdr.firstdb) %
491 XFS_DIR2_MAX_FREE_BESTS(mp)) == 0);
492 ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
493 ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) +
494 be32_to_cpu(free->hdr.nvalid));
571 } 495 }
572 /* 496 /*
573 * Point to the data entry. 497 * Get the index for our entry.
574 */ 498 */
575 dep = (xfs_dir2_data_entry_t *) 499 fi = xfs_dir2_db_to_fdindex(mp, curdb);
576 ((char *)curbp->data +
577 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
578 /* 500 /*
579 * Compare the entry, return it if it matches. 501 * If it has room, return it.
580 */ 502 */
581 if (dep->namelen == args->namelen && 503 if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
582 dep->name[0] == args->name[0] && 504 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
583 memcmp(dep->name, args->name, args->namelen) == 0) { 505 XFS_ERRLEVEL_LOW, mp);
584 args->inumber = be64_to_cpu(dep->inumber); 506 if (curfdb != newfdb)
585 *indexp = index; 507 xfs_da_brelse(tp, curbp);
586 state->extravalid = 1; 508 return XFS_ERROR(EFSCORRUPTED);
587 state->extrablk.bp = curbp;
588 state->extrablk.blkno = curdb;
589 state->extrablk.index =
590 (int)((char *)dep -
591 (char *)curbp->data);
592 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
593 return XFS_ERROR(EEXIST);
594 } 509 }
510 curfdb = newfdb;
511 if (be16_to_cpu(free->bests[fi]) >= length)
512 goto out;
595 } 513 }
596 } 514 }
515 /* Didn't find any space */
516 fi = -1;
517out:
518 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
519 if (curbp) {
520 /* Giving back a free block. */
521 state->extravalid = 1;
522 state->extrablk.bp = curbp;
523 state->extrablk.index = fi;
524 state->extrablk.blkno = curfdb;
525 state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
526 } else {
527 state->extravalid = 0;
528 }
597 /* 529 /*
598 * Didn't find a match. 530 * Return the index, that will be the insertion point.
599 * If we are holding a buffer, give it back in case our caller
600 * finds it useful.
601 */ 531 */
602 if ((state->extravalid = (curbp != NULL))) { 532 *indexp = index;
603 state->extrablk.bp = curbp; 533 return XFS_ERROR(ENOENT);
604 state->extrablk.index = -1; 534}
535
536/*
537 * Look up a leaf entry in a node-format leaf block.
538 * The extrablk in state a data block.
539 */
540STATIC int
541xfs_dir2_leafn_lookup_for_entry(
542 xfs_dabuf_t *bp, /* leaf buffer */
543 xfs_da_args_t *args, /* operation arguments */
544 int *indexp, /* out: leaf entry index */
545 xfs_da_state_t *state) /* state to fill in */
546{
547 xfs_dabuf_t *curbp = NULL; /* current data/free buffer */
548 xfs_dir2_db_t curdb = -1; /* current data block number */
549 xfs_dir2_data_entry_t *dep; /* data block entry */
550 xfs_inode_t *dp; /* incore directory inode */
551 int error; /* error return value */
552 int index; /* leaf entry index */
553 xfs_dir2_leaf_t *leaf; /* leaf structure */
554 xfs_dir2_leaf_entry_t *lep; /* leaf entry */
555 xfs_mount_t *mp; /* filesystem mount point */
556 xfs_dir2_db_t newdb; /* new data block number */
557 xfs_trans_t *tp; /* transaction pointer */
558 enum xfs_dacmp cmp; /* comparison result */
559
560 dp = args->dp;
561 tp = args->trans;
562 mp = dp->i_mount;
563 leaf = bp->data;
564 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
565#ifdef __KERNEL__
566 ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
567#endif
568 xfs_dir2_leafn_check(dp, bp);
569 /*
570 * Look up the hash value in the leaf entries.
571 */
572 index = xfs_dir2_leaf_search_hash(args, bp);
573 /*
574 * Do we have a buffer coming in?
575 */
576 if (state->extravalid) {
577 curbp = state->extrablk.bp;
578 curdb = state->extrablk.blkno;
579 }
580 /*
581 * Loop over leaf entries with the right hash value.
582 */
583 for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
584 be32_to_cpu(lep->hashval) == args->hashval;
585 lep++, index++) {
605 /* 586 /*
606 * For addname, giving back a free block. 587 * Skip stale leaf entries.
607 */ 588 */
608 if (args->addname) { 589 if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
609 state->extrablk.blkno = curfdb; 590 continue;
610 state->extrablk.magic = XFS_DIR2_FREE_MAGIC; 591 /*
592 * Pull the data block number from the entry.
593 */
594 newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
595 /*
596 * Not adding a new entry, so we really want to find
597 * the name given to us.
598 *
599 * If it's a different data block, go get it.
600 */
601 if (newdb != curdb) {
602 /*
603 * If we had a block before that we aren't saving
604 * for a CI name, drop it
605 */
606 if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT ||
607 curdb != state->extrablk.blkno))
608 xfs_da_brelse(tp, curbp);
609 /*
610 * If needing the block that is saved with a CI match,
611 * use it otherwise read in the new data block.
612 */
613 if (args->cmpresult != XFS_CMP_DIFFERENT &&
614 newdb == state->extrablk.blkno) {
615 ASSERT(state->extravalid);
616 curbp = state->extrablk.bp;
617 } else {
618 error = xfs_da_read_buf(tp, dp,
619 xfs_dir2_db_to_da(mp, newdb),
620 -1, &curbp, XFS_DATA_FORK);
621 if (error)
622 return error;
623 }
624 xfs_dir2_data_check(dp, curbp);
625 curdb = newdb;
611 } 626 }
612 /* 627 /*
613 * For other callers, giving back a data block. 628 * Point to the data entry.
614 */ 629 */
615 else { 630 dep = (xfs_dir2_data_entry_t *)((char *)curbp->data +
631 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
632 /*
633 * Compare the entry and if it's an exact match, return
634 * EEXIST immediately. If it's the first case-insensitive
635 * match, store the block & inode number and continue looking.
636 */
637 cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
638 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
639 /* If there is a CI match block, drop it */
640 if (args->cmpresult != XFS_CMP_DIFFERENT &&
641 curdb != state->extrablk.blkno)
642 xfs_da_brelse(tp, state->extrablk.bp);
643 args->cmpresult = cmp;
644 args->inumber = be64_to_cpu(dep->inumber);
645 *indexp = index;
646 state->extravalid = 1;
647 state->extrablk.bp = curbp;
616 state->extrablk.blkno = curdb; 648 state->extrablk.blkno = curdb;
649 state->extrablk.index = (int)((char *)dep -
650 (char *)curbp->data);
617 state->extrablk.magic = XFS_DIR2_DATA_MAGIC; 651 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
652 if (cmp == XFS_CMP_EXACT)
653 return XFS_ERROR(EEXIST);
618 } 654 }
619 } 655 }
620 /* 656 ASSERT(index == be16_to_cpu(leaf->hdr.count) ||
621 * Return the final index, that will be the insertion point. 657 (args->op_flags & XFS_DA_OP_OKNOENT));
622 */ 658 if (curbp) {
659 if (args->cmpresult == XFS_CMP_DIFFERENT) {
660 /* Giving back last used data block. */
661 state->extravalid = 1;
662 state->extrablk.bp = curbp;
663 state->extrablk.index = -1;
664 state->extrablk.blkno = curdb;
665 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
666 } else {
667 /* If the curbp is not the CI match block, drop it */
668 if (state->extrablk.bp != curbp)
669 xfs_da_brelse(tp, curbp);
670 }
671 } else {
672 state->extravalid = 0;
673 }
623 *indexp = index; 674 *indexp = index;
624 ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent);
625 return XFS_ERROR(ENOENT); 675 return XFS_ERROR(ENOENT);
626} 676}
627 677
628/* 678/*
679 * Look up a leaf entry in a node-format leaf block.
680 * If this is an addname then the extrablk in state is a freespace block,
681 * otherwise it's a data block.
682 */
683int
684xfs_dir2_leafn_lookup_int(
685 xfs_dabuf_t *bp, /* leaf buffer */
686 xfs_da_args_t *args, /* operation arguments */
687 int *indexp, /* out: leaf entry index */
688 xfs_da_state_t *state) /* state to fill in */
689{
690 if (args->op_flags & XFS_DA_OP_ADDNAME)
691 return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp,
692 state);
693 return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state);
694}
695
696/*
629 * Move count leaf entries from source to destination leaf. 697 * Move count leaf entries from source to destination leaf.
630 * Log entries and headers. Stale entries are preserved. 698 * Log entries and headers. Stale entries are preserved.
631 */ 699 */
@@ -823,9 +891,10 @@ xfs_dir2_leafn_rebalance(
823 */ 891 */
824 if (!state->inleaf) 892 if (!state->inleaf)
825 blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); 893 blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count);
826 894
827 /* 895 /*
828 * Finally sanity check just to make sure we are not returning a negative index 896 * Finally sanity check just to make sure we are not returning a
897 * negative index
829 */ 898 */
830 if(blk2->index < 0) { 899 if(blk2->index < 0) {
831 state->inleaf = 1; 900 state->inleaf = 1;
@@ -1332,7 +1401,7 @@ xfs_dir2_node_addname(
1332 /* 1401 /*
1333 * It worked, fix the hash values up the btree. 1402 * It worked, fix the hash values up the btree.
1334 */ 1403 */
1335 if (!args->justcheck) 1404 if (!(args->op_flags & XFS_DA_OP_JUSTCHECK))
1336 xfs_da_fixhashpath(state, &state->path); 1405 xfs_da_fixhashpath(state, &state->path);
1337 } else { 1406 } else {
1338 /* 1407 /*
@@ -1515,7 +1584,8 @@ xfs_dir2_node_addname_int(
1515 /* 1584 /*
1516 * Not allowed to allocate, return failure. 1585 * Not allowed to allocate, return failure.
1517 */ 1586 */
1518 if (args->justcheck || args->total == 0) { 1587 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) ||
1588 args->total == 0) {
1519 /* 1589 /*
1520 * Drop the freespace buffer unless it came from our 1590 * Drop the freespace buffer unless it came from our
1521 * caller. 1591 * caller.
@@ -1661,7 +1731,7 @@ xfs_dir2_node_addname_int(
1661 /* 1731 /*
1662 * If just checking, we succeeded. 1732 * If just checking, we succeeded.
1663 */ 1733 */
1664 if (args->justcheck) { 1734 if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
1665 if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) 1735 if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
1666 xfs_da_buf_done(fbp); 1736 xfs_da_buf_done(fbp);
1667 return 0; 1737 return 0;
@@ -1767,6 +1837,14 @@ xfs_dir2_node_lookup(
1767 error = xfs_da_node_lookup_int(state, &rval); 1837 error = xfs_da_node_lookup_int(state, &rval);
1768 if (error) 1838 if (error)
1769 rval = error; 1839 rval = error;
1840 else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE) {
1841 /* If a CI match, dup the actual name and return EEXIST */
1842 xfs_dir2_data_entry_t *dep;
1843
1844 dep = (xfs_dir2_data_entry_t *)((char *)state->extrablk.bp->
1845 data + state->extrablk.index);
1846 rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
1847 }
1770 /* 1848 /*
1771 * Release the btree blocks and leaf block. 1849 * Release the btree blocks and leaf block.
1772 */ 1850 */
@@ -1810,9 +1888,8 @@ xfs_dir2_node_removename(
1810 * Look up the entry we're deleting, set up the cursor. 1888 * Look up the entry we're deleting, set up the cursor.
1811 */ 1889 */
1812 error = xfs_da_node_lookup_int(state, &rval); 1890 error = xfs_da_node_lookup_int(state, &rval);
1813 if (error) { 1891 if (error)
1814 rval = error; 1892 rval = error;
1815 }
1816 /* 1893 /*
1817 * Didn't find it, upper layer screwed up. 1894 * Didn't find it, upper layer screwed up.
1818 */ 1895 */
@@ -1829,9 +1906,8 @@ xfs_dir2_node_removename(
1829 */ 1906 */
1830 error = xfs_dir2_leafn_remove(args, blk->bp, blk->index, 1907 error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
1831 &state->extrablk, &rval); 1908 &state->extrablk, &rval);
1832 if (error) { 1909 if (error)
1833 return error; 1910 return error;
1834 }
1835 /* 1911 /*
1836 * Fix the hash values up the btree. 1912 * Fix the hash values up the btree.
1837 */ 1913 */
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 919d275a1cef..b46af0013ec9 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -255,7 +255,7 @@ xfs_dir2_block_to_sf(
255 xfs_dir2_sf_check(args); 255 xfs_dir2_sf_check(args);
256out: 256out:
257 xfs_trans_log_inode(args->trans, dp, logflags); 257 xfs_trans_log_inode(args->trans, dp, logflags);
258 kmem_free(block, mp->m_dirblksize); 258 kmem_free(block);
259 return error; 259 return error;
260} 260}
261 261
@@ -332,7 +332,7 @@ xfs_dir2_sf_addname(
332 /* 332 /*
333 * Just checking or no space reservation, it doesn't fit. 333 * Just checking or no space reservation, it doesn't fit.
334 */ 334 */
335 if (args->justcheck || args->total == 0) 335 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
336 return XFS_ERROR(ENOSPC); 336 return XFS_ERROR(ENOSPC);
337 /* 337 /*
338 * Convert to block form then add the name. 338 * Convert to block form then add the name.
@@ -345,7 +345,7 @@ xfs_dir2_sf_addname(
345 /* 345 /*
346 * Just checking, it fits. 346 * Just checking, it fits.
347 */ 347 */
348 if (args->justcheck) 348 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
349 return 0; 349 return 0;
350 /* 350 /*
351 * Do it the easy way - just add it at the end. 351 * Do it the easy way - just add it at the end.
@@ -512,7 +512,7 @@ xfs_dir2_sf_addname_hard(
512 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 512 sfep = xfs_dir2_sf_nextentry(sfp, sfep);
513 memcpy(sfep, oldsfep, old_isize - nbytes); 513 memcpy(sfep, oldsfep, old_isize - nbytes);
514 } 514 }
515 kmem_free(buf, old_isize); 515 kmem_free(buf);
516 dp->i_d.di_size = new_isize; 516 dp->i_d.di_size = new_isize;
517 xfs_dir2_sf_check(args); 517 xfs_dir2_sf_check(args);
518} 518}
@@ -812,8 +812,11 @@ xfs_dir2_sf_lookup(
812{ 812{
813 xfs_inode_t *dp; /* incore directory inode */ 813 xfs_inode_t *dp; /* incore directory inode */
814 int i; /* entry index */ 814 int i; /* entry index */
815 int error;
815 xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ 816 xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */
816 xfs_dir2_sf_t *sfp; /* shortform structure */ 817 xfs_dir2_sf_t *sfp; /* shortform structure */
818 enum xfs_dacmp cmp; /* comparison result */
819 xfs_dir2_sf_entry_t *ci_sfep; /* case-insens. entry */
817 820
818 xfs_dir2_trace_args("sf_lookup", args); 821 xfs_dir2_trace_args("sf_lookup", args);
819 xfs_dir2_sf_check(args); 822 xfs_dir2_sf_check(args);
@@ -836,6 +839,7 @@ xfs_dir2_sf_lookup(
836 */ 839 */
837 if (args->namelen == 1 && args->name[0] == '.') { 840 if (args->namelen == 1 && args->name[0] == '.') {
838 args->inumber = dp->i_ino; 841 args->inumber = dp->i_ino;
842 args->cmpresult = XFS_CMP_EXACT;
839 return XFS_ERROR(EEXIST); 843 return XFS_ERROR(EEXIST);
840 } 844 }
841 /* 845 /*
@@ -844,28 +848,41 @@ xfs_dir2_sf_lookup(
844 if (args->namelen == 2 && 848 if (args->namelen == 2 &&
845 args->name[0] == '.' && args->name[1] == '.') { 849 args->name[0] == '.' && args->name[1] == '.') {
846 args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); 850 args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
851 args->cmpresult = XFS_CMP_EXACT;
847 return XFS_ERROR(EEXIST); 852 return XFS_ERROR(EEXIST);
848 } 853 }
849 /* 854 /*
850 * Loop over all the entries trying to match ours. 855 * Loop over all the entries trying to match ours.
851 */ 856 */
852 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); 857 ci_sfep = NULL;
853 i < sfp->hdr.count; 858 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count;
854 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { 859 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
855 if (sfep->namelen == args->namelen && 860 /*
856 sfep->name[0] == args->name[0] && 861 * Compare name and if it's an exact match, return the inode
857 memcmp(args->name, sfep->name, args->namelen) == 0) { 862 * number. If it's the first case-insensitive match, store the
858 args->inumber = 863 * inode number and continue looking for an exact match.
859 xfs_dir2_sf_get_inumber(sfp, 864 */
860 xfs_dir2_sf_inumberp(sfep)); 865 cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name,
861 return XFS_ERROR(EEXIST); 866 sfep->namelen);
867 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
868 args->cmpresult = cmp;
869 args->inumber = xfs_dir2_sf_get_inumber(sfp,
870 xfs_dir2_sf_inumberp(sfep));
871 if (cmp == XFS_CMP_EXACT)
872 return XFS_ERROR(EEXIST);
873 ci_sfep = sfep;
862 } 874 }
863 } 875 }
876 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
864 /* 877 /*
865 * Didn't find it. 878 * Here, we can only be doing a lookup (not a rename or replace).
879 * If a case-insensitive match was not found, return ENOENT.
866 */ 880 */
867 ASSERT(args->oknoent); 881 if (!ci_sfep)
868 return XFS_ERROR(ENOENT); 882 return XFS_ERROR(ENOENT);
883 /* otherwise process the CI match as required by the caller */
884 error = xfs_dir_cilookup_result(args, ci_sfep->name, ci_sfep->namelen);
885 return XFS_ERROR(error);
869} 886}
870 887
871/* 888/*
@@ -904,24 +921,21 @@ xfs_dir2_sf_removename(
904 * Loop over the old directory entries. 921 * Loop over the old directory entries.
905 * Find the one we're deleting. 922 * Find the one we're deleting.
906 */ 923 */
907 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); 924 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count;
908 i < sfp->hdr.count; 925 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
909 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { 926 if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
910 if (sfep->namelen == args->namelen && 927 XFS_CMP_EXACT) {
911 sfep->name[0] == args->name[0] &&
912 memcmp(sfep->name, args->name, args->namelen) == 0) {
913 ASSERT(xfs_dir2_sf_get_inumber(sfp, 928 ASSERT(xfs_dir2_sf_get_inumber(sfp,
914 xfs_dir2_sf_inumberp(sfep)) == 929 xfs_dir2_sf_inumberp(sfep)) ==
915 args->inumber); 930 args->inumber);
916 break; 931 break;
917 } 932 }
918 } 933 }
919 /* 934 /*
920 * Didn't find it. 935 * Didn't find it.
921 */ 936 */
922 if (i == sfp->hdr.count) { 937 if (i == sfp->hdr.count)
923 return XFS_ERROR(ENOENT); 938 return XFS_ERROR(ENOENT);
924 }
925 /* 939 /*
926 * Calculate sizes. 940 * Calculate sizes.
927 */ 941 */
@@ -1042,11 +1056,10 @@ xfs_dir2_sf_replace(
1042 */ 1056 */
1043 else { 1057 else {
1044 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); 1058 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
1045 i < sfp->hdr.count; 1059 i < sfp->hdr.count;
1046 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { 1060 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
1047 if (sfep->namelen == args->namelen && 1061 if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
1048 sfep->name[0] == args->name[0] && 1062 XFS_CMP_EXACT) {
1049 memcmp(args->name, sfep->name, args->namelen) == 0) {
1050#if XFS_BIG_INUMS || defined(DEBUG) 1063#if XFS_BIG_INUMS || defined(DEBUG)
1051 ino = xfs_dir2_sf_get_inumber(sfp, 1064 ino = xfs_dir2_sf_get_inumber(sfp,
1052 xfs_dir2_sf_inumberp(sfep)); 1065 xfs_dir2_sf_inumberp(sfep));
@@ -1061,7 +1074,7 @@ xfs_dir2_sf_replace(
1061 * Didn't find it. 1074 * Didn't find it.
1062 */ 1075 */
1063 if (i == sfp->hdr.count) { 1076 if (i == sfp->hdr.count) {
1064 ASSERT(args->oknoent); 1077 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
1065#if XFS_BIG_INUMS 1078#if XFS_BIG_INUMS
1066 if (i8elevated) 1079 if (i8elevated)
1067 xfs_dir2_sf_toino4(args); 1080 xfs_dir2_sf_toino4(args);
@@ -1174,7 +1187,7 @@ xfs_dir2_sf_toino4(
1174 /* 1187 /*
1175 * Clean up the inode. 1188 * Clean up the inode.
1176 */ 1189 */
1177 kmem_free(buf, oldsize); 1190 kmem_free(buf);
1178 dp->i_d.di_size = newsize; 1191 dp->i_d.di_size = newsize;
1179 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 1192 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
1180} 1193}
@@ -1251,7 +1264,7 @@ xfs_dir2_sf_toino8(
1251 /* 1264 /*
1252 * Clean up the inode. 1265 * Clean up the inode.
1253 */ 1266 */
1254 kmem_free(buf, oldsize); 1267 kmem_free(buf);
1255 dp->i_d.di_size = newsize; 1268 dp->i_d.di_size = newsize;
1256 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 1269 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
1257} 1270}
diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h
index 005629d702d2..deecc9d238f8 100644
--- a/fs/xfs/xfs_dir2_sf.h
+++ b/fs/xfs/xfs_dir2_sf.h
@@ -62,7 +62,7 @@ typedef union {
62 * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. 62 * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
63 * Only need 16 bits, this is the byte offset into the single block form. 63 * Only need 16 bits, this is the byte offset into the single block form.
64 */ 64 */
65typedef struct { __uint8_t i[2]; } xfs_dir2_sf_off_t; 65typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;
66 66
67/* 67/*
68 * The parent directory has a dedicated field, and the self-pointer must 68 * The parent directory has a dedicated field, and the self-pointer must
@@ -76,14 +76,14 @@ typedef struct xfs_dir2_sf_hdr {
76 __uint8_t count; /* count of entries */ 76 __uint8_t count; /* count of entries */
77 __uint8_t i8count; /* count of 8-byte inode #s */ 77 __uint8_t i8count; /* count of 8-byte inode #s */
78 xfs_dir2_inou_t parent; /* parent dir inode number */ 78 xfs_dir2_inou_t parent; /* parent dir inode number */
79} xfs_dir2_sf_hdr_t; 79} __arch_pack xfs_dir2_sf_hdr_t;
80 80
81typedef struct xfs_dir2_sf_entry { 81typedef struct xfs_dir2_sf_entry {
82 __uint8_t namelen; /* actual name length */ 82 __uint8_t namelen; /* actual name length */
83 xfs_dir2_sf_off_t offset; /* saved offset */ 83 xfs_dir2_sf_off_t offset; /* saved offset */
84 __uint8_t name[1]; /* name, variable size */ 84 __uint8_t name[1]; /* name, variable size */
85 xfs_dir2_inou_t inumber; /* inode number, var. offset */ 85 xfs_dir2_inou_t inumber; /* inode number, var. offset */
86} xfs_dir2_sf_entry_t; 86} __arch_pack xfs_dir2_sf_entry_t;
87 87
88typedef struct xfs_dir2_sf { 88typedef struct xfs_dir2_sf {
89 xfs_dir2_sf_hdr_t hdr; /* shortform header */ 89 xfs_dir2_sf_hdr_t hdr; /* shortform header */
diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c
index f3fb2ffd6f5c..6cc7c0c681ac 100644
--- a/fs/xfs/xfs_dir2_trace.c
+++ b/fs/xfs/xfs_dir2_trace.c
@@ -85,7 +85,8 @@ xfs_dir2_trace_args(
85 (void *)((unsigned long)(args->inumber >> 32)), 85 (void *)((unsigned long)(args->inumber >> 32)),
86 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), 86 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
87 (void *)args->dp, (void *)args->trans, 87 (void *)args->dp, (void *)args->trans,
88 (void *)(unsigned long)args->justcheck, NULL, NULL); 88 (void *)(unsigned long)(args->op_flags & XFS_DA_OP_JUSTCHECK),
89 NULL, NULL);
89} 90}
90 91
91void 92void
@@ -100,7 +101,7 @@ xfs_dir2_trace_args_b(
100 (void *)((unsigned long)(args->inumber >> 32)), 101 (void *)((unsigned long)(args->inumber >> 32)),
101 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), 102 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
102 (void *)args->dp, (void *)args->trans, 103 (void *)args->dp, (void *)args->trans,
103 (void *)(unsigned long)args->justcheck, 104 (void *)(unsigned long)(args->op_flags & XFS_DA_OP_JUSTCHECK),
104 (void *)(bp ? bp->bps[0] : NULL), NULL); 105 (void *)(bp ? bp->bps[0] : NULL), NULL);
105} 106}
106 107
@@ -117,7 +118,7 @@ xfs_dir2_trace_args_bb(
117 (void *)((unsigned long)(args->inumber >> 32)), 118 (void *)((unsigned long)(args->inumber >> 32)),
118 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), 119 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
119 (void *)args->dp, (void *)args->trans, 120 (void *)args->dp, (void *)args->trans,
120 (void *)(unsigned long)args->justcheck, 121 (void *)(unsigned long)(args->op_flags & XFS_DA_OP_JUSTCHECK),
121 (void *)(lbp ? lbp->bps[0] : NULL), 122 (void *)(lbp ? lbp->bps[0] : NULL),
122 (void *)(dbp ? dbp->bps[0] : NULL)); 123 (void *)(dbp ? dbp->bps[0] : NULL));
123} 124}
@@ -157,8 +158,8 @@ xfs_dir2_trace_args_db(
157 (void *)((unsigned long)(args->inumber >> 32)), 158 (void *)((unsigned long)(args->inumber >> 32)),
158 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), 159 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
159 (void *)args->dp, (void *)args->trans, 160 (void *)args->dp, (void *)args->trans,
160 (void *)(unsigned long)args->justcheck, (void *)(long)db, 161 (void *)(unsigned long)(args->op_flags & XFS_DA_OP_JUSTCHECK),
161 (void *)dbp); 162 (void *)(long)db, (void *)dbp);
162} 163}
163 164
164void 165void
@@ -173,7 +174,7 @@ xfs_dir2_trace_args_i(
173 (void *)((unsigned long)(args->inumber >> 32)), 174 (void *)((unsigned long)(args->inumber >> 32)),
174 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), 175 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
175 (void *)args->dp, (void *)args->trans, 176 (void *)args->dp, (void *)args->trans,
176 (void *)(unsigned long)args->justcheck, 177 (void *)(unsigned long)(args->op_flags & XFS_DA_OP_JUSTCHECK),
177 (void *)((unsigned long)(i >> 32)), 178 (void *)((unsigned long)(i >> 32)),
178 (void *)((unsigned long)(i & 0xFFFFFFFF))); 179 (void *)((unsigned long)(i & 0xFFFFFFFF)));
179} 180}
@@ -190,7 +191,8 @@ xfs_dir2_trace_args_s(
190 (void *)((unsigned long)(args->inumber >> 32)), 191 (void *)((unsigned long)(args->inumber >> 32)),
191 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), 192 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
192 (void *)args->dp, (void *)args->trans, 193 (void *)args->dp, (void *)args->trans,
193 (void *)(unsigned long)args->justcheck, (void *)(long)s, NULL); 194 (void *)(unsigned long)(args->op_flags & XFS_DA_OP_JUSTCHECK),
195 (void *)(long)s, NULL);
194} 196}
195 197
196void 198void
@@ -208,7 +210,7 @@ xfs_dir2_trace_args_sb(
208 (void *)((unsigned long)(args->inumber >> 32)), 210 (void *)((unsigned long)(args->inumber >> 32)),
209 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), 211 (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
210 (void *)args->dp, (void *)args->trans, 212 (void *)args->dp, (void *)args->trans,
211 (void *)(unsigned long)args->justcheck, (void *)(long)s, 213 (void *)(unsigned long)(args->op_flags & XFS_DA_OP_JUSTCHECK),
212 (void *)dbp); 214 (void *)(long)s, (void *)dbp);
213} 215}
214#endif /* XFS_DIR2_TRACE */ 216#endif /* XFS_DIR2_TRACE */
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index f71784ab6a60..cdc2d3464a1a 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -166,6 +166,6 @@ typedef enum {
166 166
167#define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \ 167#define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \
168 DM_FLAGS_NDELAY : 0) 168 DM_FLAGS_NDELAY : 0)
169#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) 169#define AT_DELAY_FLAG(f) ((f & XFS_ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0)
170 170
171#endif /* __XFS_DMAPI_H__ */ 171#endif /* __XFS_DMAPI_H__ */
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 05e5365d3c31..f66756cfb5e8 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -66,14 +66,6 @@ int xfs_etest[XFS_NUM_INJECT_ERROR];
66int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; 66int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
67char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; 67char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR];
68 68
69void
70xfs_error_test_init(void)
71{
72 memset(xfs_etest, 0, sizeof(xfs_etest));
73 memset(xfs_etest_fsid, 0, sizeof(xfs_etest_fsid));
74 memset(xfs_etest_fsname, 0, sizeof(xfs_etest_fsname));
75}
76
77int 69int
78xfs_error_test(int error_tag, int *fsidp, char *expression, 70xfs_error_test(int error_tag, int *fsidp, char *expression,
79 int line, char *file, unsigned long randfactor) 71 int line, char *file, unsigned long randfactor)
@@ -150,8 +142,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)
150 xfs_etest[i]); 142 xfs_etest[i]);
151 xfs_etest[i] = 0; 143 xfs_etest[i] = 0;
152 xfs_etest_fsid[i] = 0LL; 144 xfs_etest_fsid[i] = 0LL;
153 kmem_free(xfs_etest_fsname[i], 145 kmem_free(xfs_etest_fsname[i]);
154 strlen(xfs_etest_fsname[i]) + 1);
155 xfs_etest_fsname[i] = NULL; 146 xfs_etest_fsname[i] = NULL;
156 } 147 }
157 } 148 }
@@ -175,7 +166,7 @@ xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
175 newfmt = kmem_alloc(len, KM_SLEEP); 166 newfmt = kmem_alloc(len, KM_SLEEP);
176 sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt); 167 sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
177 icmn_err(level, newfmt, ap); 168 icmn_err(level, newfmt, ap);
178 kmem_free(newfmt, len); 169 kmem_free(newfmt);
179 } else { 170 } else {
180 icmn_err(level, fmt, ap); 171 icmn_err(level, fmt, ap);
181 } 172 }
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 6490d2a9f8e1..d8559d132efa 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -127,7 +127,6 @@ extern void xfs_corruption_error(char *tag, int level, struct xfs_mount *mp,
127 127
128#if (defined(DEBUG) || defined(INDUCE_IO_ERROR)) 128#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
129extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); 129extern int xfs_error_test(int, int *, char *, int, char *, unsigned long);
130extern void xfs_error_test_init(void);
131 130
132#define XFS_NUM_INJECT_ERROR 10 131#define XFS_NUM_INJECT_ERROR 10
133 132
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 132bd07b9bb8..8aa28f751b2a 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -41,8 +41,7 @@ xfs_efi_item_free(xfs_efi_log_item_t *efip)
41 int nexts = efip->efi_format.efi_nextents; 41 int nexts = efip->efi_format.efi_nextents;
42 42
43 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { 43 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
44 kmem_free(efip, sizeof(xfs_efi_log_item_t) + 44 kmem_free(efip);
45 (nexts - 1) * sizeof(xfs_extent_t));
46 } else { 45 } else {
47 kmem_zone_free(xfs_efi_zone, efip); 46 kmem_zone_free(xfs_efi_zone, efip);
48 } 47 }
@@ -374,8 +373,7 @@ xfs_efd_item_free(xfs_efd_log_item_t *efdp)
374 int nexts = efdp->efd_format.efd_nextents; 373 int nexts = efdp->efd_format.efd_nextents;
375 374
376 if (nexts > XFS_EFD_MAX_FAST_EXTENTS) { 375 if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
377 kmem_free(efdp, sizeof(xfs_efd_log_item_t) + 376 kmem_free(efdp);
378 (nexts - 1) * sizeof(xfs_extent_t));
379 } else { 377 } else {
380 kmem_zone_free(xfs_efd_zone, efdp); 378 kmem_zone_free(xfs_efd_zone, efdp);
381 } 379 }
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index 3f3785b10804..c38fd14fca29 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -397,10 +397,12 @@ int
397xfs_filestream_init(void) 397xfs_filestream_init(void)
398{ 398{
399 item_zone = kmem_zone_init(sizeof(fstrm_item_t), "fstrm_item"); 399 item_zone = kmem_zone_init(sizeof(fstrm_item_t), "fstrm_item");
400 if (!item_zone)
401 return -ENOMEM;
400#ifdef XFS_FILESTREAMS_TRACE 402#ifdef XFS_FILESTREAMS_TRACE
401 xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP); 403 xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP);
402#endif 404#endif
403 return item_zone ? 0 : -ENOMEM; 405 return 0;
404} 406}
405 407
406/* 408/*
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 3bed6433d050..01c0cc88d3f3 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -239,6 +239,7 @@ typedef struct xfs_fsop_resblks {
239#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ 239#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */
240#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ 240#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */
241#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ 241#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */
242#define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */
242#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ 243#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */
243 244
244 245
@@ -371,6 +372,9 @@ typedef struct xfs_fsop_attrlist_handlereq {
371 372
372typedef struct xfs_attr_multiop { 373typedef struct xfs_attr_multiop {
373 __u32 am_opcode; 374 __u32 am_opcode;
375#define ATTR_OP_GET 1 /* return the indicated attr's value */
376#define ATTR_OP_SET 2 /* set/create the indicated attr/value pair */
377#define ATTR_OP_REMOVE 3 /* remove the indicated attr */
374 __s32 am_error; 378 __s32 am_error;
375 void __user *am_attrname; 379 void __user *am_attrname;
376 void __user *am_attrvalue; 380 void __user *am_attrvalue;
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 381ebda4f7bc..84583cf73db3 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -95,6 +95,8 @@ xfs_fs_geometry(
95 XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) | 95 XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) |
96 (xfs_sb_version_hassector(&mp->m_sb) ? 96 (xfs_sb_version_hassector(&mp->m_sb) ?
97 XFS_FSOP_GEOM_FLAGS_SECTOR : 0) | 97 XFS_FSOP_GEOM_FLAGS_SECTOR : 0) |
98 (xfs_sb_version_hasasciici(&mp->m_sb) ?
99 XFS_FSOP_GEOM_FLAGS_DIRV2CI : 0) |
98 (xfs_sb_version_haslazysbcount(&mp->m_sb) ? 100 (xfs_sb_version_haslazysbcount(&mp->m_sb) ?
99 XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) | 101 XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) |
100 (xfs_sb_version_hasattr2(&mp->m_sb) ? 102 (xfs_sb_version_hasattr2(&mp->m_sb) ?
@@ -625,7 +627,7 @@ xfs_fs_goingdown(
625 xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); 627 xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
626 thaw_bdev(sb->s_bdev, sb); 628 thaw_bdev(sb->s_bdev, sb);
627 } 629 }
628 630
629 break; 631 break;
630 } 632 }
631 case XFS_FSOP_GOING_FLAGS_LOGFLUSH: 633 case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e569bf5d6cf0..bedc66163176 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1763,67 +1763,6 @@ xfs_itruncate_finish(
1763 return 0; 1763 return 0;
1764} 1764}
1765 1765
1766
1767/*
1768 * xfs_igrow_start
1769 *
1770 * Do the first part of growing a file: zero any data in the last
1771 * block that is beyond the old EOF. We need to do this before
1772 * the inode is joined to the transaction to modify the i_size.
1773 * That way we can drop the inode lock and call into the buffer
1774 * cache to get the buffer mapping the EOF.
1775 */
1776int
1777xfs_igrow_start(
1778 xfs_inode_t *ip,
1779 xfs_fsize_t new_size,
1780 cred_t *credp)
1781{
1782 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
1783 ASSERT(new_size > ip->i_size);
1784
1785 /*
1786 * Zero any pages that may have been created by
1787 * xfs_write_file() beyond the end of the file
1788 * and any blocks between the old and new file sizes.
1789 */
1790 return xfs_zero_eof(ip, new_size, ip->i_size);
1791}
1792
1793/*
1794 * xfs_igrow_finish
1795 *
1796 * This routine is called to extend the size of a file.
1797 * The inode must have both the iolock and the ilock locked
1798 * for update and it must be a part of the current transaction.
1799 * The xfs_igrow_start() function must have been called previously.
1800 * If the change_flag is not zero, the inode change timestamp will
1801 * be updated.
1802 */
1803void
1804xfs_igrow_finish(
1805 xfs_trans_t *tp,
1806 xfs_inode_t *ip,
1807 xfs_fsize_t new_size,
1808 int change_flag)
1809{
1810 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
1811 ASSERT(ip->i_transp == tp);
1812 ASSERT(new_size > ip->i_size);
1813
1814 /*
1815 * Update the file size. Update the inode change timestamp
1816 * if change_flag set.
1817 */
1818 ip->i_d.di_size = new_size;
1819 ip->i_size = new_size;
1820 if (change_flag)
1821 xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
1822 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1823
1824}
1825
1826
1827/* 1766/*
1828 * This is called when the inode's link count goes to 0. 1767 * This is called when the inode's link count goes to 0.
1829 * We place the on-disk inode on a list in the AGI. It 1768 * We place the on-disk inode on a list in the AGI. It
@@ -2258,7 +2197,7 @@ xfs_ifree_cluster(
2258 xfs_trans_binval(tp, bp); 2197 xfs_trans_binval(tp, bp);
2259 } 2198 }
2260 2199
2261 kmem_free(ip_found, ninodes * sizeof(xfs_inode_t *)); 2200 kmem_free(ip_found);
2262 xfs_put_perag(mp, pag); 2201 xfs_put_perag(mp, pag);
2263} 2202}
2264 2203
@@ -2470,7 +2409,7 @@ xfs_iroot_realloc(
2470 (int)new_size); 2409 (int)new_size);
2471 memcpy(np, op, new_max * (uint)sizeof(xfs_dfsbno_t)); 2410 memcpy(np, op, new_max * (uint)sizeof(xfs_dfsbno_t));
2472 } 2411 }
2473 kmem_free(ifp->if_broot, ifp->if_broot_bytes); 2412 kmem_free(ifp->if_broot);
2474 ifp->if_broot = new_broot; 2413 ifp->if_broot = new_broot;
2475 ifp->if_broot_bytes = (int)new_size; 2414 ifp->if_broot_bytes = (int)new_size;
2476 ASSERT(ifp->if_broot_bytes <= 2415 ASSERT(ifp->if_broot_bytes <=
@@ -2514,7 +2453,7 @@ xfs_idata_realloc(
2514 2453
2515 if (new_size == 0) { 2454 if (new_size == 0) {
2516 if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { 2455 if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
2517 kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes); 2456 kmem_free(ifp->if_u1.if_data);
2518 } 2457 }
2519 ifp->if_u1.if_data = NULL; 2458 ifp->if_u1.if_data = NULL;
2520 real_size = 0; 2459 real_size = 0;
@@ -2529,7 +2468,7 @@ xfs_idata_realloc(
2529 ASSERT(ifp->if_real_bytes != 0); 2468 ASSERT(ifp->if_real_bytes != 0);
2530 memcpy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data, 2469 memcpy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data,
2531 new_size); 2470 new_size);
2532 kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes); 2471 kmem_free(ifp->if_u1.if_data);
2533 ifp->if_u1.if_data = ifp->if_u2.if_inline_data; 2472 ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
2534 } 2473 }
2535 real_size = 0; 2474 real_size = 0;
@@ -2636,7 +2575,7 @@ xfs_idestroy_fork(
2636 2575
2637 ifp = XFS_IFORK_PTR(ip, whichfork); 2576 ifp = XFS_IFORK_PTR(ip, whichfork);
2638 if (ifp->if_broot != NULL) { 2577 if (ifp->if_broot != NULL) {
2639 kmem_free(ifp->if_broot, ifp->if_broot_bytes); 2578 kmem_free(ifp->if_broot);
2640 ifp->if_broot = NULL; 2579 ifp->if_broot = NULL;
2641 } 2580 }
2642 2581
@@ -2650,7 +2589,7 @@ xfs_idestroy_fork(
2650 if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) && 2589 if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) &&
2651 (ifp->if_u1.if_data != NULL)) { 2590 (ifp->if_u1.if_data != NULL)) {
2652 ASSERT(ifp->if_real_bytes != 0); 2591 ASSERT(ifp->if_real_bytes != 0);
2653 kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes); 2592 kmem_free(ifp->if_u1.if_data);
2654 ifp->if_u1.if_data = NULL; 2593 ifp->if_u1.if_data = NULL;
2655 ifp->if_real_bytes = 0; 2594 ifp->if_real_bytes = 0;
2656 } 2595 }
@@ -3058,7 +2997,7 @@ xfs_iflush_cluster(
3058 2997
3059out_free: 2998out_free:
3060 read_unlock(&pag->pag_ici_lock); 2999 read_unlock(&pag->pag_ici_lock);
3061 kmem_free(ilist, ilist_size); 3000 kmem_free(ilist);
3062 return 0; 3001 return 0;
3063 3002
3064 3003
@@ -3102,7 +3041,7 @@ cluster_corrupt_out:
3102 * Unlocks the flush lock 3041 * Unlocks the flush lock
3103 */ 3042 */
3104 xfs_iflush_abort(iq); 3043 xfs_iflush_abort(iq);
3105 kmem_free(ilist, ilist_size); 3044 kmem_free(ilist);
3106 return XFS_ERROR(EFSCORRUPTED); 3045 return XFS_ERROR(EFSCORRUPTED);
3107} 3046}
3108 3047
@@ -3143,8 +3082,6 @@ xfs_iflush(
3143 * flush lock and do nothing. 3082 * flush lock and do nothing.
3144 */ 3083 */
3145 if (xfs_inode_clean(ip)) { 3084 if (xfs_inode_clean(ip)) {
3146 ASSERT((iip != NULL) ?
3147 !(iip->ili_item.li_flags & XFS_LI_IN_AIL) : 1);
3148 xfs_ifunlock(ip); 3085 xfs_ifunlock(ip);
3149 return 0; 3086 return 0;
3150 } 3087 }
@@ -3836,7 +3773,7 @@ xfs_iext_add_indirect_multi(
3836 erp = xfs_iext_irec_new(ifp, erp_idx); 3773 erp = xfs_iext_irec_new(ifp, erp_idx);
3837 } 3774 }
3838 memmove(&erp->er_extbuf[i], nex2_ep, byte_diff); 3775 memmove(&erp->er_extbuf[i], nex2_ep, byte_diff);
3839 kmem_free(nex2_ep, byte_diff); 3776 kmem_free(nex2_ep);
3840 erp->er_extcount += nex2; 3777 erp->er_extcount += nex2;
3841 xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, nex2); 3778 xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, nex2);
3842 } 3779 }
@@ -4112,7 +4049,7 @@ xfs_iext_direct_to_inline(
4112 */ 4049 */
4113 memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, 4050 memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents,
4114 nextents * sizeof(xfs_bmbt_rec_t)); 4051 nextents * sizeof(xfs_bmbt_rec_t));
4115 kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); 4052 kmem_free(ifp->if_u1.if_extents);
4116 ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; 4053 ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
4117 ifp->if_real_bytes = 0; 4054 ifp->if_real_bytes = 0;
4118} 4055}
@@ -4186,7 +4123,7 @@ xfs_iext_indirect_to_direct(
4186 ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); 4123 ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ);
4187 4124
4188 ep = ifp->if_u1.if_ext_irec->er_extbuf; 4125 ep = ifp->if_u1.if_ext_irec->er_extbuf;
4189 kmem_free(ifp->if_u1.if_ext_irec, sizeof(xfs_ext_irec_t)); 4126 kmem_free(ifp->if_u1.if_ext_irec);
4190 ifp->if_flags &= ~XFS_IFEXTIREC; 4127 ifp->if_flags &= ~XFS_IFEXTIREC;
4191 ifp->if_u1.if_extents = ep; 4128 ifp->if_u1.if_extents = ep;
4192 ifp->if_bytes = size; 4129 ifp->if_bytes = size;
@@ -4212,7 +4149,7 @@ xfs_iext_destroy(
4212 } 4149 }
4213 ifp->if_flags &= ~XFS_IFEXTIREC; 4150 ifp->if_flags &= ~XFS_IFEXTIREC;
4214 } else if (ifp->if_real_bytes) { 4151 } else if (ifp->if_real_bytes) {
4215 kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); 4152 kmem_free(ifp->if_u1.if_extents);
4216 } else if (ifp->if_bytes) { 4153 } else if (ifp->if_bytes) {
4217 memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS * 4154 memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS *
4218 sizeof(xfs_bmbt_rec_t)); 4155 sizeof(xfs_bmbt_rec_t));
@@ -4483,7 +4420,7 @@ xfs_iext_irec_remove(
4483 if (erp->er_extbuf) { 4420 if (erp->er_extbuf) {
4484 xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, 4421 xfs_iext_irec_update_extoffs(ifp, erp_idx + 1,
4485 -erp->er_extcount); 4422 -erp->er_extcount);
4486 kmem_free(erp->er_extbuf, XFS_IEXT_BUFSZ); 4423 kmem_free(erp->er_extbuf);
4487 } 4424 }
4488 /* Compact extent records */ 4425 /* Compact extent records */
4489 erp = ifp->if_u1.if_ext_irec; 4426 erp = ifp->if_u1.if_ext_irec;
@@ -4501,8 +4438,7 @@ xfs_iext_irec_remove(
4501 xfs_iext_realloc_indirect(ifp, 4438 xfs_iext_realloc_indirect(ifp,
4502 nlists * sizeof(xfs_ext_irec_t)); 4439 nlists * sizeof(xfs_ext_irec_t));
4503 } else { 4440 } else {
4504 kmem_free(ifp->if_u1.if_ext_irec, 4441 kmem_free(ifp->if_u1.if_ext_irec);
4505 sizeof(xfs_ext_irec_t));
4506 } 4442 }
4507 ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; 4443 ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ;
4508} 4444}
@@ -4571,7 +4507,7 @@ xfs_iext_irec_compact_pages(
4571 * so er_extoffs don't get modified in 4507 * so er_extoffs don't get modified in
4572 * xfs_iext_irec_remove. 4508 * xfs_iext_irec_remove.
4573 */ 4509 */
4574 kmem_free(erp_next->er_extbuf, XFS_IEXT_BUFSZ); 4510 kmem_free(erp_next->er_extbuf);
4575 erp_next->er_extbuf = NULL; 4511 erp_next->er_extbuf = NULL;
4576 xfs_iext_irec_remove(ifp, erp_idx + 1); 4512 xfs_iext_irec_remove(ifp, erp_idx + 1);
4577 nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; 4513 nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
@@ -4596,40 +4532,63 @@ xfs_iext_irec_compact_full(
4596 int nlists; /* number of irec's (ex lists) */ 4532 int nlists; /* number of irec's (ex lists) */
4597 4533
4598 ASSERT(ifp->if_flags & XFS_IFEXTIREC); 4534 ASSERT(ifp->if_flags & XFS_IFEXTIREC);
4535
4599 nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; 4536 nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
4600 erp = ifp->if_u1.if_ext_irec; 4537 erp = ifp->if_u1.if_ext_irec;
4601 ep = &erp->er_extbuf[erp->er_extcount]; 4538 ep = &erp->er_extbuf[erp->er_extcount];
4602 erp_next = erp + 1; 4539 erp_next = erp + 1;
4603 ep_next = erp_next->er_extbuf; 4540 ep_next = erp_next->er_extbuf;
4541
4604 while (erp_idx < nlists - 1) { 4542 while (erp_idx < nlists - 1) {
4543 /*
4544 * Check how many extent records are available in this irec.
4545 * If there is none skip the whole exercise.
4546 */
4605 ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; 4547 ext_avail = XFS_LINEAR_EXTS - erp->er_extcount;
4606 ext_diff = MIN(ext_avail, erp_next->er_extcount); 4548 if (ext_avail) {
4607 memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); 4549
4608 erp->er_extcount += ext_diff;
4609 erp_next->er_extcount -= ext_diff;
4610 /* Remove next page */
4611 if (erp_next->er_extcount == 0) {
4612 /* 4550 /*
4613 * Free page before removing extent record 4551 * Copy over as many as possible extent records into
4614 * so er_extoffs don't get modified in 4552 * the previous page.
4615 * xfs_iext_irec_remove.
4616 */ 4553 */
4617 kmem_free(erp_next->er_extbuf, 4554 ext_diff = MIN(ext_avail, erp_next->er_extcount);
4618 erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); 4555 memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t));
4619 erp_next->er_extbuf = NULL; 4556 erp->er_extcount += ext_diff;
4620 xfs_iext_irec_remove(ifp, erp_idx + 1); 4557 erp_next->er_extcount -= ext_diff;
4621 erp = &ifp->if_u1.if_ext_irec[erp_idx]; 4558
4622 nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; 4559 /*
4623 /* Update next page */ 4560 * If the next irec is empty now we can simply
4624 } else { 4561 * remove it.
4625 /* Move rest of page up to become next new page */ 4562 */
4626 memmove(erp_next->er_extbuf, ep_next, 4563 if (erp_next->er_extcount == 0) {
4627 erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); 4564 /*
4628 ep_next = erp_next->er_extbuf; 4565 * Free page before removing extent record
4629 memset(&ep_next[erp_next->er_extcount], 0, 4566 * so er_extoffs don't get modified in
4630 (XFS_LINEAR_EXTS - erp_next->er_extcount) * 4567 * xfs_iext_irec_remove.
4631 sizeof(xfs_bmbt_rec_t)); 4568 */
4569 kmem_free(erp_next->er_extbuf);
4570 erp_next->er_extbuf = NULL;
4571 xfs_iext_irec_remove(ifp, erp_idx + 1);
4572 erp = &ifp->if_u1.if_ext_irec[erp_idx];
4573 nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
4574
4575 /*
4576 * If the next irec is not empty move up the content
4577 * that has not been copied to the previous page to
4578 * the beggining of this one.
4579 */
4580 } else {
4581 memmove(erp_next->er_extbuf, &ep_next[ext_diff],
4582 erp_next->er_extcount *
4583 sizeof(xfs_bmbt_rec_t));
4584 ep_next = erp_next->er_extbuf;
4585 memset(&ep_next[erp_next->er_extcount], 0,
4586 (XFS_LINEAR_EXTS -
4587 erp_next->er_extcount) *
4588 sizeof(xfs_bmbt_rec_t));
4589 }
4632 } 4590 }
4591
4633 if (erp->er_extcount == XFS_LINEAR_EXTS) { 4592 if (erp->er_extcount == XFS_LINEAR_EXTS) {
4634 erp_idx++; 4593 erp_idx++;
4635 if (erp_idx < nlists) 4594 if (erp_idx < nlists)
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 0a999fee4f03..17a04b6321ed 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -507,9 +507,6 @@ int xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
507int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *, 507int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
508 xfs_fsize_t, int, int); 508 xfs_fsize_t, int, int);
509int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); 509int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
510int xfs_igrow_start(xfs_inode_t *, xfs_fsize_t, struct cred *);
511void xfs_igrow_finish(struct xfs_trans *, xfs_inode_t *,
512 xfs_fsize_t, int);
513 510
514void xfs_idestroy_fork(xfs_inode_t *, int); 511void xfs_idestroy_fork(xfs_inode_t *, int);
515void xfs_idestroy(xfs_inode_t *); 512void xfs_idestroy(xfs_inode_t *);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 167b33f15772..0eee08a32c26 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -686,7 +686,7 @@ xfs_inode_item_unlock(
686 ASSERT(ip->i_d.di_nextents > 0); 686 ASSERT(ip->i_d.di_nextents > 0);
687 ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_DEXT); 687 ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_DEXT);
688 ASSERT(ip->i_df.if_bytes > 0); 688 ASSERT(ip->i_df.if_bytes > 0);
689 kmem_free(iip->ili_extents_buf, ip->i_df.if_bytes); 689 kmem_free(iip->ili_extents_buf);
690 iip->ili_extents_buf = NULL; 690 iip->ili_extents_buf = NULL;
691 } 691 }
692 if (iip->ili_aextents_buf != NULL) { 692 if (iip->ili_aextents_buf != NULL) {
@@ -694,7 +694,7 @@ xfs_inode_item_unlock(
694 ASSERT(ip->i_d.di_anextents > 0); 694 ASSERT(ip->i_d.di_anextents > 0);
695 ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_AEXT); 695 ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_AEXT);
696 ASSERT(ip->i_afp->if_bytes > 0); 696 ASSERT(ip->i_afp->if_bytes > 0);
697 kmem_free(iip->ili_aextents_buf, ip->i_afp->if_bytes); 697 kmem_free(iip->ili_aextents_buf);
698 iip->ili_aextents_buf = NULL; 698 iip->ili_aextents_buf = NULL;
699 } 699 }
700 700
@@ -957,8 +957,7 @@ xfs_inode_item_destroy(
957{ 957{
958#ifdef XFS_TRANS_DEBUG 958#ifdef XFS_TRANS_DEBUG
959 if (ip->i_itemp->ili_root_size != 0) { 959 if (ip->i_itemp->ili_root_size != 0) {
960 kmem_free(ip->i_itemp->ili_orig_root, 960 kmem_free(ip->i_itemp->ili_orig_root);
961 ip->i_itemp->ili_root_size);
962 } 961 }
963#endif 962#endif
964 kmem_zone_free(xfs_ili_zone, ip->i_itemp); 963 kmem_zone_free(xfs_ili_zone, ip->i_itemp);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 7edcde691d1a..67f22b2b44b3 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -889,6 +889,16 @@ xfs_iomap_write_unwritten(
889 count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); 889 count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
890 count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); 890 count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb);
891 891
892 /*
893 * Reserve enough blocks in this transaction for two complete extent
894 * btree splits. We may be converting the middle part of an unwritten
895 * extent and in this case we will insert two new extents in the btree
896 * each of which could cause a full split.
897 *
898 * This reservation amount will be used in the first call to
899 * xfs_bmbt_split() to select an AG with enough space to satisfy the
900 * rest of the operation.
901 */
892 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1; 902 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
893 903
894 do { 904 do {
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 419de15aeb43..9a3ef9dcaeb9 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -257,7 +257,7 @@ xfs_bulkstat_one(
257 *ubused = error; 257 *ubused = error;
258 258
259 out_free: 259 out_free:
260 kmem_free(buf, sizeof(*buf)); 260 kmem_free(buf);
261 return error; 261 return error;
262} 262}
263 263
@@ -708,7 +708,7 @@ xfs_bulkstat(
708 /* 708 /*
709 * Done, we're either out of filesystem or space to put the data. 709 * Done, we're either out of filesystem or space to put the data.
710 */ 710 */
711 kmem_free(irbuf, irbsize); 711 kmem_free(irbuf);
712 *ubcountp = ubelem; 712 *ubcountp = ubelem;
713 /* 713 /*
714 * Found some inodes, return them now and return the error next time. 714 * Found some inodes, return them now and return the error next time.
@@ -914,7 +914,7 @@ xfs_inumbers(
914 } 914 }
915 *lastino = XFS_AGINO_TO_INO(mp, agno, agino); 915 *lastino = XFS_AGINO_TO_INO(mp, agno, agino);
916 } 916 }
917 kmem_free(buffer, bcount * sizeof(*buffer)); 917 kmem_free(buffer);
918 if (cur) 918 if (cur)
919 xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR : 919 xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR :
920 XFS_BTREE_NOERROR)); 920 XFS_BTREE_NOERROR));
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index ad3d26ddfe31..91b00a5686cd 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -226,20 +226,24 @@ xlog_grant_sub_space(struct log *log, int bytes)
226static void 226static void
227xlog_grant_add_space_write(struct log *log, int bytes) 227xlog_grant_add_space_write(struct log *log, int bytes)
228{ 228{
229 log->l_grant_write_bytes += bytes; 229 int tmp = log->l_logsize - log->l_grant_write_bytes;
230 if (log->l_grant_write_bytes > log->l_logsize) { 230 if (tmp > bytes)
231 log->l_grant_write_bytes -= log->l_logsize; 231 log->l_grant_write_bytes += bytes;
232 else {
232 log->l_grant_write_cycle++; 233 log->l_grant_write_cycle++;
234 log->l_grant_write_bytes = bytes - tmp;
233 } 235 }
234} 236}
235 237
236static void 238static void
237xlog_grant_add_space_reserve(struct log *log, int bytes) 239xlog_grant_add_space_reserve(struct log *log, int bytes)
238{ 240{
239 log->l_grant_reserve_bytes += bytes; 241 int tmp = log->l_logsize - log->l_grant_reserve_bytes;
240 if (log->l_grant_reserve_bytes > log->l_logsize) { 242 if (tmp > bytes)
241 log->l_grant_reserve_bytes -= log->l_logsize; 243 log->l_grant_reserve_bytes += bytes;
244 else {
242 log->l_grant_reserve_cycle++; 245 log->l_grant_reserve_cycle++;
246 log->l_grant_reserve_bytes = bytes - tmp;
243 } 247 }
244} 248}
245 249
@@ -1228,7 +1232,7 @@ xlog_alloc_log(xfs_mount_t *mp,
1228 1232
1229 spin_lock_init(&log->l_icloglock); 1233 spin_lock_init(&log->l_icloglock);
1230 spin_lock_init(&log->l_grant_lock); 1234 spin_lock_init(&log->l_grant_lock);
1231 initnsema(&log->l_flushsema, 0, "ic-flush"); 1235 sv_init(&log->l_flush_wait, 0, "flush_wait");
1232 1236
1233 /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ 1237 /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */
1234 ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); 1238 ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0);
@@ -1570,10 +1574,9 @@ xlog_dealloc_log(xlog_t *log)
1570 } 1574 }
1571#endif 1575#endif
1572 next_iclog = iclog->ic_next; 1576 next_iclog = iclog->ic_next;
1573 kmem_free(iclog, sizeof(xlog_in_core_t)); 1577 kmem_free(iclog);
1574 iclog = next_iclog; 1578 iclog = next_iclog;
1575 } 1579 }
1576 freesema(&log->l_flushsema);
1577 spinlock_destroy(&log->l_icloglock); 1580 spinlock_destroy(&log->l_icloglock);
1578 spinlock_destroy(&log->l_grant_lock); 1581 spinlock_destroy(&log->l_grant_lock);
1579 1582
@@ -1587,7 +1590,7 @@ xlog_dealloc_log(xlog_t *log)
1587 } 1590 }
1588#endif 1591#endif
1589 log->l_mp->m_log = NULL; 1592 log->l_mp->m_log = NULL;
1590 kmem_free(log, sizeof(xlog_t)); 1593 kmem_free(log);
1591} /* xlog_dealloc_log */ 1594} /* xlog_dealloc_log */
1592 1595
1593/* 1596/*
@@ -2097,6 +2100,7 @@ xlog_state_do_callback(
2097 int funcdidcallbacks; /* flag: function did callbacks */ 2100 int funcdidcallbacks; /* flag: function did callbacks */
2098 int repeats; /* for issuing console warnings if 2101 int repeats; /* for issuing console warnings if
2099 * looping too many times */ 2102 * looping too many times */
2103 int wake = 0;
2100 2104
2101 spin_lock(&log->l_icloglock); 2105 spin_lock(&log->l_icloglock);
2102 first_iclog = iclog = log->l_iclog; 2106 first_iclog = iclog = log->l_iclog;
@@ -2278,15 +2282,13 @@ xlog_state_do_callback(
2278 } 2282 }
2279#endif 2283#endif
2280 2284
2281 flushcnt = 0; 2285 if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR))
2282 if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) { 2286 wake = 1;
2283 flushcnt = log->l_flushcnt;
2284 log->l_flushcnt = 0;
2285 }
2286 spin_unlock(&log->l_icloglock); 2287 spin_unlock(&log->l_icloglock);
2287 while (flushcnt--) 2288
2288 vsema(&log->l_flushsema); 2289 if (wake)
2289} /* xlog_state_do_callback */ 2290 sv_broadcast(&log->l_flush_wait);
2291}
2290 2292
2291 2293
2292/* 2294/*
@@ -2384,16 +2386,15 @@ restart:
2384 } 2386 }
2385 2387
2386 iclog = log->l_iclog; 2388 iclog = log->l_iclog;
2387 if (! (iclog->ic_state == XLOG_STATE_ACTIVE)) { 2389 if (iclog->ic_state != XLOG_STATE_ACTIVE) {
2388 log->l_flushcnt++;
2389 spin_unlock(&log->l_icloglock);
2390 xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH); 2390 xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH);
2391 XFS_STATS_INC(xs_log_noiclogs); 2391 XFS_STATS_INC(xs_log_noiclogs);
2392 /* Ensure that log writes happen */ 2392
2393 psema(&log->l_flushsema, PINOD); 2393 /* Wait for log writes to have flushed */
2394 sv_wait(&log->l_flush_wait, 0, &log->l_icloglock, 0);
2394 goto restart; 2395 goto restart;
2395 } 2396 }
2396 ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE); 2397
2397 head = &iclog->ic_header; 2398 head = &iclog->ic_header;
2398 2399
2399 atomic_inc(&iclog->ic_refcnt); /* prevents sync */ 2400 atomic_inc(&iclog->ic_refcnt); /* prevents sync */
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 8952a392b5f3..6245913196b4 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -423,10 +423,8 @@ typedef struct log {
423 int l_logBBsize; /* size of log in BB chunks */ 423 int l_logBBsize; /* size of log in BB chunks */
424 424
425 /* The following block of fields are changed while holding icloglock */ 425 /* The following block of fields are changed while holding icloglock */
426 sema_t l_flushsema ____cacheline_aligned_in_smp; 426 sv_t l_flush_wait ____cacheline_aligned_in_smp;
427 /* iclog flushing semaphore */ 427 /* waiting for iclog flush */
428 int l_flushcnt; /* # of procs waiting on this
429 * sema */
430 int l_covered_state;/* state of "covering disk 428 int l_covered_state;/* state of "covering disk
431 * log entries" */ 429 * log entries" */
432 xlog_in_core_t *l_iclog; /* head log queue */ 430 xlog_in_core_t *l_iclog; /* head log queue */
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index e65ab4af0955..9eb722ec744e 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1715,8 +1715,7 @@ xlog_check_buffer_cancelled(
1715 } else { 1715 } else {
1716 prevp->bc_next = bcp->bc_next; 1716 prevp->bc_next = bcp->bc_next;
1717 } 1717 }
1718 kmem_free(bcp, 1718 kmem_free(bcp);
1719 sizeof(xfs_buf_cancel_t));
1720 } 1719 }
1721 } 1720 }
1722 return 1; 1721 return 1;
@@ -2519,7 +2518,7 @@ write_inode_buffer:
2519 2518
2520error: 2519error:
2521 if (need_free) 2520 if (need_free)
2522 kmem_free(in_f, sizeof(*in_f)); 2521 kmem_free(in_f);
2523 return XFS_ERROR(error); 2522 return XFS_ERROR(error);
2524} 2523}
2525 2524
@@ -2830,16 +2829,14 @@ xlog_recover_free_trans(
2830 item = item->ri_next; 2829 item = item->ri_next;
2831 /* Free the regions in the item. */ 2830 /* Free the regions in the item. */
2832 for (i = 0; i < free_item->ri_cnt; i++) { 2831 for (i = 0; i < free_item->ri_cnt; i++) {
2833 kmem_free(free_item->ri_buf[i].i_addr, 2832 kmem_free(free_item->ri_buf[i].i_addr);
2834 free_item->ri_buf[i].i_len);
2835 } 2833 }
2836 /* Free the item itself */ 2834 /* Free the item itself */
2837 kmem_free(free_item->ri_buf, 2835 kmem_free(free_item->ri_buf);
2838 (free_item->ri_total * sizeof(xfs_log_iovec_t))); 2836 kmem_free(free_item);
2839 kmem_free(free_item, sizeof(xlog_recover_item_t));
2840 } while (first_item != item); 2837 } while (first_item != item);
2841 /* Free the transaction recover structure */ 2838 /* Free the transaction recover structure */
2842 kmem_free(trans, sizeof(xlog_recover_t)); 2839 kmem_free(trans);
2843} 2840}
2844 2841
2845STATIC int 2842STATIC int
@@ -3786,8 +3783,7 @@ xlog_do_log_recovery(
3786 error = xlog_do_recovery_pass(log, head_blk, tail_blk, 3783 error = xlog_do_recovery_pass(log, head_blk, tail_blk,
3787 XLOG_RECOVER_PASS1); 3784 XLOG_RECOVER_PASS1);
3788 if (error != 0) { 3785 if (error != 0) {
3789 kmem_free(log->l_buf_cancel_table, 3786 kmem_free(log->l_buf_cancel_table);
3790 XLOG_BC_TABLE_SIZE * sizeof(xfs_buf_cancel_t*));
3791 log->l_buf_cancel_table = NULL; 3787 log->l_buf_cancel_table = NULL;
3792 return error; 3788 return error;
3793 } 3789 }
@@ -3806,8 +3802,7 @@ xlog_do_log_recovery(
3806 } 3802 }
3807#endif /* DEBUG */ 3803#endif /* DEBUG */
3808 3804
3809 kmem_free(log->l_buf_cancel_table, 3805 kmem_free(log->l_buf_cancel_table);
3810 XLOG_BC_TABLE_SIZE * sizeof(xfs_buf_cancel_t*));
3811 log->l_buf_cancel_table = NULL; 3806 log->l_buf_cancel_table = NULL;
3812 3807
3813 return error; 3808 return error;
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index da3988453b71..6c5d1325e7f6 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -47,12 +47,10 @@
47 47
48STATIC int xfs_mount_log_sb(xfs_mount_t *, __int64_t); 48STATIC int xfs_mount_log_sb(xfs_mount_t *, __int64_t);
49STATIC int xfs_uuid_mount(xfs_mount_t *); 49STATIC int xfs_uuid_mount(xfs_mount_t *);
50STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
51STATIC void xfs_unmountfs_wait(xfs_mount_t *); 50STATIC void xfs_unmountfs_wait(xfs_mount_t *);
52 51
53 52
54#ifdef HAVE_PERCPU_SB 53#ifdef HAVE_PERCPU_SB
55STATIC void xfs_icsb_destroy_counters(xfs_mount_t *);
56STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, 54STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
57 int); 55 int);
58STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t, 56STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
@@ -63,7 +61,6 @@ STATIC void xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
63 61
64#else 62#else
65 63
66#define xfs_icsb_destroy_counters(mp) do { } while (0)
67#define xfs_icsb_balance_counter(mp, a, b) do { } while (0) 64#define xfs_icsb_balance_counter(mp, a, b) do { } while (0)
68#define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0) 65#define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0)
69#define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0) 66#define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0)
@@ -126,33 +123,11 @@ static const struct {
126}; 123};
127 124
128/* 125/*
129 * Return a pointer to an initialized xfs_mount structure.
130 */
131xfs_mount_t *
132xfs_mount_init(void)
133{
134 xfs_mount_t *mp;
135
136 mp = kmem_zalloc(sizeof(xfs_mount_t), KM_SLEEP);
137
138 if (xfs_icsb_init_counters(mp)) {
139 mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB;
140 }
141
142 spin_lock_init(&mp->m_sb_lock);
143 mutex_init(&mp->m_ilock);
144 mutex_init(&mp->m_growlock);
145 atomic_set(&mp->m_active_trans, 0);
146
147 return mp;
148}
149
150/*
151 * Free up the resources associated with a mount structure. Assume that 126 * Free up the resources associated with a mount structure. Assume that
152 * the structure was initially zeroed, so we can tell which fields got 127 * the structure was initially zeroed, so we can tell which fields got
153 * initialized. 128 * initialized.
154 */ 129 */
155void 130STATIC void
156xfs_mount_free( 131xfs_mount_free(
157 xfs_mount_t *mp) 132 xfs_mount_t *mp)
158{ 133{
@@ -161,11 +136,8 @@ xfs_mount_free(
161 136
162 for (agno = 0; agno < mp->m_maxagi; agno++) 137 for (agno = 0; agno < mp->m_maxagi; agno++)
163 if (mp->m_perag[agno].pagb_list) 138 if (mp->m_perag[agno].pagb_list)
164 kmem_free(mp->m_perag[agno].pagb_list, 139 kmem_free(mp->m_perag[agno].pagb_list);
165 sizeof(xfs_perag_busy_t) * 140 kmem_free(mp->m_perag);
166 XFS_PAGB_NUM_SLOTS);
167 kmem_free(mp->m_perag,
168 sizeof(xfs_perag_t) * mp->m_sb.sb_agcount);
169 } 141 }
170 142
171 spinlock_destroy(&mp->m_ail_lock); 143 spinlock_destroy(&mp->m_ail_lock);
@@ -176,13 +148,11 @@ xfs_mount_free(
176 XFS_QM_DONE(mp); 148 XFS_QM_DONE(mp);
177 149
178 if (mp->m_fsname != NULL) 150 if (mp->m_fsname != NULL)
179 kmem_free(mp->m_fsname, mp->m_fsname_len); 151 kmem_free(mp->m_fsname);
180 if (mp->m_rtname != NULL) 152 if (mp->m_rtname != NULL)
181 kmem_free(mp->m_rtname, strlen(mp->m_rtname) + 1); 153 kmem_free(mp->m_rtname);
182 if (mp->m_logname != NULL) 154 if (mp->m_logname != NULL)
183 kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); 155 kmem_free(mp->m_logname);
184
185 xfs_icsb_destroy_counters(mp);
186} 156}
187 157
188/* 158/*
@@ -288,6 +258,19 @@ xfs_mount_validate_sb(
288 return XFS_ERROR(EFSCORRUPTED); 258 return XFS_ERROR(EFSCORRUPTED);
289 } 259 }
290 260
261 /*
262 * Until this is fixed only page-sized or smaller data blocks work.
263 */
264 if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
265 xfs_fs_mount_cmn_err(flags,
266 "file system with blocksize %d bytes",
267 sbp->sb_blocksize);
268 xfs_fs_mount_cmn_err(flags,
269 "only pagesize (%ld) or less will currently work.",
270 PAGE_SIZE);
271 return XFS_ERROR(ENOSYS);
272 }
273
291 if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || 274 if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
292 xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { 275 xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
293 xfs_fs_mount_cmn_err(flags, 276 xfs_fs_mount_cmn_err(flags,
@@ -309,19 +292,6 @@ xfs_mount_validate_sb(
309 return XFS_ERROR(ENOSYS); 292 return XFS_ERROR(ENOSYS);
310 } 293 }
311 294
312 /*
313 * Until this is fixed only page-sized or smaller data blocks work.
314 */
315 if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
316 xfs_fs_mount_cmn_err(flags,
317 "file system with blocksize %d bytes",
318 sbp->sb_blocksize);
319 xfs_fs_mount_cmn_err(flags,
320 "only pagesize (%ld) or less will currently work.",
321 PAGE_SIZE);
322 return XFS_ERROR(ENOSYS);
323 }
324
325 return 0; 295 return 0;
326} 296}
327 297
@@ -994,9 +964,19 @@ xfs_mountfs(
994 * Re-check for ATTR2 in case it was found in bad_features2 964 * Re-check for ATTR2 in case it was found in bad_features2
995 * slot. 965 * slot.
996 */ 966 */
997 if (xfs_sb_version_hasattr2(&mp->m_sb)) 967 if (xfs_sb_version_hasattr2(&mp->m_sb) &&
968 !(mp->m_flags & XFS_MOUNT_NOATTR2))
998 mp->m_flags |= XFS_MOUNT_ATTR2; 969 mp->m_flags |= XFS_MOUNT_ATTR2;
970 }
971
972 if (xfs_sb_version_hasattr2(&mp->m_sb) &&
973 (mp->m_flags & XFS_MOUNT_NOATTR2)) {
974 xfs_sb_version_removeattr2(&mp->m_sb);
975 update_flags |= XFS_SB_FEATURES2;
999 976
977 /* update sb_versionnum for the clearing of the morebits */
978 if (!sbp->sb_features2)
979 update_flags |= XFS_SB_VERSIONNUM;
1000 } 980 }
1001 981
1002 /* 982 /*
@@ -1255,15 +1235,13 @@ xfs_mountfs(
1255 error2: 1235 error2:
1256 for (agno = 0; agno < sbp->sb_agcount; agno++) 1236 for (agno = 0; agno < sbp->sb_agcount; agno++)
1257 if (mp->m_perag[agno].pagb_list) 1237 if (mp->m_perag[agno].pagb_list)
1258 kmem_free(mp->m_perag[agno].pagb_list, 1238 kmem_free(mp->m_perag[agno].pagb_list);
1259 sizeof(xfs_perag_busy_t) * XFS_PAGB_NUM_SLOTS); 1239 kmem_free(mp->m_perag);
1260 kmem_free(mp->m_perag, sbp->sb_agcount * sizeof(xfs_perag_t));
1261 mp->m_perag = NULL; 1240 mp->m_perag = NULL;
1262 /* FALLTHROUGH */ 1241 /* FALLTHROUGH */
1263 error1: 1242 error1:
1264 if (uuid_mounted) 1243 if (uuid_mounted)
1265 xfs_uuid_unmount(mp); 1244 uuid_table_remove(&mp->m_sb.sb_uuid);
1266 xfs_freesb(mp);
1267 return error; 1245 return error;
1268} 1246}
1269 1247
@@ -1274,7 +1252,7 @@ xfs_mountfs(
1274 * log and makes sure that incore structures are freed. 1252 * log and makes sure that incore structures are freed.
1275 */ 1253 */
1276int 1254int
1277xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) 1255xfs_unmountfs(xfs_mount_t *mp)
1278{ 1256{
1279 __uint64_t resblks; 1257 __uint64_t resblks;
1280 int error = 0; 1258 int error = 0;
@@ -1341,9 +1319,8 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1341 */ 1319 */
1342 ASSERT(mp->m_inodes == NULL); 1320 ASSERT(mp->m_inodes == NULL);
1343 1321
1344 xfs_unmountfs_close(mp, cr);
1345 if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) 1322 if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
1346 xfs_uuid_unmount(mp); 1323 uuid_table_remove(&mp->m_sb.sb_uuid);
1347 1324
1348#if defined(DEBUG) || defined(INDUCE_IO_ERROR) 1325#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
1349 xfs_errortag_clearall(mp, 0); 1326 xfs_errortag_clearall(mp, 0);
@@ -1352,16 +1329,6 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1352 return 0; 1329 return 0;
1353} 1330}
1354 1331
1355void
1356xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
1357{
1358 if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
1359 xfs_free_buftarg(mp->m_logdev_targp, 1);
1360 if (mp->m_rtdev_targp)
1361 xfs_free_buftarg(mp->m_rtdev_targp, 1);
1362 xfs_free_buftarg(mp->m_ddev_targp, 0);
1363}
1364
1365STATIC void 1332STATIC void
1366xfs_unmountfs_wait(xfs_mount_t *mp) 1333xfs_unmountfs_wait(xfs_mount_t *mp)
1367{ 1334{
@@ -1905,16 +1872,6 @@ xfs_uuid_mount(
1905} 1872}
1906 1873
1907/* 1874/*
1908 * Remove filesystem from the UUID table.
1909 */
1910STATIC void
1911xfs_uuid_unmount(
1912 xfs_mount_t *mp)
1913{
1914 uuid_table_remove(&mp->m_sb.sb_uuid);
1915}
1916
1917/*
1918 * Used to log changes to the superblock unit and width fields which could 1875 * Used to log changes to the superblock unit and width fields which could
1919 * be altered by the mount options, as well as any potential sb_features2 1876 * be altered by the mount options, as well as any potential sb_features2
1920 * fixup. Only the first superblock is updated. 1877 * fixup. Only the first superblock is updated.
@@ -1928,7 +1885,8 @@ xfs_mount_log_sb(
1928 int error; 1885 int error;
1929 1886
1930 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID | 1887 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
1931 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2)); 1888 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2 |
1889 XFS_SB_VERSIONNUM));
1932 1890
1933 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT); 1891 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
1934 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, 1892 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
@@ -2109,7 +2067,7 @@ xfs_icsb_reinit_counters(
2109 xfs_icsb_unlock(mp); 2067 xfs_icsb_unlock(mp);
2110} 2068}
2111 2069
2112STATIC void 2070void
2113xfs_icsb_destroy_counters( 2071xfs_icsb_destroy_counters(
2114 xfs_mount_t *mp) 2072 xfs_mount_t *mp)
2115{ 2073{
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 63e0693a358a..5269bd6e3df0 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -61,6 +61,7 @@ struct xfs_bmap_free;
61struct xfs_extdelta; 61struct xfs_extdelta;
62struct xfs_swapext; 62struct xfs_swapext;
63struct xfs_mru_cache; 63struct xfs_mru_cache;
64struct xfs_nameops;
64 65
65/* 66/*
66 * Prototypes and functions for the Data Migration subsystem. 67 * Prototypes and functions for the Data Migration subsystem.
@@ -210,12 +211,14 @@ typedef struct xfs_icsb_cnts {
210 211
211extern int xfs_icsb_init_counters(struct xfs_mount *); 212extern int xfs_icsb_init_counters(struct xfs_mount *);
212extern void xfs_icsb_reinit_counters(struct xfs_mount *); 213extern void xfs_icsb_reinit_counters(struct xfs_mount *);
214extern void xfs_icsb_destroy_counters(struct xfs_mount *);
213extern void xfs_icsb_sync_counters(struct xfs_mount *, int); 215extern void xfs_icsb_sync_counters(struct xfs_mount *, int);
214extern void xfs_icsb_sync_counters_locked(struct xfs_mount *, int); 216extern void xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
215 217
216#else 218#else
217#define xfs_icsb_init_counters(mp) (0) 219#define xfs_icsb_init_counters(mp) (0)
218#define xfs_icsb_reinit_counters(mp) do { } while (0) 220#define xfs_icsb_destroy_counters(mp) do { } while (0)
221#define xfs_icsb_reinit_counters(mp) do { } while (0)
219#define xfs_icsb_sync_counters(mp, flags) do { } while (0) 222#define xfs_icsb_sync_counters(mp, flags) do { } while (0)
220#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0) 223#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
221#endif 224#endif
@@ -313,6 +316,7 @@ typedef struct xfs_mount {
313 __uint8_t m_inode_quiesce;/* call quiesce on new inodes. 316 __uint8_t m_inode_quiesce;/* call quiesce on new inodes.
314 field governed by m_ilock */ 317 field governed by m_ilock */
315 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ 318 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
319 const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */
316 int m_dirblksize; /* directory block sz--bytes */ 320 int m_dirblksize; /* directory block sz--bytes */
317 int m_dirblkfsbs; /* directory block sz--fsbs */ 321 int m_dirblkfsbs; /* directory block sz--fsbs */
318 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ 322 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
@@ -378,6 +382,7 @@ typedef struct xfs_mount {
378 counters */ 382 counters */
379#define XFS_MOUNT_FILESTREAMS (1ULL << 24) /* enable the filestreams 383#define XFS_MOUNT_FILESTREAMS (1ULL << 24) /* enable the filestreams
380 allocator */ 384 allocator */
385#define XFS_MOUNT_NOATTR2 (1ULL << 25) /* disable use of attr2 format */
381 386
382 387
383/* 388/*
@@ -510,15 +515,12 @@ typedef struct xfs_mod_sb {
510#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock)) 515#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock))
511#define XFS_MOUNT_IUNLOCK(mp) mutex_unlock(&((mp)->m_ilock)) 516#define XFS_MOUNT_IUNLOCK(mp) mutex_unlock(&((mp)->m_ilock))
512 517
513extern xfs_mount_t *xfs_mount_init(void);
514extern void xfs_mod_sb(xfs_trans_t *, __int64_t); 518extern void xfs_mod_sb(xfs_trans_t *, __int64_t);
515extern int xfs_log_sbcount(xfs_mount_t *, uint); 519extern int xfs_log_sbcount(xfs_mount_t *, uint);
516extern void xfs_mount_free(xfs_mount_t *mp);
517extern int xfs_mountfs(xfs_mount_t *mp, int); 520extern int xfs_mountfs(xfs_mount_t *mp, int);
518extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); 521extern void xfs_mountfs_check_barriers(xfs_mount_t *mp);
519 522
520extern int xfs_unmountfs(xfs_mount_t *, struct cred *); 523extern int xfs_unmountfs(xfs_mount_t *);
521extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *);
522extern int xfs_unmountfs_writesb(xfs_mount_t *); 524extern int xfs_unmountfs_writesb(xfs_mount_t *);
523extern int xfs_unmount_flush(xfs_mount_t *, int); 525extern int xfs_unmount_flush(xfs_mount_t *, int);
524extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int); 526extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
@@ -544,9 +546,6 @@ extern void xfs_qmops_put(struct xfs_mount *);
544 546
545extern struct xfs_dmops xfs_dmcore_xfs; 547extern struct xfs_dmops xfs_dmcore_xfs;
546 548
547extern int xfs_init(void);
548extern void xfs_cleanup(void);
549
550#endif /* __KERNEL__ */ 549#endif /* __KERNEL__ */
551 550
552#endif /* __XFS_MOUNT_H__ */ 551#endif /* __XFS_MOUNT_H__ */
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
index a0b2c0a2589a..afee7eb24323 100644
--- a/fs/xfs/xfs_mru_cache.c
+++ b/fs/xfs/xfs_mru_cache.c
@@ -307,15 +307,18 @@ xfs_mru_cache_init(void)
307 xfs_mru_elem_zone = kmem_zone_init(sizeof(xfs_mru_cache_elem_t), 307 xfs_mru_elem_zone = kmem_zone_init(sizeof(xfs_mru_cache_elem_t),
308 "xfs_mru_cache_elem"); 308 "xfs_mru_cache_elem");
309 if (!xfs_mru_elem_zone) 309 if (!xfs_mru_elem_zone)
310 return ENOMEM; 310 goto out;
311 311
312 xfs_mru_reap_wq = create_singlethread_workqueue("xfs_mru_cache"); 312 xfs_mru_reap_wq = create_singlethread_workqueue("xfs_mru_cache");
313 if (!xfs_mru_reap_wq) { 313 if (!xfs_mru_reap_wq)
314 kmem_zone_destroy(xfs_mru_elem_zone); 314 goto out_destroy_mru_elem_zone;
315 return ENOMEM;
316 }
317 315
318 return 0; 316 return 0;
317
318 out_destroy_mru_elem_zone:
319 kmem_zone_destroy(xfs_mru_elem_zone);
320 out:
321 return -ENOMEM;
319} 322}
320 323
321void 324void
@@ -382,9 +385,9 @@ xfs_mru_cache_create(
382 385
383exit: 386exit:
384 if (err && mru && mru->lists) 387 if (err && mru && mru->lists)
385 kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists)); 388 kmem_free(mru->lists);
386 if (err && mru) 389 if (err && mru)
387 kmem_free(mru, sizeof(*mru)); 390 kmem_free(mru);
388 391
389 return err; 392 return err;
390} 393}
@@ -424,8 +427,8 @@ xfs_mru_cache_destroy(
424 427
425 xfs_mru_cache_flush(mru); 428 xfs_mru_cache_flush(mru);
426 429
427 kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists)); 430 kmem_free(mru->lists);
428 kmem_free(mru, sizeof(*mru)); 431 kmem_free(mru);
429} 432}
430 433
431/* 434/*
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index d8063e1ad298..d700dacdb10e 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -336,22 +336,18 @@ xfs_rename(
336 ASSERT(error != EEXIST); 336 ASSERT(error != EEXIST);
337 if (error) 337 if (error)
338 goto abort_return; 338 goto abort_return;
339 xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
340
341 } else {
342 /*
343 * We always want to hit the ctime on the source inode.
344 * We do it in the if clause above for the 'new_parent &&
345 * src_is_directory' case, and here we get all the other
346 * cases. This isn't strictly required by the standards
347 * since the source inode isn't really being changed,
348 * but old unix file systems did it and some incremental
349 * backup programs won't work without it.
350 */
351 xfs_ichgtime(src_ip, XFS_ICHGTIME_CHG);
352 } 339 }
353 340
354 /* 341 /*
342 * We always want to hit the ctime on the source inode.
343 *
344 * This isn't strictly required by the standards since the source
345 * inode isn't really being changed, but old unix file systems did
346 * it and some incremental backup programs won't work without it.
347 */
348 xfs_ichgtime(src_ip, XFS_ICHGTIME_CHG);
349
350 /*
355 * Adjust the link count on src_dp. This is necessary when 351 * Adjust the link count on src_dp. This is necessary when
356 * renaming a directory, either within one parent when 352 * renaming a directory, either within one parent when
357 * the target existed, or across two parent directories. 353 * the target existed, or across two parent directories.
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index a0dc6e5bc5b9..bf87a5913504 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -2062,7 +2062,7 @@ xfs_growfs_rt(
2062 /* 2062 /*
2063 * Free the fake mp structure. 2063 * Free the fake mp structure.
2064 */ 2064 */
2065 kmem_free(nmp, sizeof(*nmp)); 2065 kmem_free(nmp);
2066 2066
2067 return error; 2067 return error;
2068} 2068}
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index d904efe7f871..3f8cf1587f4c 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -46,10 +46,12 @@ struct xfs_mount;
46#define XFS_SB_VERSION_SECTORBIT 0x0800 46#define XFS_SB_VERSION_SECTORBIT 0x0800
47#define XFS_SB_VERSION_EXTFLGBIT 0x1000 47#define XFS_SB_VERSION_EXTFLGBIT 0x1000
48#define XFS_SB_VERSION_DIRV2BIT 0x2000 48#define XFS_SB_VERSION_DIRV2BIT 0x2000
49#define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */
49#define XFS_SB_VERSION_MOREBITSBIT 0x8000 50#define XFS_SB_VERSION_MOREBITSBIT 0x8000
50#define XFS_SB_VERSION_OKSASHFBITS \ 51#define XFS_SB_VERSION_OKSASHFBITS \
51 (XFS_SB_VERSION_EXTFLGBIT | \ 52 (XFS_SB_VERSION_EXTFLGBIT | \
52 XFS_SB_VERSION_DIRV2BIT) 53 XFS_SB_VERSION_DIRV2BIT | \
54 XFS_SB_VERSION_BORGBIT)
53#define XFS_SB_VERSION_OKREALFBITS \ 55#define XFS_SB_VERSION_OKREALFBITS \
54 (XFS_SB_VERSION_ATTRBIT | \ 56 (XFS_SB_VERSION_ATTRBIT | \
55 XFS_SB_VERSION_NLINKBIT | \ 57 XFS_SB_VERSION_NLINKBIT | \
@@ -437,6 +439,12 @@ static inline int xfs_sb_version_hassector(xfs_sb_t *sbp)
437 ((sbp)->sb_versionnum & XFS_SB_VERSION_SECTORBIT); 439 ((sbp)->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
438} 440}
439 441
442static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp)
443{
444 return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
445 (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT);
446}
447
440static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) 448static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
441{ 449{
442 return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ 450 return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
@@ -473,6 +481,13 @@ static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
473 ((sbp)->sb_features2 | XFS_SB_VERSION2_ATTR2BIT))); 481 ((sbp)->sb_features2 | XFS_SB_VERSION2_ATTR2BIT)));
474} 482}
475 483
484static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp)
485{
486 sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;
487 if (!sbp->sb_features2)
488 sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
489}
490
476/* 491/*
477 * end of superblock version macros 492 * end of superblock version macros
478 */ 493 */
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 140386434aa3..e4ebddd3c500 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -889,7 +889,7 @@ shut_us_down:
889 889
890 tp->t_commit_lsn = commit_lsn; 890 tp->t_commit_lsn = commit_lsn;
891 if (nvec > XFS_TRANS_LOGVEC_COUNT) { 891 if (nvec > XFS_TRANS_LOGVEC_COUNT) {
892 kmem_free(log_vector, nvec * sizeof(xfs_log_iovec_t)); 892 kmem_free(log_vector);
893 } 893 }
894 894
895 /* 895 /*
@@ -1265,7 +1265,7 @@ xfs_trans_committed(
1265 ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); 1265 ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
1266 xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); 1266 xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag);
1267 next_licp = licp->lic_next; 1267 next_licp = licp->lic_next;
1268 kmem_free(licp, sizeof(xfs_log_item_chunk_t)); 1268 kmem_free(licp);
1269 licp = next_licp; 1269 licp = next_licp;
1270 } 1270 }
1271 1271
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 4c70bf5e9985..2a1c0f071f91 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -291,7 +291,7 @@ xfs_trans_inode_broot_debug(
291 iip = ip->i_itemp; 291 iip = ip->i_itemp;
292 if (iip->ili_root_size != 0) { 292 if (iip->ili_root_size != 0) {
293 ASSERT(iip->ili_orig_root != NULL); 293 ASSERT(iip->ili_orig_root != NULL);
294 kmem_free(iip->ili_orig_root, iip->ili_root_size); 294 kmem_free(iip->ili_orig_root);
295 iip->ili_root_size = 0; 295 iip->ili_root_size = 0;
296 iip->ili_orig_root = NULL; 296 iip->ili_orig_root = NULL;
297 } 297 }
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
index 66a09f0d894b..db5c83595526 100644
--- a/fs/xfs/xfs_trans_item.c
+++ b/fs/xfs/xfs_trans_item.c
@@ -161,7 +161,7 @@ xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
161 licpp = &((*licpp)->lic_next); 161 licpp = &((*licpp)->lic_next);
162 } 162 }
163 *licpp = licp->lic_next; 163 *licpp = licp->lic_next;
164 kmem_free(licp, sizeof(xfs_log_item_chunk_t)); 164 kmem_free(licp);
165 tp->t_items_free -= XFS_LIC_NUM_SLOTS; 165 tp->t_items_free -= XFS_LIC_NUM_SLOTS;
166 } 166 }
167} 167}
@@ -314,7 +314,7 @@ xfs_trans_free_items(
314 ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); 314 ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
315 (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN); 315 (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN);
316 next_licp = licp->lic_next; 316 next_licp = licp->lic_next;
317 kmem_free(licp, sizeof(xfs_log_item_chunk_t)); 317 kmem_free(licp);
318 licp = next_licp; 318 licp = next_licp;
319 } 319 }
320 320
@@ -363,7 +363,7 @@ xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn)
363 next_licp = licp->lic_next; 363 next_licp = licp->lic_next;
364 if (XFS_LIC_ARE_ALL_FREE(licp)) { 364 if (XFS_LIC_ARE_ALL_FREE(licp)) {
365 *licpp = next_licp; 365 *licpp = next_licp;
366 kmem_free(licp, sizeof(xfs_log_item_chunk_t)); 366 kmem_free(licp);
367 freed -= XFS_LIC_NUM_SLOTS; 367 freed -= XFS_LIC_NUM_SLOTS;
368 } else { 368 } else {
369 licpp = &(licp->lic_next); 369 licpp = &(licp->lic_next);
@@ -530,7 +530,7 @@ xfs_trans_free_busy(xfs_trans_t *tp)
530 lbcp = tp->t_busy.lbc_next; 530 lbcp = tp->t_busy.lbc_next;
531 while (lbcp != NULL) { 531 while (lbcp != NULL) {
532 lbcq = lbcp->lbc_next; 532 lbcq = lbcp->lbc_next;
533 kmem_free(lbcp, sizeof(xfs_log_busy_chunk_t)); 533 kmem_free(lbcp);
534 lbcp = lbcq; 534 lbcp = lbcq;
535 } 535 }
536 536
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 30bacd8bb0e5..4a9a43315a86 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -58,586 +58,6 @@
58#include "xfs_utils.h" 58#include "xfs_utils.h"
59 59
60 60
61int __init
62xfs_init(void)
63{
64#ifdef XFS_DABUF_DEBUG
65 extern spinlock_t xfs_dabuf_global_lock;
66 spin_lock_init(&xfs_dabuf_global_lock);
67#endif
68
69 /*
70 * Initialize all of the zone allocators we use.
71 */
72 xfs_log_ticket_zone = kmem_zone_init(sizeof(xlog_ticket_t),
73 "xfs_log_ticket");
74 xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
75 "xfs_bmap_free_item");
76 xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
77 "xfs_btree_cur");
78 xfs_da_state_zone = kmem_zone_init(sizeof(xfs_da_state_t),
79 "xfs_da_state");
80 xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
81 xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
82 xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
83 xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
84 xfs_mru_cache_init();
85 xfs_filestream_init();
86
87 /*
88 * The size of the zone allocated buf log item is the maximum
89 * size possible under XFS. This wastes a little bit of memory,
90 * but it is much faster.
91 */
92 xfs_buf_item_zone =
93 kmem_zone_init((sizeof(xfs_buf_log_item_t) +
94 (((XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK) /
95 NBWORD) * sizeof(int))),
96 "xfs_buf_item");
97 xfs_efd_zone =
98 kmem_zone_init((sizeof(xfs_efd_log_item_t) +
99 ((XFS_EFD_MAX_FAST_EXTENTS - 1) *
100 sizeof(xfs_extent_t))),
101 "xfs_efd_item");
102 xfs_efi_zone =
103 kmem_zone_init((sizeof(xfs_efi_log_item_t) +
104 ((XFS_EFI_MAX_FAST_EXTENTS - 1) *
105 sizeof(xfs_extent_t))),
106 "xfs_efi_item");
107
108 /*
109 * These zones warrant special memory allocator hints
110 */
111 xfs_inode_zone =
112 kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode",
113 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
114 KM_ZONE_SPREAD, NULL);
115 xfs_ili_zone =
116 kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
117 KM_ZONE_SPREAD, NULL);
118
119 /*
120 * Allocate global trace buffers.
121 */
122#ifdef XFS_ALLOC_TRACE
123 xfs_alloc_trace_buf = ktrace_alloc(XFS_ALLOC_TRACE_SIZE, KM_SLEEP);
124#endif
125#ifdef XFS_BMAP_TRACE
126 xfs_bmap_trace_buf = ktrace_alloc(XFS_BMAP_TRACE_SIZE, KM_SLEEP);
127#endif
128#ifdef XFS_BMBT_TRACE
129 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);
130#endif
131#ifdef XFS_ATTR_TRACE
132 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);
133#endif
134#ifdef XFS_DIR2_TRACE
135 xfs_dir2_trace_buf = ktrace_alloc(XFS_DIR2_GTRACE_SIZE, KM_SLEEP);
136#endif
137
138 xfs_dir_startup();
139
140#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
141 xfs_error_test_init();
142#endif /* DEBUG || INDUCE_IO_ERROR */
143
144 xfs_init_procfs();
145 xfs_sysctl_register();
146 return 0;
147}
148
149void __exit
150xfs_cleanup(void)
151{
152 extern kmem_zone_t *xfs_inode_zone;
153 extern kmem_zone_t *xfs_efd_zone;
154 extern kmem_zone_t *xfs_efi_zone;
155
156 xfs_cleanup_procfs();
157 xfs_sysctl_unregister();
158 xfs_filestream_uninit();
159 xfs_mru_cache_uninit();
160 xfs_acl_zone_destroy(xfs_acl_zone);
161
162#ifdef XFS_DIR2_TRACE
163 ktrace_free(xfs_dir2_trace_buf);
164#endif
165#ifdef XFS_ATTR_TRACE
166 ktrace_free(xfs_attr_trace_buf);
167#endif
168#ifdef XFS_BMBT_TRACE
169 ktrace_free(xfs_bmbt_trace_buf);
170#endif
171#ifdef XFS_BMAP_TRACE
172 ktrace_free(xfs_bmap_trace_buf);
173#endif
174#ifdef XFS_ALLOC_TRACE
175 ktrace_free(xfs_alloc_trace_buf);
176#endif
177
178 kmem_zone_destroy(xfs_bmap_free_item_zone);
179 kmem_zone_destroy(xfs_btree_cur_zone);
180 kmem_zone_destroy(xfs_inode_zone);
181 kmem_zone_destroy(xfs_trans_zone);
182 kmem_zone_destroy(xfs_da_state_zone);
183 kmem_zone_destroy(xfs_dabuf_zone);
184 kmem_zone_destroy(xfs_buf_item_zone);
185 kmem_zone_destroy(xfs_efd_zone);
186 kmem_zone_destroy(xfs_efi_zone);
187 kmem_zone_destroy(xfs_ifork_zone);
188 kmem_zone_destroy(xfs_ili_zone);
189 kmem_zone_destroy(xfs_log_ticket_zone);
190}
191
192/*
193 * xfs_start_flags
194 *
195 * This function fills in xfs_mount_t fields based on mount args.
196 * Note: the superblock has _not_ yet been read in.
197 */
198STATIC int
199xfs_start_flags(
200 struct xfs_mount_args *ap,
201 struct xfs_mount *mp)
202{
203 /* Values are in BBs */
204 if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
205 /*
206 * At this point the superblock has not been read
207 * in, therefore we do not know the block size.
208 * Before the mount call ends we will convert
209 * these to FSBs.
210 */
211 mp->m_dalign = ap->sunit;
212 mp->m_swidth = ap->swidth;
213 }
214
215 if (ap->logbufs != -1 &&
216 ap->logbufs != 0 &&
217 (ap->logbufs < XLOG_MIN_ICLOGS ||
218 ap->logbufs > XLOG_MAX_ICLOGS)) {
219 cmn_err(CE_WARN,
220 "XFS: invalid logbufs value: %d [not %d-%d]",
221 ap->logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
222 return XFS_ERROR(EINVAL);
223 }
224 mp->m_logbufs = ap->logbufs;
225 if (ap->logbufsize != -1 &&
226 ap->logbufsize != 0 &&
227 (ap->logbufsize < XLOG_MIN_RECORD_BSIZE ||
228 ap->logbufsize > XLOG_MAX_RECORD_BSIZE ||
229 !is_power_of_2(ap->logbufsize))) {
230 cmn_err(CE_WARN,
231 "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
232 ap->logbufsize);
233 return XFS_ERROR(EINVAL);
234 }
235 mp->m_logbsize = ap->logbufsize;
236 mp->m_fsname_len = strlen(ap->fsname) + 1;
237 mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
238 strcpy(mp->m_fsname, ap->fsname);
239 if (ap->rtname[0]) {
240 mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP);
241 strcpy(mp->m_rtname, ap->rtname);
242 }
243 if (ap->logname[0]) {
244 mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP);
245 strcpy(mp->m_logname, ap->logname);
246 }
247
248 if (ap->flags & XFSMNT_WSYNC)
249 mp->m_flags |= XFS_MOUNT_WSYNC;
250#if XFS_BIG_INUMS
251 if (ap->flags & XFSMNT_INO64) {
252 mp->m_flags |= XFS_MOUNT_INO64;
253 mp->m_inoadd = XFS_INO64_OFFSET;
254 }
255#endif
256 if (ap->flags & XFSMNT_RETERR)
257 mp->m_flags |= XFS_MOUNT_RETERR;
258 if (ap->flags & XFSMNT_NOALIGN)
259 mp->m_flags |= XFS_MOUNT_NOALIGN;
260 if (ap->flags & XFSMNT_SWALLOC)
261 mp->m_flags |= XFS_MOUNT_SWALLOC;
262 if (ap->flags & XFSMNT_OSYNCISOSYNC)
263 mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC;
264 if (ap->flags & XFSMNT_32BITINODES)
265 mp->m_flags |= XFS_MOUNT_32BITINODES;
266
267 if (ap->flags & XFSMNT_IOSIZE) {
268 if (ap->iosizelog > XFS_MAX_IO_LOG ||
269 ap->iosizelog < XFS_MIN_IO_LOG) {
270 cmn_err(CE_WARN,
271 "XFS: invalid log iosize: %d [not %d-%d]",
272 ap->iosizelog, XFS_MIN_IO_LOG,
273 XFS_MAX_IO_LOG);
274 return XFS_ERROR(EINVAL);
275 }
276
277 mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;
278 mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
279 }
280
281 if (ap->flags & XFSMNT_IKEEP)
282 mp->m_flags |= XFS_MOUNT_IKEEP;
283 if (ap->flags & XFSMNT_DIRSYNC)
284 mp->m_flags |= XFS_MOUNT_DIRSYNC;
285 if (ap->flags & XFSMNT_ATTR2)
286 mp->m_flags |= XFS_MOUNT_ATTR2;
287
288 if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE)
289 mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
290
291 /*
292 * no recovery flag requires a read-only mount
293 */
294 if (ap->flags & XFSMNT_NORECOVERY) {
295 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
296 cmn_err(CE_WARN,
297 "XFS: tried to mount a FS read-write without recovery!");
298 return XFS_ERROR(EINVAL);
299 }
300 mp->m_flags |= XFS_MOUNT_NORECOVERY;
301 }
302
303 if (ap->flags & XFSMNT_NOUUID)
304 mp->m_flags |= XFS_MOUNT_NOUUID;
305 if (ap->flags & XFSMNT_BARRIER)
306 mp->m_flags |= XFS_MOUNT_BARRIER;
307 else
308 mp->m_flags &= ~XFS_MOUNT_BARRIER;
309
310 if (ap->flags2 & XFSMNT2_FILESTREAMS)
311 mp->m_flags |= XFS_MOUNT_FILESTREAMS;
312
313 if (ap->flags & XFSMNT_DMAPI)
314 mp->m_flags |= XFS_MOUNT_DMAPI;
315 return 0;
316}
317
318/*
319 * This function fills in xfs_mount_t fields based on mount args.
320 * Note: the superblock _has_ now been read in.
321 */
322STATIC int
323xfs_finish_flags(
324 struct xfs_mount_args *ap,
325 struct xfs_mount *mp)
326{
327 int ronly = (mp->m_flags & XFS_MOUNT_RDONLY);
328
329 /* Fail a mount where the logbuf is smaller then the log stripe */
330 if (xfs_sb_version_haslogv2(&mp->m_sb)) {
331 if ((ap->logbufsize <= 0) &&
332 (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {
333 mp->m_logbsize = mp->m_sb.sb_logsunit;
334 } else if (ap->logbufsize > 0 &&
335 ap->logbufsize < mp->m_sb.sb_logsunit) {
336 cmn_err(CE_WARN,
337 "XFS: logbuf size must be greater than or equal to log stripe size");
338 return XFS_ERROR(EINVAL);
339 }
340 } else {
341 /* Fail a mount if the logbuf is larger than 32K */
342 if (ap->logbufsize > XLOG_BIG_RECORD_BSIZE) {
343 cmn_err(CE_WARN,
344 "XFS: logbuf size for version 1 logs must be 16K or 32K");
345 return XFS_ERROR(EINVAL);
346 }
347 }
348
349 if (xfs_sb_version_hasattr2(&mp->m_sb))
350 mp->m_flags |= XFS_MOUNT_ATTR2;
351
352 /*
353 * prohibit r/w mounts of read-only filesystems
354 */
355 if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
356 cmn_err(CE_WARN,
357 "XFS: cannot mount a read-only filesystem as read-write");
358 return XFS_ERROR(EROFS);
359 }
360
361 /*
362 * check for shared mount.
363 */
364 if (ap->flags & XFSMNT_SHARED) {
365 if (!xfs_sb_version_hasshared(&mp->m_sb))
366 return XFS_ERROR(EINVAL);
367
368 /*
369 * For IRIX 6.5, shared mounts must have the shared
370 * version bit set, have the persistent readonly
371 * field set, must be version 0 and can only be mounted
372 * read-only.
373 */
374 if (!ronly || !(mp->m_sb.sb_flags & XFS_SBF_READONLY) ||
375 (mp->m_sb.sb_shared_vn != 0))
376 return XFS_ERROR(EINVAL);
377
378 mp->m_flags |= XFS_MOUNT_SHARED;
379
380 /*
381 * Shared XFS V0 can't deal with DMI. Return EINVAL.
382 */
383 if (mp->m_sb.sb_shared_vn == 0 && (ap->flags & XFSMNT_DMAPI))
384 return XFS_ERROR(EINVAL);
385 }
386
387 if (ap->flags & XFSMNT_UQUOTA) {
388 mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
389 if (ap->flags & XFSMNT_UQUOTAENF)
390 mp->m_qflags |= XFS_UQUOTA_ENFD;
391 }
392
393 if (ap->flags & XFSMNT_GQUOTA) {
394 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
395 if (ap->flags & XFSMNT_GQUOTAENF)
396 mp->m_qflags |= XFS_OQUOTA_ENFD;
397 } else if (ap->flags & XFSMNT_PQUOTA) {
398 mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
399 if (ap->flags & XFSMNT_PQUOTAENF)
400 mp->m_qflags |= XFS_OQUOTA_ENFD;
401 }
402
403 return 0;
404}
405
406/*
407 * xfs_mount
408 *
409 * The file system configurations are:
410 * (1) device (partition) with data and internal log
411 * (2) logical volume with data and log subvolumes.
412 * (3) logical volume with data, log, and realtime subvolumes.
413 *
414 * We only have to handle opening the log and realtime volumes here if
415 * they are present. The data subvolume has already been opened by
416 * get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev.
417 */
418int
419xfs_mount(
420 struct xfs_mount *mp,
421 struct xfs_mount_args *args,
422 cred_t *credp)
423{
424 struct block_device *ddev, *logdev, *rtdev;
425 int flags = 0, error;
426
427 ddev = mp->m_super->s_bdev;
428 logdev = rtdev = NULL;
429
430 error = xfs_dmops_get(mp, args);
431 if (error)
432 return error;
433 error = xfs_qmops_get(mp, args);
434 if (error)
435 return error;
436
437 if (args->flags & XFSMNT_QUIET)
438 flags |= XFS_MFSI_QUIET;
439
440 /*
441 * Open real time and log devices - order is important.
442 */
443 if (args->logname[0]) {
444 error = xfs_blkdev_get(mp, args->logname, &logdev);
445 if (error)
446 return error;
447 }
448 if (args->rtname[0]) {
449 error = xfs_blkdev_get(mp, args->rtname, &rtdev);
450 if (error) {
451 xfs_blkdev_put(logdev);
452 return error;
453 }
454
455 if (rtdev == ddev || rtdev == logdev) {
456 cmn_err(CE_WARN,
457 "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
458 xfs_blkdev_put(logdev);
459 xfs_blkdev_put(rtdev);
460 return EINVAL;
461 }
462 }
463
464 /*
465 * Setup xfs_mount buffer target pointers
466 */
467 error = ENOMEM;
468 mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
469 if (!mp->m_ddev_targp) {
470 xfs_blkdev_put(logdev);
471 xfs_blkdev_put(rtdev);
472 return error;
473 }
474 if (rtdev) {
475 mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
476 if (!mp->m_rtdev_targp) {
477 xfs_blkdev_put(logdev);
478 xfs_blkdev_put(rtdev);
479 goto error0;
480 }
481 }
482 mp->m_logdev_targp = (logdev && logdev != ddev) ?
483 xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
484 if (!mp->m_logdev_targp) {
485 xfs_blkdev_put(logdev);
486 xfs_blkdev_put(rtdev);
487 goto error0;
488 }
489
490 /*
491 * Setup flags based on mount(2) options and then the superblock
492 */
493 error = xfs_start_flags(args, mp);
494 if (error)
495 goto error1;
496 error = xfs_readsb(mp, flags);
497 if (error)
498 goto error1;
499 error = xfs_finish_flags(args, mp);
500 if (error)
501 goto error2;
502
503 /*
504 * Setup xfs_mount buffer target pointers based on superblock
505 */
506 error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
507 mp->m_sb.sb_sectsize);
508 if (!error && logdev && logdev != ddev) {
509 unsigned int log_sector_size = BBSIZE;
510
511 if (xfs_sb_version_hassector(&mp->m_sb))
512 log_sector_size = mp->m_sb.sb_logsectsize;
513 error = xfs_setsize_buftarg(mp->m_logdev_targp,
514 mp->m_sb.sb_blocksize,
515 log_sector_size);
516 }
517 if (!error && rtdev)
518 error = xfs_setsize_buftarg(mp->m_rtdev_targp,
519 mp->m_sb.sb_blocksize,
520 mp->m_sb.sb_sectsize);
521 if (error)
522 goto error2;
523
524 if (mp->m_flags & XFS_MOUNT_BARRIER)
525 xfs_mountfs_check_barriers(mp);
526
527 if ((error = xfs_filestream_mount(mp)))
528 goto error2;
529
530 error = xfs_mountfs(mp, flags);
531 if (error)
532 goto error2;
533
534 XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, args->mtpt, args->fsname);
535
536 return 0;
537
538error2:
539 if (mp->m_sb_bp)
540 xfs_freesb(mp);
541error1:
542 xfs_binval(mp->m_ddev_targp);
543 if (logdev && logdev != ddev)
544 xfs_binval(mp->m_logdev_targp);
545 if (rtdev)
546 xfs_binval(mp->m_rtdev_targp);
547error0:
548 xfs_unmountfs_close(mp, credp);
549 xfs_qmops_put(mp);
550 xfs_dmops_put(mp);
551 return error;
552}
553
554int
555xfs_unmount(
556 xfs_mount_t *mp,
557 int flags,
558 cred_t *credp)
559{
560 xfs_inode_t *rip;
561 bhv_vnode_t *rvp;
562 int unmount_event_wanted = 0;
563 int unmount_event_flags = 0;
564 int xfs_unmountfs_needed = 0;
565 int error;
566
567 rip = mp->m_rootip;
568 rvp = XFS_ITOV(rip);
569
570#ifdef HAVE_DMAPI
571 if (mp->m_flags & XFS_MOUNT_DMAPI) {
572 error = XFS_SEND_PREUNMOUNT(mp,
573 rip, DM_RIGHT_NULL, rip, DM_RIGHT_NULL,
574 NULL, NULL, 0, 0,
575 (mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
576 0:DM_FLAGS_UNWANTED);
577 if (error)
578 return XFS_ERROR(error);
579 unmount_event_wanted = 1;
580 unmount_event_flags = (mp->m_dmevmask & (1<<DM_EVENT_UNMOUNT))?
581 0 : DM_FLAGS_UNWANTED;
582 }
583#endif
584
585 /*
586 * Blow away any referenced inode in the filestreams cache.
587 * This can and will cause log traffic as inodes go inactive
588 * here.
589 */
590 xfs_filestream_unmount(mp);
591
592 XFS_bflush(mp->m_ddev_targp);
593 error = xfs_unmount_flush(mp, 0);
594 if (error)
595 goto out;
596
597 ASSERT(vn_count(rvp) == 1);
598
599 /*
600 * Drop the reference count
601 */
602 IRELE(rip);
603
604 /*
605 * If we're forcing a shutdown, typically because of a media error,
606 * we want to make sure we invalidate dirty pages that belong to
607 * referenced vnodes as well.
608 */
609 if (XFS_FORCED_SHUTDOWN(mp)) {
610 error = xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE);
611 ASSERT(error != EFSCORRUPTED);
612 }
613 xfs_unmountfs_needed = 1;
614
615out:
616 /* Send DMAPI event, if required.
617 * Then do xfs_unmountfs() if needed.
618 * Then return error (or zero).
619 */
620 if (unmount_event_wanted) {
621 /* Note: mp structure must still exist for
622 * XFS_SEND_UNMOUNT() call.
623 */
624 XFS_SEND_UNMOUNT(mp, error == 0 ? rip : NULL,
625 DM_RIGHT_NULL, 0, error, unmount_event_flags);
626 }
627 if (xfs_unmountfs_needed) {
628 /*
629 * Call common unmount function to flush to disk
630 * and free the super block buffer & mount structures.
631 */
632 xfs_unmountfs(mp, credp);
633 xfs_qmops_put(mp);
634 xfs_dmops_put(mp);
635 kmem_free(mp, sizeof(xfs_mount_t));
636 }
637
638 return XFS_ERROR(error);
639}
640
641STATIC void 61STATIC void
642xfs_quiesce_fs( 62xfs_quiesce_fs(
643 xfs_mount_t *mp) 63 xfs_mount_t *mp)
@@ -694,30 +114,6 @@ xfs_attr_quiesce(
694 xfs_unmountfs_writesb(mp); 114 xfs_unmountfs_writesb(mp);
695} 115}
696 116
697int
698xfs_mntupdate(
699 struct xfs_mount *mp,
700 int *flags,
701 struct xfs_mount_args *args)
702{
703 if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */
704 if (mp->m_flags & XFS_MOUNT_RDONLY)
705 mp->m_flags &= ~XFS_MOUNT_RDONLY;
706 if (args->flags & XFSMNT_BARRIER) {
707 mp->m_flags |= XFS_MOUNT_BARRIER;
708 xfs_mountfs_check_barriers(mp);
709 } else {
710 mp->m_flags &= ~XFS_MOUNT_BARRIER;
711 }
712 } else if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { /* rw -> ro */
713 xfs_filestream_flush(mp);
714 xfs_sync(mp, SYNC_DATA_QUIESCE);
715 xfs_attr_quiesce(mp);
716 mp->m_flags |= XFS_MOUNT_RDONLY;
717 }
718 return 0;
719}
720
721/* 117/*
722 * xfs_unmount_flush implements a set of flush operation on special 118 * xfs_unmount_flush implements a set of flush operation on special
723 * inodes, which are needed as a separate set of operations so that 119 * inodes, which are needed as a separate set of operations so that
@@ -1048,7 +444,7 @@ xfs_sync_inodes(
1048 444
1049 if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) { 445 if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
1050 XFS_MOUNT_IUNLOCK(mp); 446 XFS_MOUNT_IUNLOCK(mp);
1051 kmem_free(ipointer, sizeof(xfs_iptr_t)); 447 kmem_free(ipointer);
1052 return 0; 448 return 0;
1053 } 449 }
1054 450
@@ -1194,7 +590,7 @@ xfs_sync_inodes(
1194 } 590 }
1195 XFS_MOUNT_IUNLOCK(mp); 591 XFS_MOUNT_IUNLOCK(mp);
1196 ASSERT(ipointer_in == B_FALSE); 592 ASSERT(ipointer_in == B_FALSE);
1197 kmem_free(ipointer, sizeof(xfs_iptr_t)); 593 kmem_free(ipointer);
1198 return XFS_ERROR(error); 594 return XFS_ERROR(error);
1199 } 595 }
1200 596
@@ -1224,7 +620,7 @@ xfs_sync_inodes(
1224 620
1225 ASSERT(ipointer_in == B_FALSE); 621 ASSERT(ipointer_in == B_FALSE);
1226 622
1227 kmem_free(ipointer, sizeof(xfs_iptr_t)); 623 kmem_free(ipointer);
1228 return XFS_ERROR(last_error); 624 return XFS_ERROR(last_error);
1229} 625}
1230 626
diff --git a/fs/xfs/xfs_vfsops.h b/fs/xfs/xfs_vfsops.h
index 1688817c55ed..a74b05087da4 100644
--- a/fs/xfs/xfs_vfsops.h
+++ b/fs/xfs/xfs_vfsops.h
@@ -8,11 +8,6 @@ struct kstatfs;
8struct xfs_mount; 8struct xfs_mount;
9struct xfs_mount_args; 9struct xfs_mount_args;
10 10
11int xfs_mount(struct xfs_mount *mp, struct xfs_mount_args *args,
12 struct cred *credp);
13int xfs_unmount(struct xfs_mount *mp, int flags, struct cred *credp);
14int xfs_mntupdate(struct xfs_mount *mp, int *flags,
15 struct xfs_mount_args *args);
16int xfs_sync(struct xfs_mount *mp, int flags); 11int xfs_sync(struct xfs_mount *mp, int flags);
17void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, 12void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
18 int lnnum); 13 int lnnum);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index e475e3717eb3..76a1166af822 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -75,26 +75,23 @@ xfs_open(
75 return 0; 75 return 0;
76} 76}
77 77
78/*
79 * xfs_setattr
80 */
81int 78int
82xfs_setattr( 79xfs_setattr(
83 xfs_inode_t *ip, 80 struct xfs_inode *ip,
84 bhv_vattr_t *vap, 81 struct iattr *iattr,
85 int flags, 82 int flags,
86 cred_t *credp) 83 cred_t *credp)
87{ 84{
88 xfs_mount_t *mp = ip->i_mount; 85 xfs_mount_t *mp = ip->i_mount;
86 struct inode *inode = XFS_ITOV(ip);
87 int mask = iattr->ia_valid;
89 xfs_trans_t *tp; 88 xfs_trans_t *tp;
90 int mask;
91 int code; 89 int code;
92 uint lock_flags; 90 uint lock_flags;
93 uint commit_flags=0; 91 uint commit_flags=0;
94 uid_t uid=0, iuid=0; 92 uid_t uid=0, iuid=0;
95 gid_t gid=0, igid=0; 93 gid_t gid=0, igid=0;
96 int timeflags = 0; 94 int timeflags = 0;
97 xfs_prid_t projid=0, iprojid=0;
98 struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; 95 struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
99 int file_owner; 96 int file_owner;
100 int need_iolock = 1; 97 int need_iolock = 1;
@@ -104,30 +101,9 @@ xfs_setattr(
104 if (mp->m_flags & XFS_MOUNT_RDONLY) 101 if (mp->m_flags & XFS_MOUNT_RDONLY)
105 return XFS_ERROR(EROFS); 102 return XFS_ERROR(EROFS);
106 103
107 /*
108 * Cannot set certain attributes.
109 */
110 mask = vap->va_mask;
111 if (mask & XFS_AT_NOSET) {
112 return XFS_ERROR(EINVAL);
113 }
114
115 if (XFS_FORCED_SHUTDOWN(mp)) 104 if (XFS_FORCED_SHUTDOWN(mp))
116 return XFS_ERROR(EIO); 105 return XFS_ERROR(EIO);
117 106
118 /*
119 * Timestamps do not need to be logged and hence do not
120 * need to be done within a transaction.
121 */
122 if (mask & XFS_AT_UPDTIMES) {
123 ASSERT((mask & ~XFS_AT_UPDTIMES) == 0);
124 timeflags = ((mask & XFS_AT_UPDATIME) ? XFS_ICHGTIME_ACC : 0) |
125 ((mask & XFS_AT_UPDCTIME) ? XFS_ICHGTIME_CHG : 0) |
126 ((mask & XFS_AT_UPDMTIME) ? XFS_ICHGTIME_MOD : 0);
127 xfs_ichgtime(ip, timeflags);
128 return 0;
129 }
130
131 olddquot1 = olddquot2 = NULL; 107 olddquot1 = olddquot2 = NULL;
132 udqp = gdqp = NULL; 108 udqp = gdqp = NULL;
133 109
@@ -139,28 +115,22 @@ xfs_setattr(
139 * If the IDs do change before we take the ilock, we're covered 115 * If the IDs do change before we take the ilock, we're covered
140 * because the i_*dquot fields will get updated anyway. 116 * because the i_*dquot fields will get updated anyway.
141 */ 117 */
142 if (XFS_IS_QUOTA_ON(mp) && 118 if (XFS_IS_QUOTA_ON(mp) && (mask & (ATTR_UID|ATTR_GID))) {
143 (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
144 uint qflags = 0; 119 uint qflags = 0;
145 120
146 if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) { 121 if ((mask & ATTR_UID) && XFS_IS_UQUOTA_ON(mp)) {
147 uid = vap->va_uid; 122 uid = iattr->ia_uid;
148 qflags |= XFS_QMOPT_UQUOTA; 123 qflags |= XFS_QMOPT_UQUOTA;
149 } else { 124 } else {
150 uid = ip->i_d.di_uid; 125 uid = ip->i_d.di_uid;
151 } 126 }
152 if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) { 127 if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp)) {
153 gid = vap->va_gid; 128 gid = iattr->ia_gid;
154 qflags |= XFS_QMOPT_GQUOTA; 129 qflags |= XFS_QMOPT_GQUOTA;
155 } else { 130 } else {
156 gid = ip->i_d.di_gid; 131 gid = ip->i_d.di_gid;
157 } 132 }
158 if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) { 133
159 projid = vap->va_projid;
160 qflags |= XFS_QMOPT_PQUOTA;
161 } else {
162 projid = ip->i_d.di_projid;
163 }
164 /* 134 /*
165 * We take a reference when we initialize udqp and gdqp, 135 * We take a reference when we initialize udqp and gdqp,
166 * so it is important that we never blindly double trip on 136 * so it is important that we never blindly double trip on
@@ -168,8 +138,8 @@ xfs_setattr(
168 */ 138 */
169 ASSERT(udqp == NULL); 139 ASSERT(udqp == NULL);
170 ASSERT(gdqp == NULL); 140 ASSERT(gdqp == NULL);
171 code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags, 141 code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, ip->i_d.di_projid,
172 &udqp, &gdqp); 142 qflags, &udqp, &gdqp);
173 if (code) 143 if (code)
174 return code; 144 return code;
175 } 145 }
@@ -180,10 +150,10 @@ xfs_setattr(
180 */ 150 */
181 tp = NULL; 151 tp = NULL;
182 lock_flags = XFS_ILOCK_EXCL; 152 lock_flags = XFS_ILOCK_EXCL;
183 if (flags & ATTR_NOLOCK) 153 if (flags & XFS_ATTR_NOLOCK)
184 need_iolock = 0; 154 need_iolock = 0;
185 if (!(mask & XFS_AT_SIZE)) { 155 if (!(mask & ATTR_SIZE)) {
186 if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) || 156 if ((mask != (ATTR_CTIME|ATTR_ATIME|ATTR_MTIME)) ||
187 (mp->m_flags & XFS_MOUNT_WSYNC)) { 157 (mp->m_flags & XFS_MOUNT_WSYNC)) {
188 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); 158 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
189 commit_flags = 0; 159 commit_flags = 0;
@@ -196,10 +166,10 @@ xfs_setattr(
196 } 166 }
197 } else { 167 } else {
198 if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) && 168 if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
199 !(flags & ATTR_DMI)) { 169 !(flags & XFS_ATTR_DMI)) {
200 int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR; 170 int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
201 code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, ip, 171 code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, ip,
202 vap->va_size, 0, dmflags, NULL); 172 iattr->ia_size, 0, dmflags, NULL);
203 if (code) { 173 if (code) {
204 lock_flags = 0; 174 lock_flags = 0;
205 goto error_return; 175 goto error_return;
@@ -219,9 +189,7 @@ xfs_setattr(
219 * Only the owner or users with CAP_FOWNER 189 * Only the owner or users with CAP_FOWNER
220 * capability may do these things. 190 * capability may do these things.
221 */ 191 */
222 if (mask & 192 if (mask & (ATTR_MODE|ATTR_UID|ATTR_GID)) {
223 (XFS_AT_MODE|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_UID|
224 XFS_AT_GID|XFS_AT_PROJID)) {
225 /* 193 /*
226 * CAP_FOWNER overrides the following restrictions: 194 * CAP_FOWNER overrides the following restrictions:
227 * 195 *
@@ -245,21 +213,21 @@ xfs_setattr(
245 * IDs of the calling process shall match the group owner of 213 * IDs of the calling process shall match the group owner of
246 * the file when setting the set-group-ID bit on that file 214 * the file when setting the set-group-ID bit on that file
247 */ 215 */
248 if (mask & XFS_AT_MODE) { 216 if (mask & ATTR_MODE) {
249 mode_t m = 0; 217 mode_t m = 0;
250 218
251 if ((vap->va_mode & S_ISUID) && !file_owner) 219 if ((iattr->ia_mode & S_ISUID) && !file_owner)
252 m |= S_ISUID; 220 m |= S_ISUID;
253 if ((vap->va_mode & S_ISGID) && 221 if ((iattr->ia_mode & S_ISGID) &&
254 !in_group_p((gid_t)ip->i_d.di_gid)) 222 !in_group_p((gid_t)ip->i_d.di_gid))
255 m |= S_ISGID; 223 m |= S_ISGID;
256#if 0 224#if 0
257 /* Linux allows this, Irix doesn't. */ 225 /* Linux allows this, Irix doesn't. */
258 if ((vap->va_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode)) 226 if ((iattr->ia_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode))
259 m |= S_ISVTX; 227 m |= S_ISVTX;
260#endif 228#endif
261 if (m && !capable(CAP_FSETID)) 229 if (m && !capable(CAP_FSETID))
262 vap->va_mode &= ~m; 230 iattr->ia_mode &= ~m;
263 } 231 }
264 } 232 }
265 233
@@ -270,7 +238,7 @@ xfs_setattr(
270 * and can change the group id only to a group of which he 238 * and can change the group id only to a group of which he
271 * or she is a member. 239 * or she is a member.
272 */ 240 */
273 if (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID)) { 241 if (mask & (ATTR_UID|ATTR_GID)) {
274 /* 242 /*
275 * These IDs could have changed since we last looked at them. 243 * These IDs could have changed since we last looked at them.
276 * But, we're assured that if the ownership did change 244 * But, we're assured that if the ownership did change
@@ -278,12 +246,9 @@ xfs_setattr(
278 * would have changed also. 246 * would have changed also.
279 */ 247 */
280 iuid = ip->i_d.di_uid; 248 iuid = ip->i_d.di_uid;
281 iprojid = ip->i_d.di_projid;
282 igid = ip->i_d.di_gid; 249 igid = ip->i_d.di_gid;
283 gid = (mask & XFS_AT_GID) ? vap->va_gid : igid; 250 gid = (mask & ATTR_GID) ? iattr->ia_gid : igid;
284 uid = (mask & XFS_AT_UID) ? vap->va_uid : iuid; 251 uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid;
285 projid = (mask & XFS_AT_PROJID) ? (xfs_prid_t)vap->va_projid :
286 iprojid;
287 252
288 /* 253 /*
289 * CAP_CHOWN overrides the following restrictions: 254 * CAP_CHOWN overrides the following restrictions:
@@ -303,11 +268,10 @@ xfs_setattr(
303 goto error_return; 268 goto error_return;
304 } 269 }
305 /* 270 /*
306 * Do a quota reservation only if uid/projid/gid is actually 271 * Do a quota reservation only if uid/gid is actually
307 * going to change. 272 * going to change.
308 */ 273 */
309 if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || 274 if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
310 (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
311 (XFS_IS_GQUOTA_ON(mp) && igid != gid)) { 275 (XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
312 ASSERT(tp); 276 ASSERT(tp);
313 code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp, 277 code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
@@ -321,13 +285,13 @@ xfs_setattr(
321 /* 285 /*
322 * Truncate file. Must have write permission and not be a directory. 286 * Truncate file. Must have write permission and not be a directory.
323 */ 287 */
324 if (mask & XFS_AT_SIZE) { 288 if (mask & ATTR_SIZE) {
325 /* Short circuit the truncate case for zero length files */ 289 /* Short circuit the truncate case for zero length files */
326 if ((vap->va_size == 0) && 290 if (iattr->ia_size == 0 &&
327 (ip->i_size == 0) && (ip->i_d.di_nextents == 0)) { 291 ip->i_size == 0 && ip->i_d.di_nextents == 0) {
328 xfs_iunlock(ip, XFS_ILOCK_EXCL); 292 xfs_iunlock(ip, XFS_ILOCK_EXCL);
329 lock_flags &= ~XFS_ILOCK_EXCL; 293 lock_flags &= ~XFS_ILOCK_EXCL;
330 if (mask & XFS_AT_CTIME) 294 if (mask & ATTR_CTIME)
331 xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 295 xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
332 code = 0; 296 code = 0;
333 goto error_return; 297 goto error_return;
@@ -350,9 +314,9 @@ xfs_setattr(
350 /* 314 /*
351 * Change file access or modified times. 315 * Change file access or modified times.
352 */ 316 */
353 if (mask & (XFS_AT_ATIME|XFS_AT_MTIME)) { 317 if (mask & (ATTR_ATIME|ATTR_MTIME)) {
354 if (!file_owner) { 318 if (!file_owner) {
355 if ((flags & ATTR_UTIME) && 319 if ((mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)) &&
356 !capable(CAP_FOWNER)) { 320 !capable(CAP_FOWNER)) {
357 code = XFS_ERROR(EPERM); 321 code = XFS_ERROR(EPERM);
358 goto error_return; 322 goto error_return;
@@ -361,90 +325,23 @@ xfs_setattr(
361 } 325 }
362 326
363 /* 327 /*
364 * Change extent size or realtime flag.
365 */
366 if (mask & (XFS_AT_EXTSIZE|XFS_AT_XFLAGS)) {
367 /*
368 * Can't change extent size if any extents are allocated.
369 */
370 if (ip->i_d.di_nextents && (mask & XFS_AT_EXTSIZE) &&
371 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
372 vap->va_extsize) ) {
373 code = XFS_ERROR(EINVAL); /* EFBIG? */
374 goto error_return;
375 }
376
377 /*
378 * Can't change realtime flag if any extents are allocated.
379 */
380 if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
381 (mask & XFS_AT_XFLAGS) &&
382 (XFS_IS_REALTIME_INODE(ip)) !=
383 (vap->va_xflags & XFS_XFLAG_REALTIME)) {
384 code = XFS_ERROR(EINVAL); /* EFBIG? */
385 goto error_return;
386 }
387 /*
388 * Extent size must be a multiple of the appropriate block
389 * size, if set at all.
390 */
391 if ((mask & XFS_AT_EXTSIZE) && vap->va_extsize != 0) {
392 xfs_extlen_t size;
393
394 if (XFS_IS_REALTIME_INODE(ip) ||
395 ((mask & XFS_AT_XFLAGS) &&
396 (vap->va_xflags & XFS_XFLAG_REALTIME))) {
397 size = mp->m_sb.sb_rextsize <<
398 mp->m_sb.sb_blocklog;
399 } else {
400 size = mp->m_sb.sb_blocksize;
401 }
402 if (vap->va_extsize % size) {
403 code = XFS_ERROR(EINVAL);
404 goto error_return;
405 }
406 }
407 /*
408 * If realtime flag is set then must have realtime data.
409 */
410 if ((mask & XFS_AT_XFLAGS) &&
411 (vap->va_xflags & XFS_XFLAG_REALTIME)) {
412 if ((mp->m_sb.sb_rblocks == 0) ||
413 (mp->m_sb.sb_rextsize == 0) ||
414 (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
415 code = XFS_ERROR(EINVAL);
416 goto error_return;
417 }
418 }
419
420 /*
421 * Can't modify an immutable/append-only file unless
422 * we have appropriate permission.
423 */
424 if ((mask & XFS_AT_XFLAGS) &&
425 (ip->i_d.di_flags &
426 (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
427 (vap->va_xflags &
428 (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
429 !capable(CAP_LINUX_IMMUTABLE)) {
430 code = XFS_ERROR(EPERM);
431 goto error_return;
432 }
433 }
434
435 /*
436 * Now we can make the changes. Before we join the inode 328 * Now we can make the changes. Before we join the inode
437 * to the transaction, if XFS_AT_SIZE is set then take care of 329 * to the transaction, if ATTR_SIZE is set then take care of
438 * the part of the truncation that must be done without the 330 * the part of the truncation that must be done without the
439 * inode lock. This needs to be done before joining the inode 331 * inode lock. This needs to be done before joining the inode
440 * to the transaction, because the inode cannot be unlocked 332 * to the transaction, because the inode cannot be unlocked
441 * once it is a part of the transaction. 333 * once it is a part of the transaction.
442 */ 334 */
443 if (mask & XFS_AT_SIZE) { 335 if (mask & ATTR_SIZE) {
444 code = 0; 336 code = 0;
445 if ((vap->va_size > ip->i_size) && 337 if (iattr->ia_size > ip->i_size) {
446 (flags & ATTR_NOSIZETOK) == 0) { 338 /*
447 code = xfs_igrow_start(ip, vap->va_size, credp); 339 * Do the first part of growing a file: zero any data
340 * in the last block that is beyond the old EOF. We
341 * need to do this before the inode is joined to the
342 * transaction to modify the i_size.
343 */
344 code = xfs_zero_eof(ip, iattr->ia_size, ip->i_size);
448 } 345 }
449 xfs_iunlock(ip, XFS_ILOCK_EXCL); 346 xfs_iunlock(ip, XFS_ILOCK_EXCL);
450 347
@@ -461,10 +358,10 @@ xfs_setattr(
461 * not within the range we care about here. 358 * not within the range we care about here.
462 */ 359 */
463 if (!code && 360 if (!code &&
464 (ip->i_size != ip->i_d.di_size) && 361 ip->i_size != ip->i_d.di_size &&
465 (vap->va_size > ip->i_d.di_size)) { 362 iattr->ia_size > ip->i_d.di_size) {
466 code = xfs_flush_pages(ip, 363 code = xfs_flush_pages(ip,
467 ip->i_d.di_size, vap->va_size, 364 ip->i_d.di_size, iattr->ia_size,
468 XFS_B_ASYNC, FI_NONE); 365 XFS_B_ASYNC, FI_NONE);
469 } 366 }
470 367
@@ -472,7 +369,7 @@ xfs_setattr(
472 vn_iowait(ip); 369 vn_iowait(ip);
473 370
474 if (!code) 371 if (!code)
475 code = xfs_itruncate_data(ip, vap->va_size); 372 code = xfs_itruncate_data(ip, iattr->ia_size);
476 if (code) { 373 if (code) {
477 ASSERT(tp == NULL); 374 ASSERT(tp == NULL);
478 lock_flags &= ~XFS_ILOCK_EXCL; 375 lock_flags &= ~XFS_ILOCK_EXCL;
@@ -501,28 +398,30 @@ xfs_setattr(
501 /* 398 /*
502 * Truncate file. Must have write permission and not be a directory. 399 * Truncate file. Must have write permission and not be a directory.
503 */ 400 */
504 if (mask & XFS_AT_SIZE) { 401 if (mask & ATTR_SIZE) {
505 /* 402 /*
506 * Only change the c/mtime if we are changing the size 403 * Only change the c/mtime if we are changing the size
507 * or we are explicitly asked to change it. This handles 404 * or we are explicitly asked to change it. This handles
508 * the semantic difference between truncate() and ftruncate() 405 * the semantic difference between truncate() and ftruncate()
509 * as implemented in the VFS. 406 * as implemented in the VFS.
510 */ 407 */
511 if (vap->va_size != ip->i_size || (mask & XFS_AT_CTIME)) 408 if (iattr->ia_size != ip->i_size || (mask & ATTR_CTIME))
512 timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; 409 timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
513 410
514 if (vap->va_size > ip->i_size) { 411 if (iattr->ia_size > ip->i_size) {
515 xfs_igrow_finish(tp, ip, vap->va_size, 412 ip->i_d.di_size = iattr->ia_size;
516 !(flags & ATTR_DMI)); 413 ip->i_size = iattr->ia_size;
517 } else if ((vap->va_size <= ip->i_size) || 414 if (!(flags & XFS_ATTR_DMI))
518 ((vap->va_size == 0) && ip->i_d.di_nextents)) { 415 xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
416 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
417 } else if (iattr->ia_size <= ip->i_size ||
418 (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
519 /* 419 /*
520 * signal a sync transaction unless 420 * signal a sync transaction unless
521 * we're truncating an already unlinked 421 * we're truncating an already unlinked
522 * file on a wsync filesystem 422 * file on a wsync filesystem
523 */ 423 */
524 code = xfs_itruncate_finish(&tp, ip, 424 code = xfs_itruncate_finish(&tp, ip, iattr->ia_size,
525 (xfs_fsize_t)vap->va_size,
526 XFS_DATA_FORK, 425 XFS_DATA_FORK,
527 ((ip->i_d.di_nlink != 0 || 426 ((ip->i_d.di_nlink != 0 ||
528 !(mp->m_flags & XFS_MOUNT_WSYNC)) 427 !(mp->m_flags & XFS_MOUNT_WSYNC))
@@ -544,9 +443,12 @@ xfs_setattr(
544 /* 443 /*
545 * Change file access modes. 444 * Change file access modes.
546 */ 445 */
547 if (mask & XFS_AT_MODE) { 446 if (mask & ATTR_MODE) {
548 ip->i_d.di_mode &= S_IFMT; 447 ip->i_d.di_mode &= S_IFMT;
549 ip->i_d.di_mode |= vap->va_mode & ~S_IFMT; 448 ip->i_d.di_mode |= iattr->ia_mode & ~S_IFMT;
449
450 inode->i_mode &= S_IFMT;
451 inode->i_mode |= iattr->ia_mode & ~S_IFMT;
550 452
551 xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE); 453 xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
552 timeflags |= XFS_ICHGTIME_CHG; 454 timeflags |= XFS_ICHGTIME_CHG;
@@ -559,7 +461,7 @@ xfs_setattr(
559 * and can change the group id only to a group of which he 461 * and can change the group id only to a group of which he
560 * or she is a member. 462 * or she is a member.
561 */ 463 */
562 if (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID)) { 464 if (mask & (ATTR_UID|ATTR_GID)) {
563 /* 465 /*
564 * CAP_FSETID overrides the following restrictions: 466 * CAP_FSETID overrides the following restrictions:
565 * 467 *
@@ -577,39 +479,24 @@ xfs_setattr(
577 */ 479 */
578 if (iuid != uid) { 480 if (iuid != uid) {
579 if (XFS_IS_UQUOTA_ON(mp)) { 481 if (XFS_IS_UQUOTA_ON(mp)) {
580 ASSERT(mask & XFS_AT_UID); 482 ASSERT(mask & ATTR_UID);
581 ASSERT(udqp); 483 ASSERT(udqp);
582 olddquot1 = XFS_QM_DQVOPCHOWN(mp, tp, ip, 484 olddquot1 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
583 &ip->i_udquot, udqp); 485 &ip->i_udquot, udqp);
584 } 486 }
585 ip->i_d.di_uid = uid; 487 ip->i_d.di_uid = uid;
488 inode->i_uid = uid;
586 } 489 }
587 if (igid != gid) { 490 if (igid != gid) {
588 if (XFS_IS_GQUOTA_ON(mp)) { 491 if (XFS_IS_GQUOTA_ON(mp)) {
589 ASSERT(!XFS_IS_PQUOTA_ON(mp)); 492 ASSERT(!XFS_IS_PQUOTA_ON(mp));
590 ASSERT(mask & XFS_AT_GID); 493 ASSERT(mask & ATTR_GID);
591 ASSERT(gdqp); 494 ASSERT(gdqp);
592 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, 495 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
593 &ip->i_gdquot, gdqp); 496 &ip->i_gdquot, gdqp);
594 } 497 }
595 ip->i_d.di_gid = gid; 498 ip->i_d.di_gid = gid;
596 } 499 inode->i_gid = gid;
597 if (iprojid != projid) {
598 if (XFS_IS_PQUOTA_ON(mp)) {
599 ASSERT(!XFS_IS_GQUOTA_ON(mp));
600 ASSERT(mask & XFS_AT_PROJID);
601 ASSERT(gdqp);
602 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
603 &ip->i_gdquot, gdqp);
604 }
605 ip->i_d.di_projid = projid;
606 /*
607 * We may have to rev the inode as well as
608 * the superblock version number since projids didn't
609 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
610 */
611 if (ip->i_d.di_version == XFS_DINODE_VERSION_1)
612 xfs_bump_ino_vers2(tp, ip);
613 } 500 }
614 501
615 xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE); 502 xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
@@ -620,82 +507,34 @@ xfs_setattr(
620 /* 507 /*
621 * Change file access or modified times. 508 * Change file access or modified times.
622 */ 509 */
623 if (mask & (XFS_AT_ATIME|XFS_AT_MTIME)) { 510 if (mask & (ATTR_ATIME|ATTR_MTIME)) {
624 if (mask & XFS_AT_ATIME) { 511 if (mask & ATTR_ATIME) {
625 ip->i_d.di_atime.t_sec = vap->va_atime.tv_sec; 512 inode->i_atime = iattr->ia_atime;
626 ip->i_d.di_atime.t_nsec = vap->va_atime.tv_nsec; 513 ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
514 ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
627 ip->i_update_core = 1; 515 ip->i_update_core = 1;
628 timeflags &= ~XFS_ICHGTIME_ACC; 516 timeflags &= ~XFS_ICHGTIME_ACC;
629 } 517 }
630 if (mask & XFS_AT_MTIME) { 518 if (mask & ATTR_MTIME) {
631 ip->i_d.di_mtime.t_sec = vap->va_mtime.tv_sec; 519 inode->i_mtime = iattr->ia_mtime;
632 ip->i_d.di_mtime.t_nsec = vap->va_mtime.tv_nsec; 520 ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
521 ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
633 timeflags &= ~XFS_ICHGTIME_MOD; 522 timeflags &= ~XFS_ICHGTIME_MOD;
634 timeflags |= XFS_ICHGTIME_CHG; 523 timeflags |= XFS_ICHGTIME_CHG;
635 } 524 }
636 if (tp && (flags & ATTR_UTIME)) 525 if (tp && (mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)))
637 xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE); 526 xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
638 } 527 }
639 528
640 /* 529 /*
641 * Change XFS-added attributes. 530 * Change file inode change time only if ATTR_CTIME set
642 */
643 if (mask & (XFS_AT_EXTSIZE|XFS_AT_XFLAGS)) {
644 if (mask & XFS_AT_EXTSIZE) {
645 /*
646 * Converting bytes to fs blocks.
647 */
648 ip->i_d.di_extsize = vap->va_extsize >>
649 mp->m_sb.sb_blocklog;
650 }
651 if (mask & XFS_AT_XFLAGS) {
652 uint di_flags;
653
654 /* can't set PREALLOC this way, just preserve it */
655 di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
656 if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
657 di_flags |= XFS_DIFLAG_IMMUTABLE;
658 if (vap->va_xflags & XFS_XFLAG_APPEND)
659 di_flags |= XFS_DIFLAG_APPEND;
660 if (vap->va_xflags & XFS_XFLAG_SYNC)
661 di_flags |= XFS_DIFLAG_SYNC;
662 if (vap->va_xflags & XFS_XFLAG_NOATIME)
663 di_flags |= XFS_DIFLAG_NOATIME;
664 if (vap->va_xflags & XFS_XFLAG_NODUMP)
665 di_flags |= XFS_DIFLAG_NODUMP;
666 if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
667 di_flags |= XFS_DIFLAG_PROJINHERIT;
668 if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
669 di_flags |= XFS_DIFLAG_NODEFRAG;
670 if (vap->va_xflags & XFS_XFLAG_FILESTREAM)
671 di_flags |= XFS_DIFLAG_FILESTREAM;
672 if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
673 if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
674 di_flags |= XFS_DIFLAG_RTINHERIT;
675 if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
676 di_flags |= XFS_DIFLAG_NOSYMLINKS;
677 if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
678 di_flags |= XFS_DIFLAG_EXTSZINHERIT;
679 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
680 if (vap->va_xflags & XFS_XFLAG_REALTIME)
681 di_flags |= XFS_DIFLAG_REALTIME;
682 if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
683 di_flags |= XFS_DIFLAG_EXTSIZE;
684 }
685 ip->i_d.di_flags = di_flags;
686 }
687 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
688 timeflags |= XFS_ICHGTIME_CHG;
689 }
690
691 /*
692 * Change file inode change time only if XFS_AT_CTIME set
693 * AND we have been called by a DMI function. 531 * AND we have been called by a DMI function.
694 */ 532 */
695 533
696 if ( (flags & ATTR_DMI) && (mask & XFS_AT_CTIME) ) { 534 if ((flags & XFS_ATTR_DMI) && (mask & ATTR_CTIME)) {
697 ip->i_d.di_ctime.t_sec = vap->va_ctime.tv_sec; 535 inode->i_ctime = iattr->ia_ctime;
698 ip->i_d.di_ctime.t_nsec = vap->va_ctime.tv_nsec; 536 ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
537 ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
699 ip->i_update_core = 1; 538 ip->i_update_core = 1;
700 timeflags &= ~XFS_ICHGTIME_CHG; 539 timeflags &= ~XFS_ICHGTIME_CHG;
701 } 540 }
@@ -704,7 +543,7 @@ xfs_setattr(
704 * Send out timestamp changes that need to be set to the 543 * Send out timestamp changes that need to be set to the
705 * current time. Not done when called by a DMI function. 544 * current time. Not done when called by a DMI function.
706 */ 545 */
707 if (timeflags && !(flags & ATTR_DMI)) 546 if (timeflags && !(flags & XFS_ATTR_DMI))
708 xfs_ichgtime(ip, timeflags); 547 xfs_ichgtime(ip, timeflags);
709 548
710 XFS_STATS_INC(xs_ig_attrchg); 549 XFS_STATS_INC(xs_ig_attrchg);
@@ -742,7 +581,7 @@ xfs_setattr(
742 } 581 }
743 582
744 if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) && 583 if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
745 !(flags & ATTR_DMI)) { 584 !(flags & XFS_ATTR_DMI)) {
746 (void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL, 585 (void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL,
747 NULL, DM_RIGHT_NULL, NULL, NULL, 586 NULL, DM_RIGHT_NULL, NULL, NULL,
748 0, 0, AT_DELAY_FLAG(flags)); 587 0, 0, AT_DELAY_FLAG(flags));
@@ -1601,12 +1440,18 @@ xfs_inactive(
1601 return VN_INACTIVE_CACHE; 1440 return VN_INACTIVE_CACHE;
1602} 1441}
1603 1442
1604 1443/*
1444 * Lookups up an inode from "name". If ci_name is not NULL, then a CI match
1445 * is allowed, otherwise it has to be an exact match. If a CI match is found,
1446 * ci_name->name will point to a the actual name (caller must free) or
1447 * will be set to NULL if an exact match is found.
1448 */
1605int 1449int
1606xfs_lookup( 1450xfs_lookup(
1607 xfs_inode_t *dp, 1451 xfs_inode_t *dp,
1608 struct xfs_name *name, 1452 struct xfs_name *name,
1609 xfs_inode_t **ipp) 1453 xfs_inode_t **ipp,
1454 struct xfs_name *ci_name)
1610{ 1455{
1611 xfs_ino_t inum; 1456 xfs_ino_t inum;
1612 int error; 1457 int error;
@@ -1618,7 +1463,7 @@ xfs_lookup(
1618 return XFS_ERROR(EIO); 1463 return XFS_ERROR(EIO);
1619 1464
1620 lock_mode = xfs_ilock_map_shared(dp); 1465 lock_mode = xfs_ilock_map_shared(dp);
1621 error = xfs_dir_lookup(NULL, dp, name, &inum); 1466 error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name);
1622 xfs_iunlock_map_shared(dp, lock_mode); 1467 xfs_iunlock_map_shared(dp, lock_mode);
1623 1468
1624 if (error) 1469 if (error)
@@ -1626,12 +1471,15 @@ xfs_lookup(
1626 1471
1627 error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0); 1472 error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
1628 if (error) 1473 if (error)
1629 goto out; 1474 goto out_free_name;
1630 1475
1631 xfs_itrace_ref(*ipp); 1476 xfs_itrace_ref(*ipp);
1632 return 0; 1477 return 0;
1633 1478
1634 out: 1479out_free_name:
1480 if (ci_name)
1481 kmem_free(ci_name->name);
1482out:
1635 *ipp = NULL; 1483 *ipp = NULL;
1636 return error; 1484 return error;
1637} 1485}
@@ -2098,13 +1946,6 @@ again:
2098#endif 1946#endif
2099} 1947}
2100 1948
2101#ifdef DEBUG
2102#define REMOVE_DEBUG_TRACE(x) {remove_which_error_return = (x);}
2103int remove_which_error_return = 0;
2104#else /* ! DEBUG */
2105#define REMOVE_DEBUG_TRACE(x)
2106#endif /* ! DEBUG */
2107
2108int 1949int
2109xfs_remove( 1950xfs_remove(
2110 xfs_inode_t *dp, 1951 xfs_inode_t *dp,
@@ -2113,6 +1954,7 @@ xfs_remove(
2113{ 1954{
2114 xfs_mount_t *mp = dp->i_mount; 1955 xfs_mount_t *mp = dp->i_mount;
2115 xfs_trans_t *tp = NULL; 1956 xfs_trans_t *tp = NULL;
1957 int is_dir = S_ISDIR(ip->i_d.di_mode);
2116 int error = 0; 1958 int error = 0;
2117 xfs_bmap_free_t free_list; 1959 xfs_bmap_free_t free_list;
2118 xfs_fsblock_t first_block; 1960 xfs_fsblock_t first_block;
@@ -2120,8 +1962,10 @@ xfs_remove(
2120 int committed; 1962 int committed;
2121 int link_zero; 1963 int link_zero;
2122 uint resblks; 1964 uint resblks;
1965 uint log_count;
2123 1966
2124 xfs_itrace_entry(dp); 1967 xfs_itrace_entry(dp);
1968 xfs_itrace_entry(ip);
2125 1969
2126 if (XFS_FORCED_SHUTDOWN(mp)) 1970 if (XFS_FORCED_SHUTDOWN(mp))
2127 return XFS_ERROR(EIO); 1971 return XFS_ERROR(EIO);
@@ -2134,19 +1978,23 @@ xfs_remove(
2134 return error; 1978 return error;
2135 } 1979 }
2136 1980
2137 xfs_itrace_entry(ip);
2138 xfs_itrace_ref(ip);
2139
2140 error = XFS_QM_DQATTACH(mp, dp, 0); 1981 error = XFS_QM_DQATTACH(mp, dp, 0);
2141 if (!error) 1982 if (error)
2142 error = XFS_QM_DQATTACH(mp, ip, 0); 1983 goto std_return;
2143 if (error) { 1984
2144 REMOVE_DEBUG_TRACE(__LINE__); 1985 error = XFS_QM_DQATTACH(mp, ip, 0);
1986 if (error)
2145 goto std_return; 1987 goto std_return;
2146 }
2147 1988
2148 tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE); 1989 if (is_dir) {
1990 tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
1991 log_count = XFS_DEFAULT_LOG_COUNT;
1992 } else {
1993 tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
1994 log_count = XFS_REMOVE_LOG_COUNT;
1995 }
2149 cancel_flags = XFS_TRANS_RELEASE_LOG_RES; 1996 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
1997
2150 /* 1998 /*
2151 * We try to get the real space reservation first, 1999 * We try to get the real space reservation first,
2152 * allowing for directory btree deletion(s) implying 2000 * allowing for directory btree deletion(s) implying
@@ -2158,25 +2006,21 @@ xfs_remove(
2158 */ 2006 */
2159 resblks = XFS_REMOVE_SPACE_RES(mp); 2007 resblks = XFS_REMOVE_SPACE_RES(mp);
2160 error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0, 2008 error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
2161 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT); 2009 XFS_TRANS_PERM_LOG_RES, log_count);
2162 if (error == ENOSPC) { 2010 if (error == ENOSPC) {
2163 resblks = 0; 2011 resblks = 0;
2164 error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0, 2012 error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
2165 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT); 2013 XFS_TRANS_PERM_LOG_RES, log_count);
2166 } 2014 }
2167 if (error) { 2015 if (error) {
2168 ASSERT(error != ENOSPC); 2016 ASSERT(error != ENOSPC);
2169 REMOVE_DEBUG_TRACE(__LINE__); 2017 cancel_flags = 0;
2170 xfs_trans_cancel(tp, 0); 2018 goto out_trans_cancel;
2171 return error;
2172 } 2019 }
2173 2020
2174 error = xfs_lock_dir_and_entry(dp, ip); 2021 error = xfs_lock_dir_and_entry(dp, ip);
2175 if (error) { 2022 if (error)
2176 REMOVE_DEBUG_TRACE(__LINE__); 2023 goto out_trans_cancel;
2177 xfs_trans_cancel(tp, cancel_flags);
2178 goto std_return;
2179 }
2180 2024
2181 /* 2025 /*
2182 * At this point, we've gotten both the directory and the entry 2026 * At this point, we've gotten both the directory and the entry
@@ -2189,6 +2033,21 @@ xfs_remove(
2189 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 2033 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
2190 2034
2191 /* 2035 /*
2036 * If we're removing a directory perform some additional validation.
2037 */
2038 if (is_dir) {
2039 ASSERT(ip->i_d.di_nlink >= 2);
2040 if (ip->i_d.di_nlink != 2) {
2041 error = XFS_ERROR(ENOTEMPTY);
2042 goto out_trans_cancel;
2043 }
2044 if (!xfs_dir_isempty(ip)) {
2045 error = XFS_ERROR(ENOTEMPTY);
2046 goto out_trans_cancel;
2047 }
2048 }
2049
2050 /*
2192 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. 2051 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
2193 */ 2052 */
2194 XFS_BMAP_INIT(&free_list, &first_block); 2053 XFS_BMAP_INIT(&free_list, &first_block);
@@ -2196,39 +2055,64 @@ xfs_remove(
2196 &first_block, &free_list, resblks); 2055 &first_block, &free_list, resblks);
2197 if (error) { 2056 if (error) {
2198 ASSERT(error != ENOENT); 2057 ASSERT(error != ENOENT);
2199 REMOVE_DEBUG_TRACE(__LINE__); 2058 goto out_bmap_cancel;
2200 goto error1;
2201 } 2059 }
2202 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 2060 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
2203 2061
2062 /*
2063 * Bump the in memory generation count on the parent
2064 * directory so that other can know that it has changed.
2065 */
2204 dp->i_gen++; 2066 dp->i_gen++;
2205 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 2067 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
2206 2068
2207 error = xfs_droplink(tp, ip); 2069 if (is_dir) {
2208 if (error) { 2070 /*
2209 REMOVE_DEBUG_TRACE(__LINE__); 2071 * Drop the link from ip's "..".
2210 goto error1; 2072 */
2073 error = xfs_droplink(tp, dp);
2074 if (error)
2075 goto out_bmap_cancel;
2076
2077 /*
2078 * Drop the link from dp to ip.
2079 */
2080 error = xfs_droplink(tp, ip);
2081 if (error)
2082 goto out_bmap_cancel;
2083 } else {
2084 /*
2085 * When removing a non-directory we need to log the parent
2086 * inode here for the i_gen update. For a directory this is
2087 * done implicitly by the xfs_droplink call for the ".." entry.
2088 */
2089 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
2211 } 2090 }
2212 2091
2213 /* Determine if this is the last link while 2092 /*
2093 * Drop the "." link from ip to self.
2094 */
2095 error = xfs_droplink(tp, ip);
2096 if (error)
2097 goto out_bmap_cancel;
2098
2099 /*
2100 * Determine if this is the last link while
2214 * we are in the transaction. 2101 * we are in the transaction.
2215 */ 2102 */
2216 link_zero = (ip)->i_d.di_nlink==0; 2103 link_zero = (ip->i_d.di_nlink == 0);
2217 2104
2218 /* 2105 /*
2219 * If this is a synchronous mount, make sure that the 2106 * If this is a synchronous mount, make sure that the
2220 * remove transaction goes to disk before returning to 2107 * remove transaction goes to disk before returning to
2221 * the user. 2108 * the user.
2222 */ 2109 */
2223 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) { 2110 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
2224 xfs_trans_set_sync(tp); 2111 xfs_trans_set_sync(tp);
2225 }
2226 2112
2227 error = xfs_bmap_finish(&tp, &free_list, &committed); 2113 error = xfs_bmap_finish(&tp, &free_list, &committed);
2228 if (error) { 2114 if (error)
2229 REMOVE_DEBUG_TRACE(__LINE__); 2115 goto out_bmap_cancel;
2230 goto error_rele;
2231 }
2232 2116
2233 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 2117 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
2234 if (error) 2118 if (error)
@@ -2240,38 +2124,26 @@ xfs_remove(
2240 * will get killed on last close in xfs_close() so we don't 2124 * will get killed on last close in xfs_close() so we don't
2241 * have to worry about that. 2125 * have to worry about that.
2242 */ 2126 */
2243 if (link_zero && xfs_inode_is_filestream(ip)) 2127 if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
2244 xfs_filestream_deassociate(ip); 2128 xfs_filestream_deassociate(ip);
2245 2129
2246 xfs_itrace_exit(ip); 2130 xfs_itrace_exit(ip);
2131 xfs_itrace_exit(dp);
2247 2132
2248/* Fall through to std_return with error = 0 */
2249 std_return: 2133 std_return:
2250 if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) { 2134 if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
2251 (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, 2135 XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
2252 dp, DM_RIGHT_NULL, 2136 NULL, DM_RIGHT_NULL, name->name, NULL,
2253 NULL, DM_RIGHT_NULL, 2137 ip->i_d.di_mode, error, 0);
2254 name->name, NULL, ip->i_d.di_mode, error, 0);
2255 } 2138 }
2256 return error;
2257 2139
2258 error1: 2140 return error;
2259 xfs_bmap_cancel(&free_list);
2260 cancel_flags |= XFS_TRANS_ABORT;
2261 xfs_trans_cancel(tp, cancel_flags);
2262 goto std_return;
2263 2141
2264 error_rele: 2142 out_bmap_cancel:
2265 /*
2266 * In this case make sure to not release the inode until after
2267 * the current transaction is aborted. Releasing it beforehand
2268 * can cause us to go to xfs_inactive and start a recursive
2269 * transaction which can easily deadlock with the current one.
2270 */
2271 xfs_bmap_cancel(&free_list); 2143 xfs_bmap_cancel(&free_list);
2272 cancel_flags |= XFS_TRANS_ABORT; 2144 cancel_flags |= XFS_TRANS_ABORT;
2145 out_trans_cancel:
2273 xfs_trans_cancel(tp, cancel_flags); 2146 xfs_trans_cancel(tp, cancel_flags);
2274
2275 goto std_return; 2147 goto std_return;
2276} 2148}
2277 2149
@@ -2638,186 +2510,6 @@ std_return:
2638} 2510}
2639 2511
2640int 2512int
2641xfs_rmdir(
2642 xfs_inode_t *dp,
2643 struct xfs_name *name,
2644 xfs_inode_t *cdp)
2645{
2646 xfs_mount_t *mp = dp->i_mount;
2647 xfs_trans_t *tp;
2648 int error;
2649 xfs_bmap_free_t free_list;
2650 xfs_fsblock_t first_block;
2651 int cancel_flags;
2652 int committed;
2653 int last_cdp_link;
2654 uint resblks;
2655
2656 xfs_itrace_entry(dp);
2657
2658 if (XFS_FORCED_SHUTDOWN(mp))
2659 return XFS_ERROR(EIO);
2660
2661 if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
2662 error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
2663 dp, DM_RIGHT_NULL,
2664 NULL, DM_RIGHT_NULL, name->name,
2665 NULL, cdp->i_d.di_mode, 0, 0);
2666 if (error)
2667 return XFS_ERROR(error);
2668 }
2669
2670 /*
2671 * Get the dquots for the inodes.
2672 */
2673 error = XFS_QM_DQATTACH(mp, dp, 0);
2674 if (!error)
2675 error = XFS_QM_DQATTACH(mp, cdp, 0);
2676 if (error) {
2677 REMOVE_DEBUG_TRACE(__LINE__);
2678 goto std_return;
2679 }
2680
2681 tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
2682 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
2683 /*
2684 * We try to get the real space reservation first,
2685 * allowing for directory btree deletion(s) implying
2686 * possible bmap insert(s). If we can't get the space
2687 * reservation then we use 0 instead, and avoid the bmap
2688 * btree insert(s) in the directory code by, if the bmap
2689 * insert tries to happen, instead trimming the LAST
2690 * block from the directory.
2691 */
2692 resblks = XFS_REMOVE_SPACE_RES(mp);
2693 error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
2694 XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
2695 if (error == ENOSPC) {
2696 resblks = 0;
2697 error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
2698 XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
2699 }
2700 if (error) {
2701 ASSERT(error != ENOSPC);
2702 cancel_flags = 0;
2703 goto error_return;
2704 }
2705 XFS_BMAP_INIT(&free_list, &first_block);
2706
2707 /*
2708 * Now lock the child directory inode and the parent directory
2709 * inode in the proper order. This will take care of validating
2710 * that the directory entry for the child directory inode has
2711 * not changed while we were obtaining a log reservation.
2712 */
2713 error = xfs_lock_dir_and_entry(dp, cdp);
2714 if (error) {
2715 xfs_trans_cancel(tp, cancel_flags);
2716 goto std_return;
2717 }
2718
2719 IHOLD(dp);
2720 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
2721
2722 IHOLD(cdp);
2723 xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
2724
2725 ASSERT(cdp->i_d.di_nlink >= 2);
2726 if (cdp->i_d.di_nlink != 2) {
2727 error = XFS_ERROR(ENOTEMPTY);
2728 goto error_return;
2729 }
2730 if (!xfs_dir_isempty(cdp)) {
2731 error = XFS_ERROR(ENOTEMPTY);
2732 goto error_return;
2733 }
2734
2735 error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
2736 &first_block, &free_list, resblks);
2737 if (error)
2738 goto error1;
2739
2740 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
2741
2742 /*
2743 * Bump the in memory generation count on the parent
2744 * directory so that other can know that it has changed.
2745 */
2746 dp->i_gen++;
2747
2748 /*
2749 * Drop the link from cdp's "..".
2750 */
2751 error = xfs_droplink(tp, dp);
2752 if (error) {
2753 goto error1;
2754 }
2755
2756 /*
2757 * Drop the link from dp to cdp.
2758 */
2759 error = xfs_droplink(tp, cdp);
2760 if (error) {
2761 goto error1;
2762 }
2763
2764 /*
2765 * Drop the "." link from cdp to self.
2766 */
2767 error = xfs_droplink(tp, cdp);
2768 if (error) {
2769 goto error1;
2770 }
2771
2772 /* Determine these before committing transaction */
2773 last_cdp_link = (cdp)->i_d.di_nlink==0;
2774
2775 /*
2776 * If this is a synchronous mount, make sure that the
2777 * rmdir transaction goes to disk before returning to
2778 * the user.
2779 */
2780 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
2781 xfs_trans_set_sync(tp);
2782 }
2783
2784 error = xfs_bmap_finish (&tp, &free_list, &committed);
2785 if (error) {
2786 xfs_bmap_cancel(&free_list);
2787 xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
2788 XFS_TRANS_ABORT));
2789 goto std_return;
2790 }
2791
2792 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
2793 if (error) {
2794 goto std_return;
2795 }
2796
2797
2798 /* Fall through to std_return with error = 0 or the errno
2799 * from xfs_trans_commit. */
2800 std_return:
2801 if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
2802 (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
2803 dp, DM_RIGHT_NULL,
2804 NULL, DM_RIGHT_NULL,
2805 name->name, NULL, cdp->i_d.di_mode,
2806 error, 0);
2807 }
2808 return error;
2809
2810 error1:
2811 xfs_bmap_cancel(&free_list);
2812 cancel_flags |= XFS_TRANS_ABORT;
2813 /* FALLTHROUGH */
2814
2815 error_return:
2816 xfs_trans_cancel(tp, cancel_flags);
2817 goto std_return;
2818}
2819
2820int
2821xfs_symlink( 2513xfs_symlink(
2822 xfs_inode_t *dp, 2514 xfs_inode_t *dp,
2823 struct xfs_name *link_name, 2515 struct xfs_name *link_name,
@@ -3242,7 +2934,6 @@ xfs_finish_reclaim(
3242{ 2934{
3243 xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); 2935 xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
3244 bhv_vnode_t *vp = XFS_ITOV_NULL(ip); 2936 bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
3245 int error;
3246 2937
3247 if (vp && VN_BAD(vp)) 2938 if (vp && VN_BAD(vp))
3248 goto reclaim; 2939 goto reclaim;
@@ -3285,29 +2976,16 @@ xfs_finish_reclaim(
3285 xfs_iflock(ip); 2976 xfs_iflock(ip);
3286 } 2977 }
3287 2978
3288 if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { 2979 /*
3289 if (ip->i_update_core || 2980 * In the case of a forced shutdown we rely on xfs_iflush() to
3290 ((ip->i_itemp != NULL) && 2981 * wait for the inode to be unpinned before returning an error.
3291 (ip->i_itemp->ili_format.ilf_fields != 0))) { 2982 */
3292 error = xfs_iflush(ip, sync_mode); 2983 if (xfs_iflush(ip, sync_mode) == 0) {
3293 /* 2984 /* synchronize with xfs_iflush_done */
3294 * If we hit an error, typically because of filesystem 2985 xfs_iflock(ip);
3295 * shutdown, we don't need to let vn_reclaim to know 2986 xfs_ifunlock(ip);
3296 * because we're gonna reclaim the inode anyway.
3297 */
3298 if (error) {
3299 xfs_iunlock(ip, XFS_ILOCK_EXCL);
3300 goto reclaim;
3301 }
3302 xfs_iflock(ip); /* synchronize with xfs_iflush_done */
3303 }
3304
3305 ASSERT(ip->i_update_core == 0);
3306 ASSERT(ip->i_itemp == NULL ||
3307 ip->i_itemp->ili_format.ilf_fields == 0);
3308 } 2987 }
3309 2988
3310 xfs_ifunlock(ip);
3311 xfs_iunlock(ip, XFS_ILOCK_EXCL); 2989 xfs_iunlock(ip, XFS_ILOCK_EXCL);
3312 2990
3313 reclaim: 2991 reclaim:
@@ -3418,7 +3096,7 @@ xfs_alloc_file_space(
3418 3096
3419 /* Generate a DMAPI event if needed. */ 3097 /* Generate a DMAPI event if needed. */
3420 if (alloc_type != 0 && offset < ip->i_size && 3098 if (alloc_type != 0 && offset < ip->i_size &&
3421 (attr_flags&ATTR_DMI) == 0 && 3099 (attr_flags & XFS_ATTR_DMI) == 0 &&
3422 DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) { 3100 DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
3423 xfs_off_t end_dmi_offset; 3101 xfs_off_t end_dmi_offset;
3424 3102
@@ -3532,7 +3210,7 @@ retry:
3532 allocatesize_fsb -= allocated_fsb; 3210 allocatesize_fsb -= allocated_fsb;
3533 } 3211 }
3534dmapi_enospc_check: 3212dmapi_enospc_check:
3535 if (error == ENOSPC && (attr_flags & ATTR_DMI) == 0 && 3213 if (error == ENOSPC && (attr_flags & XFS_ATTR_DMI) == 0 &&
3536 DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) { 3214 DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) {
3537 error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE, 3215 error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE,
3538 ip, DM_RIGHT_NULL, 3216 ip, DM_RIGHT_NULL,
@@ -3679,7 +3357,7 @@ xfs_free_file_space(
3679 end_dmi_offset = offset + len; 3357 end_dmi_offset = offset + len;
3680 endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset); 3358 endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
3681 3359
3682 if (offset < ip->i_size && (attr_flags & ATTR_DMI) == 0 && 3360 if (offset < ip->i_size && (attr_flags & XFS_ATTR_DMI) == 0 &&
3683 DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) { 3361 DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
3684 if (end_dmi_offset > ip->i_size) 3362 if (end_dmi_offset > ip->i_size)
3685 end_dmi_offset = ip->i_size; 3363 end_dmi_offset = ip->i_size;
@@ -3690,7 +3368,7 @@ xfs_free_file_space(
3690 return error; 3368 return error;
3691 } 3369 }
3692 3370
3693 if (attr_flags & ATTR_NOLOCK) 3371 if (attr_flags & XFS_ATTR_NOLOCK)
3694 need_iolock = 0; 3372 need_iolock = 0;
3695 if (need_iolock) { 3373 if (need_iolock) {
3696 xfs_ilock(ip, XFS_IOLOCK_EXCL); 3374 xfs_ilock(ip, XFS_IOLOCK_EXCL);
@@ -3867,7 +3545,7 @@ xfs_change_file_space(
3867 xfs_off_t startoffset; 3545 xfs_off_t startoffset;
3868 xfs_off_t llen; 3546 xfs_off_t llen;
3869 xfs_trans_t *tp; 3547 xfs_trans_t *tp;
3870 bhv_vattr_t va; 3548 struct iattr iattr;
3871 3549
3872 xfs_itrace_entry(ip); 3550 xfs_itrace_entry(ip);
3873 3551
@@ -3941,10 +3619,10 @@ xfs_change_file_space(
3941 break; 3619 break;
3942 } 3620 }
3943 3621
3944 va.va_mask = XFS_AT_SIZE; 3622 iattr.ia_valid = ATTR_SIZE;
3945 va.va_size = startoffset; 3623 iattr.ia_size = startoffset;
3946 3624
3947 error = xfs_setattr(ip, &va, attr_flags, credp); 3625 error = xfs_setattr(ip, &iattr, attr_flags, credp);
3948 3626
3949 if (error) 3627 if (error)
3950 return error; 3628 return error;
@@ -3974,7 +3652,7 @@ xfs_change_file_space(
3974 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 3652 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
3975 xfs_trans_ihold(tp, ip); 3653 xfs_trans_ihold(tp, ip);
3976 3654
3977 if ((attr_flags & ATTR_DMI) == 0) { 3655 if ((attr_flags & XFS_ATTR_DMI) == 0) {
3978 ip->i_d.di_mode &= ~S_ISUID; 3656 ip->i_d.di_mode &= ~S_ISUID;
3979 3657
3980 /* 3658 /*
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index 57335ba4ce53..e932a96bec54 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -2,9 +2,9 @@
2#define _XFS_VNODEOPS_H 1 2#define _XFS_VNODEOPS_H 1
3 3
4struct attrlist_cursor_kern; 4struct attrlist_cursor_kern;
5struct bhv_vattr;
6struct cred; 5struct cred;
7struct file; 6struct file;
7struct iattr;
8struct inode; 8struct inode;
9struct iovec; 9struct iovec;
10struct kiocb; 10struct kiocb;
@@ -15,14 +15,18 @@ struct xfs_iomap;
15 15
16 16
17int xfs_open(struct xfs_inode *ip); 17int xfs_open(struct xfs_inode *ip);
18int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags, 18int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags,
19 struct cred *credp); 19 struct cred *credp);
20#define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */
21#define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if operation would block */
22#define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */
23
20int xfs_readlink(struct xfs_inode *ip, char *link); 24int xfs_readlink(struct xfs_inode *ip, char *link);
21int xfs_fsync(struct xfs_inode *ip); 25int xfs_fsync(struct xfs_inode *ip);
22int xfs_release(struct xfs_inode *ip); 26int xfs_release(struct xfs_inode *ip);
23int xfs_inactive(struct xfs_inode *ip); 27int xfs_inactive(struct xfs_inode *ip);
24int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, 28int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
25 struct xfs_inode **ipp); 29 struct xfs_inode **ipp, struct xfs_name *ci_name);
26int xfs_create(struct xfs_inode *dp, struct xfs_name *name, mode_t mode, 30int xfs_create(struct xfs_inode *dp, struct xfs_name *name, mode_t mode,
27 xfs_dev_t rdev, struct xfs_inode **ipp, struct cred *credp); 31 xfs_dev_t rdev, struct xfs_inode **ipp, struct cred *credp);
28int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, 32int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
@@ -31,8 +35,6 @@ int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
31 struct xfs_name *target_name); 35 struct xfs_name *target_name);
32int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name, 36int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
33 mode_t mode, struct xfs_inode **ipp, struct cred *credp); 37 mode_t mode, struct xfs_inode **ipp, struct cred *credp);
34int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
35 struct xfs_inode *cdp);
36int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize, 38int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize,
37 xfs_off_t *offset, filldir_t filldir); 39 xfs_off_t *offset, filldir_t filldir);
38int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, 40int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,