aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2005-05-17 18:53:14 -0400
committerTony Luck <tony.luck@intel.com>2005-05-17 18:53:14 -0400
commit325a479c4c110db278ef3361460a48c4093252cc (patch)
treebcfbf4d0647d9442045639a5c19da59d55190e81 /fs
parentebcc80c1b6629a445f7471cc1ddb48faf8a84e70 (diff)
parent7f9eaedf894dbaa08c157832e9a6c9c03ffed1ed (diff)
Merge with temp tree to get David's gdb inferior calls patch
Diffstat (limited to 'fs')
-rw-r--r--fs/afs/file.c3
-rw-r--r--fs/aio.c59
-rw-r--r--fs/autofs4/autofs_i.h15
-rw-r--r--fs/autofs4/expire.c16
-rw-r--r--fs/autofs4/inode.c1
-rw-r--r--fs/autofs4/waitq.c22
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/bio.c2
-rw-r--r--fs/buffer.c22
-rw-r--r--fs/cifs/AUTHORS24
-rw-r--r--fs/cifs/CHANGES39
-rw-r--r--fs/cifs/README43
-rw-r--r--fs/cifs/TODO30
-rw-r--r--fs/cifs/cifs_debug.c43
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifs_unicode.c4
-rw-r--r--fs/cifs/cifsencrypt.c16
-rw-r--r--fs/cifs/cifsfs.c34
-rw-r--r--fs/cifs/cifsfs.h8
-rw-r--r--fs/cifs/cifsglob.h18
-rw-r--r--fs/cifs/cifspdu.h71
-rw-r--r--fs/cifs/cifsproto.h109
-rw-r--r--fs/cifs/cifssmb.c436
-rw-r--r--fs/cifs/connect.c743
-rw-r--r--fs/cifs/dir.c189
-rw-r--r--fs/cifs/fcntl.c3
-rw-r--r--fs/cifs/file.c15
-rw-r--r--fs/cifs/inode.c106
-rw-r--r--fs/cifs/ioctl.c75
-rw-r--r--fs/cifs/link.c18
-rw-r--r--fs/cifs/misc.c160
-rw-r--r--fs/cifs/netmisc.c5
-rw-r--r--fs/cifs/readdir.c120
-rw-r--r--fs/cifs/smberr.h231
-rw-r--r--fs/cifs/transport.c54
-rw-r--r--fs/cifs/xattr.c51
-rw-r--r--fs/compat.c6
-rw-r--r--fs/ext3/inode.c144
-rw-r--r--fs/fcntl.c3
-rw-r--r--fs/fs-writeback.c4
-rw-r--r--fs/hfs/mdb.c5
-rw-r--r--fs/hfs/super.c8
-rw-r--r--fs/hfsplus/super.c6
-rw-r--r--fs/hostfs/hostfs_kern.c2
-rw-r--r--fs/jffs2/file.c3
-rw-r--r--fs/jfs/inode.c35
-rw-r--r--fs/jfs/jfs_dmap.c12
-rw-r--r--fs/jfs/jfs_dtree.c6
-rw-r--r--fs/jfs/jfs_imap.c84
-rw-r--r--fs/jfs/jfs_incore.h1
-rw-r--r--fs/jfs/jfs_logmgr.c150
-rw-r--r--fs/jfs/jfs_logmgr.h9
-rw-r--r--fs/jfs/jfs_metapage.c908
-rw-r--r--fs/jfs/jfs_metapage.h80
-rw-r--r--fs/jfs/jfs_mount.c5
-rw-r--r--fs/jfs/jfs_txnmgr.c166
-rw-r--r--fs/jfs/jfs_umount.c16
-rw-r--r--fs/jfs/jfs_xtree.c61
-rw-r--r--fs/jfs/resize.c3
-rw-r--r--fs/jfs/super.c37
-rw-r--r--fs/mpage.c94
-rw-r--r--fs/proc/base.c32
-rw-r--r--fs/reiserfs/bitmap.c11
-rw-r--r--fs/reiserfs/dir.c8
-rw-r--r--fs/reiserfs/file.c13
-rw-r--r--fs/reiserfs/inode.c14
-rw-r--r--fs/reiserfs/item_ops.c5
-rw-r--r--fs/reiserfs/journal.c14
-rw-r--r--fs/reiserfs/objectid.c18
-rw-r--r--fs/reiserfs/procfs.c4
-rw-r--r--fs/reiserfs/stree.c51
-rw-r--r--fs/reiserfs/super.c35
-rw-r--r--fs/seq_file.c9
-rw-r--r--fs/sysfs/file.c4
-rw-r--r--fs/udf/file.c6
-rw-r--r--fs/udf/inode.c4
76 files changed, 3107 insertions, 1757 deletions
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 6b6bb7c8abf6..23c125128024 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -131,8 +131,7 @@ static int afs_file_readpage(struct file *file, struct page *page)
131 131
132 vnode = AFS_FS_I(inode); 132 vnode = AFS_FS_I(inode);
133 133
134 if (!PageLocked(page)) 134 BUG_ON(!PageLocked(page));
135 PAGE_BUG(page);
136 135
137 ret = -ESTALE; 136 ret = -ESTALE;
138 if (vnode->flags & AFS_VNODE_DELETED) 137 if (vnode->flags & AFS_VNODE_DELETED)
diff --git a/fs/aio.c b/fs/aio.c
index a82214d2e46d..7afa222f6802 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -40,9 +40,6 @@
40#define dprintk(x...) do { ; } while (0) 40#define dprintk(x...) do { ; } while (0)
41#endif 41#endif
42 42
43static long aio_run = 0; /* for testing only */
44static long aio_wakeups = 0; /* for testing only */
45
46/*------ sysctl variables----*/ 43/*------ sysctl variables----*/
47atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ 44atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */
48unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ 45unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
@@ -405,7 +402,6 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
405 req->ki_ctx = ctx; 402 req->ki_ctx = ctx;
406 req->ki_cancel = NULL; 403 req->ki_cancel = NULL;
407 req->ki_retry = NULL; 404 req->ki_retry = NULL;
408 req->ki_obj.user = NULL;
409 req->ki_dtor = NULL; 405 req->ki_dtor = NULL;
410 req->private = NULL; 406 req->private = NULL;
411 INIT_LIST_HEAD(&req->ki_run_list); 407 INIT_LIST_HEAD(&req->ki_run_list);
@@ -451,11 +447,6 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
451{ 447{
452 if (req->ki_dtor) 448 if (req->ki_dtor)
453 req->ki_dtor(req); 449 req->ki_dtor(req);
454 req->ki_ctx = NULL;
455 req->ki_filp = NULL;
456 req->ki_obj.user = NULL;
457 req->ki_dtor = NULL;
458 req->private = NULL;
459 kmem_cache_free(kiocb_cachep, req); 450 kmem_cache_free(kiocb_cachep, req);
460 ctx->reqs_active--; 451 ctx->reqs_active--;
461 452
@@ -623,7 +614,6 @@ static inline int __queue_kicked_iocb(struct kiocb *iocb)
623 if (list_empty(&iocb->ki_run_list)) { 614 if (list_empty(&iocb->ki_run_list)) {
624 list_add_tail(&iocb->ki_run_list, 615 list_add_tail(&iocb->ki_run_list,
625 &ctx->run_list); 616 &ctx->run_list);
626 iocb->ki_queued++;
627 return 1; 617 return 1;
628 } 618 }
629 return 0; 619 return 0;
@@ -664,10 +654,8 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
664 } 654 }
665 655
666 if (!(iocb->ki_retried & 0xff)) { 656 if (!(iocb->ki_retried & 0xff)) {
667 pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n", 657 pr_debug("%ld retry: %d of %d\n", iocb->ki_retried,
668 iocb->ki_retried, 658 iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
669 iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
670 iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
671 } 659 }
672 660
673 if (!(retry = iocb->ki_retry)) { 661 if (!(retry = iocb->ki_retry)) {
@@ -774,7 +762,6 @@ out:
774static int __aio_run_iocbs(struct kioctx *ctx) 762static int __aio_run_iocbs(struct kioctx *ctx)
775{ 763{
776 struct kiocb *iocb; 764 struct kiocb *iocb;
777 int count = 0;
778 LIST_HEAD(run_list); 765 LIST_HEAD(run_list);
779 766
780 list_splice_init(&ctx->run_list, &run_list); 767 list_splice_init(&ctx->run_list, &run_list);
@@ -789,9 +776,7 @@ static int __aio_run_iocbs(struct kioctx *ctx)
789 aio_run_iocb(iocb); 776 aio_run_iocb(iocb);
790 if (__aio_put_req(ctx, iocb)) /* drop extra ref */ 777 if (__aio_put_req(ctx, iocb)) /* drop extra ref */
791 put_ioctx(ctx); 778 put_ioctx(ctx);
792 count++;
793 } 779 }
794 aio_run++;
795 if (!list_empty(&ctx->run_list)) 780 if (!list_empty(&ctx->run_list))
796 return 1; 781 return 1;
797 return 0; 782 return 0;
@@ -890,10 +875,8 @@ static void queue_kicked_iocb(struct kiocb *iocb)
890 spin_lock_irqsave(&ctx->ctx_lock, flags); 875 spin_lock_irqsave(&ctx->ctx_lock, flags);
891 run = __queue_kicked_iocb(iocb); 876 run = __queue_kicked_iocb(iocb);
892 spin_unlock_irqrestore(&ctx->ctx_lock, flags); 877 spin_unlock_irqrestore(&ctx->ctx_lock, flags);
893 if (run) { 878 if (run)
894 aio_queue_work(ctx); 879 aio_queue_work(ctx);
895 aio_wakeups++;
896 }
897} 880}
898 881
899/* 882/*
@@ -913,7 +896,6 @@ void fastcall kick_iocb(struct kiocb *iocb)
913 return; 896 return;
914 } 897 }
915 898
916 iocb->ki_kicked++;
917 /* If its already kicked we shouldn't queue it again */ 899 /* If its already kicked we shouldn't queue it again */
918 if (!kiocbTryKick(iocb)) { 900 if (!kiocbTryKick(iocb)) {
919 queue_kicked_iocb(iocb); 901 queue_kicked_iocb(iocb);
@@ -984,7 +966,8 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
984 966
985 tail = info->tail; 967 tail = info->tail;
986 event = aio_ring_event(info, tail, KM_IRQ0); 968 event = aio_ring_event(info, tail, KM_IRQ0);
987 tail = (tail + 1) % info->nr; 969 if (++tail >= info->nr)
970 tail = 0;
988 971
989 event->obj = (u64)(unsigned long)iocb->ki_obj.user; 972 event->obj = (u64)(unsigned long)iocb->ki_obj.user;
990 event->data = iocb->ki_user_data; 973 event->data = iocb->ki_user_data;
@@ -1008,10 +991,8 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
1008 991
1009 pr_debug("added to ring %p at [%lu]\n", iocb, tail); 992 pr_debug("added to ring %p at [%lu]\n", iocb, tail);
1010 993
1011 pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n", 994 pr_debug("%ld retries: %d of %d\n", iocb->ki_retried,
1012 iocb->ki_retried, 995 iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
1013 iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
1014 iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
1015put_rq: 996put_rq:
1016 /* everything turned out well, dispose of the aiocb. */ 997 /* everything turned out well, dispose of the aiocb. */
1017 ret = __aio_put_req(ctx, iocb); 998 ret = __aio_put_req(ctx, iocb);
@@ -1119,7 +1100,6 @@ static int read_events(struct kioctx *ctx,
1119 int i = 0; 1100 int i = 0;
1120 struct io_event ent; 1101 struct io_event ent;
1121 struct aio_timeout to; 1102 struct aio_timeout to;
1122 int event_loop = 0; /* testing only */
1123 int retry = 0; 1103 int retry = 0;
1124 1104
1125 /* needed to zero any padding within an entry (there shouldn't be 1105 /* needed to zero any padding within an entry (there shouldn't be
@@ -1186,7 +1166,6 @@ retry:
1186 if (to.timed_out) /* Only check after read evt */ 1166 if (to.timed_out) /* Only check after read evt */
1187 break; 1167 break;
1188 schedule(); 1168 schedule();
1189 event_loop++;
1190 if (signal_pending(tsk)) { 1169 if (signal_pending(tsk)) {
1191 ret = -EINTR; 1170 ret = -EINTR;
1192 break; 1171 break;
@@ -1214,9 +1193,6 @@ retry:
1214 if (timeout) 1193 if (timeout)
1215 clear_timeout(&to); 1194 clear_timeout(&to);
1216out: 1195out:
1217 pr_debug("event loop executed %d times\n", event_loop);
1218 pr_debug("aio_run %ld\n", aio_run);
1219 pr_debug("aio_wakeups %ld\n", aio_wakeups);
1220 return i ? i : ret; 1196 return i ? i : ret;
1221} 1197}
1222 1198
@@ -1515,8 +1491,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1515 } 1491 }
1516 1492
1517 req->ki_filp = file; 1493 req->ki_filp = file;
1518 iocb->aio_key = req->ki_key; 1494 ret = put_user(req->ki_key, &user_iocb->aio_key);
1519 ret = put_user(iocb->aio_key, &user_iocb->aio_key);
1520 if (unlikely(ret)) { 1495 if (unlikely(ret)) {
1521 dprintk("EFAULT: aio_key\n"); 1496 dprintk("EFAULT: aio_key\n");
1522 goto out_put_req; 1497 goto out_put_req;
@@ -1531,13 +1506,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1531 req->ki_opcode = iocb->aio_lio_opcode; 1506 req->ki_opcode = iocb->aio_lio_opcode;
1532 init_waitqueue_func_entry(&req->ki_wait, aio_wake_function); 1507 init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
1533 INIT_LIST_HEAD(&req->ki_wait.task_list); 1508 INIT_LIST_HEAD(&req->ki_wait.task_list);
1534 req->ki_run_list.next = req->ki_run_list.prev = NULL;
1535 req->ki_retry = NULL;
1536 req->ki_retried = 0; 1509 req->ki_retried = 0;
1537 req->ki_kicked = 0;
1538 req->ki_queued = 0;
1539 aio_run = 0;
1540 aio_wakeups = 0;
1541 1510
1542 ret = aio_setup_iocb(req); 1511 ret = aio_setup_iocb(req);
1543 1512
@@ -1545,10 +1514,14 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1545 goto out_put_req; 1514 goto out_put_req;
1546 1515
1547 spin_lock_irq(&ctx->ctx_lock); 1516 spin_lock_irq(&ctx->ctx_lock);
1548 list_add_tail(&req->ki_run_list, &ctx->run_list); 1517 if (likely(list_empty(&ctx->run_list))) {
1549 /* drain the run list */ 1518 aio_run_iocb(req);
1550 while (__aio_run_iocbs(ctx)) 1519 } else {
1551 ; 1520 list_add_tail(&req->ki_run_list, &ctx->run_list);
1521 /* drain the run list */
1522 while (__aio_run_iocbs(ctx))
1523 ;
1524 }
1552 spin_unlock_irq(&ctx->ctx_lock); 1525 spin_unlock_irq(&ctx->ctx_lock);
1553 aio_put_req(req); /* drop extra ref to req */ 1526 aio_put_req(req); /* drop extra ref to req */
1554 return 0; 1527 return 0;
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index f5a52c871726..c7b2b8890188 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -84,6 +84,7 @@ struct autofs_wait_queue {
84 char *name; 84 char *name;
85 /* This is for status reporting upon return */ 85 /* This is for status reporting upon return */
86 int status; 86 int status;
87 atomic_t notified;
87 atomic_t wait_ctr; 88 atomic_t wait_ctr;
88}; 89};
89 90
@@ -101,6 +102,7 @@ struct autofs_sb_info {
101 int needs_reghost; 102 int needs_reghost;
102 struct super_block *sb; 103 struct super_block *sb;
103 struct semaphore wq_sem; 104 struct semaphore wq_sem;
105 spinlock_t fs_lock;
104 struct autofs_wait_queue *queues; /* Wait queue pointer */ 106 struct autofs_wait_queue *queues; /* Wait queue pointer */
105}; 107};
106 108
@@ -126,9 +128,18 @@ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) {
126static inline int autofs4_ispending(struct dentry *dentry) 128static inline int autofs4_ispending(struct dentry *dentry)
127{ 129{
128 struct autofs_info *inf = autofs4_dentry_ino(dentry); 130 struct autofs_info *inf = autofs4_dentry_ino(dentry);
131 int pending = 0;
129 132
130 return (dentry->d_flags & DCACHE_AUTOFS_PENDING) || 133 if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
131 (inf != NULL && inf->flags & AUTOFS_INF_EXPIRING); 134 return 1;
135
136 if (inf) {
137 spin_lock(&inf->sbi->fs_lock);
138 pending = inf->flags & AUTOFS_INF_EXPIRING;
139 spin_unlock(&inf->sbi->fs_lock);
140 }
141
142 return pending;
132} 143}
133 144
134static inline void autofs4_copy_atime(struct file *src, struct file *dst) 145static inline void autofs4_copy_atime(struct file *src, struct file *dst)
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 31540a6404d9..500425e24fba 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -99,6 +99,10 @@ static int autofs4_check_tree(struct vfsmount *mnt,
99 if (!autofs4_can_expire(top, timeout, do_now)) 99 if (!autofs4_can_expire(top, timeout, do_now))
100 return 0; 100 return 0;
101 101
102 /* Is someone visiting anywhere in the tree ? */
103 if (may_umount_tree(mnt))
104 return 0;
105
102 spin_lock(&dcache_lock); 106 spin_lock(&dcache_lock);
103repeat: 107repeat:
104 next = this_parent->d_subdirs.next; 108 next = this_parent->d_subdirs.next;
@@ -270,10 +274,18 @@ static struct dentry *autofs4_expire(struct super_block *sb,
270 274
271 /* Case 2: tree mount, expire iff entire tree is not busy */ 275 /* Case 2: tree mount, expire iff entire tree is not busy */
272 if (!exp_leaves) { 276 if (!exp_leaves) {
277 /* Lock the tree as we must expire as a whole */
278 spin_lock(&sbi->fs_lock);
273 if (autofs4_check_tree(mnt, dentry, timeout, do_now)) { 279 if (autofs4_check_tree(mnt, dentry, timeout, do_now)) {
274 expired = dentry; 280 struct autofs_info *inf = autofs4_dentry_ino(dentry);
275 break; 281
282 /* Set this flag early to catch sys_chdir and the like */
283 inf->flags |= AUTOFS_INF_EXPIRING;
284 spin_unlock(&sbi->fs_lock);
285 expired = dentry;
286 break;
276 } 287 }
288 spin_unlock(&sbi->fs_lock);
277 /* Case 3: direct mount, expire individual leaves */ 289 /* Case 3: direct mount, expire individual leaves */
278 } else { 290 } else {
279 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); 291 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index a52560746628..4bb14cc68040 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -206,6 +206,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
206 sbi->version = 0; 206 sbi->version = 0;
207 sbi->sub_version = 0; 207 sbi->sub_version = 0;
208 init_MUTEX(&sbi->wq_sem); 208 init_MUTEX(&sbi->wq_sem);
209 spin_lock_init(&sbi->fs_lock);
209 sbi->queues = NULL; 210 sbi->queues = NULL;
210 s->s_blocksize = 1024; 211 s->s_blocksize = 1024;
211 s->s_blocksize_bits = 10; 212 s->s_blocksize_bits = 10;
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 1ab24a662e09..5a40d36e5a51 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -210,17 +210,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
210 wq->len = len; 210 wq->len = len;
211 wq->status = -EINTR; /* Status return if interrupted */ 211 wq->status = -EINTR; /* Status return if interrupted */
212 atomic_set(&wq->wait_ctr, 2); 212 atomic_set(&wq->wait_ctr, 2);
213 atomic_set(&wq->notified, 1);
213 up(&sbi->wq_sem); 214 up(&sbi->wq_sem);
214
215 DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d",
216 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
217 /* autofs4_notify_daemon() may block */
218 if (notify != NFY_NONE) {
219 autofs4_notify_daemon(sbi,wq,
220 notify == NFY_MOUNT ?
221 autofs_ptype_missing :
222 autofs_ptype_expire_multi);
223 }
224 } else { 215 } else {
225 atomic_inc(&wq->wait_ctr); 216 atomic_inc(&wq->wait_ctr);
226 up(&sbi->wq_sem); 217 up(&sbi->wq_sem);
@@ -229,6 +220,17 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
229 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); 220 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
230 } 221 }
231 222
223 if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) {
224 int type = (notify == NFY_MOUNT ?
225 autofs_ptype_missing : autofs_ptype_expire_multi);
226
227 DPRINTK(("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
228 (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify));
229
230 /* autofs4_notify_daemon() may block */
231 autofs4_notify_daemon(sbi, wq, type);
232 }
233
232 /* wq->name is NULL if and only if the lock is already released */ 234 /* wq->name is NULL if and only if the lock is already released */
233 235
234 if ( sbi->catatonic ) { 236 if ( sbi->catatonic ) {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 6ae62cbf7c2e..ce9423bb2de3 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -945,7 +945,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
945 retval = arch_setup_additional_pages(bprm, executable_stack); 945 retval = arch_setup_additional_pages(bprm, executable_stack);
946 if (retval < 0) { 946 if (retval < 0) {
947 send_sig(SIGKILL, current, 0); 947 send_sig(SIGKILL, current, 0);
948 goto out_free_dentry; 948 goto out;
949 } 949 }
950#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ 950#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
951 951
diff --git a/fs/bio.c b/fs/bio.c
index e5349e834563..3a1472acc361 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -140,6 +140,7 @@ inline void bio_init(struct bio *bio)
140 * bio_alloc_bioset - allocate a bio for I/O 140 * bio_alloc_bioset - allocate a bio for I/O
141 * @gfp_mask: the GFP_ mask given to the slab allocator 141 * @gfp_mask: the GFP_ mask given to the slab allocator
142 * @nr_iovecs: number of iovecs to pre-allocate 142 * @nr_iovecs: number of iovecs to pre-allocate
143 * @bs: the bio_set to allocate from
143 * 144 *
144 * Description: 145 * Description:
145 * bio_alloc_bioset will first try it's on mempool to satisfy the allocation. 146 * bio_alloc_bioset will first try it's on mempool to satisfy the allocation.
@@ -629,6 +630,7 @@ out:
629 630
630/** 631/**
631 * bio_map_user - map user address into bio 632 * bio_map_user - map user address into bio
633 * @q: the request_queue_t for the bio
632 * @bdev: destination block device 634 * @bdev: destination block device
633 * @uaddr: start of user address 635 * @uaddr: start of user address
634 * @len: length in bytes 636 * @len: length in bytes
diff --git a/fs/buffer.c b/fs/buffer.c
index 3b12cf947aba..5f525b3c6d9f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -218,7 +218,7 @@ struct super_block *freeze_bdev(struct block_device *bdev)
218 sb = get_super(bdev); 218 sb = get_super(bdev);
219 if (sb && !(sb->s_flags & MS_RDONLY)) { 219 if (sb && !(sb->s_flags & MS_RDONLY)) {
220 sb->s_frozen = SB_FREEZE_WRITE; 220 sb->s_frozen = SB_FREEZE_WRITE;
221 wmb(); 221 smp_wmb();
222 222
223 sync_inodes_sb(sb, 0); 223 sync_inodes_sb(sb, 0);
224 DQUOT_SYNC(sb); 224 DQUOT_SYNC(sb);
@@ -235,7 +235,7 @@ struct super_block *freeze_bdev(struct block_device *bdev)
235 sync_inodes_sb(sb, 1); 235 sync_inodes_sb(sb, 1);
236 236
237 sb->s_frozen = SB_FREEZE_TRANS; 237 sb->s_frozen = SB_FREEZE_TRANS;
238 wmb(); 238 smp_wmb();
239 239
240 sync_blockdev(sb->s_bdev); 240 sync_blockdev(sb->s_bdev);
241 241
@@ -263,7 +263,7 @@ void thaw_bdev(struct block_device *bdev, struct super_block *sb)
263 if (sb->s_op->unlockfs) 263 if (sb->s_op->unlockfs)
264 sb->s_op->unlockfs(sb); 264 sb->s_op->unlockfs(sb);
265 sb->s_frozen = SB_UNFROZEN; 265 sb->s_frozen = SB_UNFROZEN;
266 wmb(); 266 smp_wmb();
267 wake_up(&sb->s_wait_unfrozen); 267 wake_up(&sb->s_wait_unfrozen);
268 drop_super(sb); 268 drop_super(sb);
269 } 269 }
@@ -774,15 +774,14 @@ repeat:
774/** 774/**
775 * sync_mapping_buffers - write out and wait upon a mapping's "associated" 775 * sync_mapping_buffers - write out and wait upon a mapping's "associated"
776 * buffers 776 * buffers
777 * @buffer_mapping - the mapping which backs the buffers' data 777 * @mapping: the mapping which wants those buffers written
778 * @mapping - the mapping which wants those buffers written
779 * 778 *
780 * Starts I/O against the buffers at mapping->private_list, and waits upon 779 * Starts I/O against the buffers at mapping->private_list, and waits upon
781 * that I/O. 780 * that I/O.
782 * 781 *
783 * Basically, this is a convenience function for fsync(). @buffer_mapping is 782 * Basically, this is a convenience function for fsync().
784 * the blockdev which "owns" the buffers and @mapping is a file or directory 783 * @mapping is a file or directory which needs those buffers to be written for
785 * which needs those buffers to be written for a successful fsync(). 784 * a successful fsync().
786 */ 785 */
787int sync_mapping_buffers(struct address_space *mapping) 786int sync_mapping_buffers(struct address_space *mapping)
788{ 787{
@@ -1263,6 +1262,7 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
1263 1262
1264/** 1263/**
1265 * mark_buffer_dirty - mark a buffer_head as needing writeout 1264 * mark_buffer_dirty - mark a buffer_head as needing writeout
1265 * @bh: the buffer_head to mark dirty
1266 * 1266 *
1267 * mark_buffer_dirty() will set the dirty bit against the buffer, then set its 1267 * mark_buffer_dirty() will set the dirty bit against the buffer, then set its
1268 * backing page dirty, then tag the page as dirty in its address_space's radix 1268 * backing page dirty, then tag the page as dirty in its address_space's radix
@@ -1501,6 +1501,7 @@ EXPORT_SYMBOL(__breadahead);
1501 1501
1502/** 1502/**
1503 * __bread() - reads a specified block and returns the bh 1503 * __bread() - reads a specified block and returns the bh
1504 * @bdev: the block_device to read from
1504 * @block: number of block 1505 * @block: number of block
1505 * @size: size (in bytes) to read 1506 * @size: size (in bytes) to read
1506 * 1507 *
@@ -2078,8 +2079,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
2078 int nr, i; 2079 int nr, i;
2079 int fully_mapped = 1; 2080 int fully_mapped = 1;
2080 2081
2081 if (!PageLocked(page)) 2082 BUG_ON(!PageLocked(page));
2082 PAGE_BUG(page);
2083 blocksize = 1 << inode->i_blkbits; 2083 blocksize = 1 << inode->i_blkbits;
2084 if (!page_has_buffers(page)) 2084 if (!page_has_buffers(page))
2085 create_empty_buffers(page, blocksize, 0); 2085 create_empty_buffers(page, blocksize, 0);
@@ -2917,7 +2917,7 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free)
2917 2917
2918 bh = head; 2918 bh = head;
2919 do { 2919 do {
2920 if (buffer_write_io_error(bh)) 2920 if (buffer_write_io_error(bh) && page->mapping)
2921 set_bit(AS_EIO, &page->mapping->flags); 2921 set_bit(AS_EIO, &page->mapping->flags);
2922 if (buffer_busy(bh)) 2922 if (buffer_busy(bh))
2923 goto failed; 2923 goto failed;
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
index acce36e25d2e..72fdc10dfdd7 100644
--- a/fs/cifs/AUTHORS
+++ b/fs/cifs/AUTHORS
@@ -4,13 +4,16 @@ Steve French (sfrench@samba.org)
4 4
5The author wishes to express his appreciation and thanks to: 5The author wishes to express his appreciation and thanks to:
6Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS 6Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
7improvements. Thanks to IBM for allowing me the time and test resources to pursue 7improvements. Thanks to IBM for allowing me time and test resources to pursue
8this project. Jim McDonough from IBM (and the Samba Team) for his help. 8this project, to Jim McDonough from IBM (and the Samba Team) for his help, to
9The IBM Linux JFS team for explaining many esoteric Linux filesystem features. 9the IBM Linux JFS team for explaining many esoteric Linux filesystem features.
10Jeremy Allison of the Samba team has done invaluable work in adding the server
11side of the original CIFS Unix extensions and reviewing and implementing
12portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank
10Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) 13Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
11for proving years ago that a very good smb/cifs client could be done on a Unix like 14for proving years ago that very good smb/cifs clients could be done on Unix-like
12operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin 15operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John
13and others for their work on the Linux smbfs module over the years. Thanks to 16Newbigin and others for their work on the Linux smbfs module. Thanks to
14the other members of the Storage Network Industry Association CIFS Technical 17the other members of the Storage Network Industry Association CIFS Technical
15Workgroup for their work specifying this highly complex protocol and finally 18Workgroup for their work specifying this highly complex protocol and finally
16thanks to the Samba team for their technical advice and encouragement. 19thanks to the Samba team for their technical advice and encouragement.
@@ -24,9 +27,11 @@ Shobhit Dayal
24Sergey Vlasov 27Sergey Vlasov
25Richard Hughes 28Richard Hughes
26Yury Umanets 29Yury Umanets
27Mark Hamzy 30Mark Hamzy (for some of the early cifs IPv6 work)
28Domen Puncer 31Domen Puncer
29Jesper Juhl 32Jesper Juhl (in particular for lots of whitespace/formatting cleanup)
33Vince Negri and Dave Stahl (for finding an important caching bug)
34Adrian Bunk (kcalloc cleanups)
30 35
31Test case and Bug Report contributors 36Test case and Bug Report contributors
32------------------------------------- 37-------------------------------------
@@ -36,7 +41,8 @@ Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
36Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, 41Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
37Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special 42Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
38mention to the Stanford Checker (SWAT) which pointed out many minor 43mention to the Stanford Checker (SWAT) which pointed out many minor
39bugs in error paths. 44bugs in error paths. Valuable suggestions also have come from Al Viro
45and Dave Miller.
40 46
41And thanks to the IBM LTC and Power test teams and SuSE testers for 47And thanks to the IBM LTC and Power test teams and SuSE testers for
42finding multiple bugs during excellent stress test runs. 48finding multiple bugs during excellent stress test runs.
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 5316c8dd6bff..95483baab706 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,44 @@
1Version 1.31 1Version 1.34
2------------
3Fix error mapping of the TOO_MANY_LINKS (hardlinks) case.
4Do not oops if root user kills cifs oplock kernel thread or
5kills the cifsd thread (NB: killing the cifs kernel threads is not
6recommended, unmount and rmmod cifs will kill them when they are
7no longer needed). Fix readdir to ASCII servers (ie older servers
8which do not support Unicode) and also require asterik.
9
10
11Version 1.33
12------------
13Fix caching problem, in which readdir of directory containing a file
14which was cached could cause the file's time stamp to be updated
15without invalidating the readahead data (so we could get stale
16file data on the client for that file even as the server copy changed).
17Cleanup response processing so cifsd can not loop when abnormally
18terminated.
19
20
21Version 1.32
2------------ 22------------
3Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one 23Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
4transact response for an SMB request and search entry split across two frames. 24transact response for an SMB request and search entry split across two frames.
25Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server)
26as new protocol extensions. Do not send Get/Set calls for POSIX ACLs
27unless server explicitly claims to support them in CIFS Unix extensions
28POSIX ACL capability bit. Fix packet signing when multiuser mounting with
29different users from the same client to the same server. Fix oops in
30cifs_close. Add mount option for remapping reserved characters in
31filenames (also allow recognizing files with created by SFU which have any
32of these seven reserved characters, except backslash, to be recognized).
33Fix invalid transact2 message (we were sometimes trying to interpret
34oplock breaks as SMB responses). Add ioctl for checking that the
35current uid matches the uid of the mounter (needed by umount.cifs).
36Reduce the number of large buffer allocations in cifs response processing
37(significantly reduces memory pressure under heavy stress with multiple
38processes accessing the same server at the same time).
39
40Version 1.31
41------------
5Fix updates of DOS attributes and time fields so that files on NT4 servers 42Fix updates of DOS attributes and time fields so that files on NT4 servers
6do not get marked delete on close. Display sizes of cifs buffer pools in 43do not get marked delete on close. Display sizes of cifs buffer pools in
7cifs stats. Fix oops in unmount when cifsd thread being killed by 44cifs stats. Fix oops in unmount when cifsd thread being killed by
diff --git a/fs/cifs/README b/fs/cifs/README
index 0f20edc935b5..7b4ac096cd11 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -75,7 +75,7 @@ Allowing User Mounts
75==================== 75====================
76To permit users to mount and unmount over directories they own is possible 76To permit users to mount and unmount over directories they own is possible
77with the cifs vfs. A way to enable such mounting is to mark the mount.cifs 77with the cifs vfs. A way to enable such mounting is to mark the mount.cifs
78utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to 78utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to
79umount shares they mount requires 79umount shares they mount requires
801) mount.cifs version 1.4 or later 801) mount.cifs version 1.4 or later
812) an entry for the share in /etc/fstab indicating that a user may 812) an entry for the share in /etc/fstab indicating that a user may
@@ -97,6 +97,26 @@ mount.cifs with the following flag:
97There is a corresponding manual page for cifs mounting in the Samba 3.0 and 97There is a corresponding manual page for cifs mounting in the Samba 3.0 and
98later source tree in docs/manpages/mount.cifs.8 98later source tree in docs/manpages/mount.cifs.8
99 99
100Allowing User Unmounts
101======================
102To permit users to ummount directories that they have user mounted (see above),
103the utility umount.cifs may be used. It may be invoked directly, or if
104umount.cifs is placed in /sbin, umount can invoke the cifs umount helper
105(at least for most versions of the umount utility) for umount of cifs
106mounts, unless umount is invoked with -i (which will avoid invoking a umount
107helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked
108as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions
109allow adding entries to a file to the /etc/permissions file to achieve the
110equivalent suid effect). For this utility to succeed the target path
111must be a cifs mount, and the uid of the current user must match the uid
112of the user who mounted the resource.
113
114Also note that the customary way of allowing user mounts and unmounts is
115(instead of using mount.cifs and unmount.cifs as suid) to add a line
116to the file /etc/fstab for each //server/share you wish to mount, but
117this can become unwieldy when potential mount targets include many
118or unpredictable UNC names.
119
100Samba Considerations 120Samba Considerations
101==================== 121====================
102To get the maximum benefit from the CIFS VFS, we recommend using a server that 122To get the maximum benefit from the CIFS VFS, we recommend using a server that
@@ -376,6 +396,19 @@ A partial list of the supported mount options follows:
376 attributes) to the server (default) e.g. via setfattr 396 attributes) to the server (default) e.g. via setfattr
377 and getfattr utilities. 397 and getfattr utilities.
378 nouser_xattr Do not allow getfattr/setfattr to get/set xattrs 398 nouser_xattr Do not allow getfattr/setfattr to get/set xattrs
399 mapchars Translate six of the seven reserved characters (not backslash)
400 *?<>|:
401 to the remap range (above 0xF000), which also
402 allows the CIFS client to recognize files created with
403 such characters by Windows's POSIX emulation. This can
404 also be useful when mounting to most versions of Samba
405 (which also forbids creating and opening files
406 whose names contain any of these seven characters).
407 This has no effect if the server does not support
408 Unicode on the wire.
409 nomapchars Do not translate any of these seven characters (default).
410 remount remount the share (often used to change from ro to rw mounts
411 or vice versa)
379 412
380The mount.cifs mount helper also accepts a few mount options before -o 413The mount.cifs mount helper also accepts a few mount options before -o
381including: 414including:
@@ -392,7 +425,7 @@ Misc /proc/fs/cifs Flags and Debug Info
392======================================= 425=======================================
393Informational pseudo-files: 426Informational pseudo-files:
394DebugData Displays information about active CIFS sessions 427DebugData Displays information about active CIFS sessions
395 and shares. 428 and shares, as well as the cifs.ko version.
396Stats Lists summary resource usage information as well as per 429Stats Lists summary resource usage information as well as per
397 share statistics, if CONFIG_CIFS_STATS in enabled 430 share statistics, if CONFIG_CIFS_STATS in enabled
398 in the kernel configuration. 431 in the kernel configuration.
@@ -449,7 +482,7 @@ and for more extensive tracing including the start of smb requests and responses
449Two other experimental features are under development and to test 482Two other experimental features are under development and to test
450require enabling CONFIG_CIFS_EXPERIMENTAL 483require enabling CONFIG_CIFS_EXPERIMENTAL
451 484
452 More efficient write operations and SMB buffer handling 485 More efficient write operations
453 486
454 DNOTIFY fcntl: needed for support of directory change 487 DNOTIFY fcntl: needed for support of directory change
455 notification and perhaps later for file leases) 488 notification and perhaps later for file leases)
@@ -467,8 +500,8 @@ returned success.
467 500
468Also note that "cat /proc/fs/cifs/DebugData" will display information about 501Also note that "cat /proc/fs/cifs/DebugData" will display information about
469the active sessions and the shares that are mounted. Note: NTLMv2 enablement 502the active sessions and the shares that are mounted. Note: NTLMv2 enablement
470will not work since they its implementation is not quite complete yet. 503will not work since its implementation is not quite complete yet. Do not alter
471Do not alter these configuration values unless you are doing specific testing. 504the ExtendedSecurity configuration value unless you are doing specific testing.
472Enabling extended security works to Windows 2000 Workstations and XP but not to 505Enabling extended security works to Windows 2000 Workstations and XP but not to
473Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" 506Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
474(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not 507(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index f4e3e1f67ee4..8cc881694e29 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -1,4 +1,4 @@
1version 1.22 July 30, 2004 1version 1.34 April 29, 2005
2 2
3A Partial List of Missing Features 3A Partial List of Missing Features
4================================== 4==================================
@@ -14,7 +14,7 @@ b) Better pam/winbind integration (e.g. to handle uid mapping
14better) 14better)
15 15
16c) multi-user mounts - multiplexed sessionsetups over single vc 16c) multi-user mounts - multiplexed sessionsetups over single vc
17(ie tcp session) - prettying up needed, and more testing needed 17(ie tcp session) - more testing needed
18 18
19d) Kerberos/SPNEGO session setup support - (started) 19d) Kerberos/SPNEGO session setup support - (started)
20 20
@@ -67,12 +67,26 @@ q) implement support for security and trusted categories of xattrs
67 67
68r) Implement O_DIRECT flag on open (already supported on mount) 68r) Implement O_DIRECT flag on open (already supported on mount)
69 69
70KNOWN BUGS (updated December 10, 2004) 70s) Allow remapping of last remaining character (\) to +0xF000 which
71(this character is valid for POSIX but not for Windows)
72
73t) Create UID mapping facility so server UIDs can be mapped on a per
74mount or a per server basis to client UIDs or nobody if no mapping
75exists. This is helpful when Unix extensions are negotiated to
76allow better permission checking when UIDs differ on the server
77and client. Add new protocol request to the CIFS protocol
78standard for asking the server for the corresponding name of a
79particular uid.
80
81KNOWN BUGS (updated April 29, 2005)
71==================================== 82====================================
83See http://bugzilla.samba.org - search on product "CifsVFS" for
84current bug list.
85
721) existing symbolic links (Windows reparse points) are recognized but 861) existing symbolic links (Windows reparse points) are recognized but
73can not be created remotely. They are implemented for Samba and those that 87can not be created remotely. They are implemented for Samba and those that
74support the CIFS Unix extensions but Samba has a bug currently handling 88support the CIFS Unix extensions, although earlier versions of Samba
75symlink text beginning with slash 89overly restrict the pathnames.
762) follow_link and readdir code does not follow dfs junctions 902) follow_link and readdir code does not follow dfs junctions
77but recognizes them 91but recognizes them
783) create of new files to FAT partitions on Windows servers can 923) create of new files to FAT partitions on Windows servers can
@@ -98,7 +112,5 @@ there are some easy changes that can be done to parallelize sequential writes,
98and when signing is disabled to request larger read sizes (larger than 112and when signing is disabled to request larger read sizes (larger than
99negotiated size) and send larger write sizes to modern servers. 113negotiated size) and send larger write sizes to modern servers.
100 114
1014) More exhaustively test the recently added NT4 support against various 1154) More exhaustively test against less common servers. More testing
102NT4 service pack levels, and fix cifs_setattr for setting file times and 116against Windows 9x, Windows ME servers.
103size to fall back to level 1 when error invalid level returned.
104
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index db28b561cd4b..4061e43471c1 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs_debug.c 2 * fs/cifs_debug.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2000,2003 4 * Copyright (C) International Business Machines Corp., 2000,2005
5 * 5 *
6 * Modified by Steve French (sfrench@us.ibm.com) 6 * Modified by Steve French (sfrench@us.ibm.com)
7 * 7 *
@@ -29,6 +29,7 @@
29#include "cifsglob.h" 29#include "cifsglob.h"
30#include "cifsproto.h" 30#include "cifsproto.h"
31#include "cifs_debug.h" 31#include "cifs_debug.h"
32#include "cifsfs.h"
32 33
33void 34void
34cifs_dump_mem(char *label, void *data, int length) 35cifs_dump_mem(char *label, void *data, int length)
@@ -78,8 +79,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
78 "Display Internal CIFS Data Structures for Debugging\n" 79 "Display Internal CIFS Data Structures for Debugging\n"
79 "---------------------------------------------------\n"); 80 "---------------------------------------------------\n");
80 buf += length; 81 buf += length;
81 82 length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
82 length = sprintf(buf, "Servers:\n"); 83 buf += length;
84 length = sprintf(buf, "Servers:");
83 buf += length; 85 buf += length;
84 86
85 i = 0; 87 i = 0;
@@ -87,12 +89,21 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
87 list_for_each(tmp, &GlobalSMBSessionList) { 89 list_for_each(tmp, &GlobalSMBSessionList) {
88 i++; 90 i++;
89 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); 91 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
90 length = 92 if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
91 sprintf(buf, 93 (ses->serverNOS == NULL)) {
92 "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t", 94 buf += sprintf("\nentry for %s not fully displayed\n\t",
93 i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), 95 ses->serverName);
94 ses->serverOS, ses->serverNOS, ses->capabilities,ses->status); 96
95 buf += length; 97 } else {
98 length =
99 sprintf(buf,
100 "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
101 i, ses->serverName, ses->serverDomain,
102 atomic_read(&ses->inUse),
103 ses->serverOS, ses->serverNOS,
104 ses->capabilities,ses->status);
105 buf += length;
106 }
96 if(ses->server) { 107 if(ses->server) {
97 buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d", 108 buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
98 ses->server->tcpStatus, 109 ses->server->tcpStatus,
@@ -100,7 +111,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
100 ses->server->secMode, 111 ses->server->secMode,
101 atomic_read(&ses->server->inFlight)); 112 atomic_read(&ses->server->inFlight));
102 113
103 length = sprintf(buf, "\nMIDs: \n"); 114 length = sprintf(buf, "\nMIDs:\n");
104 buf += length; 115 buf += length;
105 116
106 spin_lock(&GlobalMid_Lock); 117 spin_lock(&GlobalMid_Lock);
@@ -109,7 +120,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
109 mid_q_entry, 120 mid_q_entry,
110 qhead); 121 qhead);
111 if(mid_entry) { 122 if(mid_entry) {
112 length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid); 123 length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",
124 mid_entry->midState,
125 (int)mid_entry->command,
126 mid_entry->pid,
127 mid_entry->tsk,
128 mid_entry->mid);
113 buf += length; 129 buf += length;
114 } 130 }
115 } 131 }
@@ -121,7 +137,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
121 sprintf(buf, "\n"); 137 sprintf(buf, "\n");
122 buf++; 138 buf++;
123 139
124 length = sprintf(buf, "\nShares:\n"); 140 length = sprintf(buf, "Shares:");
125 buf += length; 141 buf += length;
126 142
127 i = 0; 143 i = 0;
@@ -200,7 +216,8 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
200 buf += item_length; 216 buf += item_length;
201 item_length = 217 item_length =
202 sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n", 218 sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
203 bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter); 219 bufAllocCount.counter,
220 cifs_min_rcv + tcpSesAllocCount.counter);
204 length += item_length; 221 length += item_length;
205 buf += item_length; 222 buf += item_length;
206 item_length = 223 item_length =
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 77da902d8f32..ec00d61d5308 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -23,6 +23,7 @@
23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ 23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ 24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ 25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
26 27
27struct cifs_sb_info { 28struct cifs_sb_info {
28 struct cifsTconInfo *tcon; /* primary mount */ 29 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index a17adf4cb9ba..99a096d3f84d 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -76,8 +76,8 @@ cifs_strtoUCS(wchar_t * to, const char *from, int len,
76 charlen)); 76 charlen));
77 to[i] = cpu_to_le16(0x003f); /* a question mark */ 77 to[i] = cpu_to_le16(0x003f); /* a question mark */
78 charlen = 1; 78 charlen = 1;
79 } 79 } else
80 to[i] = cpu_to_le16(to[i]); 80 to[i] = cpu_to_le16(to[i]);
81 81
82 } 82 }
83 83
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 78829e7d8cd0..1959c7c4b185 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -50,7 +50,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char
50 return 0; 50 return 0;
51} 51}
52 52
53int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, 53int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
54 __u32 * pexpected_response_sequence_number) 54 __u32 * pexpected_response_sequence_number)
55{ 55{
56 int rc = 0; 56 int rc = 0;
@@ -59,21 +59,21 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */ 59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
60 /* BB remember to add code to save expected sequence number in midQ entry BB */ 60 /* BB remember to add code to save expected sequence number in midQ entry BB */
61 61
62 if((cifs_pdu == NULL) || (ses == NULL)) 62 if((cifs_pdu == NULL) || (server == NULL))
63 return -EINVAL; 63 return -EINVAL;
64 64
65 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 65 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
66 return rc; 66 return rc;
67 67
68 spin_lock(&GlobalMid_Lock); 68 spin_lock(&GlobalMid_Lock);
69 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number); 69 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number);
70 cifs_pdu->Signature.Sequence.Reserved = 0; 70 cifs_pdu->Signature.Sequence.Reserved = 0;
71 71
72 *pexpected_response_sequence_number = ses->sequence_number++; 72 *pexpected_response_sequence_number = server->sequence_number++;
73 ses->sequence_number++; 73 server->sequence_number++;
74 spin_unlock(&GlobalMid_Lock); 74 spin_unlock(&GlobalMid_Lock);
75 75
76 rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature); 76 rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature);
77 if(rc) 77 if(rc)
78 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 78 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
79 else 79 else
@@ -190,7 +190,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
190 hmac_md5_update((const unsigned char *) unicode_buf, 190 hmac_md5_update((const unsigned char *) unicode_buf,
191 (user_name_len+dom_name_len)*2,&ctx); 191 (user_name_len+dom_name_len)*2,&ctx);
192 192
193 hmac_md5_final(ses->mac_signing_key,&ctx); 193 hmac_md5_final(ses->server->mac_signing_key,&ctx);
194 kfree(ucase_buf); 194 kfree(ucase_buf);
195 kfree(unicode_buf); 195 kfree(unicode_buf);
196 return 0; 196 return 0;
@@ -200,7 +200,7 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon
200 struct HMACMD5Context context; 200 struct HMACMD5Context context;
201 memcpy(v2_session_response + 8, ses->server->cryptKey,8); 201 memcpy(v2_session_response + 8, ses->server->cryptKey,8);
202 /* gen_blob(v2_session_response + 16); */ 202 /* gen_blob(v2_session_response + 16); */
203 hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context); 203 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
204 204
205 hmac_md5_update(ses->server->cryptKey,8,&context); 205 hmac_md5_update(ses->server->cryptKey,8,&context);
206/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ 206/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 5082fce3c566..8cc23e7d0d5d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -169,7 +169,8 @@ cifs_put_super(struct super_block *sb)
169static int 169static int
170cifs_statfs(struct super_block *sb, struct kstatfs *buf) 170cifs_statfs(struct super_block *sb, struct kstatfs *buf)
171{ 171{
172 int xid, rc = -EOPNOTSUPP; 172 int xid;
173 int rc = -EOPNOTSUPP;
173 struct cifs_sb_info *cifs_sb; 174 struct cifs_sb_info *cifs_sb;
174 struct cifsTconInfo *pTcon; 175 struct cifsTconInfo *pTcon;
175 176
@@ -181,31 +182,34 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
181 buf->f_type = CIFS_MAGIC_NUMBER; 182 buf->f_type = CIFS_MAGIC_NUMBER;
182 183
183 /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ 184 /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
184 buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably 185 buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would
185 be length of total path, note that some servers may be 186 presumably be total path, but note
186 able to support more than this, but best to be safe 187 that some servers (includinng Samba 3)
187 since Win2k and others can not handle very long filenames */ 188 have a shorter maximum path */
188 buf->f_files = 0; /* undefined */ 189 buf->f_files = 0; /* undefined */
189 buf->f_ffree = 0; /* unlimited */ 190 buf->f_ffree = 0; /* unlimited */
190 191
191#ifdef CONFIG_CIFS_EXPERIMENTAL 192#ifdef CONFIG_CIFS_EXPERIMENTAL
192/* BB we could add a second check for a QFS Unix capability bit */ 193/* BB we could add a second check for a QFS Unix capability bit */
193 if (pTcon->ses->capabilities & CAP_UNIX) 194/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */
194 rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls); 195 if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS &
196 le64_to_cpu(pTcon->fsUnixInfo.Capability)))
197 rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf);
195 198
196 /* Only need to call the old QFSInfo if failed 199 /* Only need to call the old QFSInfo if failed
197 on newer one */ 200 on newer one */
198 if(rc) 201 if(rc)
199#endif /* CIFS_EXPERIMENTAL */ 202#endif /* CIFS_EXPERIMENTAL */
200 rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls); 203 rc = CIFSSMBQFSInfo(xid, pTcon, buf);
201 204
202 /* 205 /*
203 int f_type; 206 int f_type;
204 __fsid_t f_fsid; 207 __fsid_t f_fsid;
205 int f_namelen; */ 208 int f_namelen; */
206 /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */ 209 /* BB get from info in tcon struct at mount time call to QFSAttrInfo */
207 FreeXid(xid); 210 FreeXid(xid);
208 return 0; /* always return success? what if volume is no longer available? */ 211 return 0; /* always return success? what if volume is no
212 longer available? */
209} 213}
210 214
211static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) 215static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
@@ -559,6 +563,10 @@ struct file_operations cifs_file_ops = {
559 .flush = cifs_flush, 563 .flush = cifs_flush,
560 .mmap = cifs_file_mmap, 564 .mmap = cifs_file_mmap,
561 .sendfile = generic_file_sendfile, 565 .sendfile = generic_file_sendfile,
566#ifdef CONFIG_CIFS_POSIX
567 .ioctl = cifs_ioctl,
568#endif /* CONFIG_CIFS_POSIX */
569
562#ifdef CONFIG_CIFS_EXPERIMENTAL 570#ifdef CONFIG_CIFS_EXPERIMENTAL
563 .readv = generic_file_readv, 571 .readv = generic_file_readv,
564 .writev = generic_file_writev, 572 .writev = generic_file_writev,
@@ -579,6 +587,10 @@ struct file_operations cifs_file_direct_ops = {
579 .fsync = cifs_fsync, 587 .fsync = cifs_fsync,
580 .flush = cifs_flush, 588 .flush = cifs_flush,
581 .sendfile = generic_file_sendfile, /* BB removeme BB */ 589 .sendfile = generic_file_sendfile, /* BB removeme BB */
590#ifdef CONFIG_CIFS_POSIX
591 .ioctl = cifs_ioctl,
592#endif /* CONFIG_CIFS_POSIX */
593
582#ifdef CONFIG_CIFS_EXPERIMENTAL 594#ifdef CONFIG_CIFS_EXPERIMENTAL
583 .dir_notify = cifs_dir_notify, 595 .dir_notify = cifs_dir_notify,
584#endif /* CONFIG_CIFS_EXPERIMENTAL */ 596#endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -591,6 +603,7 @@ struct file_operations cifs_dir_ops = {
591#ifdef CONFIG_CIFS_EXPERIMENTAL 603#ifdef CONFIG_CIFS_EXPERIMENTAL
592 .dir_notify = cifs_dir_notify, 604 .dir_notify = cifs_dir_notify,
593#endif /* CONFIG_CIFS_EXPERIMENTAL */ 605#endif /* CONFIG_CIFS_EXPERIMENTAL */
606 .ioctl = cifs_ioctl,
594}; 607};
595 608
596static void 609static void
@@ -822,6 +835,7 @@ static int cifs_oplock_thread(void * dummyarg)
822 } 835 }
823 } while(!signal_pending(current)); 836 } while(!signal_pending(current));
824 complete_and_exit (&cifs_oplock_exited, 0); 837 complete_and_exit (&cifs_oplock_exited, 0);
838 oplockThread = NULL;
825} 839}
826 840
827static int __init 841static int __init
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 451f18af3206..d00b3bfe1a52 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsfs.h 2 * fs/cifs/cifsfs.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002 4 * Copyright (c) International Business Machines Corp., 2002, 2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -91,8 +91,10 @@ extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
91 const char *symname); 91 const char *symname);
92extern int cifs_removexattr(struct dentry *, const char *); 92extern int cifs_removexattr(struct dentry *, const char *);
93extern int cifs_setxattr(struct dentry *, const char *, const void *, 93extern int cifs_setxattr(struct dentry *, const char *, const void *,
94 size_t, int); 94 size_t, int);
95extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); 95extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
97#define CIFS_VERSION "1.31" 97extern int cifs_ioctl (struct inode * inode, struct file * filep,
98 unsigned int command, unsigned long arg);
99#define CIFS_VERSION "1.34"
98#endif /* _CIFSFS_H */ 100#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 69aff1a7da9b..81babab265e1 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsglob.h 2 * fs/cifs/cifsglob.h
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2003 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -149,6 +149,8 @@ struct TCP_Server_Info {
149 __u16 timeZone; 149 __u16 timeZone;
150 char cryptKey[CIFS_CRYPTO_KEY_SIZE]; 150 char cryptKey[CIFS_CRYPTO_KEY_SIZE];
151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */ 151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */
152 __u32 sequence_number; /* needed for CIFS PDU signature */
153 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
152}; 154};
153 155
154/* 156/*
@@ -174,17 +176,16 @@ struct cifsSesInfo {
174 struct TCP_Server_Info *server; /* pointer to server info */ 176 struct TCP_Server_Info *server; /* pointer to server info */
175 atomic_t inUse; /* # of mounts (tree connections) on this ses */ 177 atomic_t inUse; /* # of mounts (tree connections) on this ses */
176 enum statusEnum status; 178 enum statusEnum status;
177 __u32 sequence_number; /* needed for CIFS PDU signature */
178 __u16 ipc_tid; /* special tid for connection to IPC share */ 179 __u16 ipc_tid; /* special tid for connection to IPC share */
179 __u16 flags; 180 __u16 flags;
180 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 181 char *serverOS; /* name of operating system underlying server */
181 char *serverOS; /* name of operating system underlying the server */ 182 char *serverNOS; /* name of network operating system of server */
182 char *serverNOS; /* name of network operating system that the server is running */
183 char *serverDomain; /* security realm of server */ 183 char *serverDomain; /* security realm of server */
184 int Suid; /* remote smb uid */ 184 int Suid; /* remote smb uid */
185 uid_t linux_uid; /* local Linux uid */ 185 uid_t linux_uid; /* local Linux uid */
186 int capabilities; 186 int capabilities;
187 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */ 187 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
188 TCP names - will ipv6 and sctp addresses fit? */
188 char userName[MAX_USERNAME_SIZE + 1]; 189 char userName[MAX_USERNAME_SIZE + 1];
189 char domainName[MAX_USERNAME_SIZE + 1]; 190 char domainName[MAX_USERNAME_SIZE + 1];
190 char * password; 191 char * password;
@@ -312,12 +313,15 @@ struct mid_q_entry {
312 __u16 mid; /* multiplex id */ 313 __u16 mid; /* multiplex id */
313 __u16 pid; /* process id */ 314 __u16 pid; /* process id */
314 __u32 sequence_number; /* for CIFS signing */ 315 __u32 sequence_number; /* for CIFS signing */
315 __u16 command; /* smb command code */
316 struct timeval when_sent; /* time when smb sent */ 316 struct timeval when_sent; /* time when smb sent */
317 struct cifsSesInfo *ses; /* smb was sent to this server */ 317 struct cifsSesInfo *ses; /* smb was sent to this server */
318 struct task_struct *tsk; /* task waiting for response */ 318 struct task_struct *tsk; /* task waiting for response */
319 struct smb_hdr *resp_buf; /* response buffer */ 319 struct smb_hdr *resp_buf; /* response buffer */
320 int midState; /* wish this were enum but can not pass to wait_event */ 320 int midState; /* wish this were enum but can not pass to wait_event */
321 __u8 command; /* smb command code */
322 unsigned multiPart:1; /* multiple responses to one SMB request */
323 unsigned largeBuf:1; /* if valid response, is pointer to large buf */
324 unsigned multiResp:1; /* multiple trans2 responses for one request */
321}; 325};
322 326
323struct oplock_q_entry { 327struct oplock_q_entry {
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index bcd4a6136f08..aede6a813167 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -330,7 +330,7 @@ struct smb_hdr {
330}; 330};
331/* given a pointer to an smb_hdr retrieve the value of byte count */ 331/* given a pointer to an smb_hdr retrieve the value of byte count */
332#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) 332#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
333 333#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
334/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ 334/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
335#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) 335#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
336 336
@@ -762,6 +762,16 @@ typedef struct smb_com_lock_req {
762 LOCKING_ANDX_RANGE Locks[1]; 762 LOCKING_ANDX_RANGE Locks[1];
763} LOCK_REQ; 763} LOCK_REQ;
764 764
765
766typedef struct cifs_posix_lock {
767 __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
768 __le16 lock_flags; /* 1 = Wait (only valid for setlock) */
769 __le32 pid;
770 __le64 start;
771 __le64 length;
772 /* BB what about additional owner info to identify network client */
773} CIFS_POSIX_LOCK;
774
765typedef struct smb_com_lock_rsp { 775typedef struct smb_com_lock_rsp {
766 struct smb_hdr hdr; /* wct = 2 */ 776 struct smb_hdr hdr; /* wct = 2 */
767 __u8 AndXCommand; 777 __u8 AndXCommand;
@@ -1098,6 +1108,8 @@ struct smb_t2_rsp {
1098#define SMB_QUERY_POSIX_ACL 0x204 1108#define SMB_QUERY_POSIX_ACL 0x204
1099#define SMB_QUERY_XATTR 0x205 1109#define SMB_QUERY_XATTR 0x205
1100#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ 1110#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
1111#define SMB_QUERY_POSIX_PERMISSION 0x207
1112#define SMB_QUERY_POSIX_LOCK 0x208
1101#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee 1113#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
1102#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 1114#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
1103#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ 1115#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
@@ -1116,6 +1128,7 @@ struct smb_t2_rsp {
1116#define SMB_SET_POSIX_ACL 0x204 1128#define SMB_SET_POSIX_ACL 0x204
1117#define SMB_SET_XATTR 0x205 1129#define SMB_SET_XATTR 0x205
1118#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ 1130#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
1131#define SMB_SET_POSIX_LOCK 0x208
1119#define SMB_SET_FILE_BASIC_INFO2 0x3ec 1132#define SMB_SET_FILE_BASIC_INFO2 0x3ec
1120#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ 1133#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
1121#define SMB_FILE_ALL_INFO2 0x3fa 1134#define SMB_FILE_ALL_INFO2 0x3fa
@@ -1237,9 +1250,25 @@ struct smb_com_transaction2_sfi_rsp {
1237 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1250 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1238 struct trans2_resp t2; 1251 struct trans2_resp t2;
1239 __u16 ByteCount; 1252 __u16 ByteCount;
1240 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ 1253 __u16 Reserved2; /* parameter word reserved -
1254 present for infolevels > 100 */
1255};
1256
1257struct smb_t2_qfi_req {
1258 struct smb_hdr hdr;
1259 struct trans2_req t2;
1260 __u8 Pad;
1261 __u16 Fid;
1262 __le16 InformationLevel;
1241}; 1263};
1242 1264
1265struct smb_t2_qfi_rsp {
1266 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1267 struct trans2_resp t2;
1268 __u16 ByteCount;
1269 __u16 Reserved2; /* parameter word reserved -
1270 present for infolevels > 100 */
1271};
1243 1272
1244/* 1273/*
1245 * Flags on T2 FINDFIRST and FINDNEXT 1274 * Flags on T2 FINDFIRST and FINDNEXT
@@ -1524,9 +1553,10 @@ typedef struct {
1524} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1553} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1525/* Linux/Unix extensions capability flags */ 1554/* Linux/Unix extensions capability flags */
1526#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1555#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1527#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 1556#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1528#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/ 1557#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1529 1558#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1559#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1530typedef struct { 1560typedef struct {
1531 /* For undefined recommended transfer size return -1 in that field */ 1561 /* For undefined recommended transfer size return -1 in that field */
1532 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ 1562 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
@@ -1971,14 +2001,39 @@ struct xsymlink {
1971 char path[1024]; 2001 char path[1024];
1972}; 2002};
1973 2003
1974typedef struct { 2004typedef struct file_xattr_info {
1975 /* BB do we need another field for flags? BB */ 2005 /* BB do we need another field for flags? BB */
1976 __u32 xattr_name_len; 2006 __u32 xattr_name_len;
1977 __u32 xattr_value_len; 2007 __u32 xattr_value_len;
1978 char xattr_name[0]; 2008 char xattr_name[0];
1979 /* followed by xattr_value[xattr_value_len], no pad */ 2009 /* followed by xattr_value[xattr_value_len], no pad */
1980} FILE_XATTR_INFO; /* extended attribute, info level 205 */ 2010} FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
1981 2011
2012
2013/* flags for chattr command */
2014#define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */
2015#define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */
2016/* Reserved for compress file 0x4 */
2017#define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */
2018#define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */
2019#define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */
2020#define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */
2021#define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */
2022/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */
2023#define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */
2024/* 0x2000 reserved for IMAGIC_FL */
2025#define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */
2026/* 0x8000 reserved for EXT3_NOTAIL_FL */
2027#define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */
2028#define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */
2029
2030#define EXT_SET_MASK 0x000300FF
2031#define EXT_GET_MASK 0x0003DFFF
2032
2033typedef struct file_chattr_info {
2034 __le64 mask; /* list of all possible attribute bits */
2035 __le64 mode; /* list of actual attribute bits on this inode */
2036} FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
1982 2037
1983#endif 2038#endif
1984 2039
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 787eef4d86d3..0010511083fc 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -57,10 +57,11 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length,
57extern int cifs_inet_pton(int, char * source, void *dst); 57extern int cifs_inet_pton(int, char * source, void *dst);
58extern int map_smb_to_linux_error(struct smb_hdr *smb); 58extern int map_smb_to_linux_error(struct smb_hdr *smb);
59extern void header_assemble(struct smb_hdr *, char /* command */ , 59extern void header_assemble(struct smb_hdr *, char /* command */ ,
60 const struct cifsTconInfo *, int 60 const struct cifsTconInfo *, int /* specifies length
61 /* length of fixed section (word count) in two byte units */ 61 of fixed section (word count) in two byte units */
62 ); 62 );
63extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); 63extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
64 struct cifsTconInfo *);
64extern void DeleteOplockQEntry(struct oplock_q_entry *); 65extern void DeleteOplockQEntry(struct oplock_q_entry *);
65extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); 66extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
66extern u64 cifs_UnixTimeToNT(struct timespec); 67extern u64 cifs_UnixTimeToNT(struct timespec);
@@ -88,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
88 89
89extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 90extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
90 const char *searchName, const struct nls_table *nls_codepage, 91 const char *searchName, const struct nls_table *nls_codepage,
91 __u16 *searchHandle, struct cifs_search_info * psrch_inf); 92 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
92 93
93extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 94extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
94 __u16 searchHandle, struct cifs_search_info * psrch_inf); 95 __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -99,42 +100,42 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
99extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 100extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
100 const unsigned char *searchName, 101 const unsigned char *searchName,
101 FILE_ALL_INFO * findData, 102 FILE_ALL_INFO * findData,
102 const struct nls_table *nls_codepage); 103 const struct nls_table *nls_codepage, int remap);
103 104
104extern int CIFSSMBUnixQPathInfo(const int xid, 105extern int CIFSSMBUnixQPathInfo(const int xid,
105 struct cifsTconInfo *tcon, 106 struct cifsTconInfo *tcon,
106 const unsigned char *searchName, 107 const unsigned char *searchName,
107 FILE_UNIX_BASIC_INFO * pFindData, 108 FILE_UNIX_BASIC_INFO * pFindData,
108 const struct nls_table *nls_codepage); 109 const struct nls_table *nls_codepage, int remap);
109 110
110extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, 111extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
111 const unsigned char *searchName, 112 const unsigned char *searchName,
112 unsigned char **targetUNCs, 113 unsigned char **targetUNCs,
113 unsigned int *number_of_UNC_in_array, 114 unsigned int *number_of_UNC_in_array,
114 const struct nls_table *nls_codepage); 115 const struct nls_table *nls_codepage, int remap);
115 116
116extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 117extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
117 const char *old_path, 118 const char *old_path,
118 const struct nls_table *nls_codepage); 119 const struct nls_table *nls_codepage, int remap);
119extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 120extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
120 const char *old_path, const struct nls_table *nls_codepage, 121 const char *old_path,
121 unsigned int *pnum_referrals, unsigned char ** preferrals); 122 const struct nls_table *nls_codepage,
123 unsigned int *pnum_referrals,
124 unsigned char ** preferrals,
125 int remap);
122extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 126extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
123 struct kstatfs *FSData, 127 struct kstatfs *FSData);
124 const struct nls_table *nls_codepage);
125extern int CIFSSMBQFSAttributeInfo(const int xid, 128extern int CIFSSMBQFSAttributeInfo(const int xid,
126 struct cifsTconInfo *tcon, 129 struct cifsTconInfo *tcon);
127 const struct nls_table *nls_codepage); 130extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
128extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, 131extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon);
129 const struct nls_table *nls_codepage);
130extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
131 const struct nls_table *nls_codepage);
132extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 132extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
133 struct kstatfs *FSData, const struct nls_table *nls_codepage); 133 struct kstatfs *FSData);
134 134
135extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, 135extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
136 const char *fileName, const FILE_BASIC_INFO * data, 136 const char *fileName, const FILE_BASIC_INFO * data,
137 const struct nls_table *nls_codepage); 137 const struct nls_table *nls_codepage,
138 int remap_special_chars);
138extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, 139extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
139 const FILE_BASIC_INFO * data, __u16 fid); 140 const FILE_BASIC_INFO * data, __u16 fid);
140#if 0 141#if 0
@@ -143,36 +144,49 @@ extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
143 const struct nls_table *nls_codepage); 144 const struct nls_table *nls_codepage);
144#endif /* possibly unneeded function */ 145#endif /* possibly unneeded function */
145extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, 146extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
146 const char *fileName, __u64 size,int setAllocationSizeFlag, 147 const char *fileName, __u64 size,
147 const struct nls_table *nls_codepage); 148 int setAllocationSizeFlag,
149 const struct nls_table *nls_codepage,
150 int remap_special_chars);
148extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, 151extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
149 __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag); 152 __u64 size, __u16 fileHandle,__u32 opener_pid,
153 int AllocSizeFlag);
150extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, 154extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
151 char *full_path, __u64 mode, __u64 uid, 155 char *full_path, __u64 mode, __u64 uid,
152 __u64 gid, dev_t dev, const struct nls_table *nls_codepage); 156 __u64 gid, dev_t dev,
157 const struct nls_table *nls_codepage,
158 int remap_special_chars);
153 159
154extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, 160extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
155 const char *newName, 161 const char *newName,
156 const struct nls_table *nls_codepage); 162 const struct nls_table *nls_codepage,
163 int remap_special_chars);
157extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, 164extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
158 const char *name, const struct nls_table *nls_codepage); 165 const char *name, const struct nls_table *nls_codepage,
166 int remap_special_chars);
159 167
160extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, 168extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
161 const char *name, 169 const char *name,
162 const struct nls_table *nls_codepage); 170 const struct nls_table *nls_codepage,
171 int remap_special_chars);
163extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, 172extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
164 const char *fromName, const char *toName, 173 const char *fromName, const char *toName,
165 const struct nls_table *nls_codepage); 174 const struct nls_table *nls_codepage,
175 int remap_special_chars);
166extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 176extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
167 int netfid, char * target_name, const struct nls_table *nls_codepage); 177 int netfid, char * target_name,
178 const struct nls_table *nls_codepage,
179 int remap_special_chars);
168extern int CIFSCreateHardLink(const int xid, 180extern int CIFSCreateHardLink(const int xid,
169 struct cifsTconInfo *tcon, 181 struct cifsTconInfo *tcon,
170 const char *fromName, const char *toName, 182 const char *fromName, const char *toName,
171 const struct nls_table *nls_codepage); 183 const struct nls_table *nls_codepage,
184 int remap_special_chars);
172extern int CIFSUnixCreateHardLink(const int xid, 185extern int CIFSUnixCreateHardLink(const int xid,
173 struct cifsTconInfo *tcon, 186 struct cifsTconInfo *tcon,
174 const char *fromName, const char *toName, 187 const char *fromName, const char *toName,
175 const struct nls_table *nls_codepage); 188 const struct nls_table *nls_codepage,
189 int remap_special_chars);
176extern int CIFSUnixCreateSymLink(const int xid, 190extern int CIFSUnixCreateSymLink(const int xid,
177 struct cifsTconInfo *tcon, 191 struct cifsTconInfo *tcon,
178 const char *fromName, const char *toName, 192 const char *fromName, const char *toName,
@@ -192,7 +206,7 @@ extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
192 const char *fileName, const int disposition, 206 const char *fileName, const int disposition,
193 const int access_flags, const int omode, 207 const int access_flags, const int omode,
194 __u16 * netfid, int *pOplock, FILE_ALL_INFO *, 208 __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
195 const struct nls_table *nls_codepage); 209 const struct nls_table *nls_codepage, int remap);
196extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, 210extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
197 const int smb_file_id); 211 const int smb_file_id);
198 212
@@ -211,8 +225,13 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
211 const char __user *buf,const int long_op); 225 const char __user *buf,const int long_op);
212extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 226extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
213 const unsigned char *searchName, __u64 * inode_number, 227 const unsigned char *searchName, __u64 * inode_number,
214 const struct nls_table *nls_codepage); 228 const struct nls_table *nls_codepage,
229 int remap_special_chars);
215#endif /* CONFIG_CIFS_EXPERIMENTAL */ 230#endif /* CONFIG_CIFS_EXPERIMENTAL */
231extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen,
232 const struct nls_table * codepage);
233extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
234 const struct nls_table * cp, int mapChars);
216 235
217extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 236extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
218 const __u16 netfid, const __u64 len, 237 const __u16 netfid, const __u64 len,
@@ -230,7 +249,7 @@ extern void tconInfoFree(struct cifsTconInfo *);
230 249
231extern int cifs_reconnect(struct TCP_Server_Info *server); 250extern int cifs_reconnect(struct TCP_Server_Info *server);
232 251
233extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); 252extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
234extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 253extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
235 __u32 expected_sequence_number); 254 __u32 expected_sequence_number);
236extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 255extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
@@ -241,29 +260,31 @@ extern int CIFSSMBCopy(int xid,
241 const char *fromName, 260 const char *fromName,
242 const __u16 target_tid, 261 const __u16 target_tid,
243 const char *toName, const int flags, 262 const char *toName, const int flags,
244 const struct nls_table *nls_codepage); 263 const struct nls_table *nls_codepage,
264 int remap_special_chars);
245extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 265extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
246 const int notify_subdirs,const __u16 netfid,__u32 filter, 266 const int notify_subdirs,const __u16 netfid,
247 const struct nls_table *nls_codepage); 267 __u32 filter, const struct nls_table *nls_codepage);
248extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 268extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
249 const unsigned char *searchName, char * EAData, 269 const unsigned char *searchName, char * EAData,
250 size_t bufsize, const struct nls_table *nls_codepage); 270 size_t bufsize, const struct nls_table *nls_codepage,
271 int remap_special_chars);
251extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, 272extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
252 const unsigned char * searchName,const unsigned char * ea_name, 273 const unsigned char * searchName,const unsigned char * ea_name,
253 unsigned char * ea_value, size_t buf_size, 274 unsigned char * ea_value, size_t buf_size,
254 const struct nls_table *nls_codepage); 275 const struct nls_table *nls_codepage, int remap_special_chars);
255extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, 276extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
256 const char *fileName, const char * ea_name, 277 const char *fileName, const char * ea_name,
257 const void * ea_value, const __u16 ea_value_len, 278 const void * ea_value, const __u16 ea_value_len,
258 const struct nls_table *nls_codepage); 279 const struct nls_table *nls_codepage, int remap_special_chars);
259extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, 280extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
260 const unsigned char *searchName, 281 const unsigned char *searchName,
261 char *acl_inf, const int buflen,const int acl_type, 282 char *acl_inf, const int buflen,const int acl_type,
262 const struct nls_table *nls_codepage); 283 const struct nls_table *nls_codepage, int remap_special_chars);
263extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, 284extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
264 const unsigned char *fileName, 285 const unsigned char *fileName,
265 const char *local_acl, const int buflen, const int acl_type, 286 const char *local_acl, const int buflen, const int acl_type,
266 const struct nls_table *nls_codepage); 287 const struct nls_table *nls_codepage, int remap_special_chars);
267int cifs_ioctl (struct inode * inode, struct file * filep, 288extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
268 unsigned int command, unsigned long arg); 289 const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
269#endif /* _CIFSPROTO_H */ 290#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index df6a619a6821..741ff0c69f37 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -75,7 +75,8 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
75 } 75 }
76 } 76 }
77 write_unlock(&GlobalSMBSeslock); 77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */ 78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
79 to this tcon */
79} 80}
80 81
81/* If the return code is zero, this function must fill in request_buf pointer */ 82/* If the return code is zero, this function must fill in request_buf pointer */
@@ -89,11 +90,12 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
89 check for tcp and smb session status done differently 90 check for tcp and smb session status done differently
90 for those three - in the calling routine */ 91 for those three - in the calling routine */
91 if(tcon) { 92 if(tcon) {
92 if((tcon->ses) && (tcon->ses->server)){ 93 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
94 (tcon->ses->server)){
93 struct nls_table *nls_codepage; 95 struct nls_table *nls_codepage;
94 /* Give Demultiplex thread up to 10 seconds to 96 /* Give Demultiplex thread up to 10 seconds to
95 reconnect, should be greater than cifs socket 97 reconnect, should be greater than cifs socket
96 timeout which is 7 seconds */ 98 timeout which is 7 seconds */
97 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 99 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
98 wait_event_interruptible_timeout(tcon->ses->server->response_q, 100 wait_event_interruptible_timeout(tcon->ses->server->response_q,
99 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); 101 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
@@ -103,8 +105,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
103 (tcon->ses->status == CifsExiting)) { 105 (tcon->ses->status == CifsExiting)) {
104 cFYI(1,("gave up waiting on reconnect in smb_init")); 106 cFYI(1,("gave up waiting on reconnect in smb_init"));
105 return -EHOSTDOWN; 107 return -EHOSTDOWN;
106 } /* else "hard" mount - keep retrying until 108 } /* else "hard" mount - keep retrying
107 process is killed or server comes back up */ 109 until process is killed or server
110 comes back on-line */
108 } else /* TCP session is reestablished now */ 111 } else /* TCP session is reestablished now */
109 break; 112 break;
110 113
@@ -115,23 +118,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
115 simultaneously reconnect the same SMB session */ 118 simultaneously reconnect the same SMB session */
116 down(&tcon->ses->sesSem); 119 down(&tcon->ses->sesSem);
117 if(tcon->ses->status == CifsNeedReconnect) 120 if(tcon->ses->status == CifsNeedReconnect)
118 rc = cifs_setup_session(0, tcon->ses, nls_codepage); 121 rc = cifs_setup_session(0, tcon->ses,
122 nls_codepage);
119 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { 123 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
120 mark_open_files_invalid(tcon); 124 mark_open_files_invalid(tcon);
121 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, 125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
122 nls_codepage); 126 , nls_codepage);
123 up(&tcon->ses->sesSem); 127 up(&tcon->ses->sesSem);
124 if(rc == 0) 128 if(rc == 0)
125 atomic_inc(&tconInfoReconnectCount); 129 atomic_inc(&tconInfoReconnectCount);
126 130
127 cFYI(1, ("reconnect tcon rc = %d", rc)); 131 cFYI(1, ("reconnect tcon rc = %d", rc));
128 /* Removed call to reopen open files here - 132 /* Removed call to reopen open files here -
129 it is safer (and faster) to reopen files 133 it is safer (and faster) to reopen files
130 one at a time as needed in read and write */ 134 one at a time as needed in read and write */
131 135
132 /* Check if handle based operation so we 136 /* Check if handle based operation so we
133 know whether we can continue or not without 137 know whether we can continue or not without
134 returning to caller to reset file handle */ 138 returning to caller to reset file handle */
135 switch(smb_command) { 139 switch(smb_command) {
136 case SMB_COM_READ_ANDX: 140 case SMB_COM_READ_ANDX:
137 case SMB_COM_WRITE_ANDX: 141 case SMB_COM_WRITE_ANDX:
@@ -182,22 +186,25 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
182 check for tcp and smb session status done differently 186 check for tcp and smb session status done differently
183 for those three - in the calling routine */ 187 for those three - in the calling routine */
184 if(tcon) { 188 if(tcon) {
185 if((tcon->ses) && (tcon->ses->server)){ 189 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
190 (tcon->ses->server)){
186 struct nls_table *nls_codepage; 191 struct nls_table *nls_codepage;
187 /* Give Demultiplex thread up to 10 seconds to 192 /* Give Demultiplex thread up to 10 seconds to
188 reconnect, should be greater than cifs socket 193 reconnect, should be greater than cifs socket
189 timeout which is 7 seconds */ 194 timeout which is 7 seconds */
190 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 195 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
191 wait_event_interruptible_timeout(tcon->ses->server->response_q, 196 wait_event_interruptible_timeout(tcon->ses->server->response_q,
192 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); 197 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
193 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 198 if(tcon->ses->server->tcpStatus ==
199 CifsNeedReconnect) {
194 /* on "soft" mounts we wait once */ 200 /* on "soft" mounts we wait once */
195 if((tcon->retry == FALSE) || 201 if((tcon->retry == FALSE) ||
196 (tcon->ses->status == CifsExiting)) { 202 (tcon->ses->status == CifsExiting)) {
197 cFYI(1,("gave up waiting on reconnect in smb_init")); 203 cFYI(1,("gave up waiting on reconnect in smb_init"));
198 return -EHOSTDOWN; 204 return -EHOSTDOWN;
199 } /* else "hard" mount - keep retrying until 205 } /* else "hard" mount - keep retrying
200 process is killed or server comes back up */ 206 until process is killed or server
207 comes on-line */
201 } else /* TCP session is reestablished now */ 208 } else /* TCP session is reestablished now */
202 break; 209 break;
203 210
@@ -208,23 +215,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
208 simultaneously reconnect the same SMB session */ 215 simultaneously reconnect the same SMB session */
209 down(&tcon->ses->sesSem); 216 down(&tcon->ses->sesSem);
210 if(tcon->ses->status == CifsNeedReconnect) 217 if(tcon->ses->status == CifsNeedReconnect)
211 rc = cifs_setup_session(0, tcon->ses, nls_codepage); 218 rc = cifs_setup_session(0, tcon->ses,
219 nls_codepage);
212 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { 220 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
213 mark_open_files_invalid(tcon); 221 mark_open_files_invalid(tcon);
214 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, 222 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
215 nls_codepage); 223 tcon, nls_codepage);
216 up(&tcon->ses->sesSem); 224 up(&tcon->ses->sesSem);
217 if(rc == 0) 225 if(rc == 0)
218 atomic_inc(&tconInfoReconnectCount); 226 atomic_inc(&tconInfoReconnectCount);
219 227
220 cFYI(1, ("reconnect tcon rc = %d", rc)); 228 cFYI(1, ("reconnect tcon rc = %d", rc));
221 /* Removed call to reopen open files here - 229 /* Removed call to reopen open files here -
222 it is safer (and faster) to reopen files 230 it is safer (and faster) to reopen files
223 one at a time as needed in read and write */ 231 one at a time as needed in read and write */
224 232
225 /* Check if handle based operation so we 233 /* Check if handle based operation so we
226 know whether we can continue or not without 234 know whether we can continue or not without
227 returning to caller to reset file handle */ 235 returning to caller to reset file handle */
228 switch(smb_command) { 236 switch(smb_command) {
229 case SMB_COM_READ_ANDX: 237 case SMB_COM_READ_ANDX:
230 case SMB_COM_WRITE_ANDX: 238 case SMB_COM_WRITE_ANDX:
@@ -286,7 +294,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
286 if(total_size < 512) { 294 if(total_size < 512) {
287 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount); 295 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
288 /* BCC le converted in SendReceive */ 296 /* BCC le converted in SendReceive */
289 pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + 297 pBCC = (pSMB->hdr.WordCount * 2) +
298 sizeof(struct smb_hdr) +
290 (char *)pSMB; 299 (char *)pSMB;
291 if((total_size <= (*(u16 *)pBCC)) && 300 if((total_size <= (*(u16 *)pBCC)) &&
292 (total_size < 301 (total_size <
@@ -337,8 +346,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
337 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
338 if (rc == 0) { 347 if (rc == 0) {
339 server->secMode = pSMBr->SecurityMode; 348 server->secMode = pSMBr->SecurityMode;
340 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/ 349 server->secType = NTLM; /* BB override default for
341 /* one byte - no need to convert this or EncryptionKeyLen from le,*/ 350 NTLMv2 or kerberos v5 */
351 /* one byte - no need to convert this or EncryptionKeyLen
352 from little endian */
342 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 353 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
343 /* probably no need to store and check maxvcs */ 354 /* probably no need to store and check maxvcs */
344 server->maxBuf = 355 server->maxBuf =
@@ -374,7 +385,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
374 pSMBr->u.extended_response. 385 pSMBr->u.extended_response.
375 GUID, 16) != 0) { 386 GUID, 16) != 0) {
376 cFYI(1, 387 cFYI(1,
377 ("UID of server does not match previous connection to same ip address")); 388 ("UID of server does not match previous connection to same ip address"));
378 memcpy(server-> 389 memcpy(server->
379 server_GUID, 390 server_GUID,
380 pSMBr->u. 391 pSMBr->u.
@@ -454,17 +465,18 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
454 up(&tcon->tconSem); 465 up(&tcon->tconSem);
455 return -EIO; 466 return -EIO;
456 } 467 }
457 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer); 468 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
469 (void **)&smb_buffer);
458 if (rc) { 470 if (rc) {
459 up(&tcon->tconSem); 471 up(&tcon->tconSem);
460 return rc; 472 return rc;
461 } else { 473 } else {
462 smb_buffer_response = smb_buffer; /* BB removeme BB */ 474 smb_buffer_response = smb_buffer; /* BB removeme BB */
463 } 475 }
464 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, 476 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
465 &length, 0); 477 &length, 0);
466 if (rc) 478 if (rc)
467 cFYI(1, (" Tree disconnect failed %d", rc)); 479 cFYI(1, ("Tree disconnect failed %d", rc));
468 480
469 if (smb_buffer) 481 if (smb_buffer)
470 cifs_small_buf_release(smb_buffer); 482 cifs_small_buf_release(smb_buffer);
@@ -538,8 +550,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
538} 550}
539 551
540int 552int
541CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, 553CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
542 const char *fileName, const struct nls_table *nls_codepage) 554 const struct nls_table *nls_codepage, int remap)
543{ 555{
544 DELETE_FILE_REQ *pSMB = NULL; 556 DELETE_FILE_REQ *pSMB = NULL;
545 DELETE_FILE_RSP *pSMBr = NULL; 557 DELETE_FILE_RSP *pSMBr = NULL;
@@ -555,12 +567,11 @@ DelFileRetry:
555 567
556 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
557 name_len = 569 name_len =
558 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX 570 cifsConvertToUCS((__u16 *) pSMB->fileName, fileName,
559 /* find define for this maxpathcomponent */ 571 PATH_MAX, nls_codepage, remap);
560 , nls_codepage);
561 name_len++; /* trailing null */ 572 name_len++; /* trailing null */
562 name_len *= 2; 573 name_len *= 2;
563 } else { /* BB improve the check for buffer overruns BB */ 574 } else { /* BB improve check for buffer overruns BB */
564 name_len = strnlen(fileName, PATH_MAX); 575 name_len = strnlen(fileName, PATH_MAX);
565 name_len++; /* trailing null */ 576 name_len++; /* trailing null */
566 strncpy(pSMB->fileName, fileName, name_len); 577 strncpy(pSMB->fileName, fileName, name_len);
@@ -589,8 +600,8 @@ DelFileRetry:
589} 600}
590 601
591int 602int
592CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, 603CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
593 const char *dirName, const struct nls_table *nls_codepage) 604 const struct nls_table *nls_codepage, int remap)
594{ 605{
595 DELETE_DIRECTORY_REQ *pSMB = NULL; 606 DELETE_DIRECTORY_REQ *pSMB = NULL;
596 DELETE_DIRECTORY_RSP *pSMBr = NULL; 607 DELETE_DIRECTORY_RSP *pSMBr = NULL;
@@ -606,12 +617,11 @@ RmDirRetry:
606 return rc; 617 return rc;
607 618
608 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 619 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
609 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX 620 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
610 /* find define for this maxpathcomponent */ 621 PATH_MAX, nls_codepage, remap);
611 , nls_codepage);
612 name_len++; /* trailing null */ 622 name_len++; /* trailing null */
613 name_len *= 2; 623 name_len *= 2;
614 } else { /* BB improve the check for buffer overruns BB */ 624 } else { /* BB improve check for buffer overruns BB */
615 name_len = strnlen(dirName, PATH_MAX); 625 name_len = strnlen(dirName, PATH_MAX);
616 name_len++; /* trailing null */ 626 name_len++; /* trailing null */
617 strncpy(pSMB->DirName, dirName, name_len); 627 strncpy(pSMB->DirName, dirName, name_len);
@@ -639,7 +649,7 @@ RmDirRetry:
639 649
640int 650int
641CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, 651CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
642 const char *name, const struct nls_table *nls_codepage) 652 const char *name, const struct nls_table *nls_codepage, int remap)
643{ 653{
644 int rc = 0; 654 int rc = 0;
645 CREATE_DIRECTORY_REQ *pSMB = NULL; 655 CREATE_DIRECTORY_REQ *pSMB = NULL;
@@ -655,12 +665,11 @@ MkDirRetry:
655 return rc; 665 return rc;
656 666
657 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
658 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX 668 name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name,
659 /* find define for this maxpathcomponent */ 669 PATH_MAX, nls_codepage, remap);
660 , nls_codepage);
661 name_len++; /* trailing null */ 670 name_len++; /* trailing null */
662 name_len *= 2; 671 name_len *= 2;
663 } else { /* BB improve the check for buffer overruns BB */ 672 } else { /* BB improve check for buffer overruns BB */
664 name_len = strnlen(name, PATH_MAX); 673 name_len = strnlen(name, PATH_MAX);
665 name_len++; /* trailing null */ 674 name_len++; /* trailing null */
666 strncpy(pSMB->DirName, name, name_len); 675 strncpy(pSMB->DirName, name, name_len);
@@ -690,7 +699,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
690 const char *fileName, const int openDisposition, 699 const char *fileName, const int openDisposition,
691 const int access_flags, const int create_options, __u16 * netfid, 700 const int access_flags, const int create_options, __u16 * netfid,
692 int *pOplock, FILE_ALL_INFO * pfile_info, 701 int *pOplock, FILE_ALL_INFO * pfile_info,
693 const struct nls_table *nls_codepage) 702 const struct nls_table *nls_codepage, int remap)
694{ 703{
695 int rc = -EACCES; 704 int rc = -EACCES;
696 OPEN_REQ *pSMB = NULL; 705 OPEN_REQ *pSMB = NULL;
@@ -710,14 +719,12 @@ openRetry:
710 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
711 count = 1; /* account for one byte pad to word boundary */ 720 count = 1; /* account for one byte pad to word boundary */
712 name_len = 721 name_len =
713 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1), 722 cifsConvertToUCS((__u16 *) (pSMB->fileName + 1),
714 fileName, PATH_MAX 723 fileName, PATH_MAX, nls_codepage, remap);
715 /* find define for this maxpathcomponent */
716 , nls_codepage);
717 name_len++; /* trailing null */ 724 name_len++; /* trailing null */
718 name_len *= 2; 725 name_len *= 2;
719 pSMB->NameLength = cpu_to_le16(name_len); 726 pSMB->NameLength = cpu_to_le16(name_len);
720 } else { /* BB improve the check for buffer overruns BB */ 727 } else { /* BB improve check for buffer overruns BB */
721 count = 0; /* no pad */ 728 count = 0; /* no pad */
722 name_len = strnlen(fileName, PATH_MAX); 729 name_len = strnlen(fileName, PATH_MAX);
723 name_len++; /* trailing null */ 730 name_len++; /* trailing null */
@@ -746,7 +753,8 @@ openRetry:
746 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
747 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 754 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
748 pSMB->CreateOptions = cpu_to_le32(create_options); 755 pSMB->CreateOptions = cpu_to_le32(create_options);
749 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/ 756 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
750 pSMB->SecurityFlags = 758 pSMB->SecurityFlags =
751 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; 759 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
752 760
@@ -760,7 +768,7 @@ openRetry:
760 if (rc) { 768 if (rc) {
761 cFYI(1, ("Error in Open = %d", rc)); 769 cFYI(1, ("Error in Open = %d", rc));
762 } else { 770 } else {
763 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ 771 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
764 *netfid = pSMBr->Fid; /* cifs fid stays in le */ 772 *netfid = pSMBr->Fid; /* cifs fid stays in le */
765 /* Let caller know file was created so we can set the mode. */ 773 /* Let caller know file was created so we can set the mode. */
766 /* Do we care about the CreateAction in any other cases? */ 774 /* Do we care about the CreateAction in any other cases? */
@@ -1017,11 +1025,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1017 __u16 count; 1025 __u16 count;
1018 1026
1019 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock)); 1027 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1020 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB, 1028 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1021 (void **) &pSMBr); 1029
1022 if (rc) 1030 if (rc)
1023 return rc; 1031 return rc;
1024 1032
1033 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1034
1025 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) { 1035 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1026 timeout = -1; /* no response expected */ 1036 timeout = -1; /* no response expected */
1027 pSMB->Timeout = 0; 1037 pSMB->Timeout = 0;
@@ -1059,7 +1069,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1059 if (rc) { 1069 if (rc) {
1060 cFYI(1, ("Send error in Lock = %d", rc)); 1070 cFYI(1, ("Send error in Lock = %d", rc));
1061 } 1071 }
1062 cifs_buf_release(pSMB); 1072 cifs_small_buf_release(pSMB);
1063 1073
1064 /* Note: On -EAGAIN error only caller can retry on handle based calls 1074 /* Note: On -EAGAIN error only caller can retry on handle based calls
1065 since file handle passed in no longer valid */ 1075 since file handle passed in no longer valid */
@@ -1108,7 +1118,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1108int 1118int
1109CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, 1119CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1110 const char *fromName, const char *toName, 1120 const char *fromName, const char *toName,
1111 const struct nls_table *nls_codepage) 1121 const struct nls_table *nls_codepage, int remap)
1112{ 1122{
1113 int rc = 0; 1123 int rc = 0;
1114 RENAME_REQ *pSMB = NULL; 1124 RENAME_REQ *pSMB = NULL;
@@ -1131,18 +1141,16 @@ renameRetry:
1131 1141
1132 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1142 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1133 name_len = 1143 name_len =
1134 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX 1144 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
1135 /* find define for this maxpathcomponent */ 1145 PATH_MAX, nls_codepage, remap);
1136 , nls_codepage);
1137 name_len++; /* trailing null */ 1146 name_len++; /* trailing null */
1138 name_len *= 2; 1147 name_len *= 2;
1139 pSMB->OldFileName[name_len] = 0x04; /* pad */ 1148 pSMB->OldFileName[name_len] = 0x04; /* pad */
1140 /* protocol requires ASCII signature byte on Unicode string */ 1149 /* protocol requires ASCII signature byte on Unicode string */
1141 pSMB->OldFileName[name_len + 1] = 0x00; 1150 pSMB->OldFileName[name_len + 1] = 0x00;
1142 name_len2 = 1151 name_len2 =
1143 cifs_strtoUCS((wchar_t *) & pSMB-> 1152 cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2],
1144 OldFileName[name_len + 2], toName, PATH_MAX, 1153 toName, PATH_MAX, nls_codepage, remap);
1145 nls_codepage);
1146 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1154 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1147 name_len2 *= 2; /* convert to bytes */ 1155 name_len2 *= 2; /* convert to bytes */
1148 } else { /* BB improve the check for buffer overruns BB */ 1156 } else { /* BB improve the check for buffer overruns BB */
@@ -1182,7 +1190,8 @@ renameRetry:
1182} 1190}
1183 1191
1184int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 1192int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1185 int netfid, char * target_name, const struct nls_table * nls_codepage) 1193 int netfid, char * target_name,
1194 const struct nls_table * nls_codepage, int remap)
1186{ 1195{
1187 struct smb_com_transaction2_sfi_req *pSMB = NULL; 1196 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1188 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; 1197 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
@@ -1227,9 +1236,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1227 /* unicode only call */ 1236 /* unicode only call */
1228 if(target_name == NULL) { 1237 if(target_name == NULL) {
1229 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); 1238 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1230 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage); 1239 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
1240 dummy_string, 24, nls_codepage, remap);
1231 } else { 1241 } else {
1232 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage); 1242 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
1243 target_name, PATH_MAX, nls_codepage, remap);
1233 } 1244 }
1234 rename_info->target_name_len = cpu_to_le32(2 * len_of_str); 1245 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1235 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2; 1246 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
@@ -1263,7 +1274,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1263int 1274int
1264CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 1275CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1265 const __u16 target_tid, const char *toName, const int flags, 1276 const __u16 target_tid, const char *toName, const int flags,
1266 const struct nls_table *nls_codepage) 1277 const struct nls_table *nls_codepage, int remap)
1267{ 1278{
1268 int rc = 0; 1279 int rc = 0;
1269 COPY_REQ *pSMB = NULL; 1280 COPY_REQ *pSMB = NULL;
@@ -1285,18 +1296,16 @@ copyRetry:
1285 pSMB->Flags = cpu_to_le16(flags & COPY_TREE); 1296 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1286 1297
1287 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1298 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1288 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 1299 name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName,
1289 fromName, 1300 fromName, PATH_MAX, nls_codepage,
1290 PATH_MAX /* find define for this maxpathcomponent */, 1301 remap);
1291 nls_codepage);
1292 name_len++; /* trailing null */ 1302 name_len++; /* trailing null */
1293 name_len *= 2; 1303 name_len *= 2;
1294 pSMB->OldFileName[name_len] = 0x04; /* pad */ 1304 pSMB->OldFileName[name_len] = 0x04; /* pad */
1295 /* protocol requires ASCII signature byte on Unicode string */ 1305 /* protocol requires ASCII signature byte on Unicode string */
1296 pSMB->OldFileName[name_len + 1] = 0x00; 1306 pSMB->OldFileName[name_len + 1] = 0x00;
1297 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> 1307 name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
1298 OldFileName[name_len + 2], toName, PATH_MAX, 1308 toName, PATH_MAX, nls_codepage, remap);
1299 nls_codepage);
1300 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1309 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1301 name_len2 *= 2; /* convert to bytes */ 1310 name_len2 *= 2; /* convert to bytes */
1302 } else { /* BB improve the check for buffer overruns BB */ 1311 } else { /* BB improve the check for buffer overruns BB */
@@ -1425,7 +1434,7 @@ createSymLinkRetry:
1425int 1434int
1426CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, 1435CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1427 const char *fromName, const char *toName, 1436 const char *fromName, const char *toName,
1428 const struct nls_table *nls_codepage) 1437 const struct nls_table *nls_codepage, int remap)
1429{ 1438{
1430 TRANSACTION2_SPI_REQ *pSMB = NULL; 1439 TRANSACTION2_SPI_REQ *pSMB = NULL;
1431 TRANSACTION2_SPI_RSP *pSMBr = NULL; 1440 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -1444,9 +1453,8 @@ createHardLinkRetry:
1444 return rc; 1453 return rc;
1445 1454
1446 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1455 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1447 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX 1456 name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName,
1448 /* find define for this maxpathcomponent */ 1457 PATH_MAX, nls_codepage, remap);
1449 , nls_codepage);
1450 name_len++; /* trailing null */ 1458 name_len++; /* trailing null */
1451 name_len *= 2; 1459 name_len *= 2;
1452 1460
@@ -1468,9 +1476,8 @@ createHardLinkRetry:
1468 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 1476 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1469 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1477 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1470 name_len_target = 1478 name_len_target =
1471 cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX 1479 cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX,
1472 /* find define for this maxpathcomponent */ 1480 nls_codepage, remap);
1473 , nls_codepage);
1474 name_len_target++; /* trailing null */ 1481 name_len_target++; /* trailing null */
1475 name_len_target *= 2; 1482 name_len_target *= 2;
1476 } else { /* BB improve the check for buffer overruns BB */ 1483 } else { /* BB improve the check for buffer overruns BB */
@@ -1512,7 +1519,7 @@ createHardLinkRetry:
1512int 1519int
1513CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, 1520CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1514 const char *fromName, const char *toName, 1521 const char *fromName, const char *toName,
1515 const struct nls_table *nls_codepage) 1522 const struct nls_table *nls_codepage, int remap)
1516{ 1523{
1517 int rc = 0; 1524 int rc = 0;
1518 NT_RENAME_REQ *pSMB = NULL; 1525 NT_RENAME_REQ *pSMB = NULL;
@@ -1539,17 +1546,15 @@ winCreateHardLinkRetry:
1539 1546
1540 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1547 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1541 name_len = 1548 name_len =
1542 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX 1549 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
1543 /* find define for this maxpathcomponent */ 1550 PATH_MAX, nls_codepage, remap);
1544 , nls_codepage);
1545 name_len++; /* trailing null */ 1551 name_len++; /* trailing null */
1546 name_len *= 2; 1552 name_len *= 2;
1547 pSMB->OldFileName[name_len] = 0; /* pad */ 1553 pSMB->OldFileName[name_len] = 0; /* pad */
1548 pSMB->OldFileName[name_len + 1] = 0x04; 1554 pSMB->OldFileName[name_len + 1] = 0x04;
1549 name_len2 = 1555 name_len2 =
1550 cifs_strtoUCS((wchar_t *) & pSMB-> 1556 cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
1551 OldFileName[name_len + 2], toName, PATH_MAX, 1557 toName, PATH_MAX, nls_codepage, remap);
1552 nls_codepage);
1553 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1558 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1554 name_len2 *= 2; /* convert to bytes */ 1559 name_len2 *= 2; /* convert to bytes */
1555 } else { /* BB improve the check for buffer overruns BB */ 1560 } else { /* BB improve the check for buffer overruns BB */
@@ -1659,6 +1664,7 @@ querySymLinkRetry:
1659 name_len = UniStrnlen((wchar_t *) ((char *) 1664 name_len = UniStrnlen((wchar_t *) ((char *)
1660 &pSMBr->hdr.Protocol +data_offset), 1665 &pSMBr->hdr.Protocol +data_offset),
1661 min_t(const int, buflen,count) / 2); 1666 min_t(const int, buflen,count) / 2);
1667 /* BB FIXME investigate remapping reserved chars here */
1662 cifs_strfromUCS_le(symlinkinfo, 1668 cifs_strfromUCS_le(symlinkinfo,
1663 (wchar_t *) ((char *)&pSMBr->hdr.Protocol + 1669 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1664 data_offset), 1670 data_offset),
@@ -1793,7 +1799,8 @@ static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace
1793} 1799}
1794 1800
1795/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */ 1801/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1796static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area) 1802static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1803 const int acl_type,const int size_of_data_area)
1797{ 1804{
1798 int size = 0; 1805 int size = 0;
1799 int i; 1806 int i;
@@ -1912,7 +1919,7 @@ int
1912CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, 1919CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1913 const unsigned char *searchName, 1920 const unsigned char *searchName,
1914 char *acl_inf, const int buflen, const int acl_type, 1921 char *acl_inf, const int buflen, const int acl_type,
1915 const struct nls_table *nls_codepage) 1922 const struct nls_table *nls_codepage, int remap)
1916{ 1923{
1917/* SMB_QUERY_POSIX_ACL */ 1924/* SMB_QUERY_POSIX_ACL */
1918 TRANSACTION2_QPI_REQ *pSMB = NULL; 1925 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -1932,8 +1939,8 @@ queryAclRetry:
1932 1939
1933 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1934 name_len = 1941 name_len =
1935 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 1942 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
1936 , nls_codepage); 1943 PATH_MAX, nls_codepage, remap);
1937 name_len++; /* trailing null */ 1944 name_len++; /* trailing null */
1938 name_len *= 2; 1945 name_len *= 2;
1939 pSMB->FileName[name_len] = 0; 1946 pSMB->FileName[name_len] = 0;
@@ -1997,8 +2004,9 @@ queryAclRetry:
1997int 2004int
1998CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, 2005CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
1999 const unsigned char *fileName, 2006 const unsigned char *fileName,
2000 const char *local_acl, const int buflen, const int acl_type, 2007 const char *local_acl, const int buflen,
2001 const struct nls_table *nls_codepage) 2008 const int acl_type,
2009 const struct nls_table *nls_codepage, int remap)
2002{ 2010{
2003 struct smb_com_transaction2_spi_req *pSMB = NULL; 2011 struct smb_com_transaction2_spi_req *pSMB = NULL;
2004 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 2012 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -2016,8 +2024,8 @@ setAclRetry:
2016 return rc; 2024 return rc;
2017 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2018 name_len = 2026 name_len =
2019 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 2027 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
2020 , nls_codepage); 2028 PATH_MAX, nls_codepage, remap);
2021 name_len++; /* trailing null */ 2029 name_len++; /* trailing null */
2022 name_len *= 2; 2030 name_len *= 2;
2023 } else { /* BB improve the check for buffer overruns BB */ 2031 } else { /* BB improve the check for buffer overruns BB */
@@ -2072,13 +2080,96 @@ setACLerrorExit:
2072 return rc; 2080 return rc;
2073} 2081}
2074 2082
2075#endif 2083/* BB fix tabs in this function FIXME BB */
2084int
2085CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2086 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2087{
2088 int rc = 0;
2089 struct smb_t2_qfi_req *pSMB = NULL;
2090 struct smb_t2_qfi_rsp *pSMBr = NULL;
2091 int bytes_returned;
2092 __u16 params, byte_count;
2093
2094 cFYI(1,("In GetExtAttr"));
2095 if(tcon == NULL)
2096 return -ENODEV;
2097
2098GetExtAttrRetry:
2099 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2100 (void **) &pSMBr);
2101 if (rc)
2102 return rc;
2103
2104 params = 2 /* level */ +2 /* fid */;
2105 pSMB->t2.TotalDataCount = 0;
2106 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2107 /* BB find exact max data count below from sess structure BB */
2108 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2109 pSMB->t2.MaxSetupCount = 0;
2110 pSMB->t2.Reserved = 0;
2111 pSMB->t2.Flags = 0;
2112 pSMB->t2.Timeout = 0;
2113 pSMB->t2.Reserved2 = 0;
2114 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2115 Fid) - 4);
2116 pSMB->t2.DataCount = 0;
2117 pSMB->t2.DataOffset = 0;
2118 pSMB->t2.SetupCount = 1;
2119 pSMB->t2.Reserved3 = 0;
2120 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2121 byte_count = params + 1 /* pad */ ;
2122 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2123 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2124 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2125 pSMB->Pad = 0;
2126 pSMB->Fid = netfid;
2127 pSMB->hdr.smb_buf_length += byte_count;
2128 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2129
2130 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2131 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2132 if (rc) {
2133 cFYI(1, ("error %d in GetExtAttr", rc));
2134 } else {
2135 /* decode response */
2136 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2137 if (rc || (pSMBr->ByteCount < 2))
2138 /* BB also check enough total bytes returned */
2139 /* If rc should we check for EOPNOSUPP and
2140 disable the srvino flag? or in caller? */
2141 rc = -EIO; /* bad smb */
2142 else {
2143 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2144 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2145 struct file_chattr_info * pfinfo;
2146 /* BB Do we need a cast or hash here ? */
2147 if(count != 16) {
2148 cFYI(1, ("Illegal size ret in GetExtAttr"));
2149 rc = -EIO;
2150 goto GetExtAttrOut;
2151 }
2152 pfinfo = (struct file_chattr_info *)
2153 (data_offset + (char *) &pSMBr->hdr.Protocol);
2154 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2155 *pMask = le64_to_cpu(pfinfo->mask);
2156 }
2157 }
2158GetExtAttrOut:
2159 cifs_buf_release(pSMB);
2160 if (rc == -EAGAIN)
2161 goto GetExtAttrRetry;
2162 return rc;
2163}
2164
2165
2166#endif /* CONFIG_POSIX */
2076 2167
2077int 2168int
2078CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2169CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2079 const unsigned char *searchName, 2170 const unsigned char *searchName,
2080 FILE_ALL_INFO * pFindData, 2171 FILE_ALL_INFO * pFindData,
2081 const struct nls_table *nls_codepage) 2172 const struct nls_table *nls_codepage, int remap)
2082{ 2173{
2083/* level 263 SMB_QUERY_FILE_ALL_INFO */ 2174/* level 263 SMB_QUERY_FILE_ALL_INFO */
2084 TRANSACTION2_QPI_REQ *pSMB = NULL; 2175 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2097,9 +2188,8 @@ QPathInfoRetry:
2097 2188
2098 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2189 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2099 name_len = 2190 name_len =
2100 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 2191 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2101 /* find define for this maxpathcomponent */ 2192 PATH_MAX, nls_codepage, remap);
2102 , nls_codepage);
2103 name_len++; /* trailing null */ 2193 name_len++; /* trailing null */
2104 name_len *= 2; 2194 name_len *= 2;
2105 } else { /* BB improve the check for buffer overruns BB */ 2195 } else { /* BB improve the check for buffer overruns BB */
@@ -2160,7 +2250,7 @@ int
2160CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, 2250CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2161 const unsigned char *searchName, 2251 const unsigned char *searchName,
2162 FILE_UNIX_BASIC_INFO * pFindData, 2252 FILE_UNIX_BASIC_INFO * pFindData,
2163 const struct nls_table *nls_codepage) 2253 const struct nls_table *nls_codepage, int remap)
2164{ 2254{
2165/* SMB_QUERY_FILE_UNIX_BASIC */ 2255/* SMB_QUERY_FILE_UNIX_BASIC */
2166 TRANSACTION2_QPI_REQ *pSMB = NULL; 2256 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2179,9 +2269,8 @@ UnixQPathInfoRetry:
2179 2269
2180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2181 name_len = 2271 name_len =
2182 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 2272 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2183 /* find define for this maxpathcomponent */ 2273 PATH_MAX, nls_codepage, remap);
2184 , nls_codepage);
2185 name_len++; /* trailing null */ 2274 name_len++; /* trailing null */
2186 name_len *= 2; 2275 name_len *= 2;
2187 } else { /* BB improve the check for buffer overruns BB */ 2276 } else { /* BB improve the check for buffer overruns BB */
@@ -2261,7 +2350,7 @@ findUniqueRetry:
2261 2350
2262 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2351 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2263 name_len = 2352 name_len =
2264 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 2353 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2265 /* find define for this maxpathcomponent */ 2354 /* find define for this maxpathcomponent */
2266 , nls_codepage); 2355 , nls_codepage);
2267 name_len++; /* trailing null */ 2356 name_len++; /* trailing null */
@@ -2325,7 +2414,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2325 const char *searchName, 2414 const char *searchName,
2326 const struct nls_table *nls_codepage, 2415 const struct nls_table *nls_codepage,
2327 __u16 * pnetfid, 2416 __u16 * pnetfid,
2328 struct cifs_search_info * psrch_inf) 2417 struct cifs_search_info * psrch_inf, int remap)
2329{ 2418{
2330/* level 257 SMB_ */ 2419/* level 257 SMB_ */
2331 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2336,7 +2425,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2336 int name_len; 2425 int name_len;
2337 __u16 params, byte_count; 2426 __u16 params, byte_count;
2338 2427
2339 cFYI(1, ("In FindFirst")); 2428 cFYI(1, ("In FindFirst for %s",searchName));
2340 2429
2341findFirstRetry: 2430findFirstRetry:
2342 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 2431 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -2346,20 +2435,30 @@ findFirstRetry:
2346 2435
2347 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2436 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2348 name_len = 2437 name_len =
2349 cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName, 2438 cifsConvertToUCS((__u16 *) pSMB->FileName,searchName,
2350 PATH_MAX, nls_codepage); 2439 PATH_MAX, nls_codepage, remap);
2351 name_len++; /* trailing null */ 2440 /* We can not add the asterik earlier in case
2441 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */
2352 name_len *= 2; 2443 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\';
2445 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0;
2448 name_len += 4; /* now the trailing null */
2353 pSMB->FileName[name_len] = 0; /* null terminate just in case */ 2449 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2354 pSMB->FileName[name_len+1] = 0; 2450 pSMB->FileName[name_len+1] = 0;
2451 name_len += 2;
2355 } else { /* BB add check for overrun of SMB buf BB */ 2452 } else { /* BB add check for overrun of SMB buf BB */
2356 name_len = strnlen(searchName, PATH_MAX); 2453 name_len = strnlen(searchName, PATH_MAX);
2357 name_len++; /* trailing null */
2358/* BB fix here and in unicode clause above ie 2454/* BB fix here and in unicode clause above ie
2359 if(name_len > buffersize-header) 2455 if(name_len > buffersize-header)
2360 free buffer exit; BB */ 2456 free buffer exit; BB */
2361 strncpy(pSMB->FileName, searchName, name_len); 2457 strncpy(pSMB->FileName, searchName, name_len);
2362 pSMB->FileName[name_len] = 0; /* just in case */ 2458 pSMB->FileName[name_len] = '\\';
2459 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3;
2363 } 2462 }
2364 2463
2365 params = 12 + name_len /* includes null */ ; 2464 params = 12 + name_len /* includes null */ ;
@@ -2422,7 +2521,6 @@ findFirstRetry:
2422 psrch_inf->srch_entries_start = 2521 psrch_inf->srch_entries_start =
2423 (char *) &pSMBr->hdr.Protocol + 2522 (char *) &pSMBr->hdr.Protocol +
2424 le16_to_cpu(pSMBr->t2.DataOffset); 2523 le16_to_cpu(pSMBr->t2.DataOffset);
2425
2426 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + 2524 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2427 le16_to_cpu(pSMBr->t2.ParameterOffset)); 2525 le16_to_cpu(pSMBr->t2.ParameterOffset));
2428 2526
@@ -2434,7 +2532,6 @@ findFirstRetry:
2434 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); 2532 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2435 psrch_inf->index_of_last_entry = 2533 psrch_inf->index_of_last_entry =
2436 psrch_inf->entries_in_buffer; 2534 psrch_inf->entries_in_buffer;
2437/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2438 *pnetfid = parms->SearchHandle; 2535 *pnetfid = parms->SearchHandle;
2439 } else { 2536 } else {
2440 cifs_buf_release(pSMB); 2537 cifs_buf_release(pSMB);
@@ -2608,7 +2705,7 @@ int
2608CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 2705CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2609 const unsigned char *searchName, 2706 const unsigned char *searchName,
2610 __u64 * inode_number, 2707 __u64 * inode_number,
2611 const struct nls_table *nls_codepage) 2708 const struct nls_table *nls_codepage, int remap)
2612{ 2709{
2613 int rc = 0; 2710 int rc = 0;
2614 TRANSACTION2_QPI_REQ *pSMB = NULL; 2711 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2629,8 +2726,8 @@ GetInodeNumberRetry:
2629 2726
2630 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2727 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2631 name_len = 2728 name_len =
2632 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 2729 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2633 PATH_MAX,nls_codepage); 2730 PATH_MAX,nls_codepage, remap);
2634 name_len++; /* trailing null */ 2731 name_len++; /* trailing null */
2635 name_len *= 2; 2732 name_len *= 2;
2636 } else { /* BB improve the check for buffer overruns BB */ 2733 } else { /* BB improve the check for buffer overruns BB */
@@ -2704,7 +2801,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2704 const unsigned char *searchName, 2801 const unsigned char *searchName,
2705 unsigned char **targetUNCs, 2802 unsigned char **targetUNCs,
2706 unsigned int *number_of_UNC_in_array, 2803 unsigned int *number_of_UNC_in_array,
2707 const struct nls_table *nls_codepage) 2804 const struct nls_table *nls_codepage, int remap)
2708{ 2805{
2709/* TRANS2_GET_DFS_REFERRAL */ 2806/* TRANS2_GET_DFS_REFERRAL */
2710 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; 2807 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
@@ -2740,10 +2837,8 @@ getDFSRetry:
2740 if (ses->capabilities & CAP_UNICODE) { 2837 if (ses->capabilities & CAP_UNICODE) {
2741 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 2838 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2742 name_len = 2839 name_len =
2743 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName, 2840 cifsConvertToUCS((__u16 *) pSMB->RequestFileName,
2744 searchName, PATH_MAX 2841 searchName, PATH_MAX, nls_codepage, remap);
2745 /* find define for this maxpathcomponent */
2746 , nls_codepage);
2747 name_len++; /* trailing null */ 2842 name_len++; /* trailing null */
2748 name_len *= 2; 2843 name_len *= 2;
2749 } else { /* BB improve the check for buffer overruns BB */ 2844 } else { /* BB improve the check for buffer overruns BB */
@@ -2871,8 +2966,7 @@ GetDFSRefExit:
2871} 2966}
2872 2967
2873int 2968int
2874CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 2969CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
2875 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2876{ 2970{
2877/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ 2971/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2878 TRANSACTION2_QFSI_REQ *pSMB = NULL; 2972 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -2955,8 +3049,7 @@ QFSInfoRetry:
2955} 3049}
2956 3050
2957int 3051int
2958CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon, 3052CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
2959 const struct nls_table *nls_codepage)
2960{ 3053{
2961/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */ 3054/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
2962 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3055 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3024,8 +3117,7 @@ QFSAttributeRetry:
3024} 3117}
3025 3118
3026int 3119int
3027CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, 3120CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3028 const struct nls_table *nls_codepage)
3029{ 3121{
3030/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */ 3122/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3031 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3123 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3078,8 +3170,8 @@ QFSDeviceRetry:
3078 else { 3170 else {
3079 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 3171 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3080 response_data = 3172 response_data =
3081 (FILE_SYSTEM_DEVICE_INFO 3173 (FILE_SYSTEM_DEVICE_INFO *)
3082 *) (((char *) &pSMBr->hdr.Protocol) + 3174 (((char *) &pSMBr->hdr.Protocol) +
3083 data_offset); 3175 data_offset);
3084 memcpy(&tcon->fsDevInfo, response_data, 3176 memcpy(&tcon->fsDevInfo, response_data,
3085 sizeof (FILE_SYSTEM_DEVICE_INFO)); 3177 sizeof (FILE_SYSTEM_DEVICE_INFO));
@@ -3094,8 +3186,7 @@ QFSDeviceRetry:
3094} 3186}
3095 3187
3096int 3188int
3097CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, 3189CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3098 const struct nls_table *nls_codepage)
3099{ 3190{
3100/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */ 3191/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3101 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3192 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3166,7 +3257,7 @@ QFSUnixRetry:
3166 3257
3167int 3258int
3168CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3259CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3169 struct kstatfs *FSData, const struct nls_table *nls_codepage) 3260 struct kstatfs *FSData)
3170{ 3261{
3171/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */ 3262/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3172 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3263 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3258,7 +3349,8 @@ QFSPosixRetry:
3258 3349
3259int 3350int
3260CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, 3351CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3261 __u64 size, int SetAllocation, const struct nls_table *nls_codepage) 3352 __u64 size, int SetAllocation,
3353 const struct nls_table *nls_codepage, int remap)
3262{ 3354{
3263 struct smb_com_transaction2_spi_req *pSMB = NULL; 3355 struct smb_com_transaction2_spi_req *pSMB = NULL;
3264 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 3356 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -3277,9 +3369,8 @@ SetEOFRetry:
3277 3369
3278 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3370 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3279 name_len = 3371 name_len =
3280 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 3372 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3281 /* find define for this maxpathcomponent */ 3373 PATH_MAX, nls_codepage, remap);
3282 , nls_codepage);
3283 name_len++; /* trailing null */ 3374 name_len++; /* trailing null */
3284 name_len *= 2; 3375 name_len *= 2;
3285 } else { /* BB improve the check for buffer overruns BB */ 3376 } else { /* BB improve the check for buffer overruns BB */
@@ -3360,11 +3451,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3360 3451
3361 cFYI(1, ("SetFileSize (via SetFileInfo) %lld", 3452 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3362 (long long)size)); 3453 (long long)size));
3363 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 3454 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3364 (void **) &pSMBr); 3455
3365 if (rc) 3456 if (rc)
3366 return rc; 3457 return rc;
3367 3458
3459 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3460
3368 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); 3461 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3369 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); 3462 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3370 3463
@@ -3424,7 +3517,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3424 } 3517 }
3425 3518
3426 if (pSMB) 3519 if (pSMB)
3427 cifs_buf_release(pSMB); 3520 cifs_small_buf_release(pSMB);
3428 3521
3429 /* Note: On -EAGAIN error only caller can retry on handle based calls 3522 /* Note: On -EAGAIN error only caller can retry on handle based calls
3430 since file handle passed in no longer valid */ 3523 since file handle passed in no longer valid */
@@ -3450,11 +3543,13 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I
3450 __u16 params, param_offset, offset, byte_count, count; 3543 __u16 params, param_offset, offset, byte_count, count;
3451 3544
3452 cFYI(1, ("Set Times (via SetFileInfo)")); 3545 cFYI(1, ("Set Times (via SetFileInfo)"));
3453 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 3546 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3454 (void **) &pSMBr); 3547
3455 if (rc) 3548 if (rc)
3456 return rc; 3549 return rc;
3457 3550
3551 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3552
3458 /* At this point there is no need to override the current pid 3553 /* At this point there is no need to override the current pid
3459 with the pid of the opener, but that could change if we someday 3554 with the pid of the opener, but that could change if we someday
3460 use an existing handle (rather than opening one on the fly) */ 3555 use an existing handle (rather than opening one on the fly) */
@@ -3500,7 +3595,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I
3500 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc)); 3595 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3501 } 3596 }
3502 3597
3503 cifs_buf_release(pSMB); 3598 cifs_small_buf_release(pSMB);
3504 3599
3505 /* Note: On -EAGAIN error only caller can retry on handle based calls 3600 /* Note: On -EAGAIN error only caller can retry on handle based calls
3506 since file handle passed in no longer valid */ 3601 since file handle passed in no longer valid */
@@ -3512,7 +3607,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I
3512int 3607int
3513CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, 3608CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3514 const FILE_BASIC_INFO * data, 3609 const FILE_BASIC_INFO * data,
3515 const struct nls_table *nls_codepage) 3610 const struct nls_table *nls_codepage, int remap)
3516{ 3611{
3517 TRANSACTION2_SPI_REQ *pSMB = NULL; 3612 TRANSACTION2_SPI_REQ *pSMB = NULL;
3518 TRANSACTION2_SPI_RSP *pSMBr = NULL; 3613 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3532,9 +3627,8 @@ SetTimesRetry:
3532 3627
3533 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3628 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3534 name_len = 3629 name_len =
3535 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 3630 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3536 /* find define for this maxpathcomponent */ 3631 PATH_MAX, nls_codepage, remap);
3537 , nls_codepage);
3538 name_len++; /* trailing null */ 3632 name_len++; /* trailing null */
3539 name_len *= 2; 3633 name_len *= 2;
3540 } else { /* BB improve the check for buffer overruns BB */ 3634 } else { /* BB improve the check for buffer overruns BB */
@@ -3614,7 +3708,7 @@ SetAttrLgcyRetry:
3614 3708
3615 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3709 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3616 name_len = 3710 name_len =
3617 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 3711 ConvertToUCS((wchar_t *) pSMB->fileName, fileName,
3618 PATH_MAX, nls_codepage); 3712 PATH_MAX, nls_codepage);
3619 name_len++; /* trailing null */ 3713 name_len++; /* trailing null */
3620 name_len *= 2; 3714 name_len *= 2;
@@ -3644,8 +3738,9 @@ SetAttrLgcyRetry:
3644 3738
3645int 3739int
3646CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, 3740CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3647 char *fileName, __u64 mode, __u64 uid, __u64 gid, 3741 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3648 dev_t device, const struct nls_table *nls_codepage) 3742 dev_t device, const struct nls_table *nls_codepage,
3743 int remap)
3649{ 3744{
3650 TRANSACTION2_SPI_REQ *pSMB = NULL; 3745 TRANSACTION2_SPI_REQ *pSMB = NULL;
3651 TRANSACTION2_SPI_RSP *pSMBr = NULL; 3746 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3664,9 +3759,8 @@ setPermsRetry:
3664 3759
3665 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3760 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3666 name_len = 3761 name_len =
3667 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 3762 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3668 /* find define for this maxpathcomponent */ 3763 PATH_MAX, nls_codepage, remap);
3669 , nls_codepage);
3670 name_len++; /* trailing null */ 3764 name_len++; /* trailing null */
3671 name_len *= 2; 3765 name_len *= 2;
3672 } else { /* BB improve the check for buffer overruns BB */ 3766 } else { /* BB improve the check for buffer overruns BB */
@@ -3789,7 +3883,7 @@ ssize_t
3789CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 3883CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3790 const unsigned char *searchName, 3884 const unsigned char *searchName,
3791 char * EAData, size_t buf_size, 3885 char * EAData, size_t buf_size,
3792 const struct nls_table *nls_codepage) 3886 const struct nls_table *nls_codepage, int remap)
3793{ 3887{
3794 /* BB assumes one setup word */ 3888 /* BB assumes one setup word */
3795 TRANSACTION2_QPI_REQ *pSMB = NULL; 3889 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -3810,9 +3904,8 @@ QAllEAsRetry:
3810 3904
3811 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3812 name_len = 3906 name_len =
3813 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 3907 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName,
3814 /* find define for this maxpathcomponent */ 3908 PATH_MAX, nls_codepage, remap);
3815 , nls_codepage);
3816 name_len++; /* trailing null */ 3909 name_len++; /* trailing null */
3817 name_len *= 2; 3910 name_len *= 2;
3818 } else { /* BB improve the check for buffer overruns BB */ 3911 } else { /* BB improve the check for buffer overruns BB */
@@ -3934,7 +4027,7 @@ QAllEAsRetry:
3934ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, 4027ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
3935 const unsigned char * searchName,const unsigned char * ea_name, 4028 const unsigned char * searchName,const unsigned char * ea_name,
3936 unsigned char * ea_value, size_t buf_size, 4029 unsigned char * ea_value, size_t buf_size,
3937 const struct nls_table *nls_codepage) 4030 const struct nls_table *nls_codepage, int remap)
3938{ 4031{
3939 TRANSACTION2_QPI_REQ *pSMB = NULL; 4032 TRANSACTION2_QPI_REQ *pSMB = NULL;
3940 TRANSACTION2_QPI_RSP *pSMBr = NULL; 4033 TRANSACTION2_QPI_RSP *pSMBr = NULL;
@@ -3954,9 +4047,8 @@ QEARetry:
3954 4047
3955 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4048 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3956 name_len = 4049 name_len =
3957 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 4050 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
3958 /* find define for this maxpathcomponent */ 4051 PATH_MAX, nls_codepage, remap);
3959 , nls_codepage);
3960 name_len++; /* trailing null */ 4052 name_len++; /* trailing null */
3961 name_len *= 2; 4053 name_len *= 2;
3962 } else { /* BB improve the check for buffer overruns BB */ 4054 } else { /* BB improve the check for buffer overruns BB */
@@ -4082,7 +4174,8 @@ QEARetry:
4082int 4174int
4083CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, 4175CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4084 const char * ea_name, const void * ea_value, 4176 const char * ea_name, const void * ea_value,
4085 const __u16 ea_value_len, const struct nls_table *nls_codepage) 4177 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4178 int remap)
4086{ 4179{
4087 struct smb_com_transaction2_spi_req *pSMB = NULL; 4180 struct smb_com_transaction2_spi_req *pSMB = NULL;
4088 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 4181 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -4101,9 +4194,8 @@ SetEARetry:
4101 4194
4102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4103 name_len = 4196 name_len =
4104 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 4197 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
4105 /* find define for this maxpathcomponent */ 4198 PATH_MAX, nls_codepage, remap);
4106 , nls_codepage);
4107 name_len++; /* trailing null */ 4199 name_len++; /* trailing null */
4108 name_len *= 2; 4200 name_len *= 2;
4109 } else { /* BB improve the check for buffer overruns BB */ 4201 } else { /* BB improve the check for buffer overruns BB */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 40470b9d5477..e568cc47a7f9 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/connect.c 2 * fs/cifs/connect.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@
28#include <linux/ctype.h> 28#include <linux/ctype.h>
29#include <linux/utsname.h> 29#include <linux/utsname.h>
30#include <linux/mempool.h> 30#include <linux/mempool.h>
31#include <linux/delay.h>
31#include <asm/uaccess.h> 32#include <asm/uaccess.h>
32#include <asm/processor.h> 33#include <asm/processor.h>
33#include "cifspdu.h" 34#include "cifspdu.h"
@@ -72,6 +73,7 @@ struct smb_vol {
72 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ 73 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
73 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ 74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
74 unsigned direct_io:1; 75 unsigned direct_io:1;
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */
75 unsigned int rsize; 77 unsigned int rsize;
76 unsigned int wsize; 78 unsigned int wsize;
77 unsigned int sockopt; 79 unsigned int sockopt;
@@ -114,7 +116,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
114 spin_unlock(&GlobalMid_Lock); 116 spin_unlock(&GlobalMid_Lock);
115 server->maxBuf = 0; 117 server->maxBuf = 0;
116 118
117 cFYI(1, ("Reconnecting tcp session ")); 119 cFYI(1, ("Reconnecting tcp session"));
118 120
119 /* before reconnecting the tcp session, mark the smb session (uid) 121 /* before reconnecting the tcp session, mark the smb session (uid)
120 and the tid bad so they are not used until reconnected */ 122 and the tid bad so they are not used until reconnected */
@@ -155,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
155 qhead); 157 qhead);
156 if(mid_entry) { 158 if(mid_entry) {
157 if(mid_entry->midState == MID_REQUEST_SUBMITTED) { 159 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
158 /* Mark other intransit requests as needing retry so 160 /* Mark other intransit requests as needing
159 we do not immediately mark the session bad again 161 retry so we do not immediately mark the
160 (ie after we reconnect below) as they timeout too */ 162 session bad again (ie after we reconnect
163 below) as they timeout too */
161 mid_entry->midState = MID_RETRY_NEEDED; 164 mid_entry->midState = MID_RETRY_NEEDED;
162 } 165 }
163 } 166 }
@@ -175,14 +178,14 @@ cifs_reconnect(struct TCP_Server_Info *server)
175 server->workstation_RFC1001_name); 178 server->workstation_RFC1001_name);
176 } 179 }
177 if(rc) { 180 if(rc) {
178 set_current_state(TASK_INTERRUPTIBLE); 181 msleep(3000);
179 schedule_timeout(3 * HZ);
180 } else { 182 } else {
181 atomic_inc(&tcpSesReconnectCount); 183 atomic_inc(&tcpSesReconnectCount);
182 spin_lock(&GlobalMid_Lock); 184 spin_lock(&GlobalMid_Lock);
183 if(server->tcpStatus != CifsExiting) 185 if(server->tcpStatus != CifsExiting)
184 server->tcpStatus = CifsGood; 186 server->tcpStatus = CifsGood;
185 spin_unlock(&GlobalMid_Lock); 187 server->sequence_number = 0;
188 spin_unlock(&GlobalMid_Lock);
186 /* atomic_set(&server->inFlight,0);*/ 189 /* atomic_set(&server->inFlight,0);*/
187 wake_up(&server->response_q); 190 wake_up(&server->response_q);
188 } 191 }
@@ -190,12 +193,129 @@ cifs_reconnect(struct TCP_Server_Info *server)
190 return rc; 193 return rc;
191} 194}
192 195
196/*
197 return codes:
198 0 not a transact2, or all data present
199 >0 transact2 with that much data missing
200 -EINVAL = invalid transact2
201
202 */
203static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
204{
205 struct smb_t2_rsp * pSMBt;
206 int total_data_size;
207 int data_in_this_rsp;
208 int remaining;
209
210 if(pSMB->Command != SMB_COM_TRANSACTION2)
211 return 0;
212
213 /* check for plausible wct, bcc and t2 data and parm sizes */
214 /* check for parm and data offset going beyond end of smb */
215 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
216 cFYI(1,("invalid transact2 word count"));
217 return -EINVAL;
218 }
219
220 pSMBt = (struct smb_t2_rsp *)pSMB;
221
222 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
223 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
224
225 remaining = total_data_size - data_in_this_rsp;
226
227 if(remaining == 0)
228 return 0;
229 else if(remaining < 0) {
230 cFYI(1,("total data %d smaller than data in frame %d",
231 total_data_size, data_in_this_rsp));
232 return -EINVAL;
233 } else {
234 cFYI(1,("missing %d bytes from transact2, check next response",
235 remaining));
236 if(total_data_size > maxBufSize) {
237 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
238 total_data_size,maxBufSize));
239 return -EINVAL;
240 }
241 return remaining;
242 }
243}
244
245static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
246{
247 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
248 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
249 int total_data_size;
250 int total_in_buf;
251 int remaining;
252 int total_in_buf2;
253 char * data_area_of_target;
254 char * data_area_of_buf2;
255 __u16 byte_count;
256
257 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
258
259 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
260 cFYI(1,("total data sizes of primary and secondary t2 differ"));
261 }
262
263 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
264
265 remaining = total_data_size - total_in_buf;
266
267 if(remaining < 0)
268 return -EINVAL;
269
270 if(remaining == 0) /* nothing to do, ignore */
271 return 0;
272
273 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
274 if(remaining < total_in_buf2) {
275 cFYI(1,("transact2 2nd response contains too much data"));
276 }
277
278 /* find end of first SMB data area */
279 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
280 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
281 /* validate target area */
282
283 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
284 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
285
286 data_area_of_target += total_in_buf;
287
288 /* copy second buffer into end of first buffer */
289 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
290 total_in_buf += total_in_buf2;
291 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
292 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
293 byte_count += total_in_buf2;
294 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
295
296 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
297 byte_count += total_in_buf2;
298
299 /* BB also add check that we are not beyond maximum buffer size */
300
301 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
302
303 if(remaining == total_in_buf2) {
304 cFYI(1,("found the last secondary response"));
305 return 0; /* we are done */
306 } else /* more responses to go */
307 return 1;
308
309}
310
193static int 311static int
194cifs_demultiplex_thread(struct TCP_Server_Info *server) 312cifs_demultiplex_thread(struct TCP_Server_Info *server)
195{ 313{
196 int length; 314 int length;
197 unsigned int pdu_length, total_read; 315 unsigned int pdu_length, total_read;
198 struct smb_hdr *smb_buffer = NULL; 316 struct smb_hdr *smb_buffer = NULL;
317 struct smb_hdr *bigbuf = NULL;
318 struct smb_hdr *smallbuf = NULL;
199 struct msghdr smb_msg; 319 struct msghdr smb_msg;
200 struct kvec iov; 320 struct kvec iov;
201 struct socket *csocket = server->ssocket; 321 struct socket *csocket = server->ssocket;
@@ -204,6 +324,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
204 struct task_struct *task_to_wake = NULL; 324 struct task_struct *task_to_wake = NULL;
205 struct mid_q_entry *mid_entry; 325 struct mid_q_entry *mid_entry;
206 char *temp; 326 char *temp;
327 int isLargeBuf = FALSE;
328 int isMultiRsp;
329 int reconnect;
207 330
208 daemonize("cifsd"); 331 daemonize("cifsd");
209 allow_signal(SIGKILL); 332 allow_signal(SIGKILL);
@@ -221,17 +344,34 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
221 } 344 }
222 345
223 while (server->tcpStatus != CifsExiting) { 346 while (server->tcpStatus != CifsExiting) {
224 if (smb_buffer == NULL) 347 if (bigbuf == NULL) {
225 smb_buffer = cifs_buf_get(); 348 bigbuf = cifs_buf_get();
226 else 349 if(bigbuf == NULL) {
227 memset(smb_buffer, 0, sizeof (struct smb_hdr)); 350 cERROR(1,("No memory for large SMB response"));
228 351 msleep(3000);
229 if (smb_buffer == NULL) { 352 /* retry will check if exiting */
230 cERROR(1,("Can not get memory for SMB response")); 353 continue;
231 set_current_state(TASK_INTERRUPTIBLE); 354 }
232 schedule_timeout(HZ * 3); /* give system time to free memory */ 355 } else if(isLargeBuf) {
233 continue; 356 /* we are reusing a dirtry large buf, clear its start */
357 memset(bigbuf, 0, sizeof (struct smb_hdr));
234 } 358 }
359
360 if (smallbuf == NULL) {
361 smallbuf = cifs_small_buf_get();
362 if(smallbuf == NULL) {
363 cERROR(1,("No memory for SMB response"));
364 msleep(1000);
365 /* retry will check if exiting */
366 continue;
367 }
368 /* beginning of smb buffer is cleared in our buf_get */
369 } else /* if existing small buf clear beginning */
370 memset(smallbuf, 0, sizeof (struct smb_hdr));
371
372 isLargeBuf = FALSE;
373 isMultiRsp = FALSE;
374 smb_buffer = smallbuf;
235 iov.iov_base = smb_buffer; 375 iov.iov_base = smb_buffer;
236 iov.iov_len = 4; 376 iov.iov_len = 4;
237 smb_msg.msg_control = NULL; 377 smb_msg.msg_control = NULL;
@@ -243,176 +383,257 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
243 if(server->tcpStatus == CifsExiting) { 383 if(server->tcpStatus == CifsExiting) {
244 break; 384 break;
245 } else if (server->tcpStatus == CifsNeedReconnect) { 385 } else if (server->tcpStatus == CifsNeedReconnect) {
246 cFYI(1,("Reconnecting after server stopped responding")); 386 cFYI(1,("Reconnect after server stopped responding"));
247 cifs_reconnect(server); 387 cifs_reconnect(server);
248 cFYI(1,("call to reconnect done")); 388 cFYI(1,("call to reconnect done"));
249 csocket = server->ssocket; 389 csocket = server->ssocket;
250 continue; 390 continue;
251 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { 391 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
252 set_current_state(TASK_INTERRUPTIBLE); 392 msleep(1); /* minimum sleep to prevent looping
253 schedule_timeout(1); /* minimum sleep to prevent looping
254 allowing socket to clear and app threads to set 393 allowing socket to clear and app threads to set
255 tcpStatus CifsNeedReconnect if server hung */ 394 tcpStatus CifsNeedReconnect if server hung */
256 continue; 395 continue;
257 } else if (length <= 0) { 396 } else if (length <= 0) {
258 if(server->tcpStatus == CifsNew) { 397 if(server->tcpStatus == CifsNew) {
259 cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); 398 cFYI(1,("tcp session abend after SMBnegprot"));
260 /* some servers kill tcp session rather than returning 399 /* some servers kill the TCP session rather than
261 smb negprot error in which case reconnecting here is 400 returning an SMB negprot error, in which
262 not going to help - return error to mount */ 401 case reconnecting here is not going to help,
402 and so simply return error to mount */
263 break; 403 break;
264 } 404 }
265 if(length == -EINTR) { 405 if(length == -EINTR) {
266 cFYI(1,("cifsd thread killed")); 406 cFYI(1,("cifsd thread killed"));
267 break; 407 break;
268 } 408 }
269 cFYI(1,("Reconnecting after unexpected peek error %d",length)); 409 cFYI(1,("Reconnect after unexpected peek error %d",
410 length));
270 cifs_reconnect(server); 411 cifs_reconnect(server);
271 csocket = server->ssocket; 412 csocket = server->ssocket;
272 wake_up(&server->response_q); 413 wake_up(&server->response_q);
273 continue; 414 continue;
274 } else if (length > 3) { 415 } else if (length < 4) {
275 pdu_length = ntohl(smb_buffer->smb_buf_length); 416 cFYI(1,
276 /* Only read pdu_length after below checks for too short (due 417 ("Frame under four bytes received (%d bytes long)",
277 to e.g. int overflow) and too long ie beyond end of buf */ 418 length));
278 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); 419 cifs_reconnect(server);
279 420 csocket = server->ssocket;
280 temp = (char *) smb_buffer; 421 wake_up(&server->response_q);
281 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { 422 continue;
282 cFYI(0,("Received 4 byte keep alive packet")); 423 }
283 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
284 cFYI(1,("Good RFC 1002 session rsp"));
285 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
286 /* we get this from Windows 98 instead of error on SMB negprot response */
287 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
288 if(server->tcpStatus == CifsNew) {
289 /* if nack on negprot (rather than
290 ret of smb negprot error) reconnecting
291 not going to help, ret error to mount */
292 break;
293 } else {
294 /* give server a second to
295 clean up before reconnect attempt */
296 set_current_state(TASK_INTERRUPTIBLE);
297 schedule_timeout(HZ);
298 /* always try 445 first on reconnect
299 since we get NACK on some if we ever
300 connected to port 139 (the NACK is
301 since we do not begin with RFC1001
302 session initialize frame) */
303 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
304 cifs_reconnect(server);
305 csocket = server->ssocket;
306 wake_up(&server->response_q);
307 continue;
308 }
309 } else if (temp[0] != (char) 0) {
310 cERROR(1,("Unknown RFC 1002 frame"));
311 cifs_dump_mem(" Received Data: ", temp, length);
312 cifs_reconnect(server);
313 csocket = server->ssocket;
314 continue;
315 } else {
316 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
317 || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
318 cERROR(1,
319 ("Invalid size SMB length %d and pdu_length %d",
320 length, pdu_length+4));
321 cifs_reconnect(server);
322 csocket = server->ssocket;
323 wake_up(&server->response_q);
324 continue;
325 } else { /* length ok */
326 length = 0;
327 iov.iov_base = 4 + (char *)smb_buffer;
328 iov.iov_len = pdu_length;
329 for (total_read = 0;
330 total_read < pdu_length;
331 total_read += length) {
332 length = kernel_recvmsg(csocket, &smb_msg,
333 &iov, 1,
334 pdu_length - total_read, 0);
335 if (length == 0) {
336 cERROR(1,
337 ("Zero length receive when expecting %d ",
338 pdu_length - total_read));
339 cifs_reconnect(server);
340 csocket = server->ssocket;
341 wake_up(&server->response_q);
342 continue;
343 }
344 }
345 length += 4; /* account for rfc1002 hdr */
346 }
347 424
348 dump_smb(smb_buffer, length); 425 /* the right amount was read from socket - 4 bytes */
349 if (checkSMB
350 (smb_buffer, smb_buffer->Mid, total_read+4)) {
351 cERROR(1, ("Bad SMB Received "));
352 continue;
353 }
354 426
355 task_to_wake = NULL; 427 pdu_length = ntohl(smb_buffer->smb_buf_length);
356 spin_lock(&GlobalMid_Lock); 428 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
357 list_for_each(tmp, &server->pending_mid_q) {
358 mid_entry = list_entry(tmp, struct
359 mid_q_entry,
360 qhead);
361 429
362 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) { 430 temp = (char *) smb_buffer;
363 cFYI(1, 431 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
364 (" Mid 0x%x matched - waking up ",mid_entry->mid)); 432 continue;
365 task_to_wake = mid_entry->tsk; 433 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
366 mid_entry->resp_buf = 434 cFYI(1,("Good RFC 1002 session rsp"));
367 smb_buffer; 435 continue;
368 mid_entry->midState = 436 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
369 MID_RESPONSE_RECEIVED; 437 /* we get this from Windows 98 instead of
370 } 438 an error on SMB negprot response */
371 } 439 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
372 spin_unlock(&GlobalMid_Lock); 440 temp[4]));
373 if (task_to_wake) { 441 if(server->tcpStatus == CifsNew) {
374 smb_buffer = NULL; /* will be freed by users thread after he is done */ 442 /* if nack on negprot (rather than
375 wake_up_process(task_to_wake); 443 ret of smb negprot error) reconnecting
376 } else if (is_valid_oplock_break(smb_buffer) == FALSE) { 444 not going to help, ret error to mount */
377 cERROR(1, ("No task to wake, unknown frame rcvd!")); 445 break;
378 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); 446 } else {
379 } 447 /* give server a second to
448 clean up before reconnect attempt */
449 msleep(1000);
450 /* always try 445 first on reconnect
451 since we get NACK on some if we ever
452 connected to port 139 (the NACK is
453 since we do not begin with RFC1001
454 session initialize frame) */
455 server->addr.sockAddr.sin_port =
456 htons(CIFS_PORT);
457 cifs_reconnect(server);
458 csocket = server->ssocket;
459 wake_up(&server->response_q);
460 continue;
380 } 461 }
381 } else { 462 } else if (temp[0] != (char) 0) {
382 cFYI(1, 463 cERROR(1,("Unknown RFC 1002 frame"));
383 ("Frame less than four bytes received %d bytes long.", 464 cifs_dump_mem(" Received Data: ", temp, length);
384 length)); 465 cifs_reconnect(server);
466 csocket = server->ssocket;
467 continue;
468 }
469
470 /* else we have an SMB response */
471 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
472 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
473 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
474 length, pdu_length+4));
385 cifs_reconnect(server); 475 cifs_reconnect(server);
386 csocket = server->ssocket; 476 csocket = server->ssocket;
387 wake_up(&server->response_q); 477 wake_up(&server->response_q);
388 continue; 478 continue;
479 }
480
481 /* else length ok */
482 reconnect = 0;
483
484 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
485 isLargeBuf = TRUE;
486 memcpy(bigbuf, smallbuf, 4);
487 smb_buffer = bigbuf;
389 } 488 }
390 } 489 length = 0;
490 iov.iov_base = 4 + (char *)smb_buffer;
491 iov.iov_len = pdu_length;
492 for (total_read = 0; total_read < pdu_length;
493 total_read += length) {
494 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
495 pdu_length - total_read, 0);
496 if((server->tcpStatus == CifsExiting) ||
497 (length == -EINTR)) {
498 /* then will exit */
499 reconnect = 2;
500 break;
501 } else if (server->tcpStatus == CifsNeedReconnect) {
502 cifs_reconnect(server);
503 csocket = server->ssocket;
504 /* Reconnect wakes up rspns q */
505 /* Now we will reread sock */
506 reconnect = 1;
507 break;
508 } else if ((length == -ERESTARTSYS) ||
509 (length == -EAGAIN)) {
510 msleep(1); /* minimum sleep to prevent looping,
511 allowing socket to clear and app
512 threads to set tcpStatus
513 CifsNeedReconnect if server hung*/
514 continue;
515 } else if (length <= 0) {
516 cERROR(1,("Received no data, expecting %d",
517 pdu_length - total_read));
518 cifs_reconnect(server);
519 csocket = server->ssocket;
520 reconnect = 1;
521 break;
522 }
523 }
524 if(reconnect == 2)
525 break;
526 else if(reconnect == 1)
527 continue;
528
529 length += 4; /* account for rfc1002 hdr */
530
531
532 dump_smb(smb_buffer, length);
533 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
534 cERROR(1, ("Bad SMB Received "));
535 continue;
536 }
537
538
539 task_to_wake = NULL;
540 spin_lock(&GlobalMid_Lock);
541 list_for_each(tmp, &server->pending_mid_q) {
542 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
543
544 if ((mid_entry->mid == smb_buffer->Mid) &&
545 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
546 (mid_entry->command == smb_buffer->Command)) {
547 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
548 /* We have a multipart transact2 resp */
549 isMultiRsp = TRUE;
550 if(mid_entry->resp_buf) {
551 /* merge response - fix up 1st*/
552 if(coalesce_t2(smb_buffer,
553 mid_entry->resp_buf)) {
554 break;
555 } else {
556 /* all parts received */
557 goto multi_t2_fnd;
558 }
559 } else {
560 if(!isLargeBuf) {
561 cERROR(1,("1st trans2 resp needs bigbuf"));
562 /* BB maybe we can fix this up, switch
563 to already allocated large buffer? */
564 } else {
565 /* Have first buffer */
566 mid_entry->resp_buf =
567 smb_buffer;
568 mid_entry->largeBuf = 1;
569 bigbuf = NULL;
570 }
571 }
572 break;
573 }
574 mid_entry->resp_buf = smb_buffer;
575 if(isLargeBuf)
576 mid_entry->largeBuf = 1;
577 else
578 mid_entry->largeBuf = 0;
579multi_t2_fnd:
580 task_to_wake = mid_entry->tsk;
581 mid_entry->midState = MID_RESPONSE_RECEIVED;
582 break;
583 }
584 }
585 spin_unlock(&GlobalMid_Lock);
586 if (task_to_wake) {
587 /* Was previous buf put in mpx struct for multi-rsp? */
588 if(!isMultiRsp) {
589 /* smb buffer will be freed by user thread */
590 if(isLargeBuf) {
591 bigbuf = NULL;
592 } else
593 smallbuf = NULL;
594 }
595 wake_up_process(task_to_wake);
596 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
597 && (isMultiRsp == FALSE)) {
598 cERROR(1, ("No task to wake, unknown frame rcvd!"));
599 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
600 }
601 } /* end while !EXITING */
602
391 spin_lock(&GlobalMid_Lock); 603 spin_lock(&GlobalMid_Lock);
392 server->tcpStatus = CifsExiting; 604 server->tcpStatus = CifsExiting;
393 server->tsk = NULL; 605 server->tsk = NULL;
394 atomic_set(&server->inFlight, 0); 606 /* check if we have blocked requests that need to free */
607 /* Note that cifs_max_pending is normally 50, but
608 can be set at module install time to as little as two */
609 if(atomic_read(&server->inFlight) >= cifs_max_pending)
610 atomic_set(&server->inFlight, cifs_max_pending - 1);
611 /* We do not want to set the max_pending too low or we
612 could end up with the counter going negative */
395 spin_unlock(&GlobalMid_Lock); 613 spin_unlock(&GlobalMid_Lock);
396 /* Although there should not be any requests blocked on 614 /* Although there should not be any requests blocked on
397 this queue it can not hurt to be paranoid and try to wake up requests 615 this queue it can not hurt to be paranoid and try to wake up requests
398 that may haven been blocked when more than 50 at time were on the wire 616 that may haven been blocked when more than 50 at time were on the wire
399 to the same server - they now will see the session is in exit state 617 to the same server - they now will see the session is in exit state
400 and get out of SendReceive. */ 618 and get out of SendReceive. */
401 wake_up_all(&server->request_q); 619 wake_up_all(&server->request_q);
402 /* give those requests time to exit */ 620 /* give those requests time to exit */
403 set_current_state(TASK_INTERRUPTIBLE); 621 msleep(125);
404 schedule_timeout(HZ/8); 622
405
406 if(server->ssocket) { 623 if(server->ssocket) {
407 sock_release(csocket); 624 sock_release(csocket);
408 server->ssocket = NULL; 625 server->ssocket = NULL;
409 } 626 }
410 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */ 627 /* buffer usuallly freed in free_mid - need to free it here on exit */
411 cifs_buf_release(smb_buffer); 628 if (bigbuf != NULL)
629 cifs_buf_release(bigbuf);
630 if (smallbuf != NULL)
631 cifs_small_buf_release(smallbuf);
412 632
413 read_lock(&GlobalSMBSeslock); 633 read_lock(&GlobalSMBSeslock);
414 if (list_empty(&server->pending_mid_q)) { 634 if (list_empty(&server->pending_mid_q)) {
415 /* loop through server session structures attached to this and mark them dead */ 635 /* loop through server session structures attached to this and
636 mark them dead */
416 list_for_each(tmp, &GlobalSMBSessionList) { 637 list_for_each(tmp, &GlobalSMBSessionList) {
417 ses = 638 ses =
418 list_entry(tmp, struct cifsSesInfo, 639 list_entry(tmp, struct cifsSesInfo,
@@ -424,12 +645,23 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
424 } 645 }
425 read_unlock(&GlobalSMBSeslock); 646 read_unlock(&GlobalSMBSeslock);
426 } else { 647 } else {
648 /* although we can not zero the server struct pointer yet,
649 since there are active requests which may depnd on them,
650 mark the corresponding SMB sessions as exiting too */
651 list_for_each(tmp, &GlobalSMBSessionList) {
652 ses = list_entry(tmp, struct cifsSesInfo,
653 cifsSessionList);
654 if (ses->server == server) {
655 ses->status = CifsExiting;
656 }
657 }
658
427 spin_lock(&GlobalMid_Lock); 659 spin_lock(&GlobalMid_Lock);
428 list_for_each(tmp, &server->pending_mid_q) { 660 list_for_each(tmp, &server->pending_mid_q) {
429 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 661 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
430 if (mid_entry->midState == MID_REQUEST_SUBMITTED) { 662 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
431 cFYI(1, 663 cFYI(1,
432 (" Clearing Mid 0x%x - waking up ",mid_entry->mid)); 664 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
433 task_to_wake = mid_entry->tsk; 665 task_to_wake = mid_entry->tsk;
434 if(task_to_wake) { 666 if(task_to_wake) {
435 wake_up_process(task_to_wake); 667 wake_up_process(task_to_wake);
@@ -438,47 +670,51 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
438 } 670 }
439 spin_unlock(&GlobalMid_Lock); 671 spin_unlock(&GlobalMid_Lock);
440 read_unlock(&GlobalSMBSeslock); 672 read_unlock(&GlobalSMBSeslock);
441 set_current_state(TASK_INTERRUPTIBLE);
442 /* 1/8th of sec is more than enough time for them to exit */ 673 /* 1/8th of sec is more than enough time for them to exit */
443 schedule_timeout(HZ/8); 674 msleep(125);
444 } 675 }
445 676
446 if (list_empty(&server->pending_mid_q)) { 677 if (list_empty(&server->pending_mid_q)) {
447 /* mpx threads have not exited yet give them 678 /* mpx threads have not exited yet give them
448 at least the smb send timeout time for long ops */ 679 at least the smb send timeout time for long ops */
680 /* due to delays on oplock break requests, we need
681 to wait at least 45 seconds before giving up
682 on a request getting a response and going ahead
683 and killing cifsd */
449 cFYI(1, ("Wait for exit from demultiplex thread")); 684 cFYI(1, ("Wait for exit from demultiplex thread"));
450 set_current_state(TASK_INTERRUPTIBLE); 685 msleep(46000);
451 schedule_timeout(46 * HZ);
452 /* if threads still have not exited they are probably never 686 /* if threads still have not exited they are probably never
453 coming home not much else we can do but free the memory */ 687 coming home not much else we can do but free the memory */
454 } 688 }
455 kfree(server);
456 689
457 write_lock(&GlobalSMBSeslock); 690 write_lock(&GlobalSMBSeslock);
458 atomic_dec(&tcpSesAllocCount); 691 atomic_dec(&tcpSesAllocCount);
459 length = tcpSesAllocCount.counter; 692 length = tcpSesAllocCount.counter;
693
694 /* last chance to mark ses pointers invalid
695 if there are any pointing to this (e.g
696 if a crazy root user tried to kill cifsd
697 kernel thread explicitly this might happen) */
698 list_for_each(tmp, &GlobalSMBSessionList) {
699 ses = list_entry(tmp, struct cifsSesInfo,
700 cifsSessionList);
701 if (ses->server == server) {
702 ses->server = NULL;
703 }
704 }
460 write_unlock(&GlobalSMBSeslock); 705 write_unlock(&GlobalSMBSeslock);
706
707 kfree(server);
461 if(length > 0) { 708 if(length > 0) {
462 mempool_resize(cifs_req_poolp, 709 mempool_resize(cifs_req_poolp,
463 length + cifs_min_rcv, 710 length + cifs_min_rcv,
464 GFP_KERNEL); 711 GFP_KERNEL);
465 } 712 }
466 713
467 set_current_state(TASK_INTERRUPTIBLE); 714 msleep(250);
468 schedule_timeout(HZ/4);
469 return 0; 715 return 0;
470} 716}
471 717
472static void *
473cifs_kcalloc(size_t size, unsigned int __nocast type)
474{
475 void *addr;
476 addr = kmalloc(size, type);
477 if (addr)
478 memset(addr, 0, size);
479 return addr;
480}
481
482static int 718static int
483cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) 719cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
484{ 720{
@@ -495,7 +731,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
495 /* does not have to be a perfect mapping since the field is 731 /* does not have to be a perfect mapping since the field is
496 informational, only used for servers that do not support 732 informational, only used for servers that do not support
497 port 445 and it can be overridden at mount time */ 733 port 445 and it can be overridden at mount time */
498 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); 734 vol->source_rfc1001_name[i] =
735 toupper(system_utsname.nodename[i]);
499 } 736 }
500 vol->source_rfc1001_name[15] = 0; 737 vol->source_rfc1001_name[15] = 0;
501 738
@@ -570,14 +807,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
570 /* NB: password legally can have multiple commas and 807 /* NB: password legally can have multiple commas and
571 the only illegal character in a password is null */ 808 the only illegal character in a password is null */
572 809
573 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { 810 if ((value[temp_len] == 0) &&
811 (value[temp_len+1] == separator[0])) {
574 /* reinsert comma */ 812 /* reinsert comma */
575 value[temp_len] = separator[0]; 813 value[temp_len] = separator[0];
576 temp_len+=2; /* move after the second comma */ 814 temp_len+=2; /* move after the second comma */
577 while(value[temp_len] != 0) { 815 while(value[temp_len] != 0) {
578 if (value[temp_len] == separator[0]) { 816 if (value[temp_len] == separator[0]) {
579 if (value[temp_len+1] == separator[0]) { 817 if (value[temp_len+1] ==
580 temp_len++; /* skip second comma */ 818 separator[0]) {
819 /* skip second comma */
820 temp_len++;
581 } else { 821 } else {
582 /* single comma indicating start 822 /* single comma indicating start
583 of next parm */ 823 of next parm */
@@ -596,17 +836,26 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
596 /* go from value to value + temp_len condensing 836 /* go from value to value + temp_len condensing
597 double commas to singles. Note that this ends up 837 double commas to singles. Note that this ends up
598 allocating a few bytes too many, which is ok */ 838 allocating a few bytes too many, which is ok */
599 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL); 839 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
840 if(vol->password == NULL) {
841 printk("CIFS: no memory for pass\n");
842 return 1;
843 }
600 for(i=0,j=0;i<temp_len;i++,j++) { 844 for(i=0,j=0;i<temp_len;i++,j++) {
601 vol->password[j] = value[i]; 845 vol->password[j] = value[i];
602 if(value[i] == separator[0] && value[i+1] == separator[0]) { 846 if(value[i] == separator[0]
847 && value[i+1] == separator[0]) {
603 /* skip second comma */ 848 /* skip second comma */
604 i++; 849 i++;
605 } 850 }
606 } 851 }
607 vol->password[j] = 0; 852 vol->password[j] = 0;
608 } else { 853 } else {
609 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL); 854 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
855 if(vol->password == NULL) {
856 printk("CIFS: no memory for pass\n");
857 return 1;
858 }
610 strcpy(vol->password, value); 859 strcpy(vol->password, value);
611 } 860 }
612 } else if (strnicmp(data, "ip", 2) == 0) { 861 } else if (strnicmp(data, "ip", 2) == 0) {
@@ -770,6 +1019,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
770 vol->noperm = 0; 1019 vol->noperm = 0;
771 } else if (strnicmp(data, "noperm", 6) == 0) { 1020 } else if (strnicmp(data, "noperm", 6) == 0) {
772 vol->noperm = 1; 1021 vol->noperm = 1;
1022 } else if (strnicmp(data, "mapchars", 8) == 0) {
1023 vol->remap = 1;
1024 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1025 vol->remap = 0;
773 } else if (strnicmp(data, "setuids", 7) == 0) { 1026 } else if (strnicmp(data, "setuids", 7) == 0) {
774 vol->setuids = 1; 1027 vol->setuids = 1;
775 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1028 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -918,14 +1171,15 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
918 1171
919int 1172int
920connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 1173connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
921 const char *old_path, const struct nls_table *nls_codepage) 1174 const char *old_path, const struct nls_table *nls_codepage,
1175 int remap)
922{ 1176{
923 unsigned char *referrals = NULL; 1177 unsigned char *referrals = NULL;
924 unsigned int num_referrals; 1178 unsigned int num_referrals;
925 int rc = 0; 1179 int rc = 0;
926 1180
927 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, 1181 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
928 &num_referrals, &referrals); 1182 &num_referrals, &referrals, remap);
929 1183
930 /* BB Add in code to: if valid refrl, if not ip address contact 1184 /* BB Add in code to: if valid refrl, if not ip address contact
931 the helper that resolves tcp names, mount to it, try to 1185 the helper that resolves tcp names, mount to it, try to
@@ -940,7 +1194,8 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
940int 1194int
941get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 1195get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
942 const char *old_path, const struct nls_table *nls_codepage, 1196 const char *old_path, const struct nls_table *nls_codepage,
943 unsigned int *pnum_referrals, unsigned char ** preferrals) 1197 unsigned int *pnum_referrals,
1198 unsigned char ** preferrals, int remap)
944{ 1199{
945 char *temp_unc; 1200 char *temp_unc;
946 int rc = 0; 1201 int rc = 0;
@@ -965,7 +1220,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
965 } 1220 }
966 if (rc == 0) 1221 if (rc == 0)
967 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, 1222 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
968 pnum_referrals, nls_codepage); 1223 pnum_referrals, nls_codepage, remap);
969 1224
970 return rc; 1225 return rc;
971} 1226}
@@ -1062,7 +1317,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1062 sessinit is sent but no second negprot */ 1317 sessinit is sent but no second negprot */
1063 struct rfc1002_session_packet * ses_init_buf; 1318 struct rfc1002_session_packet * ses_init_buf;
1064 struct smb_hdr * smb_buf; 1319 struct smb_hdr * smb_buf;
1065 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); 1320 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1066 if(ses_init_buf) { 1321 if(ses_init_buf) {
1067 ses_init_buf->trailer.session_req.called_len = 32; 1322 ses_init_buf->trailer.session_req.called_len = 32;
1068 rfc1002mangle(ses_init_buf->trailer.session_req.called_name, 1323 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
@@ -1352,6 +1607,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1352 } else 1607 } else
1353 rc = 0; 1608 rc = 0;
1354 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); 1609 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1610 srvTcp->sequence_number = 0;
1355 } 1611 }
1356 } 1612 }
1357 1613
@@ -1419,6 +1675,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1419 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; 1675 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1420 if(volume_info.server_ino) 1676 if(volume_info.server_ino)
1421 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; 1677 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1678 if(volume_info.remap)
1679 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1422 if(volume_info.no_xattr) 1680 if(volume_info.no_xattr)
1423 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1424 if(volume_info.direct_io) { 1682 if(volume_info.direct_io) {
@@ -1447,11 +1705,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1447 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 1705 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1448 && (strchr(volume_info.UNC + 3, '/') == 1706 && (strchr(volume_info.UNC + 3, '/') ==
1449 NULL)) { 1707 NULL)) {
1450 rc = connect_to_dfs_path(xid, 1708 rc = connect_to_dfs_path(xid, pSesInfo,
1451 pSesInfo, 1709 "", cifs_sb->local_nls,
1452 "", 1710 cifs_sb->mnt_cifs_flags &
1453 cifs_sb-> 1711 CIFS_MOUNT_MAP_SPECIAL_CHR);
1454 local_nls);
1455 if(volume_info.UNC) 1712 if(volume_info.UNC)
1456 kfree(volume_info.UNC); 1713 kfree(volume_info.UNC);
1457 FreeXid(xid); 1714 FreeXid(xid);
@@ -1514,10 +1771,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1514 tcon->ses = pSesInfo; 1771 tcon->ses = pSesInfo;
1515 1772
1516 /* do not care if following two calls succeed - informational only */ 1773 /* do not care if following two calls succeed - informational only */
1517 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls); 1774 CIFSSMBQFSDeviceInfo(xid, tcon);
1518 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls); 1775 CIFSSMBQFSAttributeInfo(xid, tcon);
1519 if (tcon->ses->capabilities & CAP_UNIX) { 1776 if (tcon->ses->capabilities & CAP_UNIX) {
1520 if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) { 1777 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1521 if(!volume_info.no_psx_acl) { 1778 if(!volume_info.no_psx_acl) {
1522 if(CIFS_UNIX_POSIX_ACL_CAP & 1779 if(CIFS_UNIX_POSIX_ACL_CAP &
1523 le64_to_cpu(tcon->fsUnixInfo.Capability)) 1780 le64_to_cpu(tcon->fsUnixInfo.Capability))
@@ -1707,7 +1964,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1707/* We look for obvious messed up bcc or strings in response so we do not go off 1964/* We look for obvious messed up bcc or strings in response so we do not go off
1708 the end since (at least) WIN2K and Windows XP have a major bug in not null 1965 the end since (at least) WIN2K and Windows XP have a major bug in not null
1709 terminating last Unicode string in response */ 1966 terminating last Unicode string in response */
1710 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 1967 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1968 if(ses->serverOS == NULL)
1969 goto sesssetup_nomem;
1711 cifs_strfromUCS_le(ses->serverOS, 1970 cifs_strfromUCS_le(ses->serverOS,
1712 (wchar_t *)bcc_ptr, len,nls_codepage); 1971 (wchar_t *)bcc_ptr, len,nls_codepage);
1713 bcc_ptr += 2 * (len + 1); 1972 bcc_ptr += 2 * (len + 1);
@@ -1717,7 +1976,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1717 if (remaining_words > 0) { 1976 if (remaining_words > 0) {
1718 len = UniStrnlen((wchar_t *)bcc_ptr, 1977 len = UniStrnlen((wchar_t *)bcc_ptr,
1719 remaining_words-1); 1978 remaining_words-1);
1720 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL); 1979 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1980 if(ses->serverNOS == NULL)
1981 goto sesssetup_nomem;
1721 cifs_strfromUCS_le(ses->serverNOS, 1982 cifs_strfromUCS_le(ses->serverNOS,
1722 (wchar_t *)bcc_ptr,len,nls_codepage); 1983 (wchar_t *)bcc_ptr,len,nls_codepage);
1723 bcc_ptr += 2 * (len + 1); 1984 bcc_ptr += 2 * (len + 1);
@@ -1730,10 +1991,12 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1730 } 1991 }
1731 remaining_words -= len + 1; 1992 remaining_words -= len + 1;
1732 if (remaining_words > 0) { 1993 if (remaining_words > 0) {
1733 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 1994 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1734 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 1995 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1735 ses->serverDomain = 1996 ses->serverDomain =
1736 cifs_kcalloc(2*(len+1),GFP_KERNEL); 1997 kcalloc(1, 2*(len+1),GFP_KERNEL);
1998 if(ses->serverDomain == NULL)
1999 goto sesssetup_nomem;
1737 cifs_strfromUCS_le(ses->serverDomain, 2000 cifs_strfromUCS_le(ses->serverDomain,
1738 (wchar_t *)bcc_ptr,len,nls_codepage); 2001 (wchar_t *)bcc_ptr,len,nls_codepage);
1739 bcc_ptr += 2 * (len + 1); 2002 bcc_ptr += 2 * (len + 1);
@@ -1741,21 +2004,25 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1741 ses->serverDomain[1+(2*len)] = 0; 2004 ses->serverDomain[1+(2*len)] = 0;
1742 } /* else no more room so create dummy domain string */ 2005 } /* else no more room so create dummy domain string */
1743 else 2006 else
1744 ses->serverDomain = 2007 ses->serverDomain =
1745 cifs_kcalloc(2, 2008 kcalloc(1, 2, GFP_KERNEL);
1746 GFP_KERNEL);
1747 } else { /* no room so create dummy domain and NOS string */ 2009 } else { /* no room so create dummy domain and NOS string */
2010 /* if these kcallocs fail not much we
2011 can do, but better to not fail the
2012 sesssetup itself */
1748 ses->serverDomain = 2013 ses->serverDomain =
1749 cifs_kcalloc(2, GFP_KERNEL); 2014 kcalloc(1, 2, GFP_KERNEL);
1750 ses->serverNOS = 2015 ses->serverNOS =
1751 cifs_kcalloc(2, GFP_KERNEL); 2016 kcalloc(1, 2, GFP_KERNEL);
1752 } 2017 }
1753 } else { /* ASCII */ 2018 } else { /* ASCII */
1754 len = strnlen(bcc_ptr, 1024); 2019 len = strnlen(bcc_ptr, 1024);
1755 if (((long) bcc_ptr + len) - (long) 2020 if (((long) bcc_ptr + len) - (long)
1756 pByteArea(smb_buffer_response) 2021 pByteArea(smb_buffer_response)
1757 <= BCC(smb_buffer_response)) { 2022 <= BCC(smb_buffer_response)) {
1758 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); 2023 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2024 if(ses->serverOS == NULL)
2025 goto sesssetup_nomem;
1759 strncpy(ses->serverOS,bcc_ptr, len); 2026 strncpy(ses->serverOS,bcc_ptr, len);
1760 2027
1761 bcc_ptr += len; 2028 bcc_ptr += len;
@@ -1763,14 +2030,18 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1763 bcc_ptr++; 2030 bcc_ptr++;
1764 2031
1765 len = strnlen(bcc_ptr, 1024); 2032 len = strnlen(bcc_ptr, 1024);
1766 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); 2033 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2034 if(ses->serverNOS == NULL)
2035 goto sesssetup_nomem;
1767 strncpy(ses->serverNOS, bcc_ptr, len); 2036 strncpy(ses->serverNOS, bcc_ptr, len);
1768 bcc_ptr += len; 2037 bcc_ptr += len;
1769 bcc_ptr[0] = 0; 2038 bcc_ptr[0] = 0;
1770 bcc_ptr++; 2039 bcc_ptr++;
1771 2040
1772 len = strnlen(bcc_ptr, 1024); 2041 len = strnlen(bcc_ptr, 1024);
1773 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL); 2042 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2043 if(ses->serverDomain == NULL)
2044 goto sesssetup_nomem;
1774 strncpy(ses->serverDomain, bcc_ptr, len); 2045 strncpy(ses->serverDomain, bcc_ptr, len);
1775 bcc_ptr += len; 2046 bcc_ptr += len;
1776 bcc_ptr[0] = 0; 2047 bcc_ptr[0] = 0;
@@ -1790,7 +2061,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1790 smb_buffer_response->WordCount)); 2061 smb_buffer_response->WordCount));
1791 rc = -EIO; 2062 rc = -EIO;
1792 } 2063 }
1793 2064sesssetup_nomem: /* do not return an error on nomem for the info strings,
2065 since that could make reconnection harder, and
2066 reconnection might be needed to free memory */
1794 if (smb_buffer) 2067 if (smb_buffer)
1795 cifs_buf_release(smb_buffer); 2068 cifs_buf_release(smb_buffer);
1796 2069
@@ -1967,7 +2240,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1967 the end since (at least) WIN2K and Windows XP have a major bug in not null 2240 the end since (at least) WIN2K and Windows XP have a major bug in not null
1968 terminating last Unicode string in response */ 2241 terminating last Unicode string in response */
1969 ses->serverOS = 2242 ses->serverOS =
1970 cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 2243 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1971 cifs_strfromUCS_le(ses->serverOS, 2244 cifs_strfromUCS_le(ses->serverOS,
1972 (wchar_t *) 2245 (wchar_t *)
1973 bcc_ptr, len, 2246 bcc_ptr, len,
@@ -1981,7 +2254,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1981 remaining_words 2254 remaining_words
1982 - 1); 2255 - 1);
1983 ses->serverNOS = 2256 ses->serverNOS =
1984 cifs_kcalloc(2 * (len + 1), 2257 kcalloc(1, 2 * (len + 1),
1985 GFP_KERNEL); 2258 GFP_KERNEL);
1986 cifs_strfromUCS_le(ses->serverNOS, 2259 cifs_strfromUCS_le(ses->serverNOS,
1987 (wchar_t *)bcc_ptr, 2260 (wchar_t *)bcc_ptr,
@@ -1994,7 +2267,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1994 if (remaining_words > 0) { 2267 if (remaining_words > 0) {
1995 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2268 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1996 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2269 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1997 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL); 2270 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
1998 cifs_strfromUCS_le(ses->serverDomain, 2271 cifs_strfromUCS_le(ses->serverDomain,
1999 (wchar_t *)bcc_ptr, 2272 (wchar_t *)bcc_ptr,
2000 len, 2273 len,
@@ -2005,10 +2278,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2005 } /* else no more room so create dummy domain string */ 2278 } /* else no more room so create dummy domain string */
2006 else 2279 else
2007 ses->serverDomain = 2280 ses->serverDomain =
2008 cifs_kcalloc(2,GFP_KERNEL); 2281 kcalloc(1, 2,GFP_KERNEL);
2009 } else { /* no room so create dummy domain and NOS string */ 2282 } else { /* no room so create dummy domain and NOS string */
2010 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); 2283 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2011 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); 2284 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2012 } 2285 }
2013 } else { /* ASCII */ 2286 } else { /* ASCII */
2014 2287
@@ -2016,7 +2289,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2016 if (((long) bcc_ptr + len) - (long) 2289 if (((long) bcc_ptr + len) - (long)
2017 pByteArea(smb_buffer_response) 2290 pByteArea(smb_buffer_response)
2018 <= BCC(smb_buffer_response)) { 2291 <= BCC(smb_buffer_response)) {
2019 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL); 2292 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2020 strncpy(ses->serverOS, bcc_ptr, len); 2293 strncpy(ses->serverOS, bcc_ptr, len);
2021 2294
2022 bcc_ptr += len; 2295 bcc_ptr += len;
@@ -2024,14 +2297,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2024 bcc_ptr++; 2297 bcc_ptr++;
2025 2298
2026 len = strnlen(bcc_ptr, 1024); 2299 len = strnlen(bcc_ptr, 1024);
2027 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); 2300 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2028 strncpy(ses->serverNOS, bcc_ptr, len); 2301 strncpy(ses->serverNOS, bcc_ptr, len);
2029 bcc_ptr += len; 2302 bcc_ptr += len;
2030 bcc_ptr[0] = 0; 2303 bcc_ptr[0] = 0;
2031 bcc_ptr++; 2304 bcc_ptr++;
2032 2305
2033 len = strnlen(bcc_ptr, 1024); 2306 len = strnlen(bcc_ptr, 1024);
2034 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL); 2307 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2035 strncpy(ses->serverDomain, bcc_ptr, len); 2308 strncpy(ses->serverDomain, bcc_ptr, len);
2036 bcc_ptr += len; 2309 bcc_ptr += len;
2037 bcc_ptr[0] = 0; 2310 bcc_ptr[0] = 0;
@@ -2281,7 +2554,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2281 the end since (at least) WIN2K and Windows XP have a major bug in not null 2554 the end since (at least) WIN2K and Windows XP have a major bug in not null
2282 terminating last Unicode string in response */ 2555 terminating last Unicode string in response */
2283 ses->serverOS = 2556 ses->serverOS =
2284 cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 2557 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2285 cifs_strfromUCS_le(ses->serverOS, 2558 cifs_strfromUCS_le(ses->serverOS,
2286 (wchar_t *) 2559 (wchar_t *)
2287 bcc_ptr, len, 2560 bcc_ptr, len,
@@ -2296,7 +2569,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2296 remaining_words 2569 remaining_words
2297 - 1); 2570 - 1);
2298 ses->serverNOS = 2571 ses->serverNOS =
2299 cifs_kcalloc(2 * (len + 1), 2572 kcalloc(1, 2 * (len + 1),
2300 GFP_KERNEL); 2573 GFP_KERNEL);
2301 cifs_strfromUCS_le(ses-> 2574 cifs_strfromUCS_le(ses->
2302 serverNOS, 2575 serverNOS,
@@ -2313,7 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2313 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2586 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2314 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2587 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2315 ses->serverDomain = 2588 ses->serverDomain =
2316 cifs_kcalloc(2 * 2589 kcalloc(1, 2 *
2317 (len + 2590 (len +
2318 1), 2591 1),
2319 GFP_KERNEL); 2592 GFP_KERNEL);
@@ -2339,13 +2612,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2339 } /* else no more room so create dummy domain string */ 2612 } /* else no more room so create dummy domain string */
2340 else 2613 else
2341 ses->serverDomain = 2614 ses->serverDomain =
2342 cifs_kcalloc(2, 2615 kcalloc(1, 2,
2343 GFP_KERNEL); 2616 GFP_KERNEL);
2344 } else { /* no room so create dummy domain and NOS string */ 2617 } else { /* no room so create dummy domain and NOS string */
2345 ses->serverDomain = 2618 ses->serverDomain =
2346 cifs_kcalloc(2, GFP_KERNEL); 2619 kcalloc(1, 2, GFP_KERNEL);
2347 ses->serverNOS = 2620 ses->serverNOS =
2348 cifs_kcalloc(2, GFP_KERNEL); 2621 kcalloc(1, 2, GFP_KERNEL);
2349 } 2622 }
2350 } else { /* ASCII */ 2623 } else { /* ASCII */
2351 len = strnlen(bcc_ptr, 1024); 2624 len = strnlen(bcc_ptr, 1024);
@@ -2353,7 +2626,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2353 pByteArea(smb_buffer_response) 2626 pByteArea(smb_buffer_response)
2354 <= BCC(smb_buffer_response)) { 2627 <= BCC(smb_buffer_response)) {
2355 ses->serverOS = 2628 ses->serverOS =
2356 cifs_kcalloc(len + 1, 2629 kcalloc(1, len + 1,
2357 GFP_KERNEL); 2630 GFP_KERNEL);
2358 strncpy(ses->serverOS, 2631 strncpy(ses->serverOS,
2359 bcc_ptr, len); 2632 bcc_ptr, len);
@@ -2364,7 +2637,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2364 2637
2365 len = strnlen(bcc_ptr, 1024); 2638 len = strnlen(bcc_ptr, 1024);
2366 ses->serverNOS = 2639 ses->serverNOS =
2367 cifs_kcalloc(len + 1, 2640 kcalloc(1, len + 1,
2368 GFP_KERNEL); 2641 GFP_KERNEL);
2369 strncpy(ses->serverNOS, bcc_ptr, len); 2642 strncpy(ses->serverNOS, bcc_ptr, len);
2370 bcc_ptr += len; 2643 bcc_ptr += len;
@@ -2373,7 +2646,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2373 2646
2374 len = strnlen(bcc_ptr, 1024); 2647 len = strnlen(bcc_ptr, 1024);
2375 ses->serverDomain = 2648 ses->serverDomain =
2376 cifs_kcalloc(len + 1, 2649 kcalloc(1, len + 1,
2377 GFP_KERNEL); 2650 GFP_KERNEL);
2378 strncpy(ses->serverDomain, bcc_ptr, len); 2651 strncpy(ses->serverDomain, bcc_ptr, len);
2379 bcc_ptr += len; 2652 bcc_ptr += len;
@@ -2675,7 +2948,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2675 the end since (at least) WIN2K and Windows XP have a major bug in not null 2948 the end since (at least) WIN2K and Windows XP have a major bug in not null
2676 terminating last Unicode string in response */ 2949 terminating last Unicode string in response */
2677 ses->serverOS = 2950 ses->serverOS =
2678 cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 2951 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2679 cifs_strfromUCS_le(ses->serverOS, 2952 cifs_strfromUCS_le(ses->serverOS,
2680 (wchar_t *) 2953 (wchar_t *)
2681 bcc_ptr, len, 2954 bcc_ptr, len,
@@ -2690,7 +2963,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2690 remaining_words 2963 remaining_words
2691 - 1); 2964 - 1);
2692 ses->serverNOS = 2965 ses->serverNOS =
2693 cifs_kcalloc(2 * (len + 1), 2966 kcalloc(1, 2 * (len + 1),
2694 GFP_KERNEL); 2967 GFP_KERNEL);
2695 cifs_strfromUCS_le(ses-> 2968 cifs_strfromUCS_le(ses->
2696 serverNOS, 2969 serverNOS,
@@ -2706,7 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2706 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2979 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2707 /* last string not always null terminated (e.g. for Windows XP & 2000) */ 2980 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2708 ses->serverDomain = 2981 ses->serverDomain =
2709 cifs_kcalloc(2 * 2982 kcalloc(1, 2 *
2710 (len + 2983 (len +
2711 1), 2984 1),
2712 GFP_KERNEL); 2985 GFP_KERNEL);
@@ -2731,17 +3004,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2731 = 0; 3004 = 0;
2732 } /* else no more room so create dummy domain string */ 3005 } /* else no more room so create dummy domain string */
2733 else 3006 else
2734 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL); 3007 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
2735 } else { /* no room so create dummy domain and NOS string */ 3008 } else { /* no room so create dummy domain and NOS string */
2736 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); 3009 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2737 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); 3010 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2738 } 3011 }
2739 } else { /* ASCII */ 3012 } else { /* ASCII */
2740 len = strnlen(bcc_ptr, 1024); 3013 len = strnlen(bcc_ptr, 1024);
2741 if (((long) bcc_ptr + len) - 3014 if (((long) bcc_ptr + len) -
2742 (long) pByteArea(smb_buffer_response) 3015 (long) pByteArea(smb_buffer_response)
2743 <= BCC(smb_buffer_response)) { 3016 <= BCC(smb_buffer_response)) {
2744 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); 3017 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2745 strncpy(ses->serverOS,bcc_ptr, len); 3018 strncpy(ses->serverOS,bcc_ptr, len);
2746 3019
2747 bcc_ptr += len; 3020 bcc_ptr += len;
@@ -2749,14 +3022,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2749 bcc_ptr++; 3022 bcc_ptr++;
2750 3023
2751 len = strnlen(bcc_ptr, 1024); 3024 len = strnlen(bcc_ptr, 1024);
2752 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL); 3025 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
2753 strncpy(ses->serverNOS, bcc_ptr, len); 3026 strncpy(ses->serverNOS, bcc_ptr, len);
2754 bcc_ptr += len; 3027 bcc_ptr += len;
2755 bcc_ptr[0] = 0; 3028 bcc_ptr[0] = 0;
2756 bcc_ptr++; 3029 bcc_ptr++;
2757 3030
2758 len = strnlen(bcc_ptr, 1024); 3031 len = strnlen(bcc_ptr, 1024);
2759 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL); 3032 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
2760 strncpy(ses->serverDomain, bcc_ptr, len); 3033 strncpy(ses->serverDomain, bcc_ptr, len);
2761 bcc_ptr += len; 3034 bcc_ptr += len;
2762 bcc_ptr[0] = 0; 3035 bcc_ptr[0] = 0;
@@ -2868,7 +3141,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2868 if(tcon->nativeFileSystem) 3141 if(tcon->nativeFileSystem)
2869 kfree(tcon->nativeFileSystem); 3142 kfree(tcon->nativeFileSystem);
2870 tcon->nativeFileSystem = 3143 tcon->nativeFileSystem =
2871 cifs_kcalloc(length + 2, GFP_KERNEL); 3144 kcalloc(1, length + 2, GFP_KERNEL);
2872 cifs_strfromUCS_le(tcon->nativeFileSystem, 3145 cifs_strfromUCS_le(tcon->nativeFileSystem,
2873 (wchar_t *) bcc_ptr, 3146 (wchar_t *) bcc_ptr,
2874 length, nls_codepage); 3147 length, nls_codepage);
@@ -2886,7 +3159,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2886 if(tcon->nativeFileSystem) 3159 if(tcon->nativeFileSystem)
2887 kfree(tcon->nativeFileSystem); 3160 kfree(tcon->nativeFileSystem);
2888 tcon->nativeFileSystem = 3161 tcon->nativeFileSystem =
2889 cifs_kcalloc(length + 1, GFP_KERNEL); 3162 kcalloc(1, length + 1, GFP_KERNEL);
2890 strncpy(tcon->nativeFileSystem, bcc_ptr, 3163 strncpy(tcon->nativeFileSystem, bcc_ptr,
2891 length); 3164 length);
2892 } 3165 }
@@ -2959,6 +3232,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2959 int rc = 0; 3232 int rc = 0;
2960 char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 3233 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2961 int ntlmv2_flag = FALSE; 3234 int ntlmv2_flag = FALSE;
3235 int first_time = 0;
2962 3236
2963 /* what if server changes its buffer size after dropping the session? */ 3237 /* what if server changes its buffer size after dropping the session? */
2964 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { 3238 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
@@ -2977,12 +3251,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2977 spin_unlock(&GlobalMid_Lock); 3251 spin_unlock(&GlobalMid_Lock);
2978 3252
2979 } 3253 }
3254 first_time = 1;
2980 } 3255 }
2981 if (!rc) { 3256 if (!rc) {
2982 pSesInfo->capabilities = pSesInfo->server->capabilities; 3257 pSesInfo->capabilities = pSesInfo->server->capabilities;
2983 if(linuxExtEnabled == 0) 3258 if(linuxExtEnabled == 0)
2984 pSesInfo->capabilities &= (~CAP_UNIX); 3259 pSesInfo->capabilities &= (~CAP_UNIX);
2985 pSesInfo->sequence_number = 0; 3260 /* pSesInfo->sequence_number = 0;*/
2986 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", 3261 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2987 pSesInfo->server->secMode, 3262 pSesInfo->server->secMode,
2988 pSesInfo->server->capabilities, 3263 pSesInfo->server->capabilities,
@@ -3015,7 +3290,10 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3015 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); 3290 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3016 if(v2_response) { 3291 if(v2_response) {
3017 CalcNTLMv2_response(pSesInfo,v2_response); 3292 CalcNTLMv2_response(pSesInfo,v2_response);
3018/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */ 3293 /* if(first_time)
3294 cifs_calculate_ntlmv2_mac_key(
3295 pSesInfo->server->mac_signing_key,
3296 response, ntlm_session_key, */
3019 kfree(v2_response); 3297 kfree(v2_response);
3020 /* BB Put dummy sig in SessSetup PDU? */ 3298 /* BB Put dummy sig in SessSetup PDU? */
3021 } else { 3299 } else {
@@ -3028,9 +3306,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3028 pSesInfo->server->cryptKey, 3306 pSesInfo->server->cryptKey,
3029 ntlm_session_key); 3307 ntlm_session_key);
3030 3308
3031 cifs_calculate_mac_key(pSesInfo->mac_signing_key, 3309 if(first_time)
3032 ntlm_session_key, 3310 cifs_calculate_mac_key(
3033 pSesInfo->password); 3311 pSesInfo->server->mac_signing_key,
3312 ntlm_session_key,
3313 pSesInfo->password);
3034 } 3314 }
3035 /* for better security the weaker lanman hash not sent 3315 /* for better security the weaker lanman hash not sent
3036 in AuthSessSetup so we no longer calculate it */ 3316 in AuthSessSetup so we no longer calculate it */
@@ -3046,8 +3326,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3046 pSesInfo->server->cryptKey, 3326 pSesInfo->server->cryptKey,
3047 ntlm_session_key); 3327 ntlm_session_key);
3048 3328
3049 cifs_calculate_mac_key(pSesInfo->mac_signing_key, 3329 if(first_time)
3050 ntlm_session_key, pSesInfo->password); 3330 cifs_calculate_mac_key(
3331 pSesInfo->server->mac_signing_key,
3332 ntlm_session_key, pSesInfo->password);
3333
3051 rc = CIFSSessSetup(xid, pSesInfo, 3334 rc = CIFSSessSetup(xid, pSesInfo,
3052 ntlm_session_key, nls_info); 3335 ntlm_session_key, nls_info);
3053 } 3336 }
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f54e1866f0f4..e3137aa48cdd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -101,68 +101,15 @@ cifs_bp_rename_retry:
101 return full_path; 101 return full_path;
102} 102}
103 103
104/* Note: caller must free return buffer */ 104/* char * build_wildcard_path_from_dentry(struct dentry *direntry)
105char *
106build_wildcard_path_from_dentry(struct dentry *direntry)
107{ 105{
108 struct dentry *temp;
109 int namelen = 0;
110 char *full_path;
111
112 if(direntry == NULL)
113 return NULL; /* not much we can do if dentry is freed and
114 we need to reopen the file after it was closed implicitly
115 when the server crashed */
116
117cifs_bwp_rename_retry:
118 for (temp = direntry; !IS_ROOT(temp);) {
119 namelen += (1 + temp->d_name.len);
120 temp = temp->d_parent;
121 if(temp == NULL) {
122 cERROR(1,("corrupt dentry"));
123 return NULL;
124 }
125 }
126
127 full_path = kmalloc(namelen+3, GFP_KERNEL);
128 if(full_path == NULL) 106 if(full_path == NULL)
129 return full_path; 107 return full_path;
130 108
131 full_path[namelen] = '\\'; 109 full_path[namelen] = '\\';
132 full_path[namelen+1] = '*'; 110 full_path[namelen+1] = '*';
133 full_path[namelen+2] = 0; /* trailing null */ 111 full_path[namelen+2] = 0;
134 112BB remove above eight lines BB */
135 for (temp = direntry; !IS_ROOT(temp);) {
136 namelen -= 1 + temp->d_name.len;
137 if (namelen < 0) {
138 break;
139 } else {
140 full_path[namelen] = '\\';
141 strncpy(full_path + namelen + 1, temp->d_name.name,
142 temp->d_name.len);
143 cFYI(0, (" name: %s ", full_path + namelen));
144 }
145 temp = temp->d_parent;
146 if(temp == NULL) {
147 cERROR(1,("corrupt dentry"));
148 kfree(full_path);
149 return NULL;
150 }
151 }
152 if (namelen != 0) {
153 cERROR(1,
154 ("We did not end path lookup where we expected namelen is %d",
155 namelen));
156 /* presumably this is only possible if we were racing with a rename
157 of one of the parent directories (we can not lock the dentries
158 above us to prevent this, but retrying should be harmless) */
159 kfree(full_path);
160 namelen = 0;
161 goto cifs_bwp_rename_retry;
162 }
163
164 return full_path;
165}
166 113
167/* Inode operations in similar order to how they appear in the Linux file fs.h */ 114/* Inode operations in similar order to how they appear in the Linux file fs.h */
168 115
@@ -235,7 +182,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
235 182
236 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 183 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
237 desiredAccess, CREATE_NOT_DIR, 184 desiredAccess, CREATE_NOT_DIR,
238 &fileHandle, &oplock, buf, cifs_sb->local_nls); 185 &fileHandle, &oplock, buf, cifs_sb->local_nls,
186 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
239 if (rc) { 187 if (rc) {
240 cFYI(1, ("cifs_create returned 0x%x ", rc)); 188 cFYI(1, ("cifs_create returned 0x%x ", rc));
241 } else { 189 } else {
@@ -248,13 +196,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
248 (__u64)current->euid, 196 (__u64)current->euid,
249 (__u64)current->egid, 197 (__u64)current->egid,
250 0 /* dev */, 198 0 /* dev */,
251 cifs_sb->local_nls); 199 cifs_sb->local_nls,
200 cifs_sb->mnt_cifs_flags &
201 CIFS_MOUNT_MAP_SPECIAL_CHR);
252 } else { 202 } else {
253 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 203 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
254 (__u64)-1, 204 (__u64)-1,
255 (__u64)-1, 205 (__u64)-1,
256 0 /* dev */, 206 0 /* dev */,
257 cifs_sb->local_nls); 207 cifs_sb->local_nls,
208 cifs_sb->mnt_cifs_flags &
209 CIFS_MOUNT_MAP_SPECIAL_CHR);
258 } 210 }
259 else { 211 else {
260 /* BB implement via Windows security descriptors */ 212 /* BB implement via Windows security descriptors */
@@ -284,51 +236,48 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
284 /* mknod case - do not leave file open */ 236 /* mknod case - do not leave file open */
285 CIFSSMBClose(xid, pTcon, fileHandle); 237 CIFSSMBClose(xid, pTcon, fileHandle);
286 } else if(newinode) { 238 } else if(newinode) {
287 pCifsFile = (struct cifsFileInfo *) 239 pCifsFile =
288 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); 240 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
289 241
290 if (pCifsFile) { 242 if(pCifsFile == NULL)
291 memset((char *)pCifsFile, 0, 243 goto cifs_create_out;
292 sizeof (struct cifsFileInfo)); 244 memset((char *)pCifsFile, 0,
293 pCifsFile->netfid = fileHandle; 245 sizeof (struct cifsFileInfo));
294 pCifsFile->pid = current->tgid; 246 pCifsFile->netfid = fileHandle;
295 pCifsFile->pInode = newinode; 247 pCifsFile->pid = current->tgid;
296 pCifsFile->invalidHandle = FALSE; 248 pCifsFile->pInode = newinode;
297 pCifsFile->closePend = FALSE; 249 pCifsFile->invalidHandle = FALSE;
298 init_MUTEX(&pCifsFile->fh_sem); 250 pCifsFile->closePend = FALSE;
299 /* put the following in at open now */ 251 init_MUTEX(&pCifsFile->fh_sem);
300 /* pCifsFile->pfile = file; */ 252 /* set the following in open now
301 write_lock(&GlobalSMBSeslock); 253 pCifsFile->pfile = file; */
302 list_add(&pCifsFile->tlist,&pTcon->openFileList); 254 write_lock(&GlobalSMBSeslock);
303 pCifsInode = CIFS_I(newinode); 255 list_add(&pCifsFile->tlist,&pTcon->openFileList);
304 if(pCifsInode) { 256 pCifsInode = CIFS_I(newinode);
257 if(pCifsInode) {
305 /* if readable file instance put first in list*/ 258 /* if readable file instance put first in list*/
306 if (write_only == TRUE) { 259 if (write_only == TRUE) {
307 list_add_tail(&pCifsFile->flist, 260 list_add_tail(&pCifsFile->flist,
308 &pCifsInode->openFileList); 261 &pCifsInode->openFileList);
309 } else { 262 } else {
310 list_add(&pCifsFile->flist, 263 list_add(&pCifsFile->flist,
311 &pCifsInode->openFileList); 264 &pCifsInode->openFileList);
312 }
313 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
314 pCifsInode->clientCanCacheAll = TRUE;
315 pCifsInode->clientCanCacheRead = TRUE;
316 cFYI(1,("Exclusive Oplock granted on inode %p",
317 newinode));
318 } else if((oplock & 0xF) == OPLOCK_READ)
319 pCifsInode->clientCanCacheRead = TRUE;
320 } 265 }
321 write_unlock(&GlobalSMBSeslock); 266 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
267 pCifsInode->clientCanCacheAll = TRUE;
268 pCifsInode->clientCanCacheRead = TRUE;
269 cFYI(1,("Exclusive Oplock for inode %p",
270 newinode));
271 } else if((oplock & 0xF) == OPLOCK_READ)
272 pCifsInode->clientCanCacheRead = TRUE;
322 } 273 }
274 write_unlock(&GlobalSMBSeslock);
323 } 275 }
324 } 276 }
325 277cifs_create_out:
326 if (buf) 278 kfree(buf);
327 kfree(buf); 279 kfree(full_path);
328 if (full_path)
329 kfree(full_path);
330 FreeXid(xid); 280 FreeXid(xid);
331
332 return rc; 281 return rc;
333} 282}
334 283
@@ -359,11 +308,15 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
359 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
360 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
361 mode,(__u64)current->euid,(__u64)current->egid, 310 mode,(__u64)current->euid,(__u64)current->egid,
362 device_number, cifs_sb->local_nls); 311 device_number, cifs_sb->local_nls,
312 cifs_sb->mnt_cifs_flags &
313 CIFS_MOUNT_MAP_SPECIAL_CHR);
363 } else { 314 } else {
364 rc = CIFSSMBUnixSetPerms(xid, pTcon, 315 rc = CIFSSMBUnixSetPerms(xid, pTcon,
365 full_path, mode, (__u64)-1, (__u64)-1, 316 full_path, mode, (__u64)-1, (__u64)-1,
366 device_number, cifs_sb->local_nls); 317 device_number, cifs_sb->local_nls,
318 cifs_sb->mnt_cifs_flags &
319 CIFS_MOUNT_MAP_SPECIAL_CHR);
367 } 320 }
368 321
369 if(!rc) { 322 if(!rc) {
@@ -375,10 +328,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
375 } 328 }
376 } 329 }
377 330
378 if (full_path) 331 kfree(full_path);
379 kfree(full_path);
380 FreeXid(xid); 332 FreeXid(xid);
381
382 return rc; 333 return rc;
383} 334}
384 335
@@ -447,43 +398,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
447 if file exists or not but no access BB */ 398 if file exists or not but no access BB */
448 } 399 }
449 400
450 if (full_path) 401 kfree(full_path);
451 kfree(full_path);
452 FreeXid(xid); 402 FreeXid(xid);
453 return ERR_PTR(rc); 403 return ERR_PTR(rc);
454} 404}
455 405
456int
457cifs_dir_open(struct inode *inode, struct file *file)
458{ /* NB: currently unused since searches are opened in readdir */
459 int rc = 0;
460 int xid;
461 struct cifs_sb_info *cifs_sb;
462 struct cifsTconInfo *pTcon;
463 char *full_path = NULL;
464
465 xid = GetXid();
466
467 cifs_sb = CIFS_SB(inode->i_sb);
468 pTcon = cifs_sb->tcon;
469
470 if(file->f_dentry) {
471 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
472 full_path = build_wildcard_path_from_dentry(file->f_dentry);
473 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
474 } else {
475 FreeXid(xid);
476 return -EIO;
477 }
478
479 cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
480
481 if (full_path)
482 kfree(full_path);
483 FreeXid(xid);
484 return rc;
485}
486
487static int 406static int
488cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) 407cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
489{ 408{
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 9d24c40f1967..7d2a9202c39a 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -92,7 +92,8 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
92 cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */ 92 cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */
93 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 93 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
94 GENERIC_READ | SYNCHRONIZE, 0 /* create options */, 94 GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
95 &netfid, &oplock,NULL, cifs_sb->local_nls); 95 &netfid, &oplock,NULL, cifs_sb->local_nls,
96 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
96 /* BB fixme - add this handle to a notify handle list */ 97 /* BB fixme - add this handle to a notify handle list */
97 if(rc) { 98 if(rc) {
98 cERROR(1,("Could not open directory for notify")); /* BB remove BB */ 99 cERROR(1,("Could not open directory for notify")); /* BB remove BB */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dcab7cf1b53b..dde2d251fc3d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -254,7 +254,8 @@ int cifs_open(struct inode *inode, struct file *file)
254 } 254 }
255 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 255 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
256 CREATE_NOT_DIR, &netfid, &oplock, buf, 256 CREATE_NOT_DIR, &netfid, &oplock, buf,
257 cifs_sb->local_nls); 257 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
258 & CIFS_MOUNT_MAP_SPECIAL_CHR);
258 if (rc) { 259 if (rc) {
259 cFYI(1, ("cifs_open returned 0x%x ", rc)); 260 cFYI(1, ("cifs_open returned 0x%x ", rc));
260 goto out; 261 goto out;
@@ -287,7 +288,9 @@ int cifs_open(struct inode *inode, struct file *file)
287 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 288 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
288 inode->i_mode, 289 inode->i_mode,
289 (__u64)-1, (__u64)-1, 0 /* dev */, 290 (__u64)-1, (__u64)-1, 0 /* dev */,
290 cifs_sb->local_nls); 291 cifs_sb->local_nls,
292 cifs_sb->mnt_cifs_flags &
293 CIFS_MOUNT_MAP_SPECIAL_CHR);
291 } else { 294 } else {
292 /* BB implement via Windows security descriptors eg 295 /* BB implement via Windows security descriptors eg
293 CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, 296 CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
@@ -387,7 +390,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
387 } */ 390 } */
388 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 391 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
389 CREATE_NOT_DIR, &netfid, &oplock, NULL, 392 CREATE_NOT_DIR, &netfid, &oplock, NULL,
390 cifs_sb->local_nls); 393 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
394 CIFS_MOUNT_MAP_SPECIAL_CHR);
391 if (rc) { 395 if (rc) {
392 up(&pCifsFile->fh_sem); 396 up(&pCifsFile->fh_sem);
393 cFYI(1, ("cifs_open returned 0x%x ", rc)); 397 cFYI(1, ("cifs_open returned 0x%x ", rc));
@@ -465,8 +469,10 @@ int cifs_close(struct inode *inode, struct file *file)
465 write_lock(&file->f_owner.lock); 469 write_lock(&file->f_owner.lock);
466 } 470 }
467 } 471 }
472 write_lock(&GlobalSMBSeslock);
468 list_del(&pSMBFile->flist); 473 list_del(&pSMBFile->flist);
469 list_del(&pSMBFile->tlist); 474 list_del(&pSMBFile->tlist);
475 write_unlock(&GlobalSMBSeslock);
470 write_unlock(&file->f_owner.lock); 476 write_unlock(&file->f_owner.lock);
471 kfree(pSMBFile->search_resume_name); 477 kfree(pSMBFile->search_resume_name);
472 kfree(file->private_data); 478 kfree(file->private_data);
@@ -506,7 +512,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
506 pTcon = cifs_sb->tcon; 512 pTcon = cifs_sb->tcon;
507 513
508 cFYI(1, ("Freeing private data in close dir")); 514 cFYI(1, ("Freeing private data in close dir"));
509 if (pCFileStruct->srch_inf.endOfSearch == FALSE) { 515 if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
516 (pCFileStruct->invalidHandle == FALSE)) {
510 pCFileStruct->invalidHandle = TRUE; 517 pCFileStruct->invalidHandle = TRUE;
511 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); 518 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
512 cFYI(1, ("Closing uncompleted readdir with rc %d", 519 cFYI(1, ("Closing uncompleted readdir with rc %d",
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index d73b0aa86775..670947288262 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -44,7 +44,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
44 cFYI(1, (" Getting info on %s ", search_path)); 44 cFYI(1, (" Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */ 45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls); 47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
48 CIFS_MOUNT_MAP_SPECIAL_CHR);
48/* dump_mem("\nUnixQPathInfo return data", &findData, 49/* dump_mem("\nUnixQPathInfo return data", &findData,
49 sizeof(findData)); */ 50 sizeof(findData)); */
50 if (rc) { 51 if (rc) {
@@ -63,7 +64,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
63 strncat(tmp_path, search_path, MAX_PATHCONF); 64 strncat(tmp_path, search_path, MAX_PATHCONF);
64 rc = connect_to_dfs_path(xid, pTcon->ses, 65 rc = connect_to_dfs_path(xid, pTcon->ses,
65 /* treename + */ tmp_path, 66 /* treename + */ tmp_path,
66 cifs_sb->local_nls); 67 cifs_sb->local_nls,
68 cifs_sb->mnt_cifs_flags &
69 CIFS_MOUNT_MAP_SPECIAL_CHR);
67 kfree(tmp_path); 70 kfree(tmp_path);
68 71
69 /* BB fix up inode etc. */ 72 /* BB fix up inode etc. */
@@ -210,7 +213,8 @@ int cifs_get_inode_info(struct inode **pinode,
210 pfindData = (FILE_ALL_INFO *)buf; 213 pfindData = (FILE_ALL_INFO *)buf;
211 /* could do find first instead but this returns more info */ 214 /* could do find first instead but this returns more info */
212 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, 215 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
213 cifs_sb->local_nls); 216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
217 CIFS_MOUNT_MAP_SPECIAL_CHR);
214 } 218 }
215 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 219 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
216 if (rc) { 220 if (rc) {
@@ -230,7 +234,9 @@ int cifs_get_inode_info(struct inode **pinode,
230 strncat(tmp_path, search_path, MAX_PATHCONF); 234 strncat(tmp_path, search_path, MAX_PATHCONF);
231 rc = connect_to_dfs_path(xid, pTcon->ses, 235 rc = connect_to_dfs_path(xid, pTcon->ses,
232 /* treename + */ tmp_path, 236 /* treename + */ tmp_path,
233 cifs_sb->local_nls); 237 cifs_sb->local_nls,
238 cifs_sb->mnt_cifs_flags &
239 CIFS_MOUNT_MAP_SPECIAL_CHR);
234 kfree(tmp_path); 240 kfree(tmp_path);
235 /* BB fix up inode etc. */ 241 /* BB fix up inode etc. */
236 } else if (rc) { 242 } else if (rc) {
@@ -268,7 +274,9 @@ int cifs_get_inode_info(struct inode **pinode,
268 274
269 rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 275 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
270 search_path, &inode_num, 276 search_path, &inode_num,
271 cifs_sb->local_nls); 277 cifs_sb->local_nls,
278 cifs_sb->mnt_cifs_flags &
279 CIFS_MOUNT_MAP_SPECIAL_CHR);
272 if(rc1) { 280 if(rc1) {
273 cFYI(1,("GetSrvInodeNum rc %d", rc1)); 281 cFYI(1,("GetSrvInodeNum rc %d", rc1));
274 /* BB EOPNOSUPP disable SERVER_INUM? */ 282 /* BB EOPNOSUPP disable SERVER_INUM? */
@@ -410,7 +418,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
410 FreeXid(xid); 418 FreeXid(xid);
411 return -ENOMEM; 419 return -ENOMEM;
412 } 420 }
413 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); 421 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
422 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
414 423
415 if (!rc) { 424 if (!rc) {
416 direntry->d_inode->i_nlink--; 425 direntry->d_inode->i_nlink--;
@@ -422,10 +431,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
422 431
423 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, 432 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
424 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, 433 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
425 &netfid, &oplock, NULL, cifs_sb->local_nls); 434 &netfid, &oplock, NULL, cifs_sb->local_nls,
435 cifs_sb->mnt_cifs_flags &
436 CIFS_MOUNT_MAP_SPECIAL_CHR);
426 if (rc==0) { 437 if (rc==0) {
427 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, 438 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
428 cifs_sb->local_nls); 439 cifs_sb->local_nls,
440 cifs_sb->mnt_cifs_flags &
441 CIFS_MOUNT_MAP_SPECIAL_CHR);
429 CIFSSMBClose(xid, pTcon, netfid); 442 CIFSSMBClose(xid, pTcon, netfid);
430 direntry->d_inode->i_nlink--; 443 direntry->d_inode->i_nlink--;
431 } 444 }
@@ -439,7 +452,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
439 if (!(pTcon->ses->flags & CIFS_SES_NT4)) 452 if (!(pTcon->ses->flags & CIFS_SES_NT4))
440 rc = CIFSSMBSetTimes(xid, pTcon, full_path, 453 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
441 pinfo_buf, 454 pinfo_buf,
442 cifs_sb->local_nls); 455 cifs_sb->local_nls,
456 cifs_sb->mnt_cifs_flags &
457 CIFS_MOUNT_MAP_SPECIAL_CHR);
443 else 458 else
444 rc = -EOPNOTSUPP; 459 rc = -EOPNOTSUPP;
445 460
@@ -461,7 +476,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
461 FILE_OPEN, SYNCHRONIZE | 476 FILE_OPEN, SYNCHRONIZE |
462 FILE_WRITE_ATTRIBUTES, 0, 477 FILE_WRITE_ATTRIBUTES, 0,
463 &netfid, &oplock, NULL, 478 &netfid, &oplock, NULL,
464 cifs_sb->local_nls); 479 cifs_sb->local_nls,
480 cifs_sb->mnt_cifs_flags &
481 CIFS_MOUNT_MAP_SPECIAL_CHR);
465 if (rc==0) { 482 if (rc==0) {
466 rc = CIFSSMBSetFileTimes(xid, pTcon, 483 rc = CIFSSMBSetFileTimes(xid, pTcon,
467 pinfo_buf, 484 pinfo_buf,
@@ -472,8 +489,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
472 kfree(pinfo_buf); 489 kfree(pinfo_buf);
473 } 490 }
474 if (rc==0) { 491 if (rc==0) {
475 rc = CIFSSMBDelFile(xid, pTcon, full_path, 492 rc = CIFSSMBDelFile(xid, pTcon, full_path,
476 cifs_sb->local_nls); 493 cifs_sb->local_nls,
494 cifs_sb->mnt_cifs_flags &
495 CIFS_MOUNT_MAP_SPECIAL_CHR);
477 if (!rc) { 496 if (!rc) {
478 direntry->d_inode->i_nlink--; 497 direntry->d_inode->i_nlink--;
479 } else if (rc == -ETXTBSY) { 498 } else if (rc == -ETXTBSY) {
@@ -485,11 +504,15 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
485 CREATE_NOT_DIR | 504 CREATE_NOT_DIR |
486 CREATE_DELETE_ON_CLOSE, 505 CREATE_DELETE_ON_CLOSE,
487 &netfid, &oplock, NULL, 506 &netfid, &oplock, NULL,
488 cifs_sb->local_nls); 507 cifs_sb->local_nls,
508 cifs_sb->mnt_cifs_flags &
509 CIFS_MOUNT_MAP_SPECIAL_CHR);
489 if (rc==0) { 510 if (rc==0) {
490 CIFSSMBRenameOpenFile(xid, pTcon, 511 CIFSSMBRenameOpenFile(xid, pTcon,
491 netfid, NULL, 512 netfid, NULL,
492 cifs_sb->local_nls); 513 cifs_sb->local_nls,
514 cifs_sb->mnt_cifs_flags &
515 CIFS_MOUNT_MAP_SPECIAL_CHR);
493 CIFSSMBClose(xid, pTcon, netfid); 516 CIFSSMBClose(xid, pTcon, netfid);
494 direntry->d_inode->i_nlink--; 517 direntry->d_inode->i_nlink--;
495 } 518 }
@@ -534,7 +557,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
534 return -ENOMEM; 557 return -ENOMEM;
535 } 558 }
536 /* BB add setting the equivalent of mode via CreateX w/ACLs */ 559 /* BB add setting the equivalent of mode via CreateX w/ACLs */
537 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); 560 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
561 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
538 if (rc) { 562 if (rc) {
539 cFYI(1, ("cifs_mkdir returned 0x%x ", rc)); 563 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
540 d_drop(direntry); 564 d_drop(direntry);
@@ -558,12 +582,16 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
558 (__u64)current->euid, 582 (__u64)current->euid,
559 (__u64)current->egid, 583 (__u64)current->egid,
560 0 /* dev_t */, 584 0 /* dev_t */,
561 cifs_sb->local_nls); 585 cifs_sb->local_nls,
586 cifs_sb->mnt_cifs_flags &
587 CIFS_MOUNT_MAP_SPECIAL_CHR);
562 } else { 588 } else {
563 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 589 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
564 mode, (__u64)-1, 590 mode, (__u64)-1,
565 (__u64)-1, 0 /* dev_t */, 591 (__u64)-1, 0 /* dev_t */,
566 cifs_sb->local_nls); 592 cifs_sb->local_nls,
593 cifs_sb->mnt_cifs_flags &
594 CIFS_MOUNT_MAP_SPECIAL_CHR);
567 } 595 }
568 else { 596 else {
569 /* BB to be implemented via Windows secrty descriptors 597 /* BB to be implemented via Windows secrty descriptors
@@ -600,7 +628,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
600 return -ENOMEM; 628 return -ENOMEM;
601 } 629 }
602 630
603 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls); 631 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
632 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
604 633
605 if (!rc) { 634 if (!rc) {
606 inode->i_nlink--; 635 inode->i_nlink--;
@@ -653,7 +682,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
653 } 682 }
654 683
655 rc = CIFSSMBRename(xid, pTcon, fromName, toName, 684 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
656 cifs_sb_source->local_nls); 685 cifs_sb_source->local_nls,
686 cifs_sb_source->mnt_cifs_flags &
687 CIFS_MOUNT_MAP_SPECIAL_CHR);
657 if (rc == -EEXIST) { 688 if (rc == -EEXIST) {
658 /* check if they are the same file because rename of hardlinked 689 /* check if they are the same file because rename of hardlinked
659 files is a noop */ 690 files is a noop */
@@ -665,11 +696,16 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
665 if (info_buf_source != NULL) { 696 if (info_buf_source != NULL) {
666 info_buf_target = info_buf_source + 1; 697 info_buf_target = info_buf_source + 1;
667 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, 698 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
668 info_buf_source, cifs_sb_source->local_nls); 699 info_buf_source, cifs_sb_source->local_nls,
700 cifs_sb_source->mnt_cifs_flags &
701 CIFS_MOUNT_MAP_SPECIAL_CHR);
669 if (rc == 0) { 702 if (rc == 0) {
670 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName, 703 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
671 info_buf_target, 704 info_buf_target,
672 cifs_sb_target->local_nls); 705 cifs_sb_target->local_nls,
706 /* remap based on source sb */
707 cifs_sb_source->mnt_cifs_flags &
708 CIFS_MOUNT_MAP_SPECIAL_CHR);
673 } 709 }
674 if ((rc == 0) && 710 if ((rc == 0) &&
675 (info_buf_source->UniqueId == 711 (info_buf_source->UniqueId ==
@@ -685,7 +721,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
685 cifs_unlink(target_inode, target_direntry); 721 cifs_unlink(target_inode, target_direntry);
686 rc = CIFSSMBRename(xid, pTcon, fromName, 722 rc = CIFSSMBRename(xid, pTcon, fromName,
687 toName, 723 toName,
688 cifs_sb_source->local_nls); 724 cifs_sb_source->local_nls,
725 cifs_sb_source->mnt_cifs_flags
726 & CIFS_MOUNT_MAP_SPECIAL_CHR);
689 } 727 }
690 kfree(info_buf_source); 728 kfree(info_buf_source);
691 } /* if we can not get memory just leave rc as EEXIST */ 729 } /* if we can not get memory just leave rc as EEXIST */
@@ -705,10 +743,14 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
705 might not right be right access to request */ 743 might not right be right access to request */
706 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ, 744 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
707 CREATE_NOT_DIR, &netfid, &oplock, NULL, 745 CREATE_NOT_DIR, &netfid, &oplock, NULL,
708 cifs_sb_source->local_nls); 746 cifs_sb_source->local_nls,
747 cifs_sb_source->mnt_cifs_flags &
748 CIFS_MOUNT_MAP_SPECIAL_CHR);
709 if (rc==0) { 749 if (rc==0) {
710 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, 750 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
711 cifs_sb_source->local_nls); 751 cifs_sb_source->local_nls,
752 cifs_sb_source->mnt_cifs_flags &
753 CIFS_MOUNT_MAP_SPECIAL_CHR);
712 CIFSSMBClose(xid, pTcon, netfid); 754 CIFSSMBClose(xid, pTcon, netfid);
713 } 755 }
714 } 756 }
@@ -962,7 +1004,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
962 it by handle */ 1004 it by handle */
963 rc = CIFSSMBSetEOF(xid, pTcon, full_path, 1005 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
964 attrs->ia_size, FALSE, 1006 attrs->ia_size, FALSE,
965 cifs_sb->local_nls); 1007 cifs_sb->local_nls,
1008 cifs_sb->mnt_cifs_flags &
1009 CIFS_MOUNT_MAP_SPECIAL_CHR);
966 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc)); 1010 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
967 } 1011 }
968 1012
@@ -999,7 +1043,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
999 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) 1043 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1000 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) 1044 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1001 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, 1045 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1002 0 /* dev_t */, cifs_sb->local_nls); 1046 0 /* dev_t */, cifs_sb->local_nls,
1047 cifs_sb->mnt_cifs_flags &
1048 CIFS_MOUNT_MAP_SPECIAL_CHR);
1003 else if (attrs->ia_valid & ATTR_MODE) { 1049 else if (attrs->ia_valid & ATTR_MODE) {
1004 if ((mode & S_IWUGO) == 0) /* not writeable */ { 1050 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1005 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) 1051 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
@@ -1048,7 +1094,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1048 via Handle (SetFileInfo) instead of by path */ 1094 via Handle (SetFileInfo) instead of by path */
1049 if (!(pTcon->ses->flags & CIFS_SES_NT4)) 1095 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1050 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, 1096 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1051 cifs_sb->local_nls); 1097 cifs_sb->local_nls,
1098 cifs_sb->mnt_cifs_flags &
1099 CIFS_MOUNT_MAP_SPECIAL_CHR);
1052 else 1100 else
1053 rc = -EOPNOTSUPP; 1101 rc = -EOPNOTSUPP;
1054 1102
@@ -1063,7 +1111,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1063 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 1111 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1064 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 1112 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1065 CREATE_NOT_DIR, &netfid, &oplock, 1113 CREATE_NOT_DIR, &netfid, &oplock,
1066 NULL, cifs_sb->local_nls); 1114 NULL, cifs_sb->local_nls,
1115 cifs_sb->mnt_cifs_flags &
1116 CIFS_MOUNT_MAP_SPECIAL_CHR);
1067 if (rc==0) { 1117 if (rc==0) {
1068 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf, 1118 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1069 netfid); 1119 netfid);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index b4b8e201d428..b0ea6687ab55 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -20,30 +20,93 @@
20 * along with this library; if not, write to the Free Software 20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23
23#include <linux/fs.h> 24#include <linux/fs.h>
24#include <linux/ext2_fs.h> 25#include <linux/ext2_fs.h>
25#include "cifspdu.h" 26#include "cifspdu.h"
26#include "cifsglob.h" 27#include "cifsglob.h"
27#include "cifsproto.h" 28#include "cifsproto.h"
28#include "cifs_debug.h" 29#include "cifs_debug.h"
30#include "cifsfs.h"
31
32#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
29 33
30int cifs_ioctl (struct inode * inode, struct file * filep, 34int cifs_ioctl (struct inode * inode, struct file * filep,
31 unsigned int command, unsigned long arg) 35 unsigned int command, unsigned long arg)
32{ 36{
33 int rc = -ENOTTY; /* strange error - but the precedent */ 37 int rc = -ENOTTY; /* strange error - but the precedent */
38 int xid;
39 struct cifs_sb_info *cifs_sb;
40#ifdef CONFIG_CIFS_POSIX
41 __u64 ExtAttrBits = 0;
42 __u64 ExtAttrMask = 0;
43 __u64 caps;
44 struct cifsTconInfo *tcon;
45 struct cifsFileInfo *pSMBFile =
46 (struct cifsFileInfo *)filep->private_data;
47#endif /* CONFIG_CIFS_POSIX */
48
49 xid = GetXid();
50
51 cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
52
53 cifs_sb = CIFS_SB(inode->i_sb);
54
34#ifdef CONFIG_CIFS_POSIX 55#ifdef CONFIG_CIFS_POSIX
35 cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); 56 tcon = cifs_sb->tcon;
57 if(tcon)
58 caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
59 else {
60 rc = -EIO;
61 FreeXid(xid);
62 return -EIO;
63 }
64#endif /* CONFIG_CIFS_POSIX */
65
36 switch(command) { 66 switch(command) {
67 case CIFS_IOC_CHECKUMOUNT:
68 cFYI(1,("User unmount attempted"));
69 if(cifs_sb->mnt_uid == current->uid)
70 rc = 0;
71 else {
72 rc = -EACCES;
73 cFYI(1,("uids do not match"));
74 }
75 break;
76#ifdef CONFIG_CIFS_POSIX
37 case EXT2_IOC_GETFLAGS: 77 case EXT2_IOC_GETFLAGS:
38 cFYI(1,("get flags not implemented yet")); 78 if(CIFS_UNIX_EXTATTR_CAP & caps) {
39 return -EOPNOTSUPP; 79 if (pSMBFile == NULL)
80 break;
81 rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
82 &ExtAttrBits, &ExtAttrMask);
83 if(rc == 0)
84 rc = put_user(ExtAttrBits &
85 EXT2_FL_USER_VISIBLE,
86 (int __user *)arg);
87 }
88 break;
89
40 case EXT2_IOC_SETFLAGS: 90 case EXT2_IOC_SETFLAGS:
91 if(CIFS_UNIX_EXTATTR_CAP & caps) {
92 if(get_user(ExtAttrBits,(int __user *)arg)) {
93 rc = -EFAULT;
94 break;
95 }
96 if (pSMBFile == NULL)
97 break;
98 /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
99 extAttrBits, &ExtAttrMask);*/
100
101 }
41 cFYI(1,("set flags not implemented yet")); 102 cFYI(1,("set flags not implemented yet"));
42 return -EOPNOTSUPP; 103 break;
104#endif /* CONFIG_CIFS_POSIX */
43 default: 105 default:
44 cFYI(1,("unsupported ioctl")); 106 cFYI(1,("unsupported ioctl"));
45 return rc; 107 break;
46 } 108 }
47#endif /* CONFIG_CIFS_POSIX */ 109
110 FreeXid(xid);
48 return rc; 111 return rc;
49} 112}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 1455810ba1cb..bde0fabfece0 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -59,10 +59,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
59 59
60 if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) 60 if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
61 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, 61 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
62 cifs_sb_target->local_nls); 62 cifs_sb_target->local_nls,
63 cifs_sb_target->mnt_cifs_flags &
64 CIFS_MOUNT_MAP_SPECIAL_CHR);
63 else { 65 else {
64 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, 66 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
65 cifs_sb_target->local_nls); 67 cifs_sb_target->local_nls,
68 cifs_sb_target->mnt_cifs_flags &
69 CIFS_MOUNT_MAP_SPECIAL_CHR);
66 if(rc == -EIO) 70 if(rc == -EIO)
67 rc = -EOPNOTSUPP; 71 rc = -EOPNOTSUPP;
68 } 72 }
@@ -260,7 +264,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
260 cifs_sb->local_nls); 264 cifs_sb->local_nls);
261 else { 265 else {
262 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, 266 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
263 OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls); 267 OPEN_REPARSE_POINT,&fid, &oplock, NULL,
268 cifs_sb->local_nls,
269 cifs_sb->mnt_cifs_flags &
270 CIFS_MOUNT_MAP_SPECIAL_CHR);
264 if(!rc) { 271 if(!rc) {
265 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, 272 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
266 tmpbuffer, 273 tmpbuffer,
@@ -279,7 +286,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
279 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); 286 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
280 strncat(tmp_path, full_path, MAX_PATHCONF); 287 strncat(tmp_path, full_path, MAX_PATHCONF);
281 rc = get_dfs_path(xid, pTcon->ses, tmp_path, 288 rc = get_dfs_path(xid, pTcon->ses, tmp_path,
282 cifs_sb->local_nls, &num_referrals, &referrals); 289 cifs_sb->local_nls,
290 &num_referrals, &referrals,
291 cifs_sb->mnt_cifs_flags &
292 CIFS_MOUNT_MAP_SPECIAL_CHR);
283 cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc)); 293 cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
284 if((num_referrals == 0) && (rc == 0)) 294 if((num_referrals == 0) && (rc == 0))
285 rc = -EACCES; 295 rc = -EACCES;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 7b38d3059a83..db14b503d89e 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -28,6 +28,7 @@
28#include "cifs_debug.h" 28#include "cifs_debug.h"
29#include "smberr.h" 29#include "smberr.h"
30#include "nterr.h" 30#include "nterr.h"
31#include "cifs_unicode.h"
31 32
32extern mempool_t *cifs_sm_req_poolp; 33extern mempool_t *cifs_sm_req_poolp;
33extern mempool_t *cifs_req_poolp; 34extern mempool_t *cifs_req_poolp;
@@ -451,25 +452,30 @@ is_valid_oplock_break(struct smb_hdr *buf)
451 atomic_inc(&tcon->num_oplock_brks); 452 atomic_inc(&tcon->num_oplock_brks);
452#endif 453#endif
453 list_for_each(tmp1,&tcon->openFileList){ 454 list_for_each(tmp1,&tcon->openFileList){
454 netfile = list_entry(tmp1,struct cifsFileInfo,tlist); 455 netfile = list_entry(tmp1,struct cifsFileInfo,
456 tlist);
455 if(pSMB->Fid == netfile->netfid) { 457 if(pSMB->Fid == netfile->netfid) {
456 struct cifsInodeInfo *pCifsInode; 458 struct cifsInodeInfo *pCifsInode;
457 read_unlock(&GlobalSMBSeslock); 459 read_unlock(&GlobalSMBSeslock);
458 cFYI(1,("Matching file id, processing oplock break")); 460 cFYI(1,("file id match, oplock break"));
459 pCifsInode = 461 pCifsInode =
460 CIFS_I(netfile->pInode); 462 CIFS_I(netfile->pInode);
461 pCifsInode->clientCanCacheAll = FALSE; 463 pCifsInode->clientCanCacheAll = FALSE;
462 if(pSMB->OplockLevel == 0) 464 if(pSMB->OplockLevel == 0)
463 pCifsInode->clientCanCacheRead = FALSE; 465 pCifsInode->clientCanCacheRead
466 = FALSE;
464 pCifsInode->oplockPending = TRUE; 467 pCifsInode->oplockPending = TRUE;
465 AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon); 468 AllocOplockQEntry(netfile->pInode,
469 netfile->netfid,
470 tcon);
466 cFYI(1,("about to wake up oplock thd")); 471 cFYI(1,("about to wake up oplock thd"));
467 wake_up_process(oplockThread); 472 if(oplockThread)
473 wake_up_process(oplockThread);
468 return TRUE; 474 return TRUE;
469 } 475 }
470 } 476 }
471 read_unlock(&GlobalSMBSeslock); 477 read_unlock(&GlobalSMBSeslock);
472 cFYI(1,("No matching file for oplock break on connection")); 478 cFYI(1,("No matching file for oplock break"));
473 return TRUE; 479 return TRUE;
474 } 480 }
475 } 481 }
@@ -490,7 +496,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
490 496
491 buffer = (unsigned char *) smb_buf; 497 buffer = (unsigned char *) smb_buf;
492 for (i = 0, j = 0; i < smb_buf_length; i++, j++) { 498 for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
493 if (i % 8 == 0) { /* we have reached the beginning of line */ 499 if (i % 8 == 0) { /* have reached the beginning of line */
494 printk(KERN_DEBUG "| "); 500 printk(KERN_DEBUG "| ");
495 j = 0; 501 j = 0;
496 } 502 }
@@ -501,7 +507,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
501 else 507 else
502 debug_line[1 + (2 * j)] = '_'; 508 debug_line[1 + (2 * j)] = '_';
503 509
504 if (i % 8 == 7) { /* we have reached end of line, time to print ascii */ 510 if (i % 8 == 7) { /* reached end of line, time to print ascii */
505 debug_line[16] = 0; 511 debug_line[16] = 0;
506 printk(" | %s\n", debug_line); 512 printk(" | %s\n", debug_line);
507 } 513 }
@@ -514,3 +520,141 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
514 printk( " | %s\n", debug_line); 520 printk( " | %s\n", debug_line);
515 return; 521 return;
516} 522}
523
524/* Windows maps these to the user defined 16 bit Unicode range since they are
525 reserved symbols (along with \ and /), otherwise illegal to store
526 in filenames in NTFS */
527#define UNI_ASTERIK (__u16) ('*' + 0xF000)
528#define UNI_QUESTION (__u16) ('?' + 0xF000)
529#define UNI_COLON (__u16) (':' + 0xF000)
530#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
531#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
532#define UNI_PIPE (__u16) ('|' + 0xF000)
533#define UNI_SLASH (__u16) ('\\' + 0xF000)
534
535/* Convert 16 bit Unicode pathname from wire format to string in current code
536 page. Conversion may involve remapping up the seven characters that are
537 only legal in POSIX-like OS (if they are present in the string). Path
538 names are little endian 16 bit Unicode on the wire */
539int
540cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
541 const struct nls_table * cp)
542{
543 int i,j,len;
544 __u16 src_char;
545
546 for(i = 0, j = 0; i < maxlen; i++) {
547 src_char = le16_to_cpu(source[i]);
548 switch (src_char) {
549 case 0:
550 goto cUCS_out; /* BB check this BB */
551 case UNI_COLON:
552 target[j] = ':';
553 break;
554 case UNI_ASTERIK:
555 target[j] = '*';
556 break;
557 case UNI_QUESTION:
558 target[j] = '?';
559 break;
560 /* BB We can not handle remapping slash until
561 all the calls to build_path_from_dentry
562 are modified, as they use slash as separator BB */
563 /* case UNI_SLASH:
564 target[j] = '\\';
565 break;*/
566 case UNI_PIPE:
567 target[j] = '|';
568 break;
569 case UNI_GRTRTHAN:
570 target[j] = '>';
571 break;
572 case UNI_LESSTHAN:
573 target[j] = '<';
574 default:
575 len = cp->uni2char(src_char, &target[j],
576 NLS_MAX_CHARSET_SIZE);
577 if(len > 0) {
578 j += len;
579 continue;
580 } else {
581 target[j] = '?';
582 }
583 }
584 j++;
585 /* make sure we do not overrun callers allocated temp buffer */
586 if(j >= (2 * NAME_MAX))
587 break;
588 }
589cUCS_out:
590 target[j] = 0;
591 return j;
592}
593
594/* Convert 16 bit Unicode pathname to wire format from string in current code
595 page. Conversion may involve remapping up the seven characters that are
596 only legal in POSIX-like OS (if they are present in the string). Path
597 names are little endian 16 bit Unicode on the wire */
598int
599cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
600 const struct nls_table * cp, int mapChars)
601{
602 int i,j,charlen;
603 int len_remaining = maxlen;
604 char src_char;
605
606 if(!mapChars)
607 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
608
609 for(i = 0, j = 0; i < maxlen; j++) {
610 src_char = source[i];
611 switch (src_char) {
612 case 0:
613 goto ctoUCS_out;
614 case ':':
615 target[j] = cpu_to_le16(UNI_COLON);
616 break;
617 case '*':
618 target[j] = cpu_to_le16(UNI_ASTERIK);
619 break;
620 case '?':
621 target[j] = cpu_to_le16(UNI_QUESTION);
622 break;
623 case '<':
624 target[j] = cpu_to_le16(UNI_LESSTHAN);
625 break;
626 case '>':
627 target[j] = cpu_to_le16(UNI_GRTRTHAN);
628 break;
629 case '|':
630 target[j] = cpu_to_le16(UNI_PIPE);
631 break;
632 /* BB We can not handle remapping slash until
633 all the calls to build_path_from_dentry
634 are modified, as they use slash as separator BB */
635 /* case '\\':
636 target[j] = cpu_to_le16(UNI_SLASH);
637 break;*/
638 default:
639 charlen = cp->char2uni(source+i,
640 len_remaining, target+j);
641 /* if no match, use question mark, which
642 at least in some cases servers as wild card */
643 if(charlen < 1) {
644 target[j] = cpu_to_le16(0x003f);
645 charlen = 1;
646 }
647 len_remaining -= charlen;
648 /* character may take more than one byte in the
649 the source string, but will take exactly two
650 bytes in the target string */
651 i+= charlen;
652 continue;
653 }
654 i++; /* move to next char in source string */
655 len_remaining--;
656 }
657
658ctoUCS_out:
659 return i;
660}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 4e34c89cec5d..a92af41d4411 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -78,6 +78,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
78 {ErrQuota, -EDQUOT}, 78 {ErrQuota, -EDQUOT},
79 {ErrNotALink, -ENOLINK}, 79 {ErrNotALink, -ENOLINK},
80 {ERRnetlogonNotStarted,-ENOPROTOOPT}, 80 {ERRnetlogonNotStarted,-ENOPROTOOPT},
81 {ErrTooManyLinks,-EMLINK},
81 {0, 0} 82 {0, 0}
82}; 83};
83 84
@@ -206,7 +207,7 @@ static const struct {
206 { 207 {
207 ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, { 208 ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
208 ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, { 209 ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
209 ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, { 210 ERRDOS, ERRinvlevel, NT_STATUS_INVALID_INFO_CLASS}, {
210 ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, { 211 ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
211 ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, { 212 ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
212 ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, { 213 ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
@@ -742,7 +743,7 @@ static const struct {
742 ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, { 743 ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
743 ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, { 744 ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
744 ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, { 745 ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
745 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, { 746 ERRDOS, ErrTooManyLinks, NT_STATUS_TOO_MANY_LINKS}, {
746 ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, { 747 ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
747 ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, { 748 ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
748 ERRDOS, 21, 0xc000026e}, { 749 ERRDOS, 21, 0xc000026e}, {
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index f8bea395ec9e..22557716f9af 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Directory search handling 4 * Directory search handling
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2004 6 * Copyright (C) International Business Machines Corp., 2004, 2005
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -65,14 +65,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
65 struct cifsTconInfo *pTcon; 65 struct cifsTconInfo *pTcon;
66 int rc = 0; 66 int rc = 0;
67 67
68 cFYI(1, ("For %s ", qstring->name)); 68 cFYI(1, ("For %s", qstring->name));
69 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 69 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
70 pTcon = cifs_sb->tcon; 70 pTcon = cifs_sb->tcon;
71 71
72 qstring->hash = full_name_hash(qstring->name, qstring->len); 72 qstring->hash = full_name_hash(qstring->name, qstring->len);
73 tmp_dentry = d_lookup(file->f_dentry, qstring); 73 tmp_dentry = d_lookup(file->f_dentry, qstring);
74 if (tmp_dentry) { 74 if (tmp_dentry) {
75 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode)); 75 cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
76 *ptmp_inode = tmp_dentry->d_inode; 76 *ptmp_inode = tmp_dentry->d_inode;
77/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ 77/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
78 if(*ptmp_inode == NULL) { 78 if(*ptmp_inode == NULL) {
@@ -105,8 +105,11 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
105} 105}
106 106
107static void fill_in_inode(struct inode *tmp_inode, 107static void fill_in_inode(struct inode *tmp_inode,
108 FILE_DIRECTORY_INFO *pfindData, int *pobject_type) 108 FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode)
109{ 109{
110 loff_t local_size;
111 struct timespec local_mtime;
112
110 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 113 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
111 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 114 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
112 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes); 115 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
@@ -116,6 +119,10 @@ static void fill_in_inode(struct inode *tmp_inode,
116 cifsInfo->cifsAttrs = attr; 119 cifsInfo->cifsAttrs = attr;
117 cifsInfo->time = jiffies; 120 cifsInfo->time = jiffies;
118 121
122 /* save mtime and size */
123 local_mtime = tmp_inode->i_mtime;
124 local_size = tmp_inode->i_size;
125
119 /* Linux can not store file creation time unfortunately so ignore it */ 126 /* Linux can not store file creation time unfortunately so ignore it */
120 tmp_inode->i_atime = 127 tmp_inode->i_atime =
121 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 128 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
@@ -134,7 +141,6 @@ static void fill_in_inode(struct inode *tmp_inode,
134 tmp_inode->i_mode = cifs_sb->mnt_file_mode; 141 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
135 } 142 }
136 143
137 cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
138 if (attr & ATTR_DIRECTORY) { 144 if (attr & ATTR_DIRECTORY) {
139 *pobject_type = DT_DIR; 145 *pobject_type = DT_DIR;
140 /* override default perms since we do not lock dirs */ 146 /* override default perms since we do not lock dirs */
@@ -175,30 +181,46 @@ static void fill_in_inode(struct inode *tmp_inode,
175 (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks, 181 (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
176 tmp_inode->i_blksize)); 182 tmp_inode->i_blksize));
177 if (S_ISREG(tmp_inode->i_mode)) { 183 if (S_ISREG(tmp_inode->i_mode)) {
178 cFYI(1, (" File inode ")); 184 cFYI(1, ("File inode"));
179 tmp_inode->i_op = &cifs_file_inode_ops; 185 tmp_inode->i_op = &cifs_file_inode_ops;
180 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 186 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
181 tmp_inode->i_fop = &cifs_file_direct_ops; 187 tmp_inode->i_fop = &cifs_file_direct_ops;
182 else 188 else
183 tmp_inode->i_fop = &cifs_file_ops; 189 tmp_inode->i_fop = &cifs_file_ops;
184 tmp_inode->i_data.a_ops = &cifs_addr_ops; 190 tmp_inode->i_data.a_ops = &cifs_addr_ops;
191
192 if(isNewInode)
193 return; /* No sense invalidating pages for new inode since we
194 have not started caching readahead file data yet */
195
196 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
197 (local_size == tmp_inode->i_size)) {
198 cFYI(1, ("inode exists but unchanged"));
199 } else {
200 /* file may have changed on server */
201 cFYI(1, ("invalidate inode, readdir detected change"));
202 invalidate_remote_inode(tmp_inode);
203 }
185 } else if (S_ISDIR(tmp_inode->i_mode)) { 204 } else if (S_ISDIR(tmp_inode->i_mode)) {
186 cFYI(1, (" Directory inode")); 205 cFYI(1, ("Directory inode"));
187 tmp_inode->i_op = &cifs_dir_inode_ops; 206 tmp_inode->i_op = &cifs_dir_inode_ops;
188 tmp_inode->i_fop = &cifs_dir_ops; 207 tmp_inode->i_fop = &cifs_dir_ops;
189 } else if (S_ISLNK(tmp_inode->i_mode)) { 208 } else if (S_ISLNK(tmp_inode->i_mode)) {
190 cFYI(1, (" Symbolic Link inode ")); 209 cFYI(1, ("Symbolic Link inode"));
191 tmp_inode->i_op = &cifs_symlink_inode_ops; 210 tmp_inode->i_op = &cifs_symlink_inode_ops;
192 } else { 211 } else {
193 cFYI(1, (" Init special inode ")); 212 cFYI(1, ("Init special inode"));
194 init_special_inode(tmp_inode, tmp_inode->i_mode, 213 init_special_inode(tmp_inode, tmp_inode->i_mode,
195 tmp_inode->i_rdev); 214 tmp_inode->i_rdev);
196 } 215 }
197} 216}
198 217
199static void unix_fill_in_inode(struct inode *tmp_inode, 218static void unix_fill_in_inode(struct inode *tmp_inode,
200 FILE_UNIX_INFO *pfindData, int *pobject_type) 219 FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode)
201{ 220{
221 loff_t local_size;
222 struct timespec local_mtime;
223
202 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 224 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
203 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 225 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
204 226
@@ -208,6 +230,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
208 cifsInfo->time = jiffies; 230 cifsInfo->time = jiffies;
209 atomic_inc(&cifsInfo->inUse); 231 atomic_inc(&cifsInfo->inUse);
210 232
233 /* save mtime and size */
234 local_mtime = tmp_inode->i_mtime;
235 local_size = tmp_inode->i_size;
236
211 tmp_inode->i_atime = 237 tmp_inode->i_atime =
212 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 238 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
213 tmp_inode->i_mtime = 239 tmp_inode->i_mtime =
@@ -265,6 +291,19 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
265 else 291 else
266 tmp_inode->i_fop = &cifs_file_ops; 292 tmp_inode->i_fop = &cifs_file_ops;
267 tmp_inode->i_data.a_ops = &cifs_addr_ops; 293 tmp_inode->i_data.a_ops = &cifs_addr_ops;
294
295 if(isNewInode)
296 return; /* No sense invalidating pages for new inode since we
297 have not started caching readahead file data yet */
298
299 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
300 (local_size == tmp_inode->i_size)) {
301 cFYI(1, ("inode exists but unchanged"));
302 } else {
303 /* file may have changed on server */
304 cFYI(1, ("invalidate inode, readdir detected change"));
305 invalidate_remote_inode(tmp_inode);
306 }
268 } else if (S_ISDIR(tmp_inode->i_mode)) { 307 } else if (S_ISDIR(tmp_inode->i_mode)) {
269 cFYI(1, ("Directory inode")); 308 cFYI(1, ("Directory inode"));
270 tmp_inode->i_op = &cifs_dir_inode_ops; 309 tmp_inode->i_op = &cifs_dir_inode_ops;
@@ -314,15 +353,16 @@ static int initiate_cifs_search(const int xid, struct file *file)
314 return -EINVAL; 353 return -EINVAL;
315 354
316 down(&file->f_dentry->d_sb->s_vfs_rename_sem); 355 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
317 full_path = build_wildcard_path_from_dentry(file->f_dentry); 356 full_path = build_path_from_dentry(file->f_dentry);
318 up(&file->f_dentry->d_sb->s_vfs_rename_sem); 357 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
319 358
320 if(full_path == NULL) { 359 if(full_path == NULL) {
321 return -ENOMEM; 360 return -ENOMEM;
322 } 361 }
323 362
324 cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); 363 cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos));
325 364
365ffirst_retry:
326 /* test for Unix extensions */ 366 /* test for Unix extensions */
327 if (pTcon->ses->capabilities & CAP_UNIX) { 367 if (pTcon->ses->capabilities & CAP_UNIX) {
328 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 368 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
@@ -332,10 +372,16 @@ static int initiate_cifs_search(const int xid, struct file *file)
332 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; 372 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
333 } 373 }
334 374
335 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 375 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
336 &cifsFile->netfid, &cifsFile->srch_inf); 376 &cifsFile->netfid, &cifsFile->srch_inf,
377 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
337 if(rc == 0) 378 if(rc == 0)
338 cifsFile->invalidHandle = FALSE; 379 cifsFile->invalidHandle = FALSE;
380 if((rc == -EOPNOTSUPP) &&
381 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
382 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
383 goto ffirst_retry;
384 }
339 kfree(full_path); 385 kfree(full_path);
340 return rc; 386 return rc;
341} 387}
@@ -363,10 +409,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
363 cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); 409 cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
364 /* validate that new_entry is not past end of SMB */ 410 /* validate that new_entry is not past end of SMB */
365 if(new_entry >= end_of_smb) { 411 if(new_entry >= end_of_smb) {
366 cFYI(1,("search entry %p began after end of SMB %p old entry %p", 412 cERROR(1,
367 new_entry,end_of_smb,old_entry)); 413 ("search entry %p began after end of SMB %p old entry %p",
414 new_entry, end_of_smb, old_entry));
368 return NULL; 415 return NULL;
369 } else 416 } else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) {
417 cERROR(1,("search entry %p extends after end of SMB %p",
418 new_entry, end_of_smb));
419 return NULL;
420 } else
370 return new_entry; 421 return new_entry;
371 422
372} 423}
@@ -594,7 +645,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
594 if(unicode) { 645 if(unicode) {
595 /* BB fixme - test with long names */ 646 /* BB fixme - test with long names */
596 /* Note converted filename can be longer than in unicode */ 647 /* Note converted filename can be longer than in unicode */
597 pqst->len = cifs_strfromUCS_le((char *)pqst->name,(wchar_t *)filename,len/2,nlt); 648 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
649 pqst->len = cifs_convertUCSpath((char *)pqst->name,
650 (__le16 *)filename, len/2, nlt);
651 else
652 pqst->len = cifs_strfromUCS_le((char *)pqst->name,
653 (wchar_t *)filename,len/2,nlt);
598 } else { 654 } else {
599 pqst->name = filename; 655 pqst->name = filename;
600 pqst->len = len; 656 pqst->len = len;
@@ -654,10 +710,15 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
654 insert_inode_hash(tmp_inode); 710 insert_inode_hash(tmp_inode);
655 } 711 }
656 712
713 /* we pass in rc below, indicating whether it is a new inode,
714 so we can figure out whether to invalidate the inode cached
715 data if the file has changed */
657 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { 716 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
658 unix_fill_in_inode(tmp_inode,(FILE_UNIX_INFO *)pfindEntry,&obj_type); 717 unix_fill_in_inode(tmp_inode,
718 (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc);
659 } else { 719 } else {
660 fill_in_inode(tmp_inode,(FILE_DIRECTORY_INFO *)pfindEntry,&obj_type); 720 fill_in_inode(tmp_inode,
721 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
661 } 722 }
662 723
663 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); 724 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);
@@ -823,7 +884,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
823 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 884 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
824 smbCalcSize((struct smb_hdr *) 885 smbCalcSize((struct smb_hdr *)
825 cifsFile->srch_inf.ntwrk_buf_start); 886 cifsFile->srch_inf.ntwrk_buf_start);
826 tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL); 887 /* To be safe - for UCS to UTF-8 with strings loaded
888 with the rare long characters alloc more to account for
889 such multibyte target UTF-8 characters. cifs_unicode.c,
890 which actually does the conversion, has the same limit */
891 tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
827 for(i=0;(i<num_to_fill) && (rc == 0);i++) { 892 for(i=0;(i<num_to_fill) && (rc == 0);i++) {
828 if(current_entry == NULL) { 893 if(current_entry == NULL) {
829 /* evaluate whether this case is an error */ 894 /* evaluate whether this case is an error */
@@ -832,19 +897,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
832 break; 897 break;
833 } 898 }
834 899
835 /* BB FIXME - need to enable the below code BB */
836
837 /* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
838 (cifsFile->srch_inf.info_level !=
839 something that supports server inodes)) {
840 create dentry
841 create inode
842 fill in inode new_inode (getting local i_ino)
843 }
844 also create local inode for performance reasons (so we
845 have a cache of inode metadata) unless this new mount
846 parm says otherwise */
847
848 rc = cifs_filldir(current_entry, file, 900 rc = cifs_filldir(current_entry, file,
849 filldir, direntry,tmp_buf); 901 filldir, direntry,tmp_buf);
850 file->f_pos++; 902 file->f_pos++;
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index e21f1384661f..cd41c67ff8d3 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -22,94 +22,159 @@
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 24
25#define SUCCESS 0 /* The request was successful. */ 25#define SUCCESS 0x00 /* The request was successful. */
26#define ERRDOS 0x01 /* Error is from the core DOS operating system set */ 26#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
27#define ERRSRV 0x02 /* Error is generated by the file server daemon */ 27#define ERRSRV 0x02 /* Error is generated by the file server daemon */
28#define ERRHRD 0x03 /* Error is a hardware error. */ 28#define ERRHRD 0x03 /* Error is a hardware error. */
29#define ERRCMD 0xFF /* Command was not in the "SMB" format. */ 29#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
30 30
31/* The following error codes may be generated with the SUCCESS error class.*/ 31/* The following error codes may be generated with the SUCCESS error class.*/
32 32
33#define SUCCESS 0 /* The request was successful. */ 33/*#define SUCCESS 0 The request was successful. */
34 34
35/* The following error codes may be generated with the ERRDOS error class.*/ 35/* The following error codes may be generated with the ERRDOS error class.*/
36 36
37#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */ 37#define ERRbadfunc 1 /* Invalid function. The server did not
38#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */ 38 recognize or could not perform a
39#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */ 39 system call generated by the server,
40#define ERRnofids 4 /* Too many open files. The server has no file handles available. */ 40 e.g., set the DIRECTORY attribute on
41#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */ 41 a data file, invalid seek mode. */
42#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */ 42#define ERRbadfile 2 /* File not found. The last component
43#define ERRbadmcb 7 /* Memory control blocks destroyed. */ 43 of a file's pathname could not be
44#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */ 44 found. */
45#define ERRbadmem 9 /* Invalid memory block address. */ 45#define ERRbadpath 3 /* Directory invalid. A directory
46#define ERRbadenv 10 /* Invalid environment. */ 46 component in a pathname could not be
47#define ERRbadformat 11 /* Invalid format. */ 47 found. */
48#define ERRbadaccess 12 /* Invalid open mode. */ 48#define ERRnofids 4 /* Too many open files. The server has
49#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */ 49 no file handles available. */
50#define ERRbaddrive 15 /* Invalid drive specified. */ 50#define ERRnoaccess 5 /* Access denied, the client's context
51#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */ 51 does not permit the requested
52#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */ 52 function. This includes the
53#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */ 53 following conditions: invalid rename
54#define ERRgeneral 31 54 command, write to Fid open for read
55#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */ 55 only, read on Fid open for write
56#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */ 56 only, attempt to delete a non-empty
57#define ERRunsup 50 57 directory */
58#define ERRnosuchshare 67 58#define ERRbadfid 6 /* Invalid file handle. The file handle
59#define ERRfilexists 80 /* The file named in the request already exists. */ 59 specified was not recognized by the
60#define ERRinvparm 87 60 server. */
61#define ERRdiskfull 112 61#define ERRbadmcb 7 /* Memory control blocks destroyed. */
62#define ERRinvname 123 62#define ERRnomem 8 /* Insufficient server memory to
63#define ERRinvlevel 124 63 perform the requested function. */
64#define ERRdirnotempty 145 64#define ERRbadmem 9 /* Invalid memory block address. */
65#define ERRnotlocked 158 65#define ERRbadenv 10 /* Invalid environment. */
66#define ERRalreadyexists 183 66#define ERRbadformat 11 /* Invalid format. */
67#define ERRbadpipe 230 67#define ERRbadaccess 12 /* Invalid open mode. */
68#define ERRpipebusy 231 68#define ERRbaddata 13 /* Invalid data (generated only by
69#define ERRpipeclosing 232 69 IOCTL calls within the server). */
70#define ERRnotconnected 233 70#define ERRbaddrive 15 /* Invalid drive specified. */
71#define ERRmoredata 234 71#define ERRremcd 16 /* A Delete Directory request attempted
72#define ERReasnotsupported 282 72 to remove the server's current
73#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */ 73 directory. */
74#define ErrNotALink 0x201 /* A link operation was performed on a pathname that 74#define ERRdiffdevice 17 /* Not same device (e.g., a cross
75 was not a link. */ 75 volume rename was attempted */
76#define ERRnofiles 18 /* A File Search command can find no
77 more files matching the specified
78 criteria. */
79#define ERRgeneral 31
80#define ERRbadshare 32 /* The sharing mode specified for an
81 Open conflicts with existing FIDs on
82 the file. */
83#define ERRlock 33 /* A Lock request conflicted with an
84 existing lock or specified an
85 invalid mode, or an Unlock requested
86 attempted to remove a lock held by
87 another process. */
88#define ERRunsup 50
89#define ERRnosuchshare 67
90#define ERRfilexists 80 /* The file named in the request
91 already exists. */
92#define ERRinvparm 87
93#define ERRdiskfull 112
94#define ERRinvname 123
95#define ERRinvlevel 124
96#define ERRdirnotempty 145
97#define ERRnotlocked 158
98#define ERRalreadyexists 183
99#define ERRbadpipe 230
100#define ERRpipebusy 231
101#define ERRpipeclosing 232
102#define ERRnotconnected 233
103#define ERRmoredata 234
104#define ERReasnotsupported 282
105#define ErrQuota 0x200 /* The operation would cause a quota
106 limit to be exceeded. */
107#define ErrNotALink 0x201 /* A link operation was performed on a
108 pathname that was not a link. */
76 109
77/* Following error codes may be generated with the ERRSRV error 110/* Below errors are used internally (do not come over the wire) for passthrough
78class.*/ 111 from STATUS codes to POSIX only */
112#define ErrTooManyLinks 0xFFFE
79 113
80#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */ 114/* Following error codes may be generated with the ERRSRV error class.*/
81#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */ 115
82#define ERRbadtype 3 /* used for indicating DFS referral needed */ 116#define ERRerror 1 /* Non-specific error code. It is
83#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */ 117 returned under the following
84#define ERRinvtid 5 /* The Tid specified in a command was invalid. */ 118 conditions: resource other than disk
85#define ERRinvnetname 6 /* Invalid network name in tree connect. */ 119 space exhausted (e.g. TIDs), first
86#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */ 120 SMB command was not negotiate,
87#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */ 121 multiple negotiates attempted, and
88#define ERRqtoobig 50 /* Print queue full -- no space. */ 122 internal server error. */
89#define ERRqeof 51 /* EOF on print queue dump */ 123#define ERRbadpw 2 /* Bad password - name/password pair in
90#define ERRinvpfid 52 /* Invalid print file FID. */ 124 a TreeConnect or Session Setup are
91#define ERRsmbcmd 64 /* The server did not recognize the command received. */ 125 invalid. */
92#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */ 126#define ERRbadtype 3 /* used for indicating DFS referral
93#define ERRbadBID 66 /* (obsolete) */ 127 needed */
94#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */ 128#define ERRaccess 4 /* The client does not have the
95#define ERRbadLink 68 /* (obsolete) */ 129 necessary access rights within the
96#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */ 130 specified context for requested
97#define ERRbadPID 70 131 function. */
98#define ERRsetattrmode 71 /* attribute (mode) is invalid */ 132#define ERRinvtid 5 /* The Tid specified in a command was
99#define ERRpaused 81 /* Server is paused */ 133 invalid. */
100#define ERRmsgoff 82 /* reserved - messaging off */ 134#define ERRinvnetname 6 /* Invalid network name in tree
101#define ERRnoroom 83 /* reserved - no room for message */ 135 connect. */
102#define ERRrmuns 87 /* reserved - too many remote names */ 136#define ERRinvdevice 7 /* Invalid device - printer request
103#define ERRtimeout 88 /* operation timed out */ 137 made to non-printer connection or
104#define ERRnoresource 89 /* No resources available for request */ 138 non-printer request made to printer
105#define ERRtoomanyuids 90 /* Too many UIDs active on this session */ 139 connection. */
106#define ERRbaduid 91 /* The UID is not known as a valid user */ 140#define ERRqfull 49 /* Print queue full (files) -- returned
107#define ERRusempx 250 /* temporarily unable to use raw */ 141 by open print file. */
108#define ERRusestd 251 /* temporarily unable to use either raw or mpx */ 142#define ERRqtoobig 50 /* Print queue full -- no space. */
109#define ERR_NOTIFY_ENUM_DIR 1024 143#define ERRqeof 51 /* EOF on print queue dump */
110#define ERRaccountexpired 2239 144#define ERRinvpfid 52 /* Invalid print file FID. */
111#define ERRbadclient 2240 145#define ERRsmbcmd 64 /* The server did not recognize the
112#define ERRbadLogonTime 2241 146 command received. */
113#define ERRpasswordExpired 2242 147#define ERRsrverror 65 /* The server encountered an internal
114#define ERRnetlogonNotStarted 2455 148 error, e.g., system file
115#define ERRnosupport 0xFFFF 149 unavailable. */
150#define ERRbadBID 66 /* (obsolete) */
151#define ERRfilespecs 67 /* The Fid and pathname parameters
152 contained an invalid combination of
153 values. */
154#define ERRbadLink 68 /* (obsolete) */
155#define ERRbadpermits 69 /* The access permissions specified for
156 a file or directory are not a valid
157 combination. */
158#define ERRbadPID 70
159#define ERRsetattrmode 71 /* attribute (mode) is invalid */
160#define ERRpaused 81 /* Server is paused */
161#define ERRmsgoff 82 /* reserved - messaging off */
162#define ERRnoroom 83 /* reserved - no room for message */
163#define ERRrmuns 87 /* reserved - too many remote names */
164#define ERRtimeout 88 /* operation timed out */
165#define ERRnoresource 89 /* No resources available for request
166 */
167#define ERRtoomanyuids 90 /* Too many UIDs active on this session
168 */
169#define ERRbaduid 91 /* The UID is not known as a valid user
170 */
171#define ERRusempx 250 /* temporarily unable to use raw */
172#define ERRusestd 251 /* temporarily unable to use either raw
173 or mpx */
174#define ERR_NOTIFY_ENUM_DIR 1024
175#define ERRaccountexpired 2239
176#define ERRbadclient 2240
177#define ERRbadLogonTime 2241
178#define ERRpasswordExpired 2242
179#define ERRnetlogonNotStarted 2455
180#define ERRnosupport 0xFFFF
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index af13e526b150..0046c219833d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/transport.c 2 * fs/cifs/transport.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
41 struct mid_q_entry *temp; 41 struct mid_q_entry *temp;
42 42
43 if (ses == NULL) { 43 if (ses == NULL) {
44 cERROR(1, ("Null session passed in to AllocMidQEntry ")); 44 cERROR(1, ("Null session passed in to AllocMidQEntry"));
45 return NULL; 45 return NULL;
46 } 46 }
47 if (ses->server == NULL) { 47 if (ses->server == NULL) {
@@ -79,7 +79,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
79 list_del(&midEntry->qhead); 79 list_del(&midEntry->qhead);
80 atomic_dec(&midCount); 80 atomic_dec(&midCount);
81 spin_unlock(&GlobalMid_Lock); 81 spin_unlock(&GlobalMid_Lock);
82 cifs_buf_release(midEntry->resp_buf); 82 if(midEntry->largeBuf)
83 cifs_buf_release(midEntry->resp_buf);
84 else
85 cifs_small_buf_release(midEntry->resp_buf);
83 mempool_free(midEntry, cifs_mid_poolp); 86 mempool_free(midEntry, cifs_mid_poolp);
84} 87}
85 88
@@ -182,14 +185,14 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
182 185
183int 186int
184smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, 187smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
185 unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin) 188 unsigned int smb_buf_length, struct kvec * write_vector
189 /* page list */, struct sockaddr *sin)
186{ 190{
187 int rc = 0; 191 int rc = 0;
188 int i = 0; 192 int i = 0;
189 struct msghdr smb_msg; 193 struct msghdr smb_msg;
190 number_of_pages += 1; /* account for SMB header */ 194 number_of_pages += 1; /* account for SMB header */
191 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); 195 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec));
192 if(i=0;i<num_pages-1;i++
193 unsigned len = smb_buf_length + 4; 196 unsigned len = smb_buf_length + 4;
194 197
195 if(ssocket == NULL) 198 if(ssocket == NULL)
@@ -213,7 +216,8 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
213 dump_smb(smb_buffer, len); 216 dump_smb(smb_buffer, len);
214 217
215 while (len > 0) { 218 while (len > 0) {
216 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?); 219 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages,
220 len);
217 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 221 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
218 i++; 222 i++;
219 if(i > 60) { 223 if(i > 60) {
@@ -266,6 +270,9 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
266 270
267 271
268 272
273 if(ses->server->tcpStatus == CIFS_EXITING)
274 return -ENOENT;
275
269 /* Ensure that we do not send more than 50 overlapping requests 276 /* Ensure that we do not send more than 50 overlapping requests
270 to the same server. We may make this configurable later or 277 to the same server. We may make this configurable later or
271 use ses->maxReq */ 278 use ses->maxReq */
@@ -346,11 +353,12 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
346 } 353 }
347 354
348 /* BB can we sign efficiently in this path? */ 355 /* BB can we sign efficiently in this path? */
349 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 356 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
350 357
351 midQ->midState = MID_REQUEST_SUBMITTED; 358 midQ->midState = MID_REQUEST_SUBMITTED;
352/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, 359/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
353 (struct sockaddr *) &(ses->server->addr.sockAddr));*/ 360 piovec,
361 (struct sockaddr *) &(ses->server->addr.sockAddr));*/
354 if(rc < 0) { 362 if(rc < 0) {
355 DeleteMidQEntry(midQ); 363 DeleteMidQEntry(midQ);
356 up(&ses->server->tcpSem); 364 up(&ses->server->tcpSem);
@@ -396,6 +404,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
396 return -EIO; 404 return -EIO;
397 } 405 }
398 406
407 if(ses->server->tcpStatus == CifsExiting)
408 return -ENOENT;
409
399 /* Ensure that we do not send more than 50 overlapping requests 410 /* Ensure that we do not send more than 50 overlapping requests
400 to the same server. We may make this configurable later or 411 to the same server. We may make this configurable later or
401 use ses->maxReq */ 412 use ses->maxReq */
@@ -405,7 +416,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
405 } else { 416 } else {
406 spin_lock(&GlobalMid_Lock); 417 spin_lock(&GlobalMid_Lock);
407 while(1) { 418 while(1) {
408 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ 419 if(atomic_read(&ses->server->inFlight) >=
420 cifs_max_pending){
409 spin_unlock(&GlobalMid_Lock); 421 spin_unlock(&GlobalMid_Lock);
410 wait_event(ses->server->request_q, 422 wait_event(ses->server->request_q,
411 atomic_read(&ses->server->inFlight) 423 atomic_read(&ses->server->inFlight)
@@ -475,7 +487,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
475 return -EIO; 487 return -EIO;
476 } 488 }
477 489
478 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 490 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
479 491
480 midQ->midState = MID_REQUEST_SUBMITTED; 492 midQ->midState = MID_REQUEST_SUBMITTED;
481 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 493 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
@@ -493,7 +505,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
493 up(&ses->server->tcpSem); 505 up(&ses->server->tcpSem);
494 if (long_op == -1) 506 if (long_op == -1)
495 goto cifs_no_response_exit; 507 goto cifs_no_response_exit;
496 else if (long_op == 2) /* writes past end of file can take looooong time */ 508 else if (long_op == 2) /* writes past end of file can take loong time */
497 timeout = 300 * HZ; 509 timeout = 300 * HZ;
498 else if (long_op == 1) 510 else if (long_op == 1)
499 timeout = 45 * HZ; /* should be greater than 511 timeout = 45 * HZ; /* should be greater than
@@ -559,8 +571,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
559 } 571 }
560 572
561 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 573 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
562 cERROR(1, 574 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
563 ("Frame too large received. Length: %d Xid: %d",
564 receive_len, xid)); 575 receive_len, xid));
565 rc = -EIO; 576 rc = -EIO;
566 } else { /* rcvd frame is ok */ 577 } else { /* rcvd frame is ok */
@@ -575,15 +586,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
575 dump_smb(out_buf, 92); 586 dump_smb(out_buf, 92);
576 /* convert the length into a more usable form */ 587 /* convert the length into a more usable form */
577 if((receive_len > 24) && 588 if((receive_len > 24) &&
578 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { 589 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
579 rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */ 590 SECMODE_SIGN_ENABLED))) {
580 if(rc) 591 rc = cifs_verify_signature(out_buf,
581 cFYI(1,("Unexpected signature received from server")); 592 ses->server->mac_signing_key,
593 midQ->sequence_number+1);
594 if(rc) {
595 cERROR(1,("Unexpected SMB signature"));
596 /* BB FIXME add code to kill session */
597 }
582 } 598 }
583 599
584 *pbytes_returned = out_buf->smb_buf_length; 600 *pbytes_returned = out_buf->smb_buf_length;
585 601
586 /* BB special case reconnect tid and reconnect uid here? */ 602 /* BB special case reconnect tid and uid here? */
587 rc = map_smb_to_linux_error(out_buf); 603 rc = map_smb_to_linux_error(out_buf);
588 604
589 /* convert ByteCount if necessary */ 605 /* convert ByteCount if necessary */
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 549afa184fd6..c1e02eff1d25 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -83,7 +83,8 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
83 83
84 ea_name+=5; /* skip past user. prefix */ 84 ea_name+=5; /* skip past user. prefix */
85 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL, 85 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
86 (__u16)0, cifs_sb->local_nls); 86 (__u16)0, cifs_sb->local_nls,
87 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
87 } 88 }
88remove_ea_exit: 89remove_ea_exit:
89 if (full_path) 90 if (full_path)
@@ -147,32 +148,40 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
147 } 148 }
148 ea_name += 5; /* skip past user. prefix */ 149 ea_name += 5; /* skip past user. prefix */
149 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, 150 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
150 (__u16)value_size, cifs_sb->local_nls); 151 (__u16)value_size, cifs_sb->local_nls,
152 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
151 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { 153 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
152 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 154 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
153 goto set_ea_exit; 155 goto set_ea_exit;
154 156
155 ea_name += 4; /* skip past os2. prefix */ 157 ea_name += 4; /* skip past os2. prefix */
156 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, 158 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
157 (__u16)value_size, cifs_sb->local_nls); 159 (__u16)value_size, cifs_sb->local_nls,
160 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
158 } else { 161 } else {
159 int temp; 162 int temp;
160 temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, 163 temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
161 strlen(POSIX_ACL_XATTR_ACCESS)); 164 strlen(POSIX_ACL_XATTR_ACCESS));
162 if (temp == 0) { 165 if (temp == 0) {
163#ifdef CONFIG_CIFS_POSIX 166#ifdef CONFIG_CIFS_POSIX
164 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, 167 if(sb->s_flags & MS_POSIXACL)
165 (const int)value_size, ACL_TYPE_ACCESS, 168 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
166 cifs_sb->local_nls); 169 ea_value, (const int)value_size,
170 ACL_TYPE_ACCESS,cifs_sb->local_nls,
171 cifs_sb->mnt_cifs_flags &
172 CIFS_MOUNT_MAP_SPECIAL_CHR);
167 cFYI(1,("set POSIX ACL rc %d",rc)); 173 cFYI(1,("set POSIX ACL rc %d",rc));
168#else 174#else
169 cFYI(1,("set POSIX ACL not supported")); 175 cFYI(1,("set POSIX ACL not supported"));
170#endif 176#endif
171 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 177 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
172#ifdef CONFIG_CIFS_POSIX 178#ifdef CONFIG_CIFS_POSIX
173 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, 179 if(sb->s_flags & MS_POSIXACL)
174 (const int)value_size, ACL_TYPE_DEFAULT, 180 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
175 cifs_sb->local_nls); 181 ea_value, (const int)value_size,
182 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
183 cifs_sb->mnt_cifs_flags &
184 CIFS_MOUNT_MAP_SPECIAL_CHR);
176 cFYI(1,("set POSIX default ACL rc %d",rc)); 185 cFYI(1,("set POSIX default ACL rc %d",rc));
177#else 186#else
178 cFYI(1,("set default POSIX ACL not supported")); 187 cFYI(1,("set default POSIX ACL not supported"));
@@ -238,27 +247,35 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
238 } /* BB add else when above is implemented */ 247 } /* BB add else when above is implemented */
239 ea_name += 5; /* skip past user. prefix */ 248 ea_name += 5; /* skip past user. prefix */
240 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, 249 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
241 buf_size, cifs_sb->local_nls); 250 buf_size, cifs_sb->local_nls,
251 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
242 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { 252 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
243 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 253 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
244 goto get_ea_exit; 254 goto get_ea_exit;
245 255
246 ea_name += 4; /* skip past os2. prefix */ 256 ea_name += 4; /* skip past os2. prefix */
247 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, 257 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
248 buf_size, cifs_sb->local_nls); 258 buf_size, cifs_sb->local_nls,
259 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
249 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { 260 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
250#ifdef CONFIG_CIFS_POSIX 261#ifdef CONFIG_CIFS_POSIX
251 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 262 if(sb->s_flags & MS_POSIXACL)
263 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
252 ea_value, buf_size, ACL_TYPE_ACCESS, 264 ea_value, buf_size, ACL_TYPE_ACCESS,
253 cifs_sb->local_nls); 265 cifs_sb->local_nls,
266 cifs_sb->mnt_cifs_flags &
267 CIFS_MOUNT_MAP_SPECIAL_CHR);
254#else 268#else
255 cFYI(1,("query POSIX ACL not supported yet")); 269 cFYI(1,("query POSIX ACL not supported yet"));
256#endif /* CONFIG_CIFS_POSIX */ 270#endif /* CONFIG_CIFS_POSIX */
257 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 271 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
258#ifdef CONFIG_CIFS_POSIX 272#ifdef CONFIG_CIFS_POSIX
259 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 273 if(sb->s_flags & MS_POSIXACL)
274 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
260 ea_value, buf_size, ACL_TYPE_DEFAULT, 275 ea_value, buf_size, ACL_TYPE_DEFAULT,
261 cifs_sb->local_nls); 276 cifs_sb->local_nls,
277 cifs_sb->mnt_cifs_flags &
278 CIFS_MOUNT_MAP_SPECIAL_CHR);
262#else 279#else
263 cFYI(1,("query POSIX default ACL not supported yet")); 280 cFYI(1,("query POSIX default ACL not supported yet"));
264#endif 281#endif
@@ -324,7 +341,9 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
324 search server for EAs or streams to 341 search server for EAs or streams to
325 returns as xattrs */ 342 returns as xattrs */
326 rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size, 343 rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
327 cifs_sb->local_nls); 344 cifs_sb->local_nls,
345 cifs_sb->mnt_cifs_flags &
346 CIFS_MOUNT_MAP_SPECIAL_CHR);
328 347
329 if (full_path) 348 if (full_path)
330 kfree(full_path); 349 kfree(full_path);
diff --git a/fs/compat.c b/fs/compat.c
index 67c0b94d1148..728cd8365384 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -809,7 +809,7 @@ static void *do_smb_super_data_conv(void *raw_data)
809 809
810struct compat_nfs_string { 810struct compat_nfs_string {
811 compat_uint_t len; 811 compat_uint_t len;
812 compat_uptr_t __user data; 812 compat_uptr_t data;
813}; 813};
814 814
815static inline void compat_nfs_string(struct nfs_string *dst, 815static inline void compat_nfs_string(struct nfs_string *dst,
@@ -834,10 +834,10 @@ struct compat_nfs4_mount_data_v1 {
834 struct compat_nfs_string mnt_path; 834 struct compat_nfs_string mnt_path;
835 struct compat_nfs_string hostname; 835 struct compat_nfs_string hostname;
836 compat_uint_t host_addrlen; 836 compat_uint_t host_addrlen;
837 compat_uptr_t __user host_addr; 837 compat_uptr_t host_addr;
838 compat_int_t proto; 838 compat_int_t proto;
839 compat_int_t auth_flavourlen; 839 compat_int_t auth_flavourlen;
840 compat_uptr_t __user auth_flavours; 840 compat_uptr_t auth_flavours;
841}; 841};
842 842
843static int do_nfs4_super_data_conv(void *raw_data) 843static int do_nfs4_super_data_conv(void *raw_data)
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 040eb288bb1c..ea5888688f94 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -455,12 +455,11 @@ static unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
455 * @goal: place to store the result. 455 * @goal: place to store the result.
456 * 456 *
457 * Normally this function find the prefered place for block allocation, 457 * Normally this function find the prefered place for block allocation,
458 * stores it in *@goal and returns zero. If the branch had been changed 458 * stores it in *@goal and returns zero.
459 * under us we return -EAGAIN.
460 */ 459 */
461 460
462static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4], 461static unsigned long ext3_find_goal(struct inode *inode, long block,
463 Indirect *partial, unsigned long *goal) 462 Indirect chain[4], Indirect *partial)
464{ 463{
465 struct ext3_block_alloc_info *block_i = EXT3_I(inode)->i_block_alloc_info; 464 struct ext3_block_alloc_info *block_i = EXT3_I(inode)->i_block_alloc_info;
466 465
@@ -470,15 +469,10 @@ static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4],
470 */ 469 */
471 if (block_i && (block == block_i->last_alloc_logical_block + 1) 470 if (block_i && (block == block_i->last_alloc_logical_block + 1)
472 && (block_i->last_alloc_physical_block != 0)) { 471 && (block_i->last_alloc_physical_block != 0)) {
473 *goal = block_i->last_alloc_physical_block + 1; 472 return block_i->last_alloc_physical_block + 1;
474 return 0;
475 } 473 }
476 474
477 if (verify_chain(chain, partial)) { 475 return ext3_find_near(inode, partial);
478 *goal = ext3_find_near(inode, partial);
479 return 0;
480 }
481 return -EAGAIN;
482} 476}
483 477
484/** 478/**
@@ -582,12 +576,9 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
582 * @where: location of missing link 576 * @where: location of missing link
583 * @num: number of blocks we are adding 577 * @num: number of blocks we are adding
584 * 578 *
585 * This function verifies that chain (up to the missing link) had not 579 * This function fills the missing link and does all housekeeping needed in
586 * changed, fills the missing link and does all housekeeping needed in
587 * inode (->i_blocks, etc.). In case of success we end up with the full 580 * inode (->i_blocks, etc.). In case of success we end up with the full
588 * chain to new block and return 0. Otherwise (== chain had been changed) 581 * chain to new block and return 0.
589 * we free the new blocks (forgetting their buffer_heads, indeed) and
590 * return -EAGAIN.
591 */ 582 */
592 583
593static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, 584static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
@@ -608,12 +599,6 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
608 if (err) 599 if (err)
609 goto err_out; 600 goto err_out;
610 } 601 }
611 /* Verify that place we are splicing to is still there and vacant */
612
613 if (!verify_chain(chain, where-1) || *where->p)
614 /* Writer: end */
615 goto changed;
616
617 /* That's it */ 602 /* That's it */
618 603
619 *where->p = where->key; 604 *where->p = where->key;
@@ -657,26 +642,11 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
657 } 642 }
658 return err; 643 return err;
659 644
660changed:
661 /*
662 * AKPM: if where[i].bh isn't part of the current updating
663 * transaction then we explode nastily. Test this code path.
664 */
665 jbd_debug(1, "the chain changed: try again\n");
666 err = -EAGAIN;
667
668err_out: 645err_out:
669 for (i = 1; i < num; i++) { 646 for (i = 1; i < num; i++) {
670 BUFFER_TRACE(where[i].bh, "call journal_forget"); 647 BUFFER_TRACE(where[i].bh, "call journal_forget");
671 ext3_journal_forget(handle, where[i].bh); 648 ext3_journal_forget(handle, where[i].bh);
672 } 649 }
673 /* For the normal collision cleanup case, we free up the blocks.
674 * On genuine filesystem errors we don't even think about doing
675 * that. */
676 if (err == -EAGAIN)
677 for (i = 0; i < num; i++)
678 ext3_free_blocks(handle, inode,
679 le32_to_cpu(where[i].key), 1);
680 return err; 650 return err;
681} 651}
682 652
@@ -708,7 +678,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
708 unsigned long goal; 678 unsigned long goal;
709 int left; 679 int left;
710 int boundary = 0; 680 int boundary = 0;
711 int depth = ext3_block_to_path(inode, iblock, offsets, &boundary); 681 const int depth = ext3_block_to_path(inode, iblock, offsets, &boundary);
712 struct ext3_inode_info *ei = EXT3_I(inode); 682 struct ext3_inode_info *ei = EXT3_I(inode);
713 683
714 J_ASSERT(handle != NULL || create == 0); 684 J_ASSERT(handle != NULL || create == 0);
@@ -716,54 +686,55 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
716 if (depth == 0) 686 if (depth == 0)
717 goto out; 687 goto out;
718 688
719reread:
720 partial = ext3_get_branch(inode, depth, offsets, chain, &err); 689 partial = ext3_get_branch(inode, depth, offsets, chain, &err);
721 690
722 /* Simplest case - block found, no allocation needed */ 691 /* Simplest case - block found, no allocation needed */
723 if (!partial) { 692 if (!partial) {
724 clear_buffer_new(bh_result); 693 clear_buffer_new(bh_result);
725got_it: 694 goto got_it;
726 map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
727 if (boundary)
728 set_buffer_boundary(bh_result);
729 /* Clean up and exit */
730 partial = chain+depth-1; /* the whole chain */
731 goto cleanup;
732 } 695 }
733 696
734 /* Next simple case - plain lookup or failed read of indirect block */ 697 /* Next simple case - plain lookup or failed read of indirect block */
735 if (!create || err == -EIO) { 698 if (!create || err == -EIO)
736cleanup: 699 goto cleanup;
700
701 down(&ei->truncate_sem);
702
703 /*
704 * If the indirect block is missing while we are reading
705 * the chain(ext3_get_branch() returns -EAGAIN err), or
706 * if the chain has been changed after we grab the semaphore,
707 * (either because another process truncated this branch, or
708 * another get_block allocated this branch) re-grab the chain to see if
709 * the request block has been allocated or not.
710 *
711 * Since we already block the truncate/other get_block
712 * at this point, we will have the current copy of the chain when we
713 * splice the branch into the tree.
714 */
715 if (err == -EAGAIN || !verify_chain(chain, partial)) {
737 while (partial > chain) { 716 while (partial > chain) {
738 BUFFER_TRACE(partial->bh, "call brelse");
739 brelse(partial->bh); 717 brelse(partial->bh);
740 partial--; 718 partial--;
741 } 719 }
742 BUFFER_TRACE(bh_result, "returned"); 720 partial = ext3_get_branch(inode, depth, offsets, chain, &err);
743out: 721 if (!partial) {
744 return err; 722 up(&ei->truncate_sem);
723 if (err)
724 goto cleanup;
725 clear_buffer_new(bh_result);
726 goto got_it;
727 }
745 } 728 }
746 729
747 /* 730 /*
748 * Indirect block might be removed by truncate while we were 731 * Okay, we need to do block allocation. Lazily initialize the block
749 * reading it. Handling of that case (forget what we've got and 732 * allocation info here if necessary
750 * reread) is taken out of the main path. 733 */
751 */ 734 if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
752 if (err == -EAGAIN)
753 goto changed;
754
755 goal = 0;
756 down(&ei->truncate_sem);
757
758 /* lazy initialize the block allocation info here if necessary */
759 if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) {
760 ext3_init_block_alloc_info(inode); 735 ext3_init_block_alloc_info(inode);
761 }
762 736
763 if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) { 737 goal = ext3_find_goal(inode, iblock, chain, partial);
764 up(&ei->truncate_sem);
765 goto changed;
766 }
767 738
768 left = (chain + depth) - partial; 739 left = (chain + depth) - partial;
769 740
@@ -771,38 +742,45 @@ out:
771 * Block out ext3_truncate while we alter the tree 742 * Block out ext3_truncate while we alter the tree
772 */ 743 */
773 err = ext3_alloc_branch(handle, inode, left, goal, 744 err = ext3_alloc_branch(handle, inode, left, goal,
774 offsets+(partial-chain), partial); 745 offsets + (partial - chain), partial);
775 746
776 /* The ext3_splice_branch call will free and forget any buffers 747 /*
748 * The ext3_splice_branch call will free and forget any buffers
777 * on the new chain if there is a failure, but that risks using 749 * on the new chain if there is a failure, but that risks using
778 * up transaction credits, especially for bitmaps where the 750 * up transaction credits, especially for bitmaps where the
779 * credits cannot be returned. Can we handle this somehow? We 751 * credits cannot be returned. Can we handle this somehow? We
780 * may need to return -EAGAIN upwards in the worst case. --sct */ 752 * may need to return -EAGAIN upwards in the worst case. --sct
753 */
781 if (!err) 754 if (!err)
782 err = ext3_splice_branch(handle, inode, iblock, chain, 755 err = ext3_splice_branch(handle, inode, iblock, chain,
783 partial, left); 756 partial, left);
784 /* i_disksize growing is protected by truncate_sem 757 /*
785 * don't forget to protect it if you're about to implement 758 * i_disksize growing is protected by truncate_sem. Don't forget to
786 * concurrent ext3_get_block() -bzzz */ 759 * protect it if you're about to implement concurrent
760 * ext3_get_block() -bzzz
761 */
787 if (!err && extend_disksize && inode->i_size > ei->i_disksize) 762 if (!err && extend_disksize && inode->i_size > ei->i_disksize)
788 ei->i_disksize = inode->i_size; 763 ei->i_disksize = inode->i_size;
789 up(&ei->truncate_sem); 764 up(&ei->truncate_sem);
790 if (err == -EAGAIN)
791 goto changed;
792 if (err) 765 if (err)
793 goto cleanup; 766 goto cleanup;
794 767
795 set_buffer_new(bh_result); 768 set_buffer_new(bh_result);
796 goto got_it; 769got_it:
797 770 map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
798changed: 771 if (boundary)
772 set_buffer_boundary(bh_result);
773 /* Clean up and exit */
774 partial = chain + depth - 1; /* the whole chain */
775cleanup:
799 while (partial > chain) { 776 while (partial > chain) {
800 jbd_debug(1, "buffer chain changed, retrying\n"); 777 BUFFER_TRACE(partial->bh, "call brelse");
801 BUFFER_TRACE(partial->bh, "brelsing");
802 brelse(partial->bh); 778 brelse(partial->bh);
803 partial--; 779 partial--;
804 } 780 }
805 goto reread; 781 BUFFER_TRACE(bh_result, "returned");
782out:
783 return err;
806} 784}
807 785
808static int ext3_get_block(struct inode *inode, sector_t iblock, 786static int ext3_get_block(struct inode *inode, sector_t iblock,
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 3e7ab16ed154..286a9f8f3d49 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -15,6 +15,7 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/security.h> 16#include <linux/security.h>
17#include <linux/ptrace.h> 17#include <linux/ptrace.h>
18#include <linux/signal.h>
18 19
19#include <asm/poll.h> 20#include <asm/poll.h>
20#include <asm/siginfo.h> 21#include <asm/siginfo.h>
@@ -308,7 +309,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
308 break; 309 break;
309 case F_SETSIG: 310 case F_SETSIG:
310 /* arg == 0 restores default behaviour. */ 311 /* arg == 0 restores default behaviour. */
311 if (arg < 0 || arg > _NSIG) { 312 if (!valid_signal(arg)) {
312 break; 313 break;
313 } 314 }
314 err = 0; 315 err = 0;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index d6efb36cab2a..8e050fa58218 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -512,7 +512,8 @@ restart:
512} 512}
513 513
514/** 514/**
515 * sync_inodes 515 * sync_inodes - writes all inodes to disk
516 * @wait: wait for completion
516 * 517 *
517 * sync_inodes() goes through each super block's dirty inode list, writes the 518 * sync_inodes() goes through each super block's dirty inode list, writes the
518 * inodes out, waits on the writeout and puts the inodes back on the normal 519 * inodes out, waits on the writeout and puts the inodes back on the normal
@@ -604,6 +605,7 @@ EXPORT_SYMBOL(sync_inode);
604/** 605/**
605 * generic_osync_inode - flush all dirty data for a given inode to disk 606 * generic_osync_inode - flush all dirty data for a given inode to disk
606 * @inode: inode to write 607 * @inode: inode to write
608 * @mapping: the address_space that should be flushed
607 * @what: what to write and wait upon 609 * @what: what to write and wait upon
608 * 610 *
609 * This can be called by file_write functions for files which have the 611 * This can be called by file_write functions for files which have the
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 4efb640c4d0c..217e32f37e0b 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -333,6 +333,8 @@ void hfs_mdb_close(struct super_block *sb)
333 * Release the resources associated with the in-core MDB. */ 333 * Release the resources associated with the in-core MDB. */
334void hfs_mdb_put(struct super_block *sb) 334void hfs_mdb_put(struct super_block *sb)
335{ 335{
336 if (!HFS_SB(sb))
337 return;
336 /* free the B-trees */ 338 /* free the B-trees */
337 hfs_btree_close(HFS_SB(sb)->ext_tree); 339 hfs_btree_close(HFS_SB(sb)->ext_tree);
338 hfs_btree_close(HFS_SB(sb)->cat_tree); 340 hfs_btree_close(HFS_SB(sb)->cat_tree);
@@ -340,4 +342,7 @@ void hfs_mdb_put(struct super_block *sb)
340 /* free the buffers holding the primary and alternate MDBs */ 342 /* free the buffers holding the primary and alternate MDBs */
341 brelse(HFS_SB(sb)->mdb_bh); 343 brelse(HFS_SB(sb)->mdb_bh);
342 brelse(HFS_SB(sb)->alt_mdb_bh); 344 brelse(HFS_SB(sb)->alt_mdb_bh);
345
346 kfree(HFS_SB(sb));
347 sb->s_fs_info = NULL;
343} 348}
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 1e2c193134cc..ab783f6afa3b 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -297,7 +297,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
297 res = -EINVAL; 297 res = -EINVAL;
298 if (!parse_options((char *)data, sbi)) { 298 if (!parse_options((char *)data, sbi)) {
299 hfs_warn("hfs_fs: unable to parse mount options.\n"); 299 hfs_warn("hfs_fs: unable to parse mount options.\n");
300 goto bail3; 300 goto bail;
301 } 301 }
302 302
303 sb->s_op = &hfs_super_operations; 303 sb->s_op = &hfs_super_operations;
@@ -310,7 +310,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
310 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n", 310 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
311 hfs_mdb_name(sb)); 311 hfs_mdb_name(sb));
312 res = -EINVAL; 312 res = -EINVAL;
313 goto bail2; 313 goto bail;
314 } 314 }
315 315
316 /* try to get the root inode */ 316 /* try to get the root inode */
@@ -340,10 +340,8 @@ bail_iput:
340 iput(root_inode); 340 iput(root_inode);
341bail_no_root: 341bail_no_root:
342 hfs_warn("hfs_fs: get root inode failed.\n"); 342 hfs_warn("hfs_fs: get root inode failed.\n");
343bail:
343 hfs_mdb_put(sb); 344 hfs_mdb_put(sb);
344bail2:
345bail3:
346 kfree(sbi);
347 return res; 345 return res;
348} 346}
349 347
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 5f8044664a3c..d55ad67b8e42 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -208,7 +208,9 @@ static void hfsplus_write_super(struct super_block *sb)
208static void hfsplus_put_super(struct super_block *sb) 208static void hfsplus_put_super(struct super_block *sb)
209{ 209{
210 dprint(DBG_SUPER, "hfsplus_put_super\n"); 210 dprint(DBG_SUPER, "hfsplus_put_super\n");
211 if (!(sb->s_flags & MS_RDONLY)) { 211 if (!sb->s_fs_info)
212 return;
213 if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) {
212 struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; 214 struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
213 215
214 vhdr->modify_date = hfsp_now2mt(); 216 vhdr->modify_date = hfsp_now2mt();
@@ -226,6 +228,8 @@ static void hfsplus_put_super(struct super_block *sb)
226 brelse(HFSPLUS_SB(sb).s_vhbh); 228 brelse(HFSPLUS_SB(sb).s_vhbh);
227 if (HFSPLUS_SB(sb).nls) 229 if (HFSPLUS_SB(sb).nls)
228 unload_nls(HFSPLUS_SB(sb).nls); 230 unload_nls(HFSPLUS_SB(sb).nls);
231 kfree(sb->s_fs_info);
232 sb->s_fs_info = NULL;
229} 233}
230 234
231static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) 235static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf)
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index a88ad2924851..e6c63d9cac7b 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -521,7 +521,7 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
521static struct address_space_operations hostfs_aops = { 521static struct address_space_operations hostfs_aops = {
522 .writepage = hostfs_writepage, 522 .writepage = hostfs_writepage,
523 .readpage = hostfs_readpage, 523 .readpage = hostfs_readpage,
524/* .set_page_dirty = __set_page_dirty_nobuffers, */ 524 .set_page_dirty = __set_page_dirty_nobuffers,
525 .prepare_write = hostfs_prepare_write, 525 .prepare_write = hostfs_prepare_write,
526 .commit_write = hostfs_commit_write 526 .commit_write = hostfs_commit_write
527}; 527};
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 0c607c1388f4..771a554701d6 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -79,8 +79,7 @@ static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
79 79
80 D2(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT)); 80 D2(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT));
81 81
82 if (!PageLocked(pg)) 82 BUG_ON(!PageLocked(pg));
83 PAGE_BUG(pg);
84 83
85 pg_buf = kmap(pg); 84 pg_buf = kmap(pg);
86 /* FIXME: Can kmap fail? */ 85 /* FIXME: Can kmap fail? */
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 7bc906677b0d..24a689179af2 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -175,31 +175,22 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
175{ 175{
176 s64 lblock64 = lblock; 176 s64 lblock64 = lblock;
177 int rc = 0; 177 int rc = 0;
178 int take_locks;
179 xad_t xad; 178 xad_t xad;
180 s64 xaddr; 179 s64 xaddr;
181 int xflag; 180 int xflag;
182 s32 xlen; 181 s32 xlen = max_blocks;
183
184 /*
185 * If this is a special inode (imap, dmap)
186 * the lock should already be taken
187 */
188 take_locks = (JFS_IP(ip)->fileset != AGGREGATE_I);
189 182
190 /* 183 /*
191 * Take appropriate lock on inode 184 * Take appropriate lock on inode
192 */ 185 */
193 if (take_locks) { 186 if (create)
194 if (create) 187 IWRITE_LOCK(ip);
195 IWRITE_LOCK(ip); 188 else
196 else 189 IREAD_LOCK(ip);
197 IREAD_LOCK(ip);
198 }
199 190
200 if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && 191 if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
201 (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0) 192 (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
202 == 0) && xlen) { 193 xaddr) {
203 if (xflag & XAD_NOTRECORDED) { 194 if (xflag & XAD_NOTRECORDED) {
204 if (!create) 195 if (!create)
205 /* 196 /*
@@ -238,7 +229,7 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
238#ifdef _JFS_4K 229#ifdef _JFS_4K
239 if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) 230 if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad)))
240 goto unlock; 231 goto unlock;
241 rc = extAlloc(ip, max_blocks, lblock64, &xad, FALSE); 232 rc = extAlloc(ip, xlen, lblock64, &xad, FALSE);
242 if (rc) 233 if (rc)
243 goto unlock; 234 goto unlock;
244 235
@@ -258,12 +249,10 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
258 /* 249 /*
259 * Release lock on inode 250 * Release lock on inode
260 */ 251 */
261 if (take_locks) { 252 if (create)
262 if (create) 253 IWRITE_UNLOCK(ip);
263 IWRITE_UNLOCK(ip); 254 else
264 else 255 IREAD_UNLOCK(ip);
265 IREAD_UNLOCK(ip);
266 }
267 return rc; 256 return rc;
268} 257}
269 258
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index d86e467c6e42..69007fd546ef 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -471,6 +471,7 @@ dbUpdatePMap(struct inode *ipbmap,
471 struct metapage *mp; 471 struct metapage *mp;
472 struct jfs_log *log; 472 struct jfs_log *log;
473 int lsn, difft, diffp; 473 int lsn, difft, diffp;
474 unsigned long flags;
474 475
475 /* the blocks better be within the mapsize. */ 476 /* the blocks better be within the mapsize. */
476 if (blkno + nblocks > bmp->db_mapsize) { 477 if (blkno + nblocks > bmp->db_mapsize) {
@@ -504,6 +505,7 @@ dbUpdatePMap(struct inode *ipbmap,
504 0); 505 0);
505 if (mp == NULL) 506 if (mp == NULL)
506 return -EIO; 507 return -EIO;
508 metapage_wait_for_io(mp);
507 } 509 }
508 dp = (struct dmap *) mp->data; 510 dp = (struct dmap *) mp->data;
509 511
@@ -578,34 +580,32 @@ dbUpdatePMap(struct inode *ipbmap,
578 if (mp->lsn != 0) { 580 if (mp->lsn != 0) {
579 /* inherit older/smaller lsn */ 581 /* inherit older/smaller lsn */
580 logdiff(diffp, mp->lsn, log); 582 logdiff(diffp, mp->lsn, log);
583 LOGSYNC_LOCK(log, flags);
581 if (difft < diffp) { 584 if (difft < diffp) {
582 mp->lsn = lsn; 585 mp->lsn = lsn;
583 586
584 /* move bp after tblock in logsync list */ 587 /* move bp after tblock in logsync list */
585 LOGSYNC_LOCK(log);
586 list_move(&mp->synclist, &tblk->synclist); 588 list_move(&mp->synclist, &tblk->synclist);
587 LOGSYNC_UNLOCK(log);
588 } 589 }
589 590
590 /* inherit younger/larger clsn */ 591 /* inherit younger/larger clsn */
591 LOGSYNC_LOCK(log);
592 logdiff(difft, tblk->clsn, log); 592 logdiff(difft, tblk->clsn, log);
593 logdiff(diffp, mp->clsn, log); 593 logdiff(diffp, mp->clsn, log);
594 if (difft > diffp) 594 if (difft > diffp)
595 mp->clsn = tblk->clsn; 595 mp->clsn = tblk->clsn;
596 LOGSYNC_UNLOCK(log); 596 LOGSYNC_UNLOCK(log, flags);
597 } else { 597 } else {
598 mp->log = log; 598 mp->log = log;
599 mp->lsn = lsn; 599 mp->lsn = lsn;
600 600
601 /* insert bp after tblock in logsync list */ 601 /* insert bp after tblock in logsync list */
602 LOGSYNC_LOCK(log); 602 LOGSYNC_LOCK(log, flags);
603 603
604 log->count++; 604 log->count++;
605 list_add(&mp->synclist, &tblk->synclist); 605 list_add(&mp->synclist, &tblk->synclist);
606 606
607 mp->clsn = tblk->clsn; 607 mp->clsn = tblk->clsn;
608 LOGSYNC_UNLOCK(log); 608 LOGSYNC_UNLOCK(log, flags);
609 } 609 }
610 } 610 }
611 611
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index e357890adfb2..ac41f72d6d50 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -212,7 +212,7 @@ static struct metapage *read_index_page(struct inode *inode, s64 blkno)
212 s32 xlen; 212 s32 xlen;
213 213
214 rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1); 214 rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
215 if (rc || (xlen == 0)) 215 if (rc || (xaddr == 0))
216 return NULL; 216 return NULL;
217 217
218 return read_metapage(inode, xaddr, PSIZE, 1); 218 return read_metapage(inode, xaddr, PSIZE, 1);
@@ -231,7 +231,7 @@ static struct metapage *get_index_page(struct inode *inode, s64 blkno)
231 s32 xlen; 231 s32 xlen;
232 232
233 rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1); 233 rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
234 if (rc || (xlen == 0)) 234 if (rc || (xaddr == 0))
235 return NULL; 235 return NULL;
236 236
237 return get_metapage(inode, xaddr, PSIZE, 1); 237 return get_metapage(inode, xaddr, PSIZE, 1);
@@ -3181,7 +3181,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
3181 d = (struct ldtentry *) & p->slot[stbl[i]]; 3181 d = (struct ldtentry *) & p->slot[stbl[i]];
3182 3182
3183 if (((long) jfs_dirent + d->namlen + 1) > 3183 if (((long) jfs_dirent + d->namlen + 1) >
3184 (dirent_buf + PSIZE)) { 3184 (dirent_buf + PAGE_SIZE)) {
3185 /* DBCS codepages could overrun dirent_buf */ 3185 /* DBCS codepages could overrun dirent_buf */
3186 index = i; 3186 index = i;
3187 overflow = 1; 3187 overflow = 1;
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 783831301625..7acff2ce3c80 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -502,7 +502,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
502 502
503 } 503 }
504 504
505 ip->i_mapping->a_ops = &jfs_aops; 505 ip->i_mapping->a_ops = &jfs_metapage_aops;
506 mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); 506 mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
507 507
508 /* Allocations to metadata inodes should not affect quotas */ 508 /* Allocations to metadata inodes should not affect quotas */
@@ -2573,9 +2573,18 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
2573 goto out; 2573 goto out;
2574 } 2574 }
2575 2575
2576 /* assign a buffer for the page */ 2576 /*
2577 mp = get_metapage(ipimap, xaddr, PSIZE, 1); 2577 * start transaction of update of the inode map
2578 if (!mp) { 2578 * addressing structure pointing to the new iag page;
2579 */
2580 tid = txBegin(sb, COMMIT_FORCE);
2581 down(&JFS_IP(ipimap)->commit_sem);
2582
2583 /* update the inode map addressing structure to point to it */
2584 if ((rc =
2585 xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
2586 txEnd(tid);
2587 up(&JFS_IP(ipimap)->commit_sem);
2579 /* Free the blocks allocated for the iag since it was 2588 /* Free the blocks allocated for the iag since it was
2580 * not successfully added to the inode map 2589 * not successfully added to the inode map
2581 */ 2590 */
@@ -2584,6 +2593,29 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
2584 /* release the inode map lock */ 2593 /* release the inode map lock */
2585 IWRITE_UNLOCK(ipimap); 2594 IWRITE_UNLOCK(ipimap);
2586 2595
2596 goto out;
2597 }
2598
2599 /* update the inode map's inode to reflect the extension */
2600 ipimap->i_size += PSIZE;
2601 inode_add_bytes(ipimap, PSIZE);
2602
2603 /* assign a buffer for the page */
2604 mp = get_metapage(ipimap, blkno, PSIZE, 0);
2605 if (!mp) {
2606 /*
2607 * This is very unlikely since we just created the
2608 * extent, but let's try to handle it correctly
2609 */
2610 xtTruncate(tid, ipimap, ipimap->i_size - PSIZE,
2611 COMMIT_PWMAP);
2612
2613 txAbort(tid, 0);
2614 txEnd(tid);
2615
2616 /* release the inode map lock */
2617 IWRITE_UNLOCK(ipimap);
2618
2587 rc = -EIO; 2619 rc = -EIO;
2588 goto out; 2620 goto out;
2589 } 2621 }
@@ -2605,41 +2637,11 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
2605 iagp->inosmap[i] = cpu_to_le32(ONES); 2637 iagp->inosmap[i] = cpu_to_le32(ONES);
2606 2638
2607 /* 2639 /*
2608 * Invalidate the page after writing and syncing it. 2640 * Write and sync the metapage
2609 * After it's initialized, we access it in a different
2610 * address space
2611 */ 2641 */
2612 set_bit(META_discard, &mp->flag);
2613 flush_metapage(mp); 2642 flush_metapage(mp);
2614 2643
2615 /* 2644 /*
2616 * start tyransaction of update of the inode map
2617 * addressing structure pointing to the new iag page;
2618 */
2619 tid = txBegin(sb, COMMIT_FORCE);
2620 down(&JFS_IP(ipimap)->commit_sem);
2621
2622 /* update the inode map addressing structure to point to it */
2623 if ((rc =
2624 xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
2625 txEnd(tid);
2626 up(&JFS_IP(ipimap)->commit_sem);
2627 /* Free the blocks allocated for the iag since it was
2628 * not successfully added to the inode map
2629 */
2630 dbFree(ipimap, xaddr, (s64) xlen);
2631
2632 /* release the inode map lock */
2633 IWRITE_UNLOCK(ipimap);
2634
2635 goto out;
2636 }
2637
2638 /* update the inode map's inode to reflect the extension */
2639 ipimap->i_size += PSIZE;
2640 inode_add_bytes(ipimap, PSIZE);
2641
2642 /*
2643 * txCommit(COMMIT_FORCE) will synchronously write address 2645 * txCommit(COMMIT_FORCE) will synchronously write address
2644 * index pages and inode after commit in careful update order 2646 * index pages and inode after commit in careful update order
2645 * of address index pages (right to left, bottom up); 2647 * of address index pages (right to left, bottom up);
@@ -2789,6 +2791,7 @@ diUpdatePMap(struct inode *ipimap,
2789 u32 mask; 2791 u32 mask;
2790 struct jfs_log *log; 2792 struct jfs_log *log;
2791 int lsn, difft, diffp; 2793 int lsn, difft, diffp;
2794 unsigned long flags;
2792 2795
2793 imap = JFS_IP(ipimap)->i_imap; 2796 imap = JFS_IP(ipimap)->i_imap;
2794 /* get the iag number containing the inode */ 2797 /* get the iag number containing the inode */
@@ -2805,6 +2808,7 @@ diUpdatePMap(struct inode *ipimap,
2805 IREAD_UNLOCK(ipimap); 2808 IREAD_UNLOCK(ipimap);
2806 if (rc) 2809 if (rc)
2807 return (rc); 2810 return (rc);
2811 metapage_wait_for_io(mp);
2808 iagp = (struct iag *) mp->data; 2812 iagp = (struct iag *) mp->data;
2809 /* get the inode number and extent number of the inode within 2813 /* get the inode number and extent number of the inode within
2810 * the iag and the inode number within the extent. 2814 * the iag and the inode number within the extent.
@@ -2868,30 +2872,28 @@ diUpdatePMap(struct inode *ipimap,
2868 /* inherit older/smaller lsn */ 2872 /* inherit older/smaller lsn */
2869 logdiff(difft, lsn, log); 2873 logdiff(difft, lsn, log);
2870 logdiff(diffp, mp->lsn, log); 2874 logdiff(diffp, mp->lsn, log);
2875 LOGSYNC_LOCK(log, flags);
2871 if (difft < diffp) { 2876 if (difft < diffp) {
2872 mp->lsn = lsn; 2877 mp->lsn = lsn;
2873 /* move mp after tblock in logsync list */ 2878 /* move mp after tblock in logsync list */
2874 LOGSYNC_LOCK(log);
2875 list_move(&mp->synclist, &tblk->synclist); 2879 list_move(&mp->synclist, &tblk->synclist);
2876 LOGSYNC_UNLOCK(log);
2877 } 2880 }
2878 /* inherit younger/larger clsn */ 2881 /* inherit younger/larger clsn */
2879 LOGSYNC_LOCK(log);
2880 assert(mp->clsn); 2882 assert(mp->clsn);
2881 logdiff(difft, tblk->clsn, log); 2883 logdiff(difft, tblk->clsn, log);
2882 logdiff(diffp, mp->clsn, log); 2884 logdiff(diffp, mp->clsn, log);
2883 if (difft > diffp) 2885 if (difft > diffp)
2884 mp->clsn = tblk->clsn; 2886 mp->clsn = tblk->clsn;
2885 LOGSYNC_UNLOCK(log); 2887 LOGSYNC_UNLOCK(log, flags);
2886 } else { 2888 } else {
2887 mp->log = log; 2889 mp->log = log;
2888 mp->lsn = lsn; 2890 mp->lsn = lsn;
2889 /* insert mp after tblock in logsync list */ 2891 /* insert mp after tblock in logsync list */
2890 LOGSYNC_LOCK(log); 2892 LOGSYNC_LOCK(log, flags);
2891 log->count++; 2893 log->count++;
2892 list_add(&mp->synclist, &tblk->synclist); 2894 list_add(&mp->synclist, &tblk->synclist);
2893 mp->clsn = tblk->clsn; 2895 mp->clsn = tblk->clsn;
2894 LOGSYNC_UNLOCK(log); 2896 LOGSYNC_UNLOCK(log, flags);
2895 } 2897 }
2896 write_metapage(mp); 2898 write_metapage(mp);
2897 return (0); 2899 return (0);
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index ebd77c1bed66..c0fd7b3eadc6 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -165,6 +165,7 @@ struct jfs_sb_info {
165 /* Formerly in ipbmap */ 165 /* Formerly in ipbmap */
166 struct bmap *bmap; /* incore bmap descriptor */ 166 struct bmap *bmap; /* incore bmap descriptor */
167 struct nls_table *nls_tab; /* current codepage */ 167 struct nls_table *nls_tab; /* current codepage */
168 struct inode *direct_inode; /* metadata inode */
168 uint state; /* mount/recovery state */ 169 uint state; /* mount/recovery state */
169 unsigned long flag; /* mount time flags */ 170 unsigned long flag; /* mount time flags */
170 uint p_state; /* state prior to going no integrity */ 171 uint p_state; /* state prior to going no integrity */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index b6a6869ebb4f..dfa1200daa61 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -234,6 +234,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
234 int lsn; 234 int lsn;
235 int diffp, difft; 235 int diffp, difft;
236 struct metapage *mp = NULL; 236 struct metapage *mp = NULL;
237 unsigned long flags;
237 238
238 jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p", 239 jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p",
239 log, tblk, lrd, tlck); 240 log, tblk, lrd, tlck);
@@ -254,7 +255,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
254 */ 255 */
255 lsn = log->lsn; 256 lsn = log->lsn;
256 257
257 LOGSYNC_LOCK(log); 258 LOGSYNC_LOCK(log, flags);
258 259
259 /* 260 /*
260 * initialize page lsn if first log write of the page 261 * initialize page lsn if first log write of the page
@@ -310,7 +311,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
310 } 311 }
311 } 312 }
312 313
313 LOGSYNC_UNLOCK(log); 314 LOGSYNC_UNLOCK(log, flags);
314 315
315 /* 316 /*
316 * write the log record 317 * write the log record
@@ -334,7 +335,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
334 return lsn; 335 return lsn;
335} 336}
336 337
337
338/* 338/*
339 * NAME: lmWriteRecord() 339 * NAME: lmWriteRecord()
340 * 340 *
@@ -927,9 +927,8 @@ static void lmPostGC(struct lbuf * bp)
927 * calculate new value of i_nextsync which determines when 927 * calculate new value of i_nextsync which determines when
928 * this code is called again. 928 * this code is called again.
929 * 929 *
930 * this is called only from lmLog(). 930 * PARAMETERS: log - log structure
931 * 931 * nosyncwait - 1 if called asynchronously
932 * PARAMETER: ip - pointer to logs inode.
933 * 932 *
934 * RETURN: 0 933 * RETURN: 0
935 * 934 *
@@ -945,6 +944,15 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
945 struct lrd lrd; 944 struct lrd lrd;
946 int lsn; 945 int lsn;
947 struct logsyncblk *lp; 946 struct logsyncblk *lp;
947 struct jfs_sb_info *sbi;
948 unsigned long flags;
949
950 /* push dirty metapages out to disk */
951 list_for_each_entry(sbi, &log->sb_list, log_list) {
952 filemap_flush(sbi->ipbmap->i_mapping);
953 filemap_flush(sbi->ipimap->i_mapping);
954 filemap_flush(sbi->direct_inode->i_mapping);
955 }
948 956
949 /* 957 /*
950 * forward syncpt 958 * forward syncpt
@@ -954,10 +962,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
954 */ 962 */
955 963
956 if (log->sync == log->syncpt) { 964 if (log->sync == log->syncpt) {
957 LOGSYNC_LOCK(log); 965 LOGSYNC_LOCK(log, flags);
958 /* ToDo: push dirty metapages out to disk */
959// bmLogSync(log);
960
961 if (list_empty(&log->synclist)) 966 if (list_empty(&log->synclist))
962 log->sync = log->lsn; 967 log->sync = log->lsn;
963 else { 968 else {
@@ -965,7 +970,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
965 struct logsyncblk, synclist); 970 struct logsyncblk, synclist);
966 log->sync = lp->lsn; 971 log->sync = lp->lsn;
967 } 972 }
968 LOGSYNC_UNLOCK(log); 973 LOGSYNC_UNLOCK(log, flags);
969 974
970 } 975 }
971 976
@@ -974,27 +979,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
974 * reset syncpt = sync 979 * reset syncpt = sync
975 */ 980 */
976 if (log->sync != log->syncpt) { 981 if (log->sync != log->syncpt) {
977 struct jfs_sb_info *sbi;
978
979 /*
980 * We need to make sure all of the "written" metapages
981 * actually make it to disk
982 */
983 list_for_each_entry(sbi, &log->sb_list, log_list) {
984 if (sbi->flag & JFS_NOINTEGRITY)
985 continue;
986 filemap_fdatawrite(sbi->ipbmap->i_mapping);
987 filemap_fdatawrite(sbi->ipimap->i_mapping);
988 filemap_fdatawrite(sbi->sb->s_bdev->bd_inode->i_mapping);
989 }
990 list_for_each_entry(sbi, &log->sb_list, log_list) {
991 if (sbi->flag & JFS_NOINTEGRITY)
992 continue;
993 filemap_fdatawait(sbi->ipbmap->i_mapping);
994 filemap_fdatawait(sbi->ipimap->i_mapping);
995 filemap_fdatawait(sbi->sb->s_bdev->bd_inode->i_mapping);
996 }
997
998 lrd.logtid = 0; 982 lrd.logtid = 0;
999 lrd.backchain = 0; 983 lrd.backchain = 0;
1000 lrd.type = cpu_to_le16(LOG_SYNCPT); 984 lrd.type = cpu_to_le16(LOG_SYNCPT);
@@ -1066,6 +1050,18 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
1066 return lsn; 1050 return lsn;
1067} 1051}
1068 1052
1053/*
1054 * NAME: jfs_syncpt
1055 *
1056 * FUNCTION: write log SYNCPT record for specified log
1057 *
1058 * PARAMETERS: log - log structure
1059 */
1060void jfs_syncpt(struct jfs_log *log)
1061{ LOG_LOCK(log);
1062 lmLogSync(log, 1);
1063 LOG_UNLOCK(log);
1064}
1069 1065
1070/* 1066/*
1071 * NAME: lmLogOpen() 1067 * NAME: lmLogOpen()
@@ -1547,6 +1543,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1547{ 1543{
1548 int i; 1544 int i;
1549 struct tblock *target = NULL; 1545 struct tblock *target = NULL;
1546 struct jfs_sb_info *sbi;
1550 1547
1551 /* jfs_write_inode may call us during read-only mount */ 1548 /* jfs_write_inode may call us during read-only mount */
1552 if (!log) 1549 if (!log)
@@ -1608,12 +1605,18 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1608 if (wait < 2) 1605 if (wait < 2)
1609 return; 1606 return;
1610 1607
1608 list_for_each_entry(sbi, &log->sb_list, log_list) {
1609 filemap_fdatawrite(sbi->ipbmap->i_mapping);
1610 filemap_fdatawrite(sbi->ipimap->i_mapping);
1611 filemap_fdatawrite(sbi->direct_inode->i_mapping);
1612 }
1613
1611 /* 1614 /*
1612 * If there was recent activity, we may need to wait 1615 * If there was recent activity, we may need to wait
1613 * for the lazycommit thread to catch up 1616 * for the lazycommit thread to catch up
1614 */ 1617 */
1615 if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) { 1618 if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
1616 for (i = 0; i < 800; i++) { /* Too much? */ 1619 for (i = 0; i < 200; i++) { /* Too much? */
1617 msleep(250); 1620 msleep(250);
1618 if (list_empty(&log->cqueue) && 1621 if (list_empty(&log->cqueue) &&
1619 list_empty(&log->synclist)) 1622 list_empty(&log->synclist))
@@ -1621,7 +1624,24 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1621 } 1624 }
1622 } 1625 }
1623 assert(list_empty(&log->cqueue)); 1626 assert(list_empty(&log->cqueue));
1624 assert(list_empty(&log->synclist)); 1627 if (!list_empty(&log->synclist)) {
1628 struct logsyncblk *lp;
1629
1630 list_for_each_entry(lp, &log->synclist, synclist) {
1631 if (lp->xflag & COMMIT_PAGE) {
1632 struct metapage *mp = (struct metapage *)lp;
1633 dump_mem("orphan metapage", lp,
1634 sizeof(struct metapage));
1635 dump_mem("page", mp->page, sizeof(struct page));
1636 }
1637 else
1638 dump_mem("orphan tblock", lp,
1639 sizeof(struct tblock));
1640 }
1641// current->state = TASK_INTERRUPTIBLE;
1642// schedule();
1643 }
1644 //assert(list_empty(&log->synclist));
1625 clear_bit(log_FLUSH, &log->flag); 1645 clear_bit(log_FLUSH, &log->flag);
1626} 1646}
1627 1647
@@ -1669,6 +1689,7 @@ int lmLogShutdown(struct jfs_log * log)
1669 lp->h.eor = lp->t.eor = cpu_to_le16(bp->l_eor); 1689 lp->h.eor = lp->t.eor = cpu_to_le16(bp->l_eor);
1670 lbmWrite(log, log->bp, lbmWRITE | lbmRELEASE | lbmSYNC, 0); 1690 lbmWrite(log, log->bp, lbmWRITE | lbmRELEASE | lbmSYNC, 0);
1671 lbmIOWait(log->bp, lbmFREE); 1691 lbmIOWait(log->bp, lbmFREE);
1692 log->bp = NULL;
1672 1693
1673 /* 1694 /*
1674 * synchronous update log superblock 1695 * synchronous update log superblock
@@ -1819,20 +1840,34 @@ static int lbmLogInit(struct jfs_log * log)
1819 1840
1820 log->lbuf_free = NULL; 1841 log->lbuf_free = NULL;
1821 1842
1822 for (i = 0; i < LOGPAGES; i++) { 1843 for (i = 0; i < LOGPAGES;) {
1823 lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL); 1844 char *buffer;
1824 if (lbuf == 0) 1845 uint offset;
1825 goto error; 1846 struct page *page;
1826 lbuf->l_ldata = (char *) get_zeroed_page(GFP_KERNEL); 1847
1827 if (lbuf->l_ldata == 0) { 1848 buffer = (char *) get_zeroed_page(GFP_KERNEL);
1828 kfree(lbuf); 1849 if (buffer == NULL)
1829 goto error; 1850 goto error;
1851 page = virt_to_page(buffer);
1852 for (offset = 0; offset < PAGE_SIZE; offset += LOGPSIZE) {
1853 lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL);
1854 if (lbuf == NULL) {
1855 if (offset == 0)
1856 free_page((unsigned long) buffer);
1857 goto error;
1858 }
1859 if (offset) /* we already have one reference */
1860 get_page(page);
1861 lbuf->l_offset = offset;
1862 lbuf->l_ldata = buffer + offset;
1863 lbuf->l_page = page;
1864 lbuf->l_log = log;
1865 init_waitqueue_head(&lbuf->l_ioevent);
1866
1867 lbuf->l_freelist = log->lbuf_free;
1868 log->lbuf_free = lbuf;
1869 i++;
1830 } 1870 }
1831 lbuf->l_log = log;
1832 init_waitqueue_head(&lbuf->l_ioevent);
1833
1834 lbuf->l_freelist = log->lbuf_free;
1835 log->lbuf_free = lbuf;
1836 } 1871 }
1837 1872
1838 return (0); 1873 return (0);
@@ -1857,12 +1892,10 @@ static void lbmLogShutdown(struct jfs_log * log)
1857 lbuf = log->lbuf_free; 1892 lbuf = log->lbuf_free;
1858 while (lbuf) { 1893 while (lbuf) {
1859 struct lbuf *next = lbuf->l_freelist; 1894 struct lbuf *next = lbuf->l_freelist;
1860 free_page((unsigned long) lbuf->l_ldata); 1895 __free_page(lbuf->l_page);
1861 kfree(lbuf); 1896 kfree(lbuf);
1862 lbuf = next; 1897 lbuf = next;
1863 } 1898 }
1864
1865 log->bp = NULL;
1866} 1899}
1867 1900
1868 1901
@@ -1974,9 +2007,9 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
1974 2007
1975 bio->bi_sector = bp->l_blkno << (log->l2bsize - 9); 2008 bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
1976 bio->bi_bdev = log->bdev; 2009 bio->bi_bdev = log->bdev;
1977 bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata); 2010 bio->bi_io_vec[0].bv_page = bp->l_page;
1978 bio->bi_io_vec[0].bv_len = LOGPSIZE; 2011 bio->bi_io_vec[0].bv_len = LOGPSIZE;
1979 bio->bi_io_vec[0].bv_offset = 0; 2012 bio->bi_io_vec[0].bv_offset = bp->l_offset;
1980 2013
1981 bio->bi_vcnt = 1; 2014 bio->bi_vcnt = 1;
1982 bio->bi_idx = 0; 2015 bio->bi_idx = 0;
@@ -2115,9 +2148,9 @@ static void lbmStartIO(struct lbuf * bp)
2115 bio = bio_alloc(GFP_NOFS, 1); 2148 bio = bio_alloc(GFP_NOFS, 1);
2116 bio->bi_sector = bp->l_blkno << (log->l2bsize - 9); 2149 bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
2117 bio->bi_bdev = log->bdev; 2150 bio->bi_bdev = log->bdev;
2118 bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata); 2151 bio->bi_io_vec[0].bv_page = bp->l_page;
2119 bio->bi_io_vec[0].bv_len = LOGPSIZE; 2152 bio->bi_io_vec[0].bv_len = LOGPSIZE;
2120 bio->bi_io_vec[0].bv_offset = 0; 2153 bio->bi_io_vec[0].bv_offset = bp->l_offset;
2121 2154
2122 bio->bi_vcnt = 1; 2155 bio->bi_vcnt = 1;
2123 bio->bi_idx = 0; 2156 bio->bi_idx = 0;
@@ -2127,16 +2160,13 @@ static void lbmStartIO(struct lbuf * bp)
2127 bio->bi_private = bp; 2160 bio->bi_private = bp;
2128 2161
2129 /* check if journaling to disk has been disabled */ 2162 /* check if journaling to disk has been disabled */
2130 if (!log->no_integrity) { 2163 if (log->no_integrity) {
2164 bio->bi_size = 0;
2165 lbmIODone(bio, 0, 0);
2166 } else {
2131 submit_bio(WRITE_SYNC, bio); 2167 submit_bio(WRITE_SYNC, bio);
2132 INCREMENT(lmStat.submitted); 2168 INCREMENT(lmStat.submitted);
2133 } 2169 }
2134 else {
2135 bio->bi_size = 0;
2136 lbmIODone(bio, 0, 0); /* 2nd argument appears to not be used => 0
2137 * 3rd argument appears to not be used => 0
2138 */
2139 }
2140} 2170}
2141 2171
2142 2172
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 141ad74010c9..51291fbc420c 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -463,9 +463,10 @@ struct lbuf {
463 463
464 s64 l_blkno; /* 8: log page block number */ 464 s64 l_blkno; /* 8: log page block number */
465 caddr_t l_ldata; /* 4: data page */ 465 caddr_t l_ldata; /* 4: data page */
466 struct page *l_page; /* The page itself */
467 uint l_offset; /* Offset of l_ldata within the page */
466 468
467 wait_queue_head_t l_ioevent; /* 4: i/o done event */ 469 wait_queue_head_t l_ioevent; /* 4: i/o done event */
468 struct page *l_page; /* The page itself */
469}; 470};
470 471
471/* Reuse l_freelist for redrive list */ 472/* Reuse l_freelist for redrive list */
@@ -489,8 +490,9 @@ struct logsyncblk {
489 */ 490 */
490 491
491#define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock) 492#define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock)
492#define LOGSYNC_LOCK(log) spin_lock(&(log)->synclock) 493#define LOGSYNC_LOCK(log, flags) spin_lock_irqsave(&(log)->synclock, flags)
493#define LOGSYNC_UNLOCK(log) spin_unlock(&(log)->synclock) 494#define LOGSYNC_UNLOCK(log, flags) \
495 spin_unlock_irqrestore(&(log)->synclock, flags)
494 496
495/* compute the difference in bytes of lsn from sync point */ 497/* compute the difference in bytes of lsn from sync point */
496#define logdiff(diff, lsn, log)\ 498#define logdiff(diff, lsn, log)\
@@ -506,5 +508,6 @@ extern int lmLogShutdown(struct jfs_log * log);
506extern int lmLogInit(struct jfs_log * log); 508extern int lmLogInit(struct jfs_log * log);
507extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize); 509extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
508extern void jfs_flush_journal(struct jfs_log * log, int wait); 510extern void jfs_flush_journal(struct jfs_log * log, int wait);
511extern void jfs_syncpt(struct jfs_log *log);
509 512
510#endif /* _H_JFS_LOGMGR */ 513#endif /* _H_JFS_LOGMGR */
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 4c0a3ac75c08..41bf078dce05 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) International Business Machines Corp., 2000-2003 2 * Copyright (C) International Business Machines Corp., 2000-2005
3 * Portions Copyright (C) Christoph Hellwig, 2001-2002 3 * Portions Copyright (C) Christoph Hellwig, 2001-2002
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -18,10 +18,11 @@
18 */ 18 */
19 19
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/mm.h>
22#include <linux/bio.h>
21#include <linux/init.h> 23#include <linux/init.h>
22#include <linux/buffer_head.h> 24#include <linux/buffer_head.h>
23#include <linux/mempool.h> 25#include <linux/mempool.h>
24#include <linux/delay.h>
25#include "jfs_incore.h" 26#include "jfs_incore.h"
26#include "jfs_superblock.h" 27#include "jfs_superblock.h"
27#include "jfs_filsys.h" 28#include "jfs_filsys.h"
@@ -29,8 +30,6 @@
29#include "jfs_txnmgr.h" 30#include "jfs_txnmgr.h"
30#include "jfs_debug.h" 31#include "jfs_debug.h"
31 32
32static DEFINE_SPINLOCK(meta_lock);
33
34#ifdef CONFIG_JFS_STATISTICS 33#ifdef CONFIG_JFS_STATISTICS
35static struct { 34static struct {
36 uint pagealloc; /* # of page allocations */ 35 uint pagealloc; /* # of page allocations */
@@ -39,22 +38,8 @@ static struct {
39} mpStat; 38} mpStat;
40#endif 39#endif
41 40
42 41#define metapage_locked(mp) test_bit(META_locked, &(mp)->flag)
43#define HASH_BITS 10 /* This makes hash_table 1 4K page */ 42#define trylock_metapage(mp) test_and_set_bit(META_locked, &(mp)->flag)
44#define HASH_SIZE (1 << HASH_BITS)
45static struct metapage **hash_table = NULL;
46static unsigned long hash_order;
47
48
49static inline int metapage_locked(struct metapage *mp)
50{
51 return test_bit(META_locked, &mp->flag);
52}
53
54static inline int trylock_metapage(struct metapage *mp)
55{
56 return test_and_set_bit(META_locked, &mp->flag);
57}
58 43
59static inline void unlock_metapage(struct metapage *mp) 44static inline void unlock_metapage(struct metapage *mp)
60{ 45{
@@ -62,26 +47,26 @@ static inline void unlock_metapage(struct metapage *mp)
62 wake_up(&mp->wait); 47 wake_up(&mp->wait);
63} 48}
64 49
65static void __lock_metapage(struct metapage *mp) 50static inline void __lock_metapage(struct metapage *mp)
66{ 51{
67 DECLARE_WAITQUEUE(wait, current); 52 DECLARE_WAITQUEUE(wait, current);
68
69 INCREMENT(mpStat.lockwait); 53 INCREMENT(mpStat.lockwait);
70
71 add_wait_queue_exclusive(&mp->wait, &wait); 54 add_wait_queue_exclusive(&mp->wait, &wait);
72 do { 55 do {
73 set_current_state(TASK_UNINTERRUPTIBLE); 56 set_current_state(TASK_UNINTERRUPTIBLE);
74 if (metapage_locked(mp)) { 57 if (metapage_locked(mp)) {
75 spin_unlock(&meta_lock); 58 unlock_page(mp->page);
76 schedule(); 59 schedule();
77 spin_lock(&meta_lock); 60 lock_page(mp->page);
78 } 61 }
79 } while (trylock_metapage(mp)); 62 } while (trylock_metapage(mp));
80 __set_current_state(TASK_RUNNING); 63 __set_current_state(TASK_RUNNING);
81 remove_wait_queue(&mp->wait, &wait); 64 remove_wait_queue(&mp->wait, &wait);
82} 65}
83 66
84/* needs meta_lock */ 67/*
68 * Must have mp->page locked
69 */
85static inline void lock_metapage(struct metapage *mp) 70static inline void lock_metapage(struct metapage *mp)
86{ 71{
87 if (trylock_metapage(mp)) 72 if (trylock_metapage(mp))
@@ -92,6 +77,110 @@ static inline void lock_metapage(struct metapage *mp)
92static kmem_cache_t *metapage_cache; 77static kmem_cache_t *metapage_cache;
93static mempool_t *metapage_mempool; 78static mempool_t *metapage_mempool;
94 79
80#define MPS_PER_PAGE (PAGE_CACHE_SIZE >> L2PSIZE)
81
82#if MPS_PER_PAGE > 1
83
84struct meta_anchor {
85 int mp_count;
86 atomic_t io_count;
87 struct metapage *mp[MPS_PER_PAGE];
88};
89#define mp_anchor(page) ((struct meta_anchor *)page->private)
90
91static inline struct metapage *page_to_mp(struct page *page, uint offset)
92{
93 if (!PagePrivate(page))
94 return NULL;
95 return mp_anchor(page)->mp[offset >> L2PSIZE];
96}
97
98static inline int insert_metapage(struct page *page, struct metapage *mp)
99{
100 struct meta_anchor *a;
101 int index;
102 int l2mp_blocks; /* log2 blocks per metapage */
103
104 if (PagePrivate(page))
105 a = mp_anchor(page);
106 else {
107 a = kmalloc(sizeof(struct meta_anchor), GFP_NOFS);
108 if (!a)
109 return -ENOMEM;
110 memset(a, 0, sizeof(struct meta_anchor));
111 page->private = (unsigned long)a;
112 SetPagePrivate(page);
113 kmap(page);
114 }
115
116 if (mp) {
117 l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits;
118 index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1);
119 a->mp_count++;
120 a->mp[index] = mp;
121 }
122
123 return 0;
124}
125
126static inline void remove_metapage(struct page *page, struct metapage *mp)
127{
128 struct meta_anchor *a = mp_anchor(page);
129 int l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits;
130 int index;
131
132 index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1);
133
134 BUG_ON(a->mp[index] != mp);
135
136 a->mp[index] = NULL;
137 if (--a->mp_count == 0) {
138 kfree(a);
139 page->private = 0;
140 ClearPagePrivate(page);
141 kunmap(page);
142 }
143}
144
145static inline void inc_io(struct page *page)
146{
147 atomic_inc(&mp_anchor(page)->io_count);
148}
149
150static inline void dec_io(struct page *page, void (*handler) (struct page *))
151{
152 if (atomic_dec_and_test(&mp_anchor(page)->io_count))
153 handler(page);
154}
155
156#else
157static inline struct metapage *page_to_mp(struct page *page, uint offset)
158{
159 return PagePrivate(page) ? (struct metapage *)page->private : NULL;
160}
161
162static inline int insert_metapage(struct page *page, struct metapage *mp)
163{
164 if (mp) {
165 page->private = (unsigned long)mp;
166 SetPagePrivate(page);
167 kmap(page);
168 }
169 return 0;
170}
171
172static inline void remove_metapage(struct page *page, struct metapage *mp)
173{
174 page->private = 0;
175 ClearPagePrivate(page);
176 kunmap(page);
177}
178
179#define inc_io(page) do {} while(0)
180#define dec_io(page, handler) handler(page)
181
182#endif
183
95static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) 184static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
96{ 185{
97 struct metapage *mp = (struct metapage *)foo; 186 struct metapage *mp = (struct metapage *)foo;
@@ -139,16 +228,6 @@ int __init metapage_init(void)
139 kmem_cache_destroy(metapage_cache); 228 kmem_cache_destroy(metapage_cache);
140 return -ENOMEM; 229 return -ENOMEM;
141 } 230 }
142 /*
143 * Now the hash list
144 */
145 for (hash_order = 0;
146 ((PAGE_SIZE << hash_order) / sizeof(void *)) < HASH_SIZE;
147 hash_order++);
148 hash_table =
149 (struct metapage **) __get_free_pages(GFP_KERNEL, hash_order);
150 assert(hash_table);
151 memset(hash_table, 0, PAGE_SIZE << hash_order);
152 231
153 return 0; 232 return 0;
154} 233}
@@ -159,73 +238,388 @@ void metapage_exit(void)
159 kmem_cache_destroy(metapage_cache); 238 kmem_cache_destroy(metapage_cache);
160} 239}
161 240
241static inline void drop_metapage(struct page *page, struct metapage *mp)
242{
243 if (mp->count || mp->nohomeok || test_bit(META_dirty, &mp->flag) ||
244 test_bit(META_io, &mp->flag))
245 return;
246 remove_metapage(page, mp);
247 INCREMENT(mpStat.pagefree);
248 free_metapage(mp);
249}
250
162/* 251/*
163 * Basically same hash as in pagemap.h, but using our hash table 252 * Metapage address space operations
164 */ 253 */
165static struct metapage **meta_hash(struct address_space *mapping, 254
166 unsigned long index) 255static sector_t metapage_get_blocks(struct inode *inode, sector_t lblock,
256 unsigned int *len)
167{ 257{
168#define i (((unsigned long)mapping)/ \ 258 int rc = 0;
169 (sizeof(struct inode) & ~(sizeof(struct inode) -1 ))) 259 int xflag;
170#define s(x) ((x) + ((x) >> HASH_BITS)) 260 s64 xaddr;
171 return hash_table + (s(i + index) & (HASH_SIZE - 1)); 261 sector_t file_blocks = (inode->i_size + inode->i_blksize - 1) >>
172#undef i 262 inode->i_blkbits;
173#undef s 263
264 if (lblock >= file_blocks)
265 return 0;
266 if (lblock + *len > file_blocks)
267 *len = file_blocks - lblock;
268
269 if (inode->i_ino) {
270 rc = xtLookup(inode, (s64)lblock, *len, &xflag, &xaddr, len, 0);
271 if ((rc == 0) && *len)
272 lblock = (sector_t)xaddr;
273 else
274 lblock = 0;
275 } /* else no mapping */
276
277 return lblock;
174} 278}
175 279
176static struct metapage *search_hash(struct metapage ** hash_ptr, 280static void last_read_complete(struct page *page)
177 struct address_space *mapping,
178 unsigned long index)
179{ 281{
180 struct metapage *ptr; 282 if (!PageError(page))
283 SetPageUptodate(page);
284 unlock_page(page);
285}
286
287static int metapage_read_end_io(struct bio *bio, unsigned int bytes_done,
288 int err)
289{
290 struct page *page = bio->bi_private;
291
292 if (bio->bi_size)
293 return 1;
181 294
182 for (ptr = *hash_ptr; ptr; ptr = ptr->hash_next) { 295 if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
183 if ((ptr->mapping == mapping) && (ptr->index == index)) 296 printk(KERN_ERR "metapage_read_end_io: I/O error\n");
184 return ptr; 297 SetPageError(page);
185 } 298 }
186 299
187 return NULL; 300 dec_io(page, last_read_complete);
301 bio_put(bio);
302
303 return 0;
188} 304}
189 305
190static void add_to_hash(struct metapage * mp, struct metapage ** hash_ptr) 306static void remove_from_logsync(struct metapage *mp)
191{ 307{
192 if (*hash_ptr) 308 struct jfs_log *log = mp->log;
193 (*hash_ptr)->hash_prev = mp; 309 unsigned long flags;
310/*
311 * This can race. Recheck that log hasn't been set to null, and after
312 * acquiring logsync lock, recheck lsn
313 */
314 if (!log)
315 return;
316
317 LOGSYNC_LOCK(log, flags);
318 if (mp->lsn) {
319 mp->log = NULL;
320 mp->lsn = 0;
321 mp->clsn = 0;
322 log->count--;
323 list_del(&mp->synclist);
324 }
325 LOGSYNC_UNLOCK(log, flags);
326}
194 327
195 mp->hash_prev = NULL; 328static void last_write_complete(struct page *page)
196 mp->hash_next = *hash_ptr; 329{
197 *hash_ptr = mp; 330 struct metapage *mp;
331 unsigned int offset;
332
333 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
334 mp = page_to_mp(page, offset);
335 if (mp && test_bit(META_io, &mp->flag)) {
336 if (mp->lsn)
337 remove_from_logsync(mp);
338 clear_bit(META_io, &mp->flag);
339 }
340 /*
341 * I'd like to call drop_metapage here, but I don't think it's
342 * safe unless I have the page locked
343 */
344 }
345 end_page_writeback(page);
198} 346}
199 347
200static void remove_from_hash(struct metapage * mp, struct metapage ** hash_ptr) 348static int metapage_write_end_io(struct bio *bio, unsigned int bytes_done,
349 int err)
201{ 350{
202 if (mp->hash_prev) 351 struct page *page = bio->bi_private;
203 mp->hash_prev->hash_next = mp->hash_next; 352
204 else { 353 BUG_ON(!PagePrivate(page));
205 assert(*hash_ptr == mp); 354
206 *hash_ptr = mp->hash_next; 355 if (bio->bi_size)
356 return 1;
357
358 if (! test_bit(BIO_UPTODATE, &bio->bi_flags)) {
359 printk(KERN_ERR "metapage_write_end_io: I/O error\n");
360 SetPageError(page);
361 }
362 dec_io(page, last_write_complete);
363 bio_put(bio);
364 return 0;
365}
366
367static int metapage_writepage(struct page *page, struct writeback_control *wbc)
368{
369 struct bio *bio = NULL;
370 unsigned int block_offset; /* block offset of mp within page */
371 struct inode *inode = page->mapping->host;
372 unsigned int blocks_per_mp = JFS_SBI(inode->i_sb)->nbperpage;
373 unsigned int len;
374 unsigned int xlen;
375 struct metapage *mp;
376 int redirty = 0;
377 sector_t lblock;
378 sector_t pblock;
379 sector_t next_block = 0;
380 sector_t page_start;
381 unsigned long bio_bytes = 0;
382 unsigned long bio_offset = 0;
383 unsigned int offset;
384
385 page_start = (sector_t)page->index <<
386 (PAGE_CACHE_SHIFT - inode->i_blkbits);
387 BUG_ON(!PageLocked(page));
388 BUG_ON(PageWriteback(page));
389
390 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
391 mp = page_to_mp(page, offset);
392
393 if (!mp || !test_bit(META_dirty, &mp->flag))
394 continue;
395
396 if (mp->nohomeok && !test_bit(META_forcewrite, &mp->flag)) {
397 redirty = 1;
398 continue;
399 }
400
401 clear_bit(META_dirty, &mp->flag);
402 block_offset = offset >> inode->i_blkbits;
403 lblock = page_start + block_offset;
404 if (bio) {
405 if (xlen && lblock == next_block) {
406 /* Contiguous, in memory & on disk */
407 len = min(xlen, blocks_per_mp);
408 xlen -= len;
409 bio_bytes += len << inode->i_blkbits;
410 set_bit(META_io, &mp->flag);
411 continue;
412 }
413 /* Not contiguous */
414 if (bio_add_page(bio, page, bio_bytes, bio_offset) <
415 bio_bytes)
416 goto add_failed;
417 /*
418 * Increment counter before submitting i/o to keep
419 * count from hitting zero before we're through
420 */
421 inc_io(page);
422 if (!bio->bi_size)
423 goto dump_bio;
424 submit_bio(WRITE, bio);
425 bio = NULL;
426 } else {
427 set_page_writeback(page);
428 inc_io(page);
429 }
430 xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits;
431 pblock = metapage_get_blocks(inode, lblock, &xlen);
432 if (!pblock) {
433 /* Need better error handling */
434 printk(KERN_ERR "JFS: metapage_get_blocks failed\n");
435 dec_io(page, last_write_complete);
436 continue;
437 }
438 set_bit(META_io, &mp->flag);
439 len = min(xlen, (uint) JFS_SBI(inode->i_sb)->nbperpage);
440
441 bio = bio_alloc(GFP_NOFS, 1);
442 bio->bi_bdev = inode->i_sb->s_bdev;
443 bio->bi_sector = pblock << (inode->i_blkbits - 9);
444 bio->bi_end_io = metapage_write_end_io;
445 bio->bi_private = page;
446
447 /* Don't call bio_add_page yet, we may add to this vec */
448 bio_offset = offset;
449 bio_bytes = len << inode->i_blkbits;
450
451 xlen -= len;
452 next_block = lblock + len;
453 }
454 if (bio) {
455 if (bio_add_page(bio, page, bio_bytes, bio_offset) < bio_bytes)
456 goto add_failed;
457 if (!bio->bi_size)
458 goto dump_bio;
459
460 submit_bio(WRITE, bio);
461 }
462 if (redirty)
463 redirty_page_for_writepage(wbc, page);
464
465 unlock_page(page);
466
467 return 0;
468add_failed:
469 /* We should never reach here, since we're only adding one vec */
470 printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
471 goto skip;
472dump_bio:
473 dump_mem("bio", bio, sizeof(*bio));
474skip:
475 bio_put(bio);
476 unlock_page(page);
477 dec_io(page, last_write_complete);
478
479 return -EIO;
480}
481
482static int metapage_readpage(struct file *fp, struct page *page)
483{
484 struct inode *inode = page->mapping->host;
485 struct bio *bio = NULL;
486 unsigned int block_offset;
487 unsigned int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits;
488 sector_t page_start; /* address of page in fs blocks */
489 sector_t pblock;
490 unsigned int xlen;
491 unsigned int len;
492 unsigned int offset;
493
494 BUG_ON(!PageLocked(page));
495 page_start = (sector_t)page->index <<
496 (PAGE_CACHE_SHIFT - inode->i_blkbits);
497
498 block_offset = 0;
499 while (block_offset < blocks_per_page) {
500 xlen = blocks_per_page - block_offset;
501 pblock = metapage_get_blocks(inode, page_start + block_offset,
502 &xlen);
503 if (pblock) {
504 if (!PagePrivate(page))
505 insert_metapage(page, NULL);
506 inc_io(page);
507 if (bio)
508 submit_bio(READ, bio);
509
510 bio = bio_alloc(GFP_NOFS, 1);
511 bio->bi_bdev = inode->i_sb->s_bdev;
512 bio->bi_sector = pblock << (inode->i_blkbits - 9);
513 bio->bi_end_io = metapage_read_end_io;
514 bio->bi_private = page;
515 len = xlen << inode->i_blkbits;
516 offset = block_offset << inode->i_blkbits;
517 if (bio_add_page(bio, page, len, offset) < len)
518 goto add_failed;
519 block_offset += xlen;
520 } else
521 block_offset++;
207 } 522 }
523 if (bio)
524 submit_bio(READ, bio);
525 else
526 unlock_page(page);
527
528 return 0;
208 529
209 if (mp->hash_next) 530add_failed:
210 mp->hash_next->hash_prev = mp->hash_prev; 531 printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
532 bio_put(bio);
533 dec_io(page, last_read_complete);
534 return -EIO;
211} 535}
212 536
537static int metapage_releasepage(struct page *page, int gfp_mask)
538{
539 struct metapage *mp;
540 int busy = 0;
541 unsigned int offset;
542
543 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
544 mp = page_to_mp(page, offset);
545
546 if (!mp)
547 continue;
548
549 jfs_info("metapage_releasepage: mp = 0x%p", mp);
550 if (mp->count || mp->nohomeok) {
551 jfs_info("count = %ld, nohomeok = %d", mp->count,
552 mp->nohomeok);
553 busy = 1;
554 continue;
555 }
556 wait_on_page_writeback(page);
557 //WARN_ON(test_bit(META_dirty, &mp->flag));
558 if (test_bit(META_dirty, &mp->flag)) {
559 dump_mem("dirty mp in metapage_releasepage", mp,
560 sizeof(struct metapage));
561 dump_mem("page", page, sizeof(struct page));
562 dump_stack();
563 }
564 WARN_ON(mp->lsn);
565 if (mp->lsn)
566 remove_from_logsync(mp);
567 remove_metapage(page, mp);
568 INCREMENT(mpStat.pagefree);
569 free_metapage(mp);
570 }
571 if (busy)
572 return -1;
573
574 return 0;
575}
576
577static int metapage_invalidatepage(struct page *page, unsigned long offset)
578{
579 BUG_ON(offset);
580
581 if (PageWriteback(page))
582 return 0;
583
584 return metapage_releasepage(page, 0);
585}
586
587struct address_space_operations jfs_metapage_aops = {
588 .readpage = metapage_readpage,
589 .writepage = metapage_writepage,
590 .sync_page = block_sync_page,
591 .releasepage = metapage_releasepage,
592 .invalidatepage = metapage_invalidatepage,
593 .set_page_dirty = __set_page_dirty_nobuffers,
594};
595
213struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, 596struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
214 unsigned int size, int absolute, 597 unsigned int size, int absolute,
215 unsigned long new) 598 unsigned long new)
216{ 599{
217 struct metapage **hash_ptr;
218 int l2BlocksPerPage; 600 int l2BlocksPerPage;
219 int l2bsize; 601 int l2bsize;
220 struct address_space *mapping; 602 struct address_space *mapping;
221 struct metapage *mp; 603 struct metapage *mp = NULL;
604 struct page *page;
222 unsigned long page_index; 605 unsigned long page_index;
223 unsigned long page_offset; 606 unsigned long page_offset;
224 607
225 jfs_info("__get_metapage: inode = 0x%p, lblock = 0x%lx", inode, lblock); 608 jfs_info("__get_metapage: ino = %ld, lblock = 0x%lx, abs=%d",
226 609 inode->i_ino, lblock, absolute);
610
611 l2bsize = inode->i_blkbits;
612 l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
613 page_index = lblock >> l2BlocksPerPage;
614 page_offset = (lblock - (page_index << l2BlocksPerPage)) << l2bsize;
615 if ((page_offset + size) > PAGE_CACHE_SIZE) {
616 jfs_err("MetaData crosses page boundary!!");
617 jfs_err("lblock = %lx, size = %d", lblock, size);
618 dump_stack();
619 return NULL;
620 }
227 if (absolute) 621 if (absolute)
228 mapping = inode->i_sb->s_bdev->bd_inode->i_mapping; 622 mapping = JFS_SBI(inode->i_sb)->direct_inode->i_mapping;
229 else { 623 else {
230 /* 624 /*
231 * If an nfs client tries to read an inode that is larger 625 * If an nfs client tries to read an inode that is larger
@@ -237,312 +631,212 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
237 mapping = inode->i_mapping; 631 mapping = inode->i_mapping;
238 } 632 }
239 633
240 hash_ptr = meta_hash(mapping, lblock); 634 if (new && (PSIZE == PAGE_CACHE_SIZE)) {
241again: 635 page = grab_cache_page(mapping, page_index);
242 spin_lock(&meta_lock); 636 if (!page) {
243 mp = search_hash(hash_ptr, mapping, lblock); 637 jfs_err("grab_cache_page failed!");
638 return NULL;
639 }
640 SetPageUptodate(page);
641 } else {
642 page = read_cache_page(mapping, page_index,
643 (filler_t *)mapping->a_ops->readpage, NULL);
644 if (IS_ERR(page)) {
645 jfs_err("read_cache_page failed!");
646 return NULL;
647 }
648 lock_page(page);
649 }
650
651 mp = page_to_mp(page, page_offset);
244 if (mp) { 652 if (mp) {
245 page_found: 653 if (mp->logical_size != size) {
246 if (test_bit(META_stale, &mp->flag)) { 654 jfs_error(inode->i_sb,
247 spin_unlock(&meta_lock); 655 "__get_metapage: mp->logical_size != size");
248 msleep(1); 656 jfs_err("logical_size = %d, size = %d",
249 goto again; 657 mp->logical_size, size);
658 dump_stack();
659 goto unlock;
250 } 660 }
251 mp->count++; 661 mp->count++;
252 lock_metapage(mp); 662 lock_metapage(mp);
253 spin_unlock(&meta_lock);
254 if (test_bit(META_discard, &mp->flag)) { 663 if (test_bit(META_discard, &mp->flag)) {
255 if (!new) { 664 if (!new) {
256 jfs_error(inode->i_sb, 665 jfs_error(inode->i_sb,
257 "__get_metapage: using a " 666 "__get_metapage: using a "
258 "discarded metapage"); 667 "discarded metapage");
259 release_metapage(mp); 668 discard_metapage(mp);
260 return NULL; 669 goto unlock;
261 } 670 }
262 clear_bit(META_discard, &mp->flag); 671 clear_bit(META_discard, &mp->flag);
263 } 672 }
264 jfs_info("__get_metapage: found 0x%p, in hash", mp);
265 if (mp->logical_size != size) {
266 jfs_error(inode->i_sb,
267 "__get_metapage: mp->logical_size != size");
268 release_metapage(mp);
269 return NULL;
270 }
271 } else { 673 } else {
272 l2bsize = inode->i_blkbits; 674 INCREMENT(mpStat.pagealloc);
273 l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize; 675 mp = alloc_metapage(GFP_NOFS);
274 page_index = lblock >> l2BlocksPerPage; 676 mp->page = page;
275 page_offset = (lblock - (page_index << l2BlocksPerPage)) <<
276 l2bsize;
277 if ((page_offset + size) > PAGE_CACHE_SIZE) {
278 spin_unlock(&meta_lock);
279 jfs_err("MetaData crosses page boundary!!");
280 return NULL;
281 }
282
283 /*
284 * Locks held on aggregate inode pages are usually
285 * not held long, and they are taken in critical code
286 * paths (committing dirty inodes, txCommit thread)
287 *
288 * Attempt to get metapage without blocking, tapping into
289 * reserves if necessary.
290 */
291 mp = NULL;
292 if (JFS_IP(inode)->fileset == AGGREGATE_I) {
293 mp = alloc_metapage(GFP_ATOMIC);
294 if (!mp) {
295 /*
296 * mempool is supposed to protect us from
297 * failing here. We will try a blocking
298 * call, but a deadlock is possible here
299 */
300 printk(KERN_WARNING
301 "__get_metapage: atomic call to mempool_alloc failed.\n");
302 printk(KERN_WARNING
303 "Will attempt blocking call\n");
304 }
305 }
306 if (!mp) {
307 struct metapage *mp2;
308
309 spin_unlock(&meta_lock);
310 mp = alloc_metapage(GFP_NOFS);
311 spin_lock(&meta_lock);
312
313 /* we dropped the meta_lock, we need to search the
314 * hash again.
315 */
316 mp2 = search_hash(hash_ptr, mapping, lblock);
317 if (mp2) {
318 free_metapage(mp);
319 mp = mp2;
320 goto page_found;
321 }
322 }
323 mp->flag = 0; 677 mp->flag = 0;
324 lock_metapage(mp);
325 if (absolute)
326 set_bit(META_absolute, &mp->flag);
327 mp->xflag = COMMIT_PAGE; 678 mp->xflag = COMMIT_PAGE;
328 mp->count = 1; 679 mp->count = 1;
329 atomic_set(&mp->nohomeok,0); 680 mp->nohomeok = 0;
330 mp->mapping = mapping;
331 mp->index = lblock;
332 mp->page = NULL;
333 mp->logical_size = size; 681 mp->logical_size = size;
334 add_to_hash(mp, hash_ptr); 682 mp->data = page_address(page) + page_offset;
335 spin_unlock(&meta_lock); 683 mp->index = lblock;
336 684 if (unlikely(insert_metapage(page, mp))) {
337 if (new) { 685 free_metapage(mp);
338 jfs_info("__get_metapage: Calling grab_cache_page"); 686 goto unlock;
339 mp->page = grab_cache_page(mapping, page_index);
340 if (!mp->page) {
341 jfs_err("grab_cache_page failed!");
342 goto freeit;
343 } else {
344 INCREMENT(mpStat.pagealloc);
345 unlock_page(mp->page);
346 }
347 } else {
348 jfs_info("__get_metapage: Calling read_cache_page");
349 mp->page = read_cache_page(mapping, lblock,
350 (filler_t *)mapping->a_ops->readpage, NULL);
351 if (IS_ERR(mp->page)) {
352 jfs_err("read_cache_page failed!");
353 goto freeit;
354 } else
355 INCREMENT(mpStat.pagealloc);
356 } 687 }
357 mp->data = kmap(mp->page) + page_offset; 688 lock_metapage(mp);
358 } 689 }
359 690
360 if (new) 691 if (new) {
692 jfs_info("zeroing mp = 0x%p", mp);
361 memset(mp->data, 0, PSIZE); 693 memset(mp->data, 0, PSIZE);
694 }
362 695
363 jfs_info("__get_metapage: returning = 0x%p", mp); 696 unlock_page(page);
697 jfs_info("__get_metapage: returning = 0x%p data = 0x%p", mp, mp->data);
364 return mp; 698 return mp;
365 699
366freeit: 700unlock:
367 spin_lock(&meta_lock); 701 unlock_page(page);
368 remove_from_hash(mp, hash_ptr);
369 free_metapage(mp);
370 spin_unlock(&meta_lock);
371 return NULL; 702 return NULL;
372} 703}
373 704
374void hold_metapage(struct metapage * mp, int force) 705void grab_metapage(struct metapage * mp)
375{ 706{
376 spin_lock(&meta_lock); 707 jfs_info("grab_metapage: mp = 0x%p", mp);
377 708 page_cache_get(mp->page);
709 lock_page(mp->page);
378 mp->count++; 710 mp->count++;
379 711 lock_metapage(mp);
380 if (force) { 712 unlock_page(mp->page);
381 ASSERT (!(test_bit(META_forced, &mp->flag)));
382 if (trylock_metapage(mp))
383 set_bit(META_forced, &mp->flag);
384 } else
385 lock_metapage(mp);
386
387 spin_unlock(&meta_lock);
388} 713}
389 714
390static void __write_metapage(struct metapage * mp) 715void force_metapage(struct metapage *mp)
391{ 716{
392 int l2bsize = mp->mapping->host->i_blkbits; 717 struct page *page = mp->page;
393 int l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize; 718 jfs_info("force_metapage: mp = 0x%p", mp);
394 unsigned long page_index; 719 set_bit(META_forcewrite, &mp->flag);
395 unsigned long page_offset; 720 clear_bit(META_sync, &mp->flag);
396 int rc; 721 page_cache_get(page);
397 722 lock_page(page);
398 jfs_info("__write_metapage: mp = 0x%p", mp); 723 set_page_dirty(page);
399 724 write_one_page(page, 1);
400 page_index = mp->page->index; 725 clear_bit(META_forcewrite, &mp->flag);
401 page_offset = 726 page_cache_release(page);
402 (mp->index - (page_index << l2BlocksPerPage)) << l2bsize; 727}
403 728
729extern void hold_metapage(struct metapage *mp)
730{
404 lock_page(mp->page); 731 lock_page(mp->page);
405 rc = mp->mapping->a_ops->prepare_write(NULL, mp->page, page_offset, 732}
406 page_offset + 733
407 mp->logical_size); 734extern void put_metapage(struct metapage *mp)
408 if (rc) { 735{
409 jfs_err("prepare_write return %d!", rc); 736 if (mp->count || mp->nohomeok) {
410 ClearPageUptodate(mp->page); 737 /* Someone else will release this */
411 unlock_page(mp->page); 738 unlock_page(mp->page);
412 clear_bit(META_dirty, &mp->flag);
413 return; 739 return;
414 } 740 }
415 rc = mp->mapping->a_ops->commit_write(NULL, mp->page, page_offset, 741 page_cache_get(mp->page);
416 page_offset + 742 mp->count++;
417 mp->logical_size); 743 lock_metapage(mp);
418 if (rc) {
419 jfs_err("commit_write returned %d", rc);
420 }
421
422 unlock_page(mp->page); 744 unlock_page(mp->page);
423 clear_bit(META_dirty, &mp->flag); 745 release_metapage(mp);
424
425 jfs_info("__write_metapage done");
426}
427
428static inline void sync_metapage(struct metapage *mp)
429{
430 struct page *page = mp->page;
431
432 page_cache_get(page);
433 lock_page(page);
434
435 /* we're done with this page - no need to check for errors */
436 if (page_has_buffers(page))
437 write_one_page(page, 1);
438 else
439 unlock_page(page);
440 page_cache_release(page);
441} 746}
442 747
443void release_metapage(struct metapage * mp) 748void release_metapage(struct metapage * mp)
444{ 749{
445 struct jfs_log *log; 750 struct page *page = mp->page;
446
447 jfs_info("release_metapage: mp = 0x%p, flag = 0x%lx", mp, mp->flag); 751 jfs_info("release_metapage: mp = 0x%p, flag = 0x%lx", mp, mp->flag);
448 752
449 spin_lock(&meta_lock); 753 BUG_ON(!page);
450 if (test_bit(META_forced, &mp->flag)) { 754
451 clear_bit(META_forced, &mp->flag); 755 lock_page(page);
452 mp->count--; 756 unlock_metapage(mp);
453 spin_unlock(&meta_lock);
454 return;
455 }
456 757
457 assert(mp->count); 758 assert(mp->count);
458 if (--mp->count || atomic_read(&mp->nohomeok)) { 759 if (--mp->count || mp->nohomeok) {
459 unlock_metapage(mp); 760 unlock_page(page);
460 spin_unlock(&meta_lock); 761 page_cache_release(page);
461 return; 762 return;
462 } 763 }
463 764
464 if (mp->page) { 765 if (test_bit(META_dirty, &mp->flag)) {
465 set_bit(META_stale, &mp->flag); 766 set_page_dirty(page);
466 spin_unlock(&meta_lock);
467 kunmap(mp->page);
468 mp->data = NULL;
469 if (test_bit(META_dirty, &mp->flag))
470 __write_metapage(mp);
471 if (test_bit(META_sync, &mp->flag)) { 767 if (test_bit(META_sync, &mp->flag)) {
472 sync_metapage(mp);
473 clear_bit(META_sync, &mp->flag); 768 clear_bit(META_sync, &mp->flag);
769 write_one_page(page, 1);
770 lock_page(page); /* write_one_page unlocks the page */
474 } 771 }
772 } else if (mp->lsn) /* discard_metapage doesn't remove it */
773 remove_from_logsync(mp);
475 774
476 if (test_bit(META_discard, &mp->flag)) { 775#if MPS_PER_PAGE == 1
477 lock_page(mp->page); 776 /*
478 block_invalidatepage(mp->page, 0); 777 * If we know this is the only thing in the page, we can throw
479 unlock_page(mp->page); 778 * the page out of the page cache. If pages are larger, we
480 } 779 * don't want to do this.
481 780 */
482 page_cache_release(mp->page);
483 mp->page = NULL;
484 INCREMENT(mpStat.pagefree);
485 spin_lock(&meta_lock);
486 }
487 781
488 if (mp->lsn) { 782 /* Retest mp->count since we may have released page lock */
489 /* 783 if (test_bit(META_discard, &mp->flag) && !mp->count) {
490 * Remove metapage from logsynclist. 784 clear_page_dirty(page);
491 */ 785 ClearPageUptodate(page);
492 log = mp->log; 786#ifdef _NOT_YET
493 LOGSYNC_LOCK(log); 787 if (page->mapping) {
494 mp->log = NULL; 788 /* Remove from page cache and page cache reference */
495 mp->lsn = 0; 789 remove_from_page_cache(page);
496 mp->clsn = 0; 790 page_cache_release(page);
497 log->count--; 791 metapage_releasepage(page, 0);
498 list_del(&mp->synclist); 792 }
499 LOGSYNC_UNLOCK(log); 793#endif
500 } 794 }
501 remove_from_hash(mp, meta_hash(mp->mapping, mp->index)); 795#else
502 spin_unlock(&meta_lock); 796 /* Try to keep metapages from using up too much memory */
503 797 drop_metapage(page, mp);
504 free_metapage(mp); 798#endif
799 unlock_page(page);
800 page_cache_release(page);
505} 801}
506 802
507void __invalidate_metapages(struct inode *ip, s64 addr, int len) 803void __invalidate_metapages(struct inode *ip, s64 addr, int len)
508{ 804{
509 struct metapage **hash_ptr; 805 sector_t lblock;
510 unsigned long lblock;
511 int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits; 806 int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits;
807 int BlocksPerPage = 1 << l2BlocksPerPage;
512 /* All callers are interested in block device's mapping */ 808 /* All callers are interested in block device's mapping */
513 struct address_space *mapping = ip->i_sb->s_bdev->bd_inode->i_mapping; 809 struct address_space *mapping =
810 JFS_SBI(ip->i_sb)->direct_inode->i_mapping;
514 struct metapage *mp; 811 struct metapage *mp;
515 struct page *page; 812 struct page *page;
813 unsigned int offset;
516 814
517 /* 815 /*
518 * First, mark metapages to discard. They will eventually be 816 * Mark metapages to discard. They will eventually be
519 * released, but should not be written. 817 * released, but should not be written.
520 */ 818 */
521 for (lblock = addr; lblock < addr + len; 819 for (lblock = addr & ~(BlocksPerPage - 1); lblock < addr + len;
522 lblock += 1 << l2BlocksPerPage) { 820 lblock += BlocksPerPage) {
523 hash_ptr = meta_hash(mapping, lblock); 821 page = find_lock_page(mapping, lblock >> l2BlocksPerPage);
524again: 822 if (!page)
525 spin_lock(&meta_lock); 823 continue;
526 mp = search_hash(hash_ptr, mapping, lblock); 824 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
527 if (mp) { 825 mp = page_to_mp(page, offset);
528 if (test_bit(META_stale, &mp->flag)) { 826 if (!mp)
529 spin_unlock(&meta_lock); 827 continue;
530 msleep(1); 828 if (mp->index < addr)
531 goto again; 829 continue;
532 } 830 if (mp->index >= addr + len)
831 break;
533 832
534 clear_bit(META_dirty, &mp->flag); 833 clear_bit(META_dirty, &mp->flag);
535 set_bit(META_discard, &mp->flag); 834 set_bit(META_discard, &mp->flag);
536 spin_unlock(&meta_lock); 835 if (mp->lsn)
537 } else { 836 remove_from_logsync(mp);
538 spin_unlock(&meta_lock);
539 page = find_lock_page(mapping, lblock>>l2BlocksPerPage);
540 if (page) {
541 block_invalidatepage(page, 0);
542 unlock_page(page);
543 page_cache_release(page);
544 }
545 } 837 }
838 unlock_page(page);
839 page_cache_release(page);
546 } 840 }
547} 841}
548 842
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index 0e58aba58c37..991e9fb84c75 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -33,38 +33,27 @@ struct metapage {
33 unsigned long flag; /* See Below */ 33 unsigned long flag; /* See Below */
34 unsigned long count; /* Reference count */ 34 unsigned long count; /* Reference count */
35 void *data; /* Data pointer */ 35 void *data; /* Data pointer */
36 36 sector_t index; /* block address of page */
37 /* list management stuff */
38 struct metapage *hash_prev;
39 struct metapage *hash_next; /* Also used for free list */
40
41 /*
42 * mapping & index become redundant, but we need these here to
43 * add the metapage to the hash before we have the real page
44 */
45 struct address_space *mapping;
46 unsigned long index;
47 wait_queue_head_t wait; 37 wait_queue_head_t wait;
48 38
49 /* implementation */ 39 /* implementation */
50 struct page *page; 40 struct page *page;
51 unsigned long logical_size; 41 unsigned int logical_size;
52 42
53 /* Journal management */ 43 /* Journal management */
54 int clsn; 44 int clsn;
55 atomic_t nohomeok; 45 int nohomeok;
56 struct jfs_log *log; 46 struct jfs_log *log;
57}; 47};
58 48
59/* metapage flag */ 49/* metapage flag */
60#define META_locked 0 50#define META_locked 0
61#define META_absolute 1 51#define META_free 1
62#define META_free 2 52#define META_dirty 2
63#define META_dirty 3 53#define META_sync 3
64#define META_sync 4 54#define META_discard 4
65#define META_discard 5 55#define META_forcewrite 5
66#define META_forced 6 56#define META_io 6
67#define META_stale 7
68 57
69#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag) 58#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
70 59
@@ -80,7 +69,16 @@ extern struct metapage *__get_metapage(struct inode *inode,
80 __get_metapage(inode, lblock, size, absolute, TRUE) 69 __get_metapage(inode, lblock, size, absolute, TRUE)
81 70
82extern void release_metapage(struct metapage *); 71extern void release_metapage(struct metapage *);
83extern void hold_metapage(struct metapage *, int); 72extern void grab_metapage(struct metapage *);
73extern void force_metapage(struct metapage *);
74
75/*
76 * hold_metapage and put_metapage are used in conjuction. The page lock
77 * is not dropped between the two, so no other threads can get or release
78 * the metapage
79 */
80extern void hold_metapage(struct metapage *);
81extern void put_metapage(struct metapage *);
84 82
85static inline void write_metapage(struct metapage *mp) 83static inline void write_metapage(struct metapage *mp)
86{ 84{
@@ -101,6 +99,46 @@ static inline void discard_metapage(struct metapage *mp)
101 release_metapage(mp); 99 release_metapage(mp);
102} 100}
103 101
102static inline void metapage_nohomeok(struct metapage *mp)
103{
104 struct page *page = mp->page;
105 lock_page(page);
106 if (!mp->nohomeok++) {
107 mark_metapage_dirty(mp);
108 page_cache_get(page);
109 wait_on_page_writeback(page);
110 }
111 unlock_page(page);
112}
113
114/*
115 * This serializes access to mp->lsn when metapages are added to logsynclist
116 * without setting nohomeok. i.e. updating imap & dmap
117 */
118static inline void metapage_wait_for_io(struct metapage *mp)
119{
120 if (test_bit(META_io, &mp->flag))
121 wait_on_page_writeback(mp->page);
122}
123
124/*
125 * This is called when already holding the metapage
126 */
127static inline void _metapage_homeok(struct metapage *mp)
128{
129 if (!--mp->nohomeok)
130 page_cache_release(mp->page);
131}
132
133static inline void metapage_homeok(struct metapage *mp)
134{
135 hold_metapage(mp);
136 _metapage_homeok(mp);
137 put_metapage(mp);
138}
139
140extern struct address_space_operations jfs_metapage_aops;
141
104/* 142/*
105 * This routines invalidate all pages for an extent. 143 * This routines invalidate all pages for an extent.
106 */ 144 */
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index c535ffd638e8..032d111bc330 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -285,11 +285,6 @@ int jfs_mount_rw(struct super_block *sb, int remount)
285 */ 285 */
286 logMOUNT(sb); 286 logMOUNT(sb);
287 287
288 /*
289 * Set page cache allocation policy
290 */
291 mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);
292
293 return rc; 288 return rc;
294} 289}
295 290
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index f40301d93f74..e93d01aa12c4 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -227,6 +227,7 @@ static lid_t txLockAlloc(void)
227 227
228static void txLockFree(lid_t lid) 228static void txLockFree(lid_t lid)
229{ 229{
230 TxLock[lid].tid = 0;
230 TxLock[lid].next = TxAnchor.freelock; 231 TxLock[lid].next = TxAnchor.freelock;
231 TxAnchor.freelock = lid; 232 TxAnchor.freelock = lid;
232 TxAnchor.tlocksInUse--; 233 TxAnchor.tlocksInUse--;
@@ -566,9 +567,6 @@ void txEnd(tid_t tid)
566 * synchronize with logsync barrier 567 * synchronize with logsync barrier
567 */ 568 */
568 if (test_bit(log_SYNCBARRIER, &log->flag)) { 569 if (test_bit(log_SYNCBARRIER, &log->flag)) {
569 /* forward log syncpt */
570 /* lmSync(log); */
571
572 jfs_info("log barrier off: 0x%x", log->lsn); 570 jfs_info("log barrier off: 0x%x", log->lsn);
573 571
574 /* enable new transactions start */ 572 /* enable new transactions start */
@@ -576,15 +574,22 @@ void txEnd(tid_t tid)
576 574
577 /* wakeup all waitors for logsync barrier */ 575 /* wakeup all waitors for logsync barrier */
578 TXN_WAKEUP(&log->syncwait); 576 TXN_WAKEUP(&log->syncwait);
577
578 TXN_UNLOCK();
579
580 /* forward log syncpt */
581 jfs_syncpt(log);
582
583 goto wakeup;
579 } 584 }
580 } 585 }
581 586
587 TXN_UNLOCK();
588wakeup:
582 /* 589 /*
583 * wakeup all waitors for a free tblock 590 * wakeup all waitors for a free tblock
584 */ 591 */
585 TXN_WAKEUP(&TxAnchor.freewait); 592 TXN_WAKEUP(&TxAnchor.freewait);
586
587 TXN_UNLOCK();
588} 593}
589 594
590 595
@@ -633,8 +638,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
633 638
634 /* is page locked by the requester transaction ? */ 639 /* is page locked by the requester transaction ? */
635 tlck = lid_to_tlock(lid); 640 tlck = lid_to_tlock(lid);
636 if ((xtid = tlck->tid) == tid) 641 if ((xtid = tlck->tid) == tid) {
642 TXN_UNLOCK();
637 goto grantLock; 643 goto grantLock;
644 }
638 645
639 /* 646 /*
640 * is page locked by anonymous transaction/lock ? 647 * is page locked by anonymous transaction/lock ?
@@ -649,6 +656,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
649 */ 656 */
650 if (xtid == 0) { 657 if (xtid == 0) {
651 tlck->tid = tid; 658 tlck->tid = tid;
659 TXN_UNLOCK();
652 tblk = tid_to_tblock(tid); 660 tblk = tid_to_tblock(tid);
653 /* 661 /*
654 * The order of the tlocks in the transaction is important 662 * The order of the tlocks in the transaction is important
@@ -706,17 +714,18 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
706 */ 714 */
707 tlck->tid = tid; 715 tlck->tid = tid;
708 716
717 TXN_UNLOCK();
718
709 /* mark tlock for meta-data page */ 719 /* mark tlock for meta-data page */
710 if (mp->xflag & COMMIT_PAGE) { 720 if (mp->xflag & COMMIT_PAGE) {
711 721
712 tlck->flag = tlckPAGELOCK; 722 tlck->flag = tlckPAGELOCK;
713 723
714 /* mark the page dirty and nohomeok */ 724 /* mark the page dirty and nohomeok */
715 mark_metapage_dirty(mp); 725 metapage_nohomeok(mp);
716 atomic_inc(&mp->nohomeok);
717 726
718 jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p", 727 jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",
719 mp, atomic_read(&mp->nohomeok), tid, tlck); 728 mp, mp->nohomeok, tid, tlck);
720 729
721 /* if anonymous transaction, and buffer is on the group 730 /* if anonymous transaction, and buffer is on the group
722 * commit synclist, mark inode to show this. This will 731 * commit synclist, mark inode to show this. This will
@@ -762,8 +771,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
762 if (tlck->next == 0) { 771 if (tlck->next == 0) {
763 /* This inode's first anonymous transaction */ 772 /* This inode's first anonymous transaction */
764 jfs_ip->atltail = lid; 773 jfs_ip->atltail = lid;
774 TXN_LOCK();
765 list_add_tail(&jfs_ip->anon_inode_list, 775 list_add_tail(&jfs_ip->anon_inode_list,
766 &TxAnchor.anon_list); 776 &TxAnchor.anon_list);
777 TXN_UNLOCK();
767 } 778 }
768 } 779 }
769 780
@@ -821,8 +832,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
821 grantLock: 832 grantLock:
822 tlck->type |= type; 833 tlck->type |= type;
823 834
824 TXN_UNLOCK();
825
826 return tlck; 835 return tlck;
827 836
828 /* 837 /*
@@ -841,11 +850,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
841 BUG(); 850 BUG();
842 } 851 }
843 INCREMENT(stattx.waitlock); /* statistics */ 852 INCREMENT(stattx.waitlock); /* statistics */
853 TXN_UNLOCK();
844 release_metapage(mp); 854 release_metapage(mp);
855 TXN_LOCK();
856 xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */
845 857
846 jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d", 858 jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
847 tid, xtid, lid); 859 tid, xtid, lid);
848 TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor); 860
861 /* Recheck everything since dropping TXN_LOCK */
862 if (xtid && (tlck->mp == mp) && (mp->lid == lid))
863 TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
864 else
865 TXN_UNLOCK();
849 jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid); 866 jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid);
850 867
851 return NULL; 868 return NULL;
@@ -906,6 +923,7 @@ static void txUnlock(struct tblock * tblk)
906 struct metapage *mp; 923 struct metapage *mp;
907 struct jfs_log *log; 924 struct jfs_log *log;
908 int difft, diffp; 925 int difft, diffp;
926 unsigned long flags;
909 927
910 jfs_info("txUnlock: tblk = 0x%p", tblk); 928 jfs_info("txUnlock: tblk = 0x%p", tblk);
911 log = JFS_SBI(tblk->sb)->log; 929 log = JFS_SBI(tblk->sb)->log;
@@ -925,19 +943,14 @@ static void txUnlock(struct tblock * tblk)
925 assert(mp->xflag & COMMIT_PAGE); 943 assert(mp->xflag & COMMIT_PAGE);
926 944
927 /* hold buffer 945 /* hold buffer
928 *
929 * It's possible that someone else has the metapage.
930 * The only things were changing are nohomeok, which
931 * is handled atomically, and clsn which is protected
932 * by the LOGSYNC_LOCK.
933 */ 946 */
934 hold_metapage(mp, 1); 947 hold_metapage(mp);
935 948
936 assert(atomic_read(&mp->nohomeok) > 0); 949 assert(mp->nohomeok > 0);
937 atomic_dec(&mp->nohomeok); 950 _metapage_homeok(mp);
938 951
939 /* inherit younger/larger clsn */ 952 /* inherit younger/larger clsn */
940 LOGSYNC_LOCK(log); 953 LOGSYNC_LOCK(log, flags);
941 if (mp->clsn) { 954 if (mp->clsn) {
942 logdiff(difft, tblk->clsn, log); 955 logdiff(difft, tblk->clsn, log);
943 logdiff(diffp, mp->clsn, log); 956 logdiff(diffp, mp->clsn, log);
@@ -945,16 +958,11 @@ static void txUnlock(struct tblock * tblk)
945 mp->clsn = tblk->clsn; 958 mp->clsn = tblk->clsn;
946 } else 959 } else
947 mp->clsn = tblk->clsn; 960 mp->clsn = tblk->clsn;
948 LOGSYNC_UNLOCK(log); 961 LOGSYNC_UNLOCK(log, flags);
949 962
950 assert(!(tlck->flag & tlckFREEPAGE)); 963 assert(!(tlck->flag & tlckFREEPAGE));
951 964
952 if (tlck->flag & tlckWRITEPAGE) { 965 put_metapage(mp);
953 write_metapage(mp);
954 } else {
955 /* release page which has been forced */
956 release_metapage(mp);
957 }
958 } 966 }
959 967
960 /* insert tlock, and linelock(s) of the tlock if any, 968 /* insert tlock, and linelock(s) of the tlock if any,
@@ -981,10 +989,10 @@ static void txUnlock(struct tblock * tblk)
981 * has been inserted in logsync list at txUpdateMap()) 989 * has been inserted in logsync list at txUpdateMap())
982 */ 990 */
983 if (tblk->lsn) { 991 if (tblk->lsn) {
984 LOGSYNC_LOCK(log); 992 LOGSYNC_LOCK(log, flags);
985 log->count--; 993 log->count--;
986 list_del(&tblk->synclist); 994 list_del(&tblk->synclist);
987 LOGSYNC_UNLOCK(log); 995 LOGSYNC_UNLOCK(log, flags);
988 } 996 }
989} 997}
990 998
@@ -1573,8 +1581,8 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1573 * the last entry, so don't bother logging this 1581 * the last entry, so don't bother logging this
1574 */ 1582 */
1575 mp->lid = 0; 1583 mp->lid = 0;
1576 hold_metapage(mp, 0); 1584 grab_metapage(mp);
1577 atomic_dec(&mp->nohomeok); 1585 metapage_homeok(mp);
1578 discard_metapage(mp); 1586 discard_metapage(mp);
1579 tlck->mp = NULL; 1587 tlck->mp = NULL;
1580 return 0; 1588 return 0;
@@ -1712,7 +1720,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1712 struct maplock *maplock; 1720 struct maplock *maplock;
1713 struct xdlistlock *xadlock; 1721 struct xdlistlock *xadlock;
1714 struct pxd_lock *pxdlock; 1722 struct pxd_lock *pxdlock;
1715 pxd_t *pxd; 1723 pxd_t *page_pxd;
1716 int next, lwm, hwm; 1724 int next, lwm, hwm;
1717 1725
1718 ip = tlck->ip; 1726 ip = tlck->ip;
@@ -1722,7 +1730,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1722 lrd->log.redopage.type = cpu_to_le16(LOG_XTREE); 1730 lrd->log.redopage.type = cpu_to_le16(LOG_XTREE);
1723 lrd->log.redopage.l2linesize = cpu_to_le16(L2XTSLOTSIZE); 1731 lrd->log.redopage.l2linesize = cpu_to_le16(L2XTSLOTSIZE);
1724 1732
1725 pxd = &lrd->log.redopage.pxd; 1733 page_pxd = &lrd->log.redopage.pxd;
1726 1734
1727 if (tlck->type & tlckBTROOT) { 1735 if (tlck->type & tlckBTROOT) {
1728 lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT); 1736 lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
@@ -1752,9 +1760,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1752 * applying the after-image to the meta-data page. 1760 * applying the after-image to the meta-data page.
1753 */ 1761 */
1754 lrd->type = cpu_to_le16(LOG_REDOPAGE); 1762 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1755// *pxd = mp->cm_pxd; 1763// *page_pxd = mp->cm_pxd;
1756 PXDaddress(pxd, mp->index); 1764 PXDaddress(page_pxd, mp->index);
1757 PXDlength(pxd, 1765 PXDlength(page_pxd,
1758 mp->logical_size >> tblk->sb->s_blocksize_bits); 1766 mp->logical_size >> tblk->sb->s_blocksize_bits);
1759 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck)); 1767 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1760 1768
@@ -1776,25 +1784,31 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1776 tlck->flag |= tlckUPDATEMAP; 1784 tlck->flag |= tlckUPDATEMAP;
1777 xadlock->flag = mlckALLOCXADLIST; 1785 xadlock->flag = mlckALLOCXADLIST;
1778 xadlock->count = next - lwm; 1786 xadlock->count = next - lwm;
1779 if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) { 1787 if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
1780 int i; 1788 int i;
1789 pxd_t *pxd;
1781 /* 1790 /*
1782 * Lazy commit may allow xtree to be modified before 1791 * Lazy commit may allow xtree to be modified before
1783 * txUpdateMap runs. Copy xad into linelock to 1792 * txUpdateMap runs. Copy xad into linelock to
1784 * preserve correct data. 1793 * preserve correct data.
1794 *
1795 * We can fit twice as may pxd's as xads in the lock
1785 */ 1796 */
1786 xadlock->xdlist = &xtlck->pxdlock; 1797 xadlock->flag = mlckALLOCPXDLIST;
1787 memcpy(xadlock->xdlist, &p->xad[lwm], 1798 pxd = xadlock->xdlist = &xtlck->pxdlock;
1788 sizeof(xad_t) * xadlock->count); 1799 for (i = 0; i < xadlock->count; i++) {
1789 1800 PXDaddress(pxd, addressXAD(&p->xad[lwm + i]));
1790 for (i = 0; i < xadlock->count; i++) 1801 PXDlength(pxd, lengthXAD(&p->xad[lwm + i]));
1791 p->xad[lwm + i].flag &= 1802 p->xad[lwm + i].flag &=
1792 ~(XAD_NEW | XAD_EXTENDED); 1803 ~(XAD_NEW | XAD_EXTENDED);
1804 pxd++;
1805 }
1793 } else { 1806 } else {
1794 /* 1807 /*
1795 * xdlist will point to into inode's xtree, ensure 1808 * xdlist will point to into inode's xtree, ensure
1796 * that transaction is not committed lazily. 1809 * that transaction is not committed lazily.
1797 */ 1810 */
1811 xadlock->flag = mlckALLOCXADLIST;
1798 xadlock->xdlist = &p->xad[lwm]; 1812 xadlock->xdlist = &p->xad[lwm];
1799 tblk->xflag &= ~COMMIT_LAZY; 1813 tblk->xflag &= ~COMMIT_LAZY;
1800 } 1814 }
@@ -1836,8 +1850,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1836 if (tblk->xflag & COMMIT_TRUNCATE) { 1850 if (tblk->xflag & COMMIT_TRUNCATE) {
1837 /* write NOREDOPAGE for the page */ 1851 /* write NOREDOPAGE for the page */
1838 lrd->type = cpu_to_le16(LOG_NOREDOPAGE); 1852 lrd->type = cpu_to_le16(LOG_NOREDOPAGE);
1839 PXDaddress(pxd, mp->index); 1853 PXDaddress(page_pxd, mp->index);
1840 PXDlength(pxd, 1854 PXDlength(page_pxd,
1841 mp->logical_size >> tblk->sb-> 1855 mp->logical_size >> tblk->sb->
1842 s_blocksize_bits); 1856 s_blocksize_bits);
1843 lrd->backchain = 1857 lrd->backchain =
@@ -1872,22 +1886,32 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1872 * deleted page itself; 1886 * deleted page itself;
1873 */ 1887 */
1874 tlck->flag |= tlckUPDATEMAP; 1888 tlck->flag |= tlckUPDATEMAP;
1875 xadlock->flag = mlckFREEXADLIST;
1876 xadlock->count = hwm - XTENTRYSTART + 1; 1889 xadlock->count = hwm - XTENTRYSTART + 1;
1877 if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) { 1890 if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
1891 int i;
1892 pxd_t *pxd;
1878 /* 1893 /*
1879 * Lazy commit may allow xtree to be modified before 1894 * Lazy commit may allow xtree to be modified before
1880 * txUpdateMap runs. Copy xad into linelock to 1895 * txUpdateMap runs. Copy xad into linelock to
1881 * preserve correct data. 1896 * preserve correct data.
1897 *
1898 * We can fit twice as may pxd's as xads in the lock
1882 */ 1899 */
1883 xadlock->xdlist = &xtlck->pxdlock; 1900 xadlock->flag = mlckFREEPXDLIST;
1884 memcpy(xadlock->xdlist, &p->xad[XTENTRYSTART], 1901 pxd = xadlock->xdlist = &xtlck->pxdlock;
1885 sizeof(xad_t) * xadlock->count); 1902 for (i = 0; i < xadlock->count; i++) {
1903 PXDaddress(pxd,
1904 addressXAD(&p->xad[XTENTRYSTART + i]));
1905 PXDlength(pxd,
1906 lengthXAD(&p->xad[XTENTRYSTART + i]));
1907 pxd++;
1908 }
1886 } else { 1909 } else {
1887 /* 1910 /*
1888 * xdlist will point to into inode's xtree, ensure 1911 * xdlist will point to into inode's xtree, ensure
1889 * that transaction is not committed lazily. 1912 * that transaction is not committed lazily.
1890 */ 1913 */
1914 xadlock->flag = mlckFREEXADLIST;
1891 xadlock->xdlist = &p->xad[XTENTRYSTART]; 1915 xadlock->xdlist = &p->xad[XTENTRYSTART];
1892 tblk->xflag &= ~COMMIT_LAZY; 1916 tblk->xflag &= ~COMMIT_LAZY;
1893 } 1917 }
@@ -1918,7 +1942,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1918 * header ? 1942 * header ?
1919 */ 1943 */
1920 if (tlck->type & tlckTRUNCATE) { 1944 if (tlck->type & tlckTRUNCATE) {
1921 pxd_t tpxd; /* truncated extent of xad */ 1945 pxd_t pxd; /* truncated extent of xad */
1922 int twm; 1946 int twm;
1923 1947
1924 /* 1948 /*
@@ -1947,8 +1971,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1947 * applying the after-image to the meta-data page. 1971 * applying the after-image to the meta-data page.
1948 */ 1972 */
1949 lrd->type = cpu_to_le16(LOG_REDOPAGE); 1973 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1950 PXDaddress(pxd, mp->index); 1974 PXDaddress(page_pxd, mp->index);
1951 PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits); 1975 PXDlength(page_pxd,
1976 mp->logical_size >> tblk->sb->s_blocksize_bits);
1952 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck)); 1977 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1953 1978
1954 /* 1979 /*
@@ -1966,7 +1991,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1966 lrd->log.updatemap.type = cpu_to_le16(LOG_FREEPXD); 1991 lrd->log.updatemap.type = cpu_to_le16(LOG_FREEPXD);
1967 lrd->log.updatemap.nxd = cpu_to_le16(1); 1992 lrd->log.updatemap.nxd = cpu_to_le16(1);
1968 lrd->log.updatemap.pxd = pxdlock->pxd; 1993 lrd->log.updatemap.pxd = pxdlock->pxd;
1969 tpxd = pxdlock->pxd; /* save to format maplock */ 1994 pxd = pxdlock->pxd; /* save to format maplock */
1970 lrd->backchain = 1995 lrd->backchain =
1971 cpu_to_le32(lmLog(log, tblk, lrd, NULL)); 1996 cpu_to_le32(lmLog(log, tblk, lrd, NULL));
1972 } 1997 }
@@ -2035,7 +2060,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
2035 pxdlock = (struct pxd_lock *) xadlock; 2060 pxdlock = (struct pxd_lock *) xadlock;
2036 pxdlock->flag = mlckFREEPXD; 2061 pxdlock->flag = mlckFREEPXD;
2037 pxdlock->count = 1; 2062 pxdlock->count = 1;
2038 pxdlock->pxd = tpxd; 2063 pxdlock->pxd = pxd;
2039 2064
2040 jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d " 2065 jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d "
2041 "hwm:%d", ip, mp, pxdlock->count, hwm); 2066 "hwm:%d", ip, mp, pxdlock->count, hwm);
@@ -2253,7 +2278,8 @@ void txForce(struct tblock * tblk)
2253 tlck->flag &= ~tlckWRITEPAGE; 2278 tlck->flag &= ~tlckWRITEPAGE;
2254 2279
2255 /* do not release page to freelist */ 2280 /* do not release page to freelist */
2256 2281 force_metapage(mp);
2282#if 0
2257 /* 2283 /*
2258 * The "right" thing to do here is to 2284 * The "right" thing to do here is to
2259 * synchronously write the metadata. 2285 * synchronously write the metadata.
@@ -2265,9 +2291,10 @@ void txForce(struct tblock * tblk)
2265 * we can get by with synchronously writing 2291 * we can get by with synchronously writing
2266 * the pages when they are released. 2292 * the pages when they are released.
2267 */ 2293 */
2268 assert(atomic_read(&mp->nohomeok)); 2294 assert(mp->nohomeok);
2269 set_bit(META_dirty, &mp->flag); 2295 set_bit(META_dirty, &mp->flag);
2270 set_bit(META_sync, &mp->flag); 2296 set_bit(META_sync, &mp->flag);
2297#endif
2271 } 2298 }
2272 } 2299 }
2273 } 2300 }
@@ -2327,7 +2354,7 @@ static void txUpdateMap(struct tblock * tblk)
2327 */ 2354 */
2328 mp = tlck->mp; 2355 mp = tlck->mp;
2329 ASSERT(mp->xflag & COMMIT_PAGE); 2356 ASSERT(mp->xflag & COMMIT_PAGE);
2330 hold_metapage(mp, 0); 2357 grab_metapage(mp);
2331 } 2358 }
2332 2359
2333 /* 2360 /*
@@ -2377,8 +2404,8 @@ static void txUpdateMap(struct tblock * tblk)
2377 ASSERT(mp->lid == lid); 2404 ASSERT(mp->lid == lid);
2378 tlck->mp->lid = 0; 2405 tlck->mp->lid = 0;
2379 } 2406 }
2380 assert(atomic_read(&mp->nohomeok) == 1); 2407 assert(mp->nohomeok == 1);
2381 atomic_dec(&mp->nohomeok); 2408 metapage_homeok(mp);
2382 discard_metapage(mp); 2409 discard_metapage(mp);
2383 tlck->mp = NULL; 2410 tlck->mp = NULL;
2384 } 2411 }
@@ -2844,24 +2871,9 @@ static void LogSyncRelease(struct metapage * mp)
2844{ 2871{
2845 struct jfs_log *log = mp->log; 2872 struct jfs_log *log = mp->log;
2846 2873
2847 assert(atomic_read(&mp->nohomeok)); 2874 assert(mp->nohomeok);
2848 assert(log); 2875 assert(log);
2849 atomic_dec(&mp->nohomeok); 2876 metapage_homeok(mp);
2850
2851 if (atomic_read(&mp->nohomeok))
2852 return;
2853
2854 hold_metapage(mp, 0);
2855
2856 LOGSYNC_LOCK(log);
2857 mp->log = NULL;
2858 mp->lsn = 0;
2859 mp->clsn = 0;
2860 log->count--;
2861 list_del_init(&mp->synclist);
2862 LOGSYNC_UNLOCK(log);
2863
2864 release_metapage(mp);
2865} 2877}
2866 2878
2867/* 2879/*
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index f31a9e3f3fec..5cf91785b541 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -49,7 +49,6 @@
49 */ 49 */
50int jfs_umount(struct super_block *sb) 50int jfs_umount(struct super_block *sb)
51{ 51{
52 struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
53 struct jfs_sb_info *sbi = JFS_SBI(sb); 52 struct jfs_sb_info *sbi = JFS_SBI(sb);
54 struct inode *ipbmap = sbi->ipbmap; 53 struct inode *ipbmap = sbi->ipbmap;
55 struct inode *ipimap = sbi->ipimap; 54 struct inode *ipimap = sbi->ipimap;
@@ -109,8 +108,8 @@ int jfs_umount(struct super_block *sb)
109 * Make sure all metadata makes it to disk before we mark 108 * Make sure all metadata makes it to disk before we mark
110 * the superblock as clean 109 * the superblock as clean
111 */ 110 */
112 filemap_fdatawrite(bdev_mapping); 111 filemap_fdatawrite(sbi->direct_inode->i_mapping);
113 filemap_fdatawait(bdev_mapping); 112 filemap_fdatawait(sbi->direct_inode->i_mapping);
114 113
115 /* 114 /*
116 * ensure all file system file pages are propagated to their 115 * ensure all file system file pages are propagated to their
@@ -123,9 +122,6 @@ int jfs_umount(struct super_block *sb)
123 if (log) { /* log = NULL if read-only mount */ 122 if (log) { /* log = NULL if read-only mount */
124 updateSuper(sb, FM_CLEAN); 123 updateSuper(sb, FM_CLEAN);
125 124
126 /* Restore default gfp_mask for bdev */
127 mapping_set_gfp_mask(bdev_mapping, GFP_USER);
128
129 /* 125 /*
130 * close log: 126 * close log:
131 * 127 *
@@ -140,7 +136,6 @@ int jfs_umount(struct super_block *sb)
140 136
141int jfs_umount_rw(struct super_block *sb) 137int jfs_umount_rw(struct super_block *sb)
142{ 138{
143 struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
144 struct jfs_sb_info *sbi = JFS_SBI(sb); 139 struct jfs_sb_info *sbi = JFS_SBI(sb);
145 struct jfs_log *log = sbi->log; 140 struct jfs_log *log = sbi->log;
146 141
@@ -166,13 +161,10 @@ int jfs_umount_rw(struct super_block *sb)
166 * mark the superblock clean before everything is flushed to 161 * mark the superblock clean before everything is flushed to
167 * disk. 162 * disk.
168 */ 163 */
169 filemap_fdatawrite(bdev_mapping); 164 filemap_fdatawrite(sbi->direct_inode->i_mapping);
170 filemap_fdatawait(bdev_mapping); 165 filemap_fdatawait(sbi->direct_inode->i_mapping);
171 166
172 updateSuper(sb, FM_CLEAN); 167 updateSuper(sb, FM_CLEAN);
173 168
174 /* Restore default gfp_mask for bdev */
175 mapping_set_gfp_mask(bdev_mapping, GFP_USER);
176
177 return lmLogClose(sb); 169 return lmLogClose(sb);
178} 170}
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index 11c58c54b818..2c1f311914a1 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -111,8 +111,8 @@ static struct {
111/* 111/*
112 * forward references 112 * forward references
113 */ 113 */
114static int xtSearch(struct inode *ip, 114static int xtSearch(struct inode *ip, s64 xoff, s64 *next, int *cmpp,
115 s64 xoff, int *cmpp, struct btstack * btstack, int flag); 115 struct btstack * btstack, int flag);
116 116
117static int xtSplitUp(tid_t tid, 117static int xtSplitUp(tid_t tid,
118 struct inode *ip, 118 struct inode *ip,
@@ -159,11 +159,12 @@ int xtLookup(struct inode *ip, s64 lstart,
159 xtpage_t *p; 159 xtpage_t *p;
160 int index; 160 int index;
161 xad_t *xad; 161 xad_t *xad;
162 s64 size, xoff, xend; 162 s64 next, size, xoff, xend;
163 int xlen; 163 int xlen;
164 s64 xaddr; 164 s64 xaddr;
165 165
166 *plen = 0; 166 *paddr = 0;
167 *plen = llen;
167 168
168 if (!no_check) { 169 if (!no_check) {
169 /* is lookup offset beyond eof ? */ 170 /* is lookup offset beyond eof ? */
@@ -180,7 +181,7 @@ int xtLookup(struct inode *ip, s64 lstart,
180 * search for the xad entry covering the logical extent 181 * search for the xad entry covering the logical extent
181 */ 182 */
182//search: 183//search:
183 if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) { 184 if ((rc = xtSearch(ip, lstart, &next, &cmp, &btstack, 0))) {
184 jfs_err("xtLookup: xtSearch returned %d", rc); 185 jfs_err("xtLookup: xtSearch returned %d", rc);
185 return rc; 186 return rc;
186 } 187 }
@@ -198,8 +199,11 @@ int xtLookup(struct inode *ip, s64 lstart,
198 * lstart is a page start address, 199 * lstart is a page start address,
199 * i.e., lstart cannot start in a hole; 200 * i.e., lstart cannot start in a hole;
200 */ 201 */
201 if (cmp) 202 if (cmp) {
203 if (next)
204 *plen = min(next - lstart, llen);
202 goto out; 205 goto out;
206 }
203 207
204 /* 208 /*
205 * lxd covered by xad 209 * lxd covered by xad
@@ -284,7 +288,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
284 if (lstart >= size) 288 if (lstart >= size)
285 return 0; 289 return 0;
286 290
287 if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) 291 if ((rc = xtSearch(ip, lstart, NULL, &cmp, &btstack, 0)))
288 return rc; 292 return rc;
289 293
290 /* 294 /*
@@ -488,6 +492,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
488 * parameters: 492 * parameters:
489 * ip - file object; 493 * ip - file object;
490 * xoff - extent offset; 494 * xoff - extent offset;
495 * nextp - address of next extent (if any) for search miss
491 * cmpp - comparison result: 496 * cmpp - comparison result:
492 * btstack - traverse stack; 497 * btstack - traverse stack;
493 * flag - search process flag (XT_INSERT); 498 * flag - search process flag (XT_INSERT);
@@ -497,7 +502,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
497 * *cmpp is set to result of comparison with the entry returned. 502 * *cmpp is set to result of comparison with the entry returned.
498 * the page containing the entry is pinned at exit. 503 * the page containing the entry is pinned at exit.
499 */ 504 */
500static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ 505static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
501 int *cmpp, struct btstack * btstack, int flag) 506 int *cmpp, struct btstack * btstack, int flag)
502{ 507{
503 struct jfs_inode_info *jfs_ip = JFS_IP(ip); 508 struct jfs_inode_info *jfs_ip = JFS_IP(ip);
@@ -511,6 +516,7 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */
511 struct btframe *btsp; 516 struct btframe *btsp;
512 int nsplit = 0; /* number of pages to split */ 517 int nsplit = 0; /* number of pages to split */
513 s64 t64; 518 s64 t64;
519 s64 next = 0;
514 520
515 INCREMENT(xtStat.search); 521 INCREMENT(xtStat.search);
516 522
@@ -579,6 +585,7 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */
579 * previous and this entry 585 * previous and this entry
580 */ 586 */
581 *cmpp = 1; 587 *cmpp = 1;
588 next = t64;
582 goto out; 589 goto out;
583 } 590 }
584 591
@@ -623,6 +630,9 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */
623 /* update sequential access heuristics */ 630 /* update sequential access heuristics */
624 jfs_ip->btindex = index; 631 jfs_ip->btindex = index;
625 632
633 if (nextp)
634 *nextp = next;
635
626 INCREMENT(xtStat.fastSearch); 636 INCREMENT(xtStat.fastSearch);
627 return 0; 637 return 0;
628 } 638 }
@@ -675,10 +685,11 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */
675 685
676 return 0; 686 return 0;
677 } 687 }
678
679 /* search hit - internal page: 688 /* search hit - internal page:
680 * descend/search its child page 689 * descend/search its child page
681 */ 690 */
691 if (index < p->header.nextindex - 1)
692 next = offsetXAD(&p->xad[index + 1]);
682 goto next; 693 goto next;
683 } 694 }
684 695
@@ -694,6 +705,8 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */
694 * base is the smallest index with key (Kj) greater than 705 * base is the smallest index with key (Kj) greater than
695 * search key (K) and may be zero or maxentry index. 706 * search key (K) and may be zero or maxentry index.
696 */ 707 */
708 if (base < p->header.nextindex)
709 next = offsetXAD(&p->xad[base]);
697 /* 710 /*
698 * search miss - leaf page: 711 * search miss - leaf page:
699 * 712 *
@@ -727,6 +740,9 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */
727 jfs_ip->btorder = BT_RANDOM; 740 jfs_ip->btorder = BT_RANDOM;
728 jfs_ip->btindex = base; 741 jfs_ip->btindex = base;
729 742
743 if (nextp)
744 *nextp = next;
745
730 return 0; 746 return 0;
731 } 747 }
732 748
@@ -793,6 +809,7 @@ int xtInsert(tid_t tid, /* transaction id */
793 struct xtsplit split; /* split information */ 809 struct xtsplit split; /* split information */
794 xad_t *xad; 810 xad_t *xad;
795 int cmp; 811 int cmp;
812 s64 next;
796 struct tlock *tlck; 813 struct tlock *tlck;
797 struct xtlock *xtlck; 814 struct xtlock *xtlck;
798 815
@@ -806,7 +823,7 @@ int xtInsert(tid_t tid, /* transaction id */
806 * n.b. xtSearch() may return index of maxentry of 823 * n.b. xtSearch() may return index of maxentry of
807 * the full page. 824 * the full page.
808 */ 825 */
809 if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) 826 if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
810 return rc; 827 return rc;
811 828
812 /* retrieve search result */ 829 /* retrieve search result */
@@ -814,7 +831,7 @@ int xtInsert(tid_t tid, /* transaction id */
814 831
815 /* This test must follow XT_GETSEARCH since mp must be valid if 832 /* This test must follow XT_GETSEARCH since mp must be valid if
816 * we branch to out: */ 833 * we branch to out: */
817 if (cmp == 0) { 834 if ((cmp == 0) || (next && (xlen > next - xoff))) {
818 rc = -EEXIST; 835 rc = -EEXIST;
819 goto out; 836 goto out;
820 } 837 }
@@ -1626,7 +1643,7 @@ int xtExtend(tid_t tid, /* transaction id */
1626 jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen); 1643 jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
1627 1644
1628 /* there must exist extent to be extended */ 1645 /* there must exist extent to be extended */
1629 if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT))) 1646 if ((rc = xtSearch(ip, xoff - 1, NULL, &cmp, &btstack, XT_INSERT)))
1630 return rc; 1647 return rc;
1631 1648
1632 /* retrieve search result */ 1649 /* retrieve search result */
@@ -1794,7 +1811,7 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
1794*/ 1811*/
1795 1812
1796 /* there must exist extent to be tailgated */ 1813 /* there must exist extent to be tailgated */
1797 if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) 1814 if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, XT_INSERT)))
1798 return rc; 1815 return rc;
1799 1816
1800 /* retrieve search result */ 1817 /* retrieve search result */
@@ -1977,7 +1994,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
1977 nxlen = lengthXAD(nxad); 1994 nxlen = lengthXAD(nxad);
1978 nxaddr = addressXAD(nxad); 1995 nxaddr = addressXAD(nxad);
1979 1996
1980 if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) 1997 if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
1981 return rc; 1998 return rc;
1982 1999
1983 /* retrieve search result */ 2000 /* retrieve search result */
@@ -2291,7 +2308,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
2291 if (nextindex == le16_to_cpu(p->header.maxentry)) { 2308 if (nextindex == le16_to_cpu(p->header.maxentry)) {
2292 XT_PUTPAGE(mp); 2309 XT_PUTPAGE(mp);
2293 2310
2294 if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) 2311 if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
2295 return rc; 2312 return rc;
2296 2313
2297 /* retrieve search result */ 2314 /* retrieve search result */
@@ -2438,6 +2455,7 @@ int xtAppend(tid_t tid, /* transaction id */
2438 int nsplit, nblocks, xlen; 2455 int nsplit, nblocks, xlen;
2439 struct pxdlist pxdlist; 2456 struct pxdlist pxdlist;
2440 pxd_t *pxd; 2457 pxd_t *pxd;
2458 s64 next;
2441 2459
2442 xaddr = *xaddrp; 2460 xaddr = *xaddrp;
2443 xlen = *xlenp; 2461 xlen = *xlenp;
@@ -2452,7 +2470,7 @@ int xtAppend(tid_t tid, /* transaction id */
2452 * n.b. xtSearch() may return index of maxentry of 2470 * n.b. xtSearch() may return index of maxentry of
2453 * the full page. 2471 * the full page.
2454 */ 2472 */
2455 if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) 2473 if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
2456 return rc; 2474 return rc;
2457 2475
2458 /* retrieve search result */ 2476 /* retrieve search result */
@@ -2462,6 +2480,9 @@ int xtAppend(tid_t tid, /* transaction id */
2462 rc = -EEXIST; 2480 rc = -EEXIST;
2463 goto out; 2481 goto out;
2464 } 2482 }
2483
2484 if (next)
2485 xlen = min(xlen, (int)(next - xoff));
2465//insert: 2486//insert:
2466 /* 2487 /*
2467 * insert entry for new extent 2488 * insert entry for new extent
@@ -2600,7 +2621,7 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
2600 /* 2621 /*
2601 * find the matching entry; xtSearch() pins the page 2622 * find the matching entry; xtSearch() pins the page
2602 */ 2623 */
2603 if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0))) 2624 if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
2604 return rc; 2625 return rc;
2605 2626
2606 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index); 2627 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
@@ -2852,7 +2873,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
2852 */ 2873 */
2853 if (xtype == DATAEXT) { 2874 if (xtype == DATAEXT) {
2854 /* search in leaf entry */ 2875 /* search in leaf entry */
2855 rc = xtSearch(ip, xoff, &cmp, &btstack, 0); 2876 rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
2856 if (rc) 2877 if (rc)
2857 return rc; 2878 return rc;
2858 2879
@@ -2958,7 +2979,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
2958 } 2979 }
2959 2980
2960 /* get back parent page */ 2981 /* get back parent page */
2961 if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0))) 2982 if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
2962 return rc; 2983 return rc;
2963 2984
2964 XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); 2985 XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
@@ -3991,7 +4012,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
3991 4012
3992 if (committed_size) { 4013 if (committed_size) {
3993 xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1; 4014 xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1;
3994 rc = xtSearch(ip, xoff, &cmp, &btstack, 0); 4015 rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
3995 if (rc) 4016 if (rc)
3996 return rc; 4017 return rc;
3997 4018
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 2eb6869b6e72..c6dc254d3253 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -209,6 +209,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
209 */ 209 */
210 txQuiesce(sb); 210 txQuiesce(sb);
211 211
212 /* Reset size of direct inode */
213 sbi->direct_inode->i_size = sb->s_bdev->bd_inode->i_size;
214
212 if (sbi->mntflag & JFS_INLINELOG) { 215 if (sbi->mntflag & JFS_INLINELOG) {
213 /* 216 /*
214 * deactivate old inline log 217 * deactivate old inline log
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 5856866e24fc..5e774ed7fb64 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -210,6 +210,10 @@ static void jfs_put_super(struct super_block *sb)
210 unload_nls(sbi->nls_tab); 210 unload_nls(sbi->nls_tab);
211 sbi->nls_tab = NULL; 211 sbi->nls_tab = NULL;
212 212
213 truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
214 iput(sbi->direct_inode);
215 sbi->direct_inode = NULL;
216
213 kfree(sbi); 217 kfree(sbi);
214} 218}
215 219
@@ -358,6 +362,12 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
358 } 362 }
359 363
360 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { 364 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
365 /*
366 * Invalidate any previously read metadata. fsck may have
367 * changed the on-disk data since we mounted r/o
368 */
369 truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0);
370
361 JFS_SBI(sb)->flag = flag; 371 JFS_SBI(sb)->flag = flag;
362 return jfs_mount_rw(sb, 1); 372 return jfs_mount_rw(sb, 1);
363 } 373 }
@@ -428,12 +438,26 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
428 sb->s_op = &jfs_super_operations; 438 sb->s_op = &jfs_super_operations;
429 sb->s_export_op = &jfs_export_operations; 439 sb->s_export_op = &jfs_export_operations;
430 440
441 /*
442 * Initialize direct-mapping inode/address-space
443 */
444 inode = new_inode(sb);
445 if (inode == NULL)
446 goto out_kfree;
447 inode->i_ino = 0;
448 inode->i_nlink = 1;
449 inode->i_size = sb->s_bdev->bd_inode->i_size;
450 inode->i_mapping->a_ops = &jfs_metapage_aops;
451 mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
452
453 sbi->direct_inode = inode;
454
431 rc = jfs_mount(sb); 455 rc = jfs_mount(sb);
432 if (rc) { 456 if (rc) {
433 if (!silent) { 457 if (!silent) {
434 jfs_err("jfs_mount failed w/return code = %d", rc); 458 jfs_err("jfs_mount failed w/return code = %d", rc);
435 } 459 }
436 goto out_kfree; 460 goto out_mount_failed;
437 } 461 }
438 if (sb->s_flags & MS_RDONLY) 462 if (sb->s_flags & MS_RDONLY)
439 sbi->log = NULL; 463 sbi->log = NULL;
@@ -482,6 +506,13 @@ out_no_rw:
482 if (rc) { 506 if (rc) {
483 jfs_err("jfs_umount failed with return code %d", rc); 507 jfs_err("jfs_umount failed with return code %d", rc);
484 } 508 }
509out_mount_failed:
510 filemap_fdatawrite(sbi->direct_inode->i_mapping);
511 filemap_fdatawait(sbi->direct_inode->i_mapping);
512 truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
513 make_bad_inode(sbi->direct_inode);
514 iput(sbi->direct_inode);
515 sbi->direct_inode = NULL;
485out_kfree: 516out_kfree:
486 if (sbi->nls_tab) 517 if (sbi->nls_tab)
487 unload_nls(sbi->nls_tab); 518 unload_nls(sbi->nls_tab);
@@ -527,8 +558,10 @@ static int jfs_sync_fs(struct super_block *sb, int wait)
527 struct jfs_log *log = JFS_SBI(sb)->log; 558 struct jfs_log *log = JFS_SBI(sb)->log;
528 559
529 /* log == NULL indicates read-only mount */ 560 /* log == NULL indicates read-only mount */
530 if (log) 561 if (log) {
531 jfs_flush_journal(log, wait); 562 jfs_flush_journal(log, wait);
563 jfs_syncpt(log);
564 }
532 565
533 return 0; 566 return 0;
534} 567}
diff --git a/fs/mpage.c b/fs/mpage.c
index e7d8d1a77606..32c7c8fcfce7 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -160,52 +160,6 @@ map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block)
160 } while (page_bh != head); 160 } while (page_bh != head);
161} 161}
162 162
163/**
164 * mpage_readpages - populate an address space with some pages, and
165 * start reads against them.
166 *
167 * @mapping: the address_space
168 * @pages: The address of a list_head which contains the target pages. These
169 * pages have their ->index populated and are otherwise uninitialised.
170 *
171 * The page at @pages->prev has the lowest file offset, and reads should be
172 * issued in @pages->prev to @pages->next order.
173 *
174 * @nr_pages: The number of pages at *@pages
175 * @get_block: The filesystem's block mapper function.
176 *
177 * This function walks the pages and the blocks within each page, building and
178 * emitting large BIOs.
179 *
180 * If anything unusual happens, such as:
181 *
182 * - encountering a page which has buffers
183 * - encountering a page which has a non-hole after a hole
184 * - encountering a page with non-contiguous blocks
185 *
186 * then this code just gives up and calls the buffer_head-based read function.
187 * It does handle a page which has holes at the end - that is a common case:
188 * the end-of-file on blocksize < PAGE_CACHE_SIZE setups.
189 *
190 * BH_Boundary explanation:
191 *
192 * There is a problem. The mpage read code assembles several pages, gets all
193 * their disk mappings, and then submits them all. That's fine, but obtaining
194 * the disk mappings may require I/O. Reads of indirect blocks, for example.
195 *
196 * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be
197 * submitted in the following order:
198 * 12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16
199 * because the indirect block has to be read to get the mappings of blocks
200 * 13,14,15,16. Obviously, this impacts performance.
201 *
202 * So what we do it to allow the filesystem's get_block() function to set
203 * BH_Boundary when it maps block 11. BH_Boundary says: mapping of the block
204 * after this one will require I/O against a block which is probably close to
205 * this one. So you should push what I/O you have currently accumulated.
206 *
207 * This all causes the disk requests to be issued in the correct order.
208 */
209static struct bio * 163static struct bio *
210do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, 164do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
211 sector_t *last_block_in_bio, get_block_t get_block) 165 sector_t *last_block_in_bio, get_block_t get_block)
@@ -320,6 +274,52 @@ confused:
320 goto out; 274 goto out;
321} 275}
322 276
277/**
278 * mpage_readpages - populate an address space with some pages, and
279 * start reads against them.
280 *
281 * @mapping: the address_space
282 * @pages: The address of a list_head which contains the target pages. These
283 * pages have their ->index populated and are otherwise uninitialised.
284 *
285 * The page at @pages->prev has the lowest file offset, and reads should be
286 * issued in @pages->prev to @pages->next order.
287 *
288 * @nr_pages: The number of pages at *@pages
289 * @get_block: The filesystem's block mapper function.
290 *
291 * This function walks the pages and the blocks within each page, building and
292 * emitting large BIOs.
293 *
294 * If anything unusual happens, such as:
295 *
296 * - encountering a page which has buffers
297 * - encountering a page which has a non-hole after a hole
298 * - encountering a page with non-contiguous blocks
299 *
300 * then this code just gives up and calls the buffer_head-based read function.
301 * It does handle a page which has holes at the end - that is a common case:
302 * the end-of-file on blocksize < PAGE_CACHE_SIZE setups.
303 *
304 * BH_Boundary explanation:
305 *
306 * There is a problem. The mpage read code assembles several pages, gets all
307 * their disk mappings, and then submits them all. That's fine, but obtaining
308 * the disk mappings may require I/O. Reads of indirect blocks, for example.
309 *
310 * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be
311 * submitted in the following order:
312 * 12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16
313 * because the indirect block has to be read to get the mappings of blocks
314 * 13,14,15,16. Obviously, this impacts performance.
315 *
316 * So what we do it to allow the filesystem's get_block() function to set
317 * BH_Boundary when it maps block 11. BH_Boundary says: mapping of the block
318 * after this one will require I/O against a block which is probably close to
319 * this one. So you should push what I/O you have currently accumulated.
320 *
321 * This all causes the disk requests to be issued in the correct order.
322 */
323int 323int
324mpage_readpages(struct address_space *mapping, struct list_head *pages, 324mpage_readpages(struct address_space *mapping, struct list_head *pages,
325 unsigned nr_pages, get_block_t get_block) 325 unsigned nr_pages, get_block_t get_block)
@@ -727,6 +727,8 @@ retry:
727 &last_block_in_bio, &ret, wbc, 727 &last_block_in_bio, &ret, wbc,
728 writepage_fn); 728 writepage_fn);
729 } 729 }
730 if (unlikely(ret == WRITEPAGE_ACTIVATE))
731 unlock_page(page);
730 if (ret || (--(wbc->nr_to_write) <= 0)) 732 if (ret || (--(wbc->nr_to_write) <= 0))
731 done = 1; 733 done = 1;
732 if (wbc->nonblocking && bdi_write_congested(bdi)) { 734 if (wbc->nonblocking && bdi_write_congested(bdi)) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 39fd336cfdb9..07cafdf74ef2 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1419,6 +1419,8 @@ static struct file_operations proc_tgid_attr_operations;
1419static struct inode_operations proc_tgid_attr_inode_operations; 1419static struct inode_operations proc_tgid_attr_inode_operations;
1420#endif 1420#endif
1421 1421
1422static int get_tid_list(int index, unsigned int *tids, struct inode *dir);
1423
1422/* SMP-safe */ 1424/* SMP-safe */
1423static struct dentry *proc_pident_lookup(struct inode *dir, 1425static struct dentry *proc_pident_lookup(struct inode *dir,
1424 struct dentry *dentry, 1426 struct dentry *dentry,
@@ -1458,7 +1460,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1458 */ 1460 */
1459 switch(p->type) { 1461 switch(p->type) {
1460 case PROC_TGID_TASK: 1462 case PROC_TGID_TASK:
1461 inode->i_nlink = 3; 1463 inode->i_nlink = 2 + get_tid_list(2, NULL, dir);
1462 inode->i_op = &proc_task_inode_operations; 1464 inode->i_op = &proc_task_inode_operations;
1463 inode->i_fop = &proc_task_operations; 1465 inode->i_fop = &proc_task_operations;
1464 break; 1466 break;
@@ -1701,13 +1703,13 @@ static struct inode_operations proc_self_inode_operations = {
1701}; 1703};
1702 1704
1703/** 1705/**
1704 * proc_pid_unhash - Unhash /proc/<pid> entry from the dcache. 1706 * proc_pid_unhash - Unhash /proc/@pid entry from the dcache.
1705 * @p: task that should be flushed. 1707 * @p: task that should be flushed.
1706 * 1708 *
1707 * Drops the /proc/<pid> dcache entry from the hash chains. 1709 * Drops the /proc/@pid dcache entry from the hash chains.
1708 * 1710 *
1709 * Dropping /proc/<pid> entries and detach_pid must be synchroneous, 1711 * Dropping /proc/@pid entries and detach_pid must be synchroneous,
1710 * otherwise e.g. /proc/<pid>/exe might point to the wrong executable, 1712 * otherwise e.g. /proc/@pid/exe might point to the wrong executable,
1711 * if the pid value is immediately reused. This is enforced by 1713 * if the pid value is immediately reused. This is enforced by
1712 * - caller must acquire spin_lock(p->proc_lock) 1714 * - caller must acquire spin_lock(p->proc_lock)
1713 * - must be called before detach_pid() 1715 * - must be called before detach_pid()
@@ -1739,8 +1741,8 @@ struct dentry *proc_pid_unhash(struct task_struct *p)
1739} 1741}
1740 1742
1741/** 1743/**
1742 * proc_pid_flush - recover memory used by stale /proc/<pid>/x entries 1744 * proc_pid_flush - recover memory used by stale /proc/@pid/x entries
1743 * @proc_entry: directoy to prune. 1745 * @proc_dentry: directoy to prune.
1744 * 1746 *
1745 * Shrink the /proc directory that was used by the just killed thread. 1747 * Shrink the /proc directory that was used by the just killed thread.
1746 */ 1748 */
@@ -1800,8 +1802,12 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
1800 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; 1802 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
1801 inode->i_op = &proc_tgid_base_inode_operations; 1803 inode->i_op = &proc_tgid_base_inode_operations;
1802 inode->i_fop = &proc_tgid_base_operations; 1804 inode->i_fop = &proc_tgid_base_operations;
1803 inode->i_nlink = 3;
1804 inode->i_flags|=S_IMMUTABLE; 1805 inode->i_flags|=S_IMMUTABLE;
1806#ifdef CONFIG_SECURITY
1807 inode->i_nlink = 5;
1808#else
1809 inode->i_nlink = 4;
1810#endif
1805 1811
1806 dentry->d_op = &pid_base_dentry_operations; 1812 dentry->d_op = &pid_base_dentry_operations;
1807 1813
@@ -1855,8 +1861,12 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
1855 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; 1861 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
1856 inode->i_op = &proc_tid_base_inode_operations; 1862 inode->i_op = &proc_tid_base_inode_operations;
1857 inode->i_fop = &proc_tid_base_operations; 1863 inode->i_fop = &proc_tid_base_operations;
1858 inode->i_nlink = 3;
1859 inode->i_flags|=S_IMMUTABLE; 1864 inode->i_flags|=S_IMMUTABLE;
1865#ifdef CONFIG_SECURITY
1866 inode->i_nlink = 4;
1867#else
1868 inode->i_nlink = 3;
1869#endif
1860 1870
1861 dentry->d_op = &pid_base_dentry_operations; 1871 dentry->d_op = &pid_base_dentry_operations;
1862 1872
@@ -1935,7 +1945,8 @@ static int get_tid_list(int index, unsigned int *tids, struct inode *dir)
1935 1945
1936 if (--index >= 0) 1946 if (--index >= 0)
1937 continue; 1947 continue;
1938 tids[nr_tids] = tid; 1948 if (tids != NULL)
1949 tids[nr_tids] = tid;
1939 nr_tids++; 1950 nr_tids++;
1940 if (nr_tids >= PROC_MAXPIDS) 1951 if (nr_tids >= PROC_MAXPIDS)
1941 break; 1952 break;
@@ -2035,6 +2046,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
2035 } 2046 }
2036 2047
2037 nr_tids = get_tid_list(pos, tid_array, inode); 2048 nr_tids = get_tid_list(pos, tid_array, inode);
2049 inode->i_nlink = pos + nr_tids;
2038 2050
2039 for (i = 0; i < nr_tids; i++) { 2051 for (i = 0; i < nr_tids; i++) {
2040 unsigned long j = PROC_NUMBUF; 2052 unsigned long j = PROC_NUMBUF;
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index a4e2ed544bbe..49c479c9454a 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -260,8 +260,9 @@ static inline int block_group_used(struct super_block *s, u32 id) {
260/* 260/*
261 * the packing is returned in disk byte order 261 * the packing is returned in disk byte order
262 */ 262 */
263u32 reiserfs_choose_packing(struct inode *dir) { 263__le32 reiserfs_choose_packing(struct inode *dir)
264 u32 packing; 264{
265 __le32 packing;
265 if (TEST_OPTION(packing_groups, dir->i_sb)) { 266 if (TEST_OPTION(packing_groups, dir->i_sb)) {
266 u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id); 267 u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id);
267 /* 268 /*
@@ -655,7 +656,7 @@ static int get_left_neighbor(reiserfs_blocknr_hint_t *hint)
655 struct buffer_head * bh; 656 struct buffer_head * bh;
656 struct item_head * ih; 657 struct item_head * ih;
657 int pos_in_item; 658 int pos_in_item;
658 __u32 * item; 659 __le32 * item;
659 int ret = 0; 660 int ret = 0;
660 661
661 if (!hint->path) /* reiserfs code can call this function w/o pointer to path 662 if (!hint->path) /* reiserfs code can call this function w/o pointer to path
@@ -736,7 +737,7 @@ static inline int this_blocknr_allocation_would_make_it_a_large_file(reiserfs_bl
736#ifdef DISPLACE_NEW_PACKING_LOCALITIES 737#ifdef DISPLACE_NEW_PACKING_LOCALITIES
737static inline void displace_new_packing_locality (reiserfs_blocknr_hint_t *hint) 738static inline void displace_new_packing_locality (reiserfs_blocknr_hint_t *hint)
738{ 739{
739 struct reiserfs_key * key = &hint->key; 740 struct in_core_key * key = &hint->key;
740 741
741 hint->th->displace_new_blocks = 0; 742 hint->th->displace_new_blocks = 0;
742 hint->search_start = hint->beg + keyed_hash((char*)(&key->k_objectid),4) % (hint->end - hint->beg); 743 hint->search_start = hint->beg + keyed_hash((char*)(&key->k_objectid),4) % (hint->end - hint->beg);
@@ -777,7 +778,7 @@ static inline int old_way (reiserfs_blocknr_hint_t * hint)
777 778
778static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint) 779static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint)
779{ 780{
780 struct reiserfs_key * key = &hint->key; 781 struct in_core_key * key = &hint->key;
781 b_blocknr_t slice_start; 782 b_blocknr_t slice_start;
782 783
783 slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100); 784 slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100);
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index d1514a9b0514..fbde4b01a325 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -209,8 +209,8 @@ static int reiserfs_readdir (struct file * filp, void * dirent, filldir_t filldi
209/* compose directory item containing "." and ".." entries (entries are 209/* compose directory item containing "." and ".." entries (entries are
210 not aligned to 4 byte boundary) */ 210 not aligned to 4 byte boundary) */
211/* the last four params are LE */ 211/* the last four params are LE */
212void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, 212void make_empty_dir_item_v1 (char * body, __le32 dirid, __le32 objid,
213 __u32 par_dirid, __u32 par_objid) 213 __le32 par_dirid, __le32 par_objid)
214{ 214{
215 struct reiserfs_de_head * deh; 215 struct reiserfs_de_head * deh;
216 216
@@ -242,8 +242,8 @@ void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid,
242} 242}
243 243
244/* compose directory item containing "." and ".." entries */ 244/* compose directory item containing "." and ".." entries */
245void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, 245void make_empty_dir_item (char * body, __le32 dirid, __le32 objid,
246 __u32 par_dirid, __u32 par_objid) 246 __le32 par_dirid, __le32 par_objid)
247{ 247{
248 struct reiserfs_de_head * deh; 248 struct reiserfs_de_head * deh;
249 249
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 26950113af8c..2230afff1870 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -166,7 +166,7 @@ static int reiserfs_allocate_blocks_for_region(
166 struct cpu_key key; // cpu key of item that we are going to deal with 166 struct cpu_key key; // cpu key of item that we are going to deal with
167 struct item_head *ih; // pointer to item head that we are going to deal with 167 struct item_head *ih; // pointer to item head that we are going to deal with
168 struct buffer_head *bh; // Buffer head that contains items that we are going to deal with 168 struct buffer_head *bh; // Buffer head that contains items that we are going to deal with
169 __u32 * item; // pointer to item we are going to deal with 169 __le32 * item; // pointer to item we are going to deal with
170 INITIALIZE_PATH(path); // path to item, that we are going to deal with. 170 INITIALIZE_PATH(path); // path to item, that we are going to deal with.
171 b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored. 171 b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored.
172 reiserfs_blocknr_hint_t hint; // hint structure for block allocator. 172 reiserfs_blocknr_hint_t hint; // hint structure for block allocator.
@@ -891,7 +891,7 @@ static int reiserfs_prepare_file_region_for_write(
891 struct item_head *ih = NULL; // pointer to item head that we are going to deal with 891 struct item_head *ih = NULL; // pointer to item head that we are going to deal with
892 struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with 892 struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with
893 INITIALIZE_PATH(path); // path to item, that we are going to deal with. 893 INITIALIZE_PATH(path); // path to item, that we are going to deal with.
894 __u32 * item=NULL; // pointer to item we are going to deal with 894 __le32 * item=NULL; // pointer to item we are going to deal with
895 int item_pos=-1; /* Position in indirect item */ 895 int item_pos=-1; /* Position in indirect item */
896 896
897 897
@@ -1284,10 +1284,11 @@ static ssize_t reiserfs_file_write( struct file *file, /* the file we are going
1284 reiserfs_claim_blocks_to_be_allocated(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits)); 1284 reiserfs_claim_blocks_to_be_allocated(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
1285 reiserfs_write_unlock(inode->i_sb); 1285 reiserfs_write_unlock(inode->i_sb);
1286 1286
1287 if ( !num_pages ) { /* If we do not have enough space even for */ 1287 if ( !num_pages ) { /* If we do not have enough space even for a single page... */
1288 res = -ENOSPC; /* single page, return -ENOSPC */ 1288 if ( pos > inode->i_size+inode->i_sb->s_blocksize-(pos & (inode->i_sb->s_blocksize-1))) {
1289 if ( pos > (inode->i_size & (inode->i_sb->s_blocksize-1))) 1289 res = -ENOSPC;
1290 break; // In case we are writing past the file end, break. 1290 break; // In case we are writing past the end of the last file block, break.
1291 }
1291 // Otherwise we are possibly overwriting the file, so 1292 // Otherwise we are possibly overwriting the file, so
1292 // let's set write size to be equal or less than blocksize. 1293 // let's set write size to be equal or less than blocksize.
1293 // This way we get it correctly for file holes. 1294 // This way we get it correctly for file holes.
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 7543031396f4..2711dff1b7b4 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -173,7 +173,7 @@ static inline void fix_tail_page_for_writing(struct page *page) {
173 done already or non-hole position has been found in the indirect item */ 173 done already or non-hole position has been found in the indirect item */
174static inline int allocation_needed (int retval, b_blocknr_t allocated, 174static inline int allocation_needed (int retval, b_blocknr_t allocated,
175 struct item_head * ih, 175 struct item_head * ih,
176 __u32 * item, int pos_in_item) 176 __le32 * item, int pos_in_item)
177{ 177{
178 if (allocated) 178 if (allocated)
179 return 0; 179 return 0;
@@ -278,7 +278,7 @@ research:
278 bh = get_last_bh (&path); 278 bh = get_last_bh (&path);
279 ih = get_ih (&path); 279 ih = get_ih (&path);
280 if (is_indirect_le_ih (ih)) { 280 if (is_indirect_le_ih (ih)) {
281 __u32 * ind_item = (__u32 *)B_I_PITEM (bh, ih); 281 __le32 * ind_item = (__le32 *)B_I_PITEM (bh, ih);
282 282
283 /* FIXME: here we could cache indirect item or part of it in 283 /* FIXME: here we could cache indirect item or part of it in
284 the inode to avoid search_by_key in case of subsequent 284 the inode to avoid search_by_key in case of subsequent
@@ -581,7 +581,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
581 struct cpu_key key; 581 struct cpu_key key;
582 struct buffer_head * bh, * unbh = NULL; 582 struct buffer_head * bh, * unbh = NULL;
583 struct item_head * ih, tmp_ih; 583 struct item_head * ih, tmp_ih;
584 __u32 * item; 584 __le32 * item;
585 int done; 585 int done;
586 int fs_gen; 586 int fs_gen;
587 struct reiserfs_transaction_handle *th = NULL; 587 struct reiserfs_transaction_handle *th = NULL;
@@ -746,7 +746,7 @@ start_trans:
746 done = 0; 746 done = 0;
747 do { 747 do {
748 if (is_statdata_le_ih (ih)) { 748 if (is_statdata_le_ih (ih)) {
749 __u32 unp = 0; 749 __le32 unp = 0;
750 struct cpu_key tmp_key; 750 struct cpu_key tmp_key;
751 751
752 /* indirect item has to be inserted */ 752 /* indirect item has to be inserted */
@@ -1341,8 +1341,8 @@ void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args
1341 key.version = KEY_FORMAT_3_5; 1341 key.version = KEY_FORMAT_3_5;
1342 key.on_disk_key.k_dir_id = dirino; 1342 key.on_disk_key.k_dir_id = dirino;
1343 key.on_disk_key.k_objectid = inode->i_ino; 1343 key.on_disk_key.k_objectid = inode->i_ino;
1344 key.on_disk_key.u.k_offset_v1.k_offset = SD_OFFSET; 1344 key.on_disk_key.k_offset = 0;
1345 key.on_disk_key.u.k_offset_v1.k_uniqueness = SD_UNIQUENESS; 1345 key.on_disk_key.k_type = 0;
1346 1346
1347 /* look for the object's stat data */ 1347 /* look for the object's stat data */
1348 retval = search_item (inode->i_sb, &key, &path_to_sd); 1348 retval = search_item (inode->i_sb, &key, &path_to_sd);
@@ -2067,7 +2067,7 @@ static int map_block_for_writepage(struct inode *inode,
2067 struct item_head tmp_ih ; 2067 struct item_head tmp_ih ;
2068 struct item_head *ih ; 2068 struct item_head *ih ;
2069 struct buffer_head *bh ; 2069 struct buffer_head *bh ;
2070 __u32 *item ; 2070 __le32 *item ;
2071 struct cpu_key key ; 2071 struct cpu_key key ;
2072 INITIALIZE_PATH(path) ; 2072 INITIALIZE_PATH(path) ;
2073 int pos_in_item ; 2073 int pos_in_item ;
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c
index 9cf7c13b120d..0ce33db1acdf 100644
--- a/fs/reiserfs/item_ops.c
+++ b/fs/reiserfs/item_ops.c
@@ -296,10 +296,11 @@ static void print_sequence (__u32 start, int len)
296static void indirect_print_item (struct item_head * ih, char * item) 296static void indirect_print_item (struct item_head * ih, char * item)
297{ 297{
298 int j; 298 int j;
299 __u32 * unp, prev = INT_MAX; 299 __le32 * unp;
300 __u32 prev = INT_MAX;
300 int num; 301 int num;
301 302
302 unp = (__u32 *)item; 303 unp = (__le32 *)item;
303 304
304 if (ih_item_len(ih) % UNFM_P_SIZE) 305 if (ih_item_len(ih) % UNFM_P_SIZE)
305 reiserfs_warning (NULL, "indirect_print_item: invalid item len"); 306 reiserfs_warning (NULL, "indirect_print_item: invalid item len");
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index c9ad3a7849f4..3072cfdee959 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2306,13 +2306,16 @@ static int journal_init_dev( struct super_block *super,
2306 if( !IS_ERR( journal -> j_dev_file ) ) { 2306 if( !IS_ERR( journal -> j_dev_file ) ) {
2307 struct inode *jdev_inode = journal->j_dev_file->f_mapping->host; 2307 struct inode *jdev_inode = journal->j_dev_file->f_mapping->host;
2308 if( !S_ISBLK( jdev_inode -> i_mode ) ) { 2308 if( !S_ISBLK( jdev_inode -> i_mode ) ) {
2309 reiserfs_warning (super, "journal_init_dev: '%s' is " 2309 reiserfs_warning(super, "journal_init_dev: '%s' is "
2310 "not a block device", jdev_name ); 2310 "not a block device", jdev_name );
2311 result = -ENOTBLK; 2311 result = -ENOTBLK;
2312 release_journal_dev( super, journal );
2312 } else { 2313 } else {
2313 /* ok */ 2314 /* ok */
2314 journal->j_dev_bd = I_BDEV(jdev_inode); 2315 journal->j_dev_bd = I_BDEV(jdev_inode);
2315 set_blocksize(journal->j_dev_bd, super->s_blocksize); 2316 set_blocksize(journal->j_dev_bd, super->s_blocksize);
2317 reiserfs_info(super, "journal_init_dev: journal device: %s\n",
2318 bdevname(journal->j_dev_bd, b));
2316 } 2319 }
2317 } else { 2320 } else {
2318 result = PTR_ERR( journal -> j_dev_file ); 2321 result = PTR_ERR( journal -> j_dev_file );
@@ -2321,11 +2324,6 @@ static int journal_init_dev( struct super_block *super,
2321 "journal_init_dev: Cannot open '%s': %i", 2324 "journal_init_dev: Cannot open '%s': %i",
2322 jdev_name, result ); 2325 jdev_name, result );
2323 } 2326 }
2324 if( result != 0 ) {
2325 release_journal_dev( super, journal );
2326 }
2327 reiserfs_info(super, "journal_init_dev: journal device: %s\n",
2328 bdevname(journal->j_dev_bd, b));
2329 return result; 2327 return result;
2330} 2328}
2331 2329
@@ -2393,7 +2391,7 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo
2393 jh = (struct reiserfs_journal_header *)(bhjh->b_data); 2391 jh = (struct reiserfs_journal_header *)(bhjh->b_data);
2394 2392
2395 /* make sure that journal matches to the super block */ 2393 /* make sure that journal matches to the super block */
2396 if (is_reiserfs_jr(rs) && (jh->jh_journal.jp_journal_magic != sb_jp_journal_magic(rs))) { 2394 if (is_reiserfs_jr(rs) && (le32_to_cpu(jh->jh_journal.jp_journal_magic) != sb_jp_journal_magic(rs))) {
2397 reiserfs_warning (p_s_sb, "sh-460: journal header magic %x " 2395 reiserfs_warning (p_s_sb, "sh-460: journal header magic %x "
2398 "(device %s) does not match to magic found in super " 2396 "(device %s) does not match to magic found in super "
2399 "block %x", 2397 "block %x",
diff --git a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c
index 0785c43a7486..bfe8e25ef293 100644
--- a/fs/reiserfs/objectid.c
+++ b/fs/reiserfs/objectid.c
@@ -11,13 +11,13 @@
11 11
12// find where objectid map starts 12// find where objectid map starts
13#define objectid_map(s,rs) (old_format_only (s) ? \ 13#define objectid_map(s,rs) (old_format_only (s) ? \
14 (__u32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\ 14 (__le32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\
15 (__u32 *)((rs) + 1)) 15 (__le32 *)((rs) + 1))
16 16
17 17
18#ifdef CONFIG_REISERFS_CHECK 18#ifdef CONFIG_REISERFS_CHECK
19 19
20static void check_objectid_map (struct super_block * s, __u32 * map) 20static void check_objectid_map (struct super_block * s, __le32 * map)
21{ 21{
22 if (le32_to_cpu (map[0]) != 1) 22 if (le32_to_cpu (map[0]) != 1)
23 reiserfs_panic (s, "vs-15010: check_objectid_map: map corrupted: %lx", 23 reiserfs_panic (s, "vs-15010: check_objectid_map: map corrupted: %lx",
@@ -27,7 +27,7 @@ static void check_objectid_map (struct super_block * s, __u32 * map)
27} 27}
28 28
29#else 29#else
30static void check_objectid_map (struct super_block * s, __u32 * map) 30static void check_objectid_map (struct super_block * s, __le32 * map)
31{;} 31{;}
32#endif 32#endif
33 33
@@ -52,7 +52,7 @@ __u32 reiserfs_get_unused_objectid (struct reiserfs_transaction_handle *th)
52{ 52{
53 struct super_block * s = th->t_super; 53 struct super_block * s = th->t_super;
54 struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s); 54 struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s);
55 __u32 * map = objectid_map (s, rs); 55 __le32 * map = objectid_map (s, rs);
56 __u32 unused_objectid; 56 __u32 unused_objectid;
57 57
58 BUG_ON (!th->t_trans_id); 58 BUG_ON (!th->t_trans_id);
@@ -97,7 +97,7 @@ void reiserfs_release_objectid (struct reiserfs_transaction_handle *th,
97{ 97{
98 struct super_block * s = th->t_super; 98 struct super_block * s = th->t_super;
99 struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s); 99 struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s);
100 __u32 * map = objectid_map (s, rs); 100 __le32 * map = objectid_map (s, rs);
101 int i = 0; 101 int i = 0;
102 102
103 BUG_ON (!th->t_trans_id); 103 BUG_ON (!th->t_trans_id);
@@ -172,12 +172,12 @@ int reiserfs_convert_objectid_map_v1(struct super_block *s) {
172 int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2 ; 172 int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2 ;
173 int old_max = sb_oid_maxsize(disk_sb); 173 int old_max = sb_oid_maxsize(disk_sb);
174 struct reiserfs_super_block_v1 *disk_sb_v1 ; 174 struct reiserfs_super_block_v1 *disk_sb_v1 ;
175 __u32 *objectid_map, *new_objectid_map ; 175 __le32 *objectid_map, *new_objectid_map ;
176 int i ; 176 int i ;
177 177
178 disk_sb_v1=(struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data); 178 disk_sb_v1=(struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data);
179 objectid_map = (__u32 *)(disk_sb_v1 + 1) ; 179 objectid_map = (__le32 *)(disk_sb_v1 + 1) ;
180 new_objectid_map = (__u32 *)(disk_sb + 1) ; 180 new_objectid_map = (__le32 *)(disk_sb + 1) ;
181 181
182 if (cur_size > new_size) { 182 if (cur_size > new_size) {
183 /* mark everyone used that was listed as free at the end of the objectid 183 /* mark everyone used that was listed as free at the end of the objectid
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index f4ea81ae0e0f..e242ebc7f6f6 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -73,8 +73,8 @@ int reiserfs_global_version_in_proc( char *buffer, char **start, off_t offset,
73#define DFL( x ) D4C( rs -> s_v1.x ) 73#define DFL( x ) D4C( rs -> s_v1.x )
74 74
75#define objectid_map( s, rs ) (old_format_only (s) ? \ 75#define objectid_map( s, rs ) (old_format_only (s) ? \
76 (__u32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \ 76 (__le32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \
77 (__u32 *)(rs + 1)) 77 (__le32 *)(rs + 1))
78#define MAP( i ) D4C( objectid_map( sb, rs )[ i ] ) 78#define MAP( i ) D4C( objectid_map( sb, rs )[ i ] )
79 79
80#define DJF( x ) le32_to_cpu( rs -> x ) 80#define DJF( x ) le32_to_cpu( rs -> x )
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 73ec5212178b..da23ba75f3d5 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -87,22 +87,20 @@ inline void copy_item_head(struct item_head * p_v_to,
87inline int comp_short_keys (const struct reiserfs_key * le_key, 87inline int comp_short_keys (const struct reiserfs_key * le_key,
88 const struct cpu_key * cpu_key) 88 const struct cpu_key * cpu_key)
89{ 89{
90 __u32 * p_s_le_u32, * p_s_cpu_u32; 90 __u32 n;
91 int n_key_length = REISERFS_SHORT_KEY_LEN; 91 n = le32_to_cpu(le_key->k_dir_id);
92 92 if (n < cpu_key->on_disk_key.k_dir_id)
93 p_s_le_u32 = (__u32 *)le_key;
94 p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key;
95 for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) {
96 if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 )
97 return -1; 93 return -1;
98 if ( le32_to_cpu (*p_s_le_u32) > *p_s_cpu_u32 ) 94 if (n > cpu_key->on_disk_key.k_dir_id)
95 return 1;
96 n = le32_to_cpu(le_key->k_objectid);
97 if (n < cpu_key->on_disk_key.k_objectid)
98 return -1;
99 if (n > cpu_key->on_disk_key.k_objectid)
99 return 1; 100 return 1;
100 }
101
102 return 0; 101 return 0;
103} 102}
104 103
105
106/* k1 is pointer to on-disk structure which is stored in little-endian 104/* k1 is pointer to on-disk structure which is stored in little-endian
107 form. k2 is pointer to cpu variable. 105 form. k2 is pointer to cpu variable.
108 Compare keys using all 4 key fields. 106 Compare keys using all 4 key fields.
@@ -152,18 +150,15 @@ inline int comp_short_le_keys (const struct reiserfs_key * key1, const struct re
152 150
153inline void le_key2cpu_key (struct cpu_key * to, const struct reiserfs_key * from) 151inline void le_key2cpu_key (struct cpu_key * to, const struct reiserfs_key * from)
154{ 152{
153 int version;
155 to->on_disk_key.k_dir_id = le32_to_cpu (from->k_dir_id); 154 to->on_disk_key.k_dir_id = le32_to_cpu (from->k_dir_id);
156 to->on_disk_key.k_objectid = le32_to_cpu (from->k_objectid); 155 to->on_disk_key.k_objectid = le32_to_cpu (from->k_objectid);
157 156
158 // find out version of the key 157 // find out version of the key
159 to->version = le_key_version (from); 158 version = le_key_version (from);
160 if (to->version == KEY_FORMAT_3_5) { 159 to->version = version;
161 to->on_disk_key.u.k_offset_v1.k_offset = le32_to_cpu (from->u.k_offset_v1.k_offset); 160 to->on_disk_key.k_offset = le_key_k_offset(version, from);
162 to->on_disk_key.u.k_offset_v1.k_uniqueness = le32_to_cpu (from->u.k_offset_v1.k_uniqueness); 161 to->on_disk_key.k_type = le_key_k_type(version, from);
163 } else {
164 to->on_disk_key.u.k_offset_v2.k_offset = offset_v2_k_offset(&from->u.k_offset_v2);
165 to->on_disk_key.u.k_offset_v2.k_type = offset_v2_k_type(&from->u.k_offset_v2);
166 }
167} 162}
168 163
169 164
@@ -228,8 +223,14 @@ extern struct tree_balance * cur_tb;
228const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; 223const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}};
229 224
230/* Maximal possible key. It is never in the tree. */ 225/* Maximal possible key. It is never in the tree. */
231const struct reiserfs_key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; 226const struct reiserfs_key MAX_KEY = {
227 __constant_cpu_to_le32(0xffffffff),
228 __constant_cpu_to_le32(0xffffffff),
229 {{__constant_cpu_to_le32(0xffffffff),
230 __constant_cpu_to_le32(0xffffffff)},}
231};
232 232
233const struct in_core_key MAX_IN_CORE_KEY = {~0U, ~0U, ~0ULL>>4, 15};
233 234
234/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom 235/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom
235 of the path, and going upwards. We must check the path's validity at each step. If the key is not in 236 of the path, and going upwards. We must check the path's validity at each step. If the key is not in
@@ -997,7 +998,7 @@ static char prepare_for_delete_or_cut(
997 int n_unfm_number, /* Number of the item unformatted nodes. */ 998 int n_unfm_number, /* Number of the item unformatted nodes. */
998 n_counter, 999 n_counter,
999 n_blk_size; 1000 n_blk_size;
1000 __u32 * p_n_unfm_pointer; /* Pointer to the unformatted node number. */ 1001 __le32 * p_n_unfm_pointer; /* Pointer to the unformatted node number. */
1001 __u32 tmp; 1002 __u32 tmp;
1002 struct item_head s_ih; /* Item header. */ 1003 struct item_head s_ih; /* Item header. */
1003 char c_mode; /* Returned mode of the balance. */ 1004 char c_mode; /* Returned mode of the balance. */
@@ -1059,7 +1060,7 @@ static char prepare_for_delete_or_cut(
1059 /* pointers to be cut */ 1060 /* pointers to be cut */
1060 n_unfm_number -= pos_in_item (p_s_path); 1061 n_unfm_number -= pos_in_item (p_s_path);
1061 /* Set pointer to the last unformatted node pointer that is to be cut. */ 1062 /* Set pointer to the last unformatted node pointer that is to be cut. */
1062 p_n_unfm_pointer = (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed; 1063 p_n_unfm_pointer = (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed;
1063 1064
1064 1065
1065 /* We go through the unformatted nodes pointers of the indirect 1066 /* We go through the unformatted nodes pointers of the indirect
@@ -1081,8 +1082,8 @@ static char prepare_for_delete_or_cut(
1081 need_research = 1 ; 1082 need_research = 1 ;
1082 break; 1083 break;
1083 } 1084 }
1084 RFALSE( p_n_unfm_pointer < (__u32 *)B_I_PITEM(p_s_bh, &s_ih) || 1085 RFALSE( p_n_unfm_pointer < (__le32 *)B_I_PITEM(p_s_bh, &s_ih) ||
1085 p_n_unfm_pointer > (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1, 1086 p_n_unfm_pointer > (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1,
1086 "vs-5265: pointer out of range"); 1087 "vs-5265: pointer out of range");
1087 1088
1088 /* Hole, nothing to remove. */ 1089 /* Hole, nothing to remove. */
@@ -1431,7 +1432,7 @@ int reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inode
1431#if defined( USE_INODE_GENERATION_COUNTER ) 1432#if defined( USE_INODE_GENERATION_COUNTER )
1432 if( !old_format_only ( th -> t_super ) ) 1433 if( !old_format_only ( th -> t_super ) )
1433 { 1434 {
1434 __u32 *inode_generation; 1435 __le32 *inode_generation;
1435 1436
1436 inode_generation = 1437 inode_generation =
1437 &REISERFS_SB(th -> t_super) -> s_rs -> s_inode_generation; 1438 &REISERFS_SB(th -> t_super) -> s_rs -> s_inode_generation;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index bcdf2438d152..31e75125f48b 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -110,7 +110,7 @@ static void reiserfs_unlockfs(struct super_block *s) {
110 reiserfs_allow_writes(s) ; 110 reiserfs_allow_writes(s) ;
111} 111}
112 112
113extern const struct reiserfs_key MAX_KEY; 113extern const struct in_core_key MAX_IN_CORE_KEY;
114 114
115 115
116/* this is used to delete "save link" when there are no items of a 116/* this is used to delete "save link" when there are no items of a
@@ -164,7 +164,7 @@ static int finish_unfinished (struct super_block * s)
164 164
165 /* compose key to look for "save" links */ 165 /* compose key to look for "save" links */
166 max_cpu_key.version = KEY_FORMAT_3_5; 166 max_cpu_key.version = KEY_FORMAT_3_5;
167 max_cpu_key.on_disk_key = MAX_KEY; 167 max_cpu_key.on_disk_key = MAX_IN_CORE_KEY;
168 max_cpu_key.key_length = 3; 168 max_cpu_key.key_length = 3;
169 169
170#ifdef CONFIG_QUOTA 170#ifdef CONFIG_QUOTA
@@ -216,10 +216,10 @@ static int finish_unfinished (struct super_block * s)
216 216
217 /* reiserfs_iget needs k_dirid and k_objectid only */ 217 /* reiserfs_iget needs k_dirid and k_objectid only */
218 item = B_I_PITEM (bh, ih); 218 item = B_I_PITEM (bh, ih);
219 obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__u32 *)item); 219 obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__le32 *)item);
220 obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid); 220 obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid);
221 obj_key.on_disk_key.u.k_offset_v1.k_offset = 0; 221 obj_key.on_disk_key.k_offset = 0;
222 obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0; 222 obj_key.on_disk_key.k_type = 0;
223 223
224 pathrelse (&path); 224 pathrelse (&path);
225 225
@@ -304,7 +304,7 @@ void add_save_link (struct reiserfs_transaction_handle * th,
304 int retval; 304 int retval;
305 struct cpu_key key; 305 struct cpu_key key;
306 struct item_head ih; 306 struct item_head ih;
307 __u32 link; 307 __le32 link;
308 308
309 BUG_ON (!th->t_trans_id); 309 BUG_ON (!th->t_trans_id);
310 310
@@ -889,12 +889,18 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
889 char * p; 889 char * p;
890 890
891 p = NULL; 891 p = NULL;
892 /* "resize=NNN" */ 892 /* "resize=NNN" or "resize=auto" */
893 *blocks = simple_strtoul (arg, &p, 0); 893
894 if (*p != '\0') { 894 if (!strcmp(arg, "auto")) {
895 /* NNN does not look like a number */ 895 /* From JFS code, to auto-get the size.*/
896 reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg); 896 *blocks = s->s_bdev->bd_inode->i_size >> s->s_blocksize_bits;
897 return 0; 897 } else {
898 *blocks = simple_strtoul (arg, &p, 0);
899 if (*p != '\0') {
900 /* NNN does not look like a number */
901 reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg);
902 return 0;
903 }
898 } 904 }
899 } 905 }
900 906
@@ -903,7 +909,8 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
903 unsigned long val = simple_strtoul (arg, &p, 0); 909 unsigned long val = simple_strtoul (arg, &p, 0);
904 /* commit=NNN (time in seconds) */ 910 /* commit=NNN (time in seconds) */
905 if ( *p != '\0' || val >= (unsigned int)-1) { 911 if ( *p != '\0' || val >= (unsigned int)-1) {
906 reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg); return 0; 912 reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg);
913 return 0;
907 } 914 }
908 *commit_max_age = (unsigned int)val; 915 *commit_max_age = (unsigned int)val;
909 } 916 }
@@ -1329,7 +1336,7 @@ static int read_super_block (struct super_block * s, int offset)
1329 return 1; 1336 return 1;
1330 } 1337 }
1331 1338
1332 if ( rs->s_v1.s_root_block == -1 ) { 1339 if ( rs->s_v1.s_root_block == cpu_to_le32(-1) ) {
1333 brelse(bh) ; 1340 brelse(bh) ;
1334 reiserfs_warning (s, "Unfinished reiserfsck --rebuild-tree run detected. Please run\n" 1341 reiserfs_warning (s, "Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
1335 "reiserfsck --rebuild-tree and wait for a completion. If that fails\n" 1342 "reiserfsck --rebuild-tree and wait for a completion. If that fails\n"
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 650c43ba86c4..38ef913767ff 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -51,7 +51,10 @@ EXPORT_SYMBOL(seq_open);
51 51
52/** 52/**
53 * seq_read - ->read() method for sequential files. 53 * seq_read - ->read() method for sequential files.
54 * @file, @buf, @size, @ppos: see file_operations method 54 * @file: the file to read from
55 * @buf: the buffer to read to
56 * @size: the maximum number of bytes to read
57 * @ppos: the current position in the file
55 * 58 *
56 * Ready-made ->f_op->read() 59 * Ready-made ->f_op->read()
57 */ 60 */
@@ -219,7 +222,9 @@ Eoverflow:
219 222
220/** 223/**
221 * seq_lseek - ->llseek() method for sequential files. 224 * seq_lseek - ->llseek() method for sequential files.
222 * @file, @offset, @origin: see file_operations method 225 * @file: the file in question
226 * @offset: new position
227 * @origin: 0 for absolute, 1 for relative position
223 * 228 *
224 * Ready-made ->f_op->llseek() 229 * Ready-made ->f_op->llseek()
225 */ 230 */
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index da25aeb0e062..364208071e17 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -96,7 +96,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
96/** 96/**
97 * flush_read_buffer - push buffer to userspace. 97 * flush_read_buffer - push buffer to userspace.
98 * @buffer: data buffer for file. 98 * @buffer: data buffer for file.
99 * @userbuf: user-passed buffer. 99 * @buf: user-passed buffer.
100 * @count: number of bytes requested. 100 * @count: number of bytes requested.
101 * @ppos: file position. 101 * @ppos: file position.
102 * 102 *
@@ -164,7 +164,7 @@ out:
164/** 164/**
165 * fill_write_buffer - copy buffer from userspace. 165 * fill_write_buffer - copy buffer from userspace.
166 * @buffer: data buffer for file. 166 * @buffer: data buffer for file.
167 * @userbuf: data from user. 167 * @buf: data from user.
168 * @count: number of bytes in @userbuf. 168 * @count: number of bytes in @userbuf.
169 * 169 *
170 * Allocate @buffer->page if it hasn't been already, then 170 * Allocate @buffer->page if it hasn't been already, then
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 2faa4172b9f7..bb40d63f328f 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -49,8 +49,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page)
49 struct inode *inode = page->mapping->host; 49 struct inode *inode = page->mapping->host;
50 char *kaddr; 50 char *kaddr;
51 51
52 if (!PageLocked(page)) 52 BUG_ON(!PageLocked(page));
53 PAGE_BUG(page);
54 53
55 kaddr = kmap(page); 54 kaddr = kmap(page);
56 memset(kaddr, 0, PAGE_CACHE_SIZE); 55 memset(kaddr, 0, PAGE_CACHE_SIZE);
@@ -67,8 +66,7 @@ static int udf_adinicb_writepage(struct page *page, struct writeback_control *wb
67 struct inode *inode = page->mapping->host; 66 struct inode *inode = page->mapping->host;
68 char *kaddr; 67 char *kaddr;
69 68
70 if (!PageLocked(page)) 69 BUG_ON(!PageLocked(page));
71 PAGE_BUG(page);
72 70
73 kaddr = kmap(page); 71 kaddr = kmap(page);
74 memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size); 72 memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 0506e1173784..3d68de39fad6 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -167,8 +167,8 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
167 } 167 }
168 168
169 page = grab_cache_page(inode->i_mapping, 0); 169 page = grab_cache_page(inode->i_mapping, 0);
170 if (!PageLocked(page)) 170 BUG_ON(!PageLocked(page));
171 PAGE_BUG(page); 171
172 if (!PageUptodate(page)) 172 if (!PageUptodate(page))
173 { 173 {
174 kaddr = kmap(page); 174 kaddr = kmap(page);