diff options
author | Tony Luck <tony.luck@intel.com> | 2005-05-17 18:53:14 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-05-17 18:53:14 -0400 |
commit | 325a479c4c110db278ef3361460a48c4093252cc (patch) | |
tree | bcfbf4d0647d9442045639a5c19da59d55190e81 /fs | |
parent | ebcc80c1b6629a445f7471cc1ddb48faf8a84e70 (diff) | |
parent | 7f9eaedf894dbaa08c157832e9a6c9c03ffed1ed (diff) |
Merge with temp tree to get David's gdb inferior calls patch
Diffstat (limited to 'fs')
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) |
@@ -40,9 +40,6 @@ | |||
40 | #define dprintk(x...) do { ; } while (0) | 40 | #define dprintk(x...) do { ; } while (0) |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | static long aio_run = 0; /* for testing only */ | ||
44 | static long aio_wakeups = 0; /* for testing only */ | ||
45 | |||
46 | /*------ sysctl variables----*/ | 43 | /*------ sysctl variables----*/ |
47 | atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ | 44 | atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ |
48 | unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ | 45 | unsigned 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: | |||
774 | static int __aio_run_iocbs(struct kioctx *ctx) | 762 | static 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); | ||
1015 | put_rq: | 996 | put_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); |
1216 | out: | 1195 | out: |
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) { | |||
126 | static inline int autofs4_ispending(struct dentry *dentry) | 128 | static 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 | ||
134 | static inline void autofs4_copy_atime(struct file *src, struct file *dst) | 145 | static 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); |
103 | repeat: | 107 | repeat: |
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 | ||
@@ -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 | */ |
787 | int sync_mapping_buffers(struct address_space *mapping) | 786 | int 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 | ||
5 | The author wishes to express his appreciation and thanks to: | 5 | The author wishes to express his appreciation and thanks to: |
6 | Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS | 6 | Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS |
7 | improvements. Thanks to IBM for allowing me the time and test resources to pursue | 7 | improvements. Thanks to IBM for allowing me time and test resources to pursue |
8 | this project. Jim McDonough from IBM (and the Samba Team) for his help. | 8 | this project, to Jim McDonough from IBM (and the Samba Team) for his help, to |
9 | The IBM Linux JFS team for explaining many esoteric Linux filesystem features. | 9 | the IBM Linux JFS team for explaining many esoteric Linux filesystem features. |
10 | Jeremy Allison of the Samba team has done invaluable work in adding the server | ||
11 | side of the original CIFS Unix extensions and reviewing and implementing | ||
12 | portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank | ||
10 | Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) | 13 | Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) |
11 | for proving years ago that a very good smb/cifs client could be done on a Unix like | 14 | for proving years ago that very good smb/cifs clients could be done on Unix-like |
12 | operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin | 15 | operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John |
13 | and others for their work on the Linux smbfs module over the years. Thanks to | 16 | Newbigin and others for their work on the Linux smbfs module. Thanks to |
14 | the other members of the Storage Network Industry Association CIFS Technical | 17 | the other members of the Storage Network Industry Association CIFS Technical |
15 | Workgroup for their work specifying this highly complex protocol and finally | 18 | Workgroup for their work specifying this highly complex protocol and finally |
16 | thanks to the Samba team for their technical advice and encouragement. | 19 | thanks to the Samba team for their technical advice and encouragement. |
@@ -24,9 +27,11 @@ Shobhit Dayal | |||
24 | Sergey Vlasov | 27 | Sergey Vlasov |
25 | Richard Hughes | 28 | Richard Hughes |
26 | Yury Umanets | 29 | Yury Umanets |
27 | Mark Hamzy | 30 | Mark Hamzy (for some of the early cifs IPv6 work) |
28 | Domen Puncer | 31 | Domen Puncer |
29 | Jesper Juhl | 32 | Jesper Juhl (in particular for lots of whitespace/formatting cleanup) |
33 | Vince Negri and Dave Stahl (for finding an important caching bug) | ||
34 | Adrian Bunk (kcalloc cleanups) | ||
30 | 35 | ||
31 | Test case and Bug Report contributors | 36 | Test case and Bug Report contributors |
32 | ------------------------------------- | 37 | ------------------------------------- |
@@ -36,7 +41,8 @@ Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, | |||
36 | Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, | 41 | Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, |
37 | Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special | 42 | Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special |
38 | mention to the Stanford Checker (SWAT) which pointed out many minor | 43 | mention to the Stanford Checker (SWAT) which pointed out many minor |
39 | bugs in error paths. | 44 | bugs in error paths. Valuable suggestions also have come from Al Viro |
45 | and Dave Miller. | ||
40 | 46 | ||
41 | And thanks to the IBM LTC and Power test teams and SuSE testers for | 47 | And thanks to the IBM LTC and Power test teams and SuSE testers for |
42 | finding multiple bugs during excellent stress test runs. | 48 | finding 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 @@ | |||
1 | Version 1.31 | 1 | Version 1.34 |
2 | ------------ | ||
3 | Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. | ||
4 | Do not oops if root user kills cifs oplock kernel thread or | ||
5 | kills the cifsd thread (NB: killing the cifs kernel threads is not | ||
6 | recommended, unmount and rmmod cifs will kill them when they are | ||
7 | no longer needed). Fix readdir to ASCII servers (ie older servers | ||
8 | which do not support Unicode) and also require asterik. | ||
9 | |||
10 | |||
11 | Version 1.33 | ||
12 | ------------ | ||
13 | Fix caching problem, in which readdir of directory containing a file | ||
14 | which was cached could cause the file's time stamp to be updated | ||
15 | without invalidating the readahead data (so we could get stale | ||
16 | file data on the client for that file even as the server copy changed). | ||
17 | Cleanup response processing so cifsd can not loop when abnormally | ||
18 | terminated. | ||
19 | |||
20 | |||
21 | Version 1.32 | ||
2 | ------------ | 22 | ------------ |
3 | Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one | 23 | Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one |
4 | transact response for an SMB request and search entry split across two frames. | 24 | transact response for an SMB request and search entry split across two frames. |
25 | Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) | ||
26 | as new protocol extensions. Do not send Get/Set calls for POSIX ACLs | ||
27 | unless server explicitly claims to support them in CIFS Unix extensions | ||
28 | POSIX ACL capability bit. Fix packet signing when multiuser mounting with | ||
29 | different users from the same client to the same server. Fix oops in | ||
30 | cifs_close. Add mount option for remapping reserved characters in | ||
31 | filenames (also allow recognizing files with created by SFU which have any | ||
32 | of these seven reserved characters, except backslash, to be recognized). | ||
33 | Fix invalid transact2 message (we were sometimes trying to interpret | ||
34 | oplock breaks as SMB responses). Add ioctl for checking that the | ||
35 | current uid matches the uid of the mounter (needed by umount.cifs). | ||
36 | Reduce the number of large buffer allocations in cifs response processing | ||
37 | (significantly reduces memory pressure under heavy stress with multiple | ||
38 | processes accessing the same server at the same time). | ||
39 | |||
40 | Version 1.31 | ||
41 | ------------ | ||
5 | Fix updates of DOS attributes and time fields so that files on NT4 servers | 42 | Fix updates of DOS attributes and time fields so that files on NT4 servers |
6 | do not get marked delete on close. Display sizes of cifs buffer pools in | 43 | do not get marked delete on close. Display sizes of cifs buffer pools in |
7 | cifs stats. Fix oops in unmount when cifsd thread being killed by | 44 | cifs 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 | ==================== |
76 | To permit users to mount and unmount over directories they own is possible | 76 | To permit users to mount and unmount over directories they own is possible |
77 | with the cifs vfs. A way to enable such mounting is to mark the mount.cifs | 77 | with the cifs vfs. A way to enable such mounting is to mark the mount.cifs |
78 | utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to | 78 | utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to |
79 | umount shares they mount requires | 79 | umount shares they mount requires |
80 | 1) mount.cifs version 1.4 or later | 80 | 1) mount.cifs version 1.4 or later |
81 | 2) an entry for the share in /etc/fstab indicating that a user may | 81 | 2) an entry for the share in /etc/fstab indicating that a user may |
@@ -97,6 +97,26 @@ mount.cifs with the following flag: | |||
97 | There is a corresponding manual page for cifs mounting in the Samba 3.0 and | 97 | There is a corresponding manual page for cifs mounting in the Samba 3.0 and |
98 | later source tree in docs/manpages/mount.cifs.8 | 98 | later source tree in docs/manpages/mount.cifs.8 |
99 | 99 | ||
100 | Allowing User Unmounts | ||
101 | ====================== | ||
102 | To permit users to ummount directories that they have user mounted (see above), | ||
103 | the utility umount.cifs may be used. It may be invoked directly, or if | ||
104 | umount.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 | ||
106 | mounts, unless umount is invoked with -i (which will avoid invoking a umount | ||
107 | helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked | ||
108 | as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions | ||
109 | allow adding entries to a file to the /etc/permissions file to achieve the | ||
110 | equivalent suid effect). For this utility to succeed the target path | ||
111 | must be a cifs mount, and the uid of the current user must match the uid | ||
112 | of the user who mounted the resource. | ||
113 | |||
114 | Also 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 | ||
116 | to the file /etc/fstab for each //server/share you wish to mount, but | ||
117 | this can become unwieldy when potential mount targets include many | ||
118 | or unpredictable UNC names. | ||
119 | |||
100 | Samba Considerations | 120 | Samba Considerations |
101 | ==================== | 121 | ==================== |
102 | To get the maximum benefit from the CIFS VFS, we recommend using a server that | 122 | To 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 | ||
380 | The mount.cifs mount helper also accepts a few mount options before -o | 413 | The mount.cifs mount helper also accepts a few mount options before -o |
381 | including: | 414 | including: |
@@ -392,7 +425,7 @@ Misc /proc/fs/cifs Flags and Debug Info | |||
392 | ======================================= | 425 | ======================================= |
393 | Informational pseudo-files: | 426 | Informational pseudo-files: |
394 | DebugData Displays information about active CIFS sessions | 427 | DebugData Displays information about active CIFS sessions |
395 | and shares. | 428 | and shares, as well as the cifs.ko version. |
396 | Stats Lists summary resource usage information as well as per | 429 | Stats 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 | |||
449 | Two other experimental features are under development and to test | 482 | Two other experimental features are under development and to test |
450 | require enabling CONFIG_CIFS_EXPERIMENTAL | 483 | require 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 | ||
468 | Also note that "cat /proc/fs/cifs/DebugData" will display information about | 501 | Also note that "cat /proc/fs/cifs/DebugData" will display information about |
469 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement | 502 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement |
470 | will not work since they its implementation is not quite complete yet. | 503 | will not work since its implementation is not quite complete yet. Do not alter |
471 | Do not alter these configuration values unless you are doing specific testing. | 504 | the ExtendedSecurity configuration value unless you are doing specific testing. |
472 | Enabling extended security works to Windows 2000 Workstations and XP but not to | 505 | Enabling extended security works to Windows 2000 Workstations and XP but not to |
473 | Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" | 506 | Windows 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 @@ | |||
1 | version 1.22 July 30, 2004 | 1 | version 1.34 April 29, 2005 |
2 | 2 | ||
3 | A Partial List of Missing Features | 3 | A Partial List of Missing Features |
4 | ================================== | 4 | ================================== |
@@ -14,7 +14,7 @@ b) Better pam/winbind integration (e.g. to handle uid mapping | |||
14 | better) | 14 | better) |
15 | 15 | ||
16 | c) multi-user mounts - multiplexed sessionsetups over single vc | 16 | c) 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 | ||
19 | d) Kerberos/SPNEGO session setup support - (started) | 19 | d) Kerberos/SPNEGO session setup support - (started) |
20 | 20 | ||
@@ -67,12 +67,26 @@ q) implement support for security and trusted categories of xattrs | |||
67 | 67 | ||
68 | r) Implement O_DIRECT flag on open (already supported on mount) | 68 | r) Implement O_DIRECT flag on open (already supported on mount) |
69 | 69 | ||
70 | KNOWN BUGS (updated December 10, 2004) | 70 | s) Allow remapping of last remaining character (\) to +0xF000 which |
71 | (this character is valid for POSIX but not for Windows) | ||
72 | |||
73 | t) Create UID mapping facility so server UIDs can be mapped on a per | ||
74 | mount or a per server basis to client UIDs or nobody if no mapping | ||
75 | exists. This is helpful when Unix extensions are negotiated to | ||
76 | allow better permission checking when UIDs differ on the server | ||
77 | and client. Add new protocol request to the CIFS protocol | ||
78 | standard for asking the server for the corresponding name of a | ||
79 | particular uid. | ||
80 | |||
81 | KNOWN BUGS (updated April 29, 2005) | ||
71 | ==================================== | 82 | ==================================== |
83 | See http://bugzilla.samba.org - search on product "CifsVFS" for | ||
84 | current bug list. | ||
85 | |||
72 | 1) existing symbolic links (Windows reparse points) are recognized but | 86 | 1) existing symbolic links (Windows reparse points) are recognized but |
73 | can not be created remotely. They are implemented for Samba and those that | 87 | can not be created remotely. They are implemented for Samba and those that |
74 | support the CIFS Unix extensions but Samba has a bug currently handling | 88 | support the CIFS Unix extensions, although earlier versions of Samba |
75 | symlink text beginning with slash | 89 | overly restrict the pathnames. |
76 | 2) follow_link and readdir code does not follow dfs junctions | 90 | 2) follow_link and readdir code does not follow dfs junctions |
77 | but recognizes them | 91 | but recognizes them |
78 | 3) create of new files to FAT partitions on Windows servers can | 92 | 3) 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, | |||
98 | and when signing is disabled to request larger read sizes (larger than | 112 | and when signing is disabled to request larger read sizes (larger than |
99 | negotiated size) and send larger write sizes to modern servers. | 113 | negotiated size) and send larger write sizes to modern servers. |
100 | 114 | ||
101 | 4) More exhaustively test the recently added NT4 support against various | 115 | 4) More exhaustively test against less common servers. More testing |
102 | NT4 service pack levels, and fix cifs_setattr for setting file times and | 116 | against Windows 9x, Windows ME servers. |
103 | size 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 | ||
33 | void | 34 | void |
34 | cifs_dump_mem(char *label, void *data, int length) | 35 | cifs_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 | ||
27 | struct cifs_sb_info { | 28 | struct 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 | ||
53 | int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, | 53 | int 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) | |||
169 | static int | 169 | static int |
170 | cifs_statfs(struct super_block *sb, struct kstatfs *buf) | 170 | cifs_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 | ||
211 | static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) | 215 | static 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 | ||
596 | static void | 609 | static 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 | ||
827 | static int __init | 841 | static 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); |
92 | extern int cifs_removexattr(struct dentry *, const char *); | 92 | extern int cifs_removexattr(struct dentry *, const char *); |
93 | extern int cifs_setxattr(struct dentry *, const char *, const void *, | 93 | extern int cifs_setxattr(struct dentry *, const char *, const void *, |
94 | size_t, int); | 94 | size_t, int); |
95 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | 95 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); |
96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
97 | #define CIFS_VERSION "1.31" | 97 | extern 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 | ||
323 | struct oplock_q_entry { | 327 | struct 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 | |||
766 | typedef 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 | |||
765 | typedef struct smb_com_lock_rsp { | 775 | typedef 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 | |||
1257 | struct 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 | ||
1265 | struct 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 */ | ||
1530 | typedef struct { | 1560 | typedef 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 | ||
1974 | typedef struct { | 2004 | typedef 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 | |||
2033 | typedef 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, | |||
57 | extern int cifs_inet_pton(int, char * source, void *dst); | 57 | extern int cifs_inet_pton(int, char * source, void *dst); |
58 | extern int map_smb_to_linux_error(struct smb_hdr *smb); | 58 | extern int map_smb_to_linux_error(struct smb_hdr *smb); |
59 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 59 | extern 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 | ); |
63 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); | 63 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, |
64 | struct cifsTconInfo *); | ||
64 | extern void DeleteOplockQEntry(struct oplock_q_entry *); | 65 | extern void DeleteOplockQEntry(struct oplock_q_entry *); |
65 | extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); | 66 | extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); |
66 | extern u64 cifs_UnixTimeToNT(struct timespec); | 67 | extern u64 cifs_UnixTimeToNT(struct timespec); |
@@ -88,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
88 | 89 | ||
89 | extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | 90 | extern 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 | ||
93 | extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | 94 | extern 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, | |||
99 | extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 100 | extern 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 | ||
104 | extern int CIFSSMBUnixQPathInfo(const int xid, | 105 | extern 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 | ||
110 | extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 111 | extern 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 | ||
116 | extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 117 | extern 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); |
119 | extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 120 | extern 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); | ||
122 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 126 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, |
123 | struct kstatfs *FSData, | 127 | struct kstatfs *FSData); |
124 | const struct nls_table *nls_codepage); | ||
125 | extern int CIFSSMBQFSAttributeInfo(const int xid, | 128 | extern int CIFSSMBQFSAttributeInfo(const int xid, |
126 | struct cifsTconInfo *tcon, | 129 | struct cifsTconInfo *tcon); |
127 | const struct nls_table *nls_codepage); | 130 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); |
128 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, | 131 | extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon); |
129 | const struct nls_table *nls_codepage); | ||
130 | extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, | ||
131 | const struct nls_table *nls_codepage); | ||
132 | extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 132 | extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, |
133 | struct kstatfs *FSData, const struct nls_table *nls_codepage); | 133 | struct kstatfs *FSData); |
134 | 134 | ||
135 | extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, | 135 | extern 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); | ||
138 | extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | 139 | extern 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 */ |
145 | extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, | 146 | extern 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); | ||
148 | extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, | 151 | extern 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); | ||
150 | extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, | 154 | extern 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 | ||
154 | extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, | 160 | extern 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); | ||
157 | extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, | 164 | extern 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 | ||
160 | extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, | 168 | extern 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); | ||
163 | extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, | 172 | extern 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); | ||
166 | extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, | 176 | extern 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); | ||
168 | extern int CIFSCreateHardLink(const int xid, | 180 | extern 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); | ||
172 | extern int CIFSUnixCreateHardLink(const int xid, | 185 | extern 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); | ||
176 | extern int CIFSUnixCreateSymLink(const int xid, | 190 | extern 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); |
196 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, | 210 | extern 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); |
212 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 226 | extern 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 */ |
231 | extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, | ||
232 | const struct nls_table * codepage); | ||
233 | extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | ||
234 | const struct nls_table * cp, int mapChars); | ||
216 | 235 | ||
217 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 236 | extern 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 | ||
231 | extern int cifs_reconnect(struct TCP_Server_Info *server); | 250 | extern int cifs_reconnect(struct TCP_Server_Info *server); |
232 | 251 | ||
233 | extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); | 252 | extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); |
234 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, | 253 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, |
235 | __u32 expected_sequence_number); | 254 | __u32 expected_sequence_number); |
236 | extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); | 255 | extern 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); | ||
245 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | 265 | extern 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); |
248 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 268 | extern 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); | ||
251 | extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, | 272 | extern 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); |
255 | extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, | 276 | extern 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); |
259 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 280 | extern 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); |
263 | extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, | 284 | extern 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); |
267 | int cifs_ioctl (struct inode * inode, struct file * filep, | 288 | extern 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 | ||
540 | int | 552 | int |
541 | CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, | 553 | CIFSSMBDelFile(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 | ||
591 | int | 602 | int |
592 | CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, | 603 | CIFSSMBRmDir(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 | ||
640 | int | 650 | int |
641 | CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, | 651 | CIFSSMBMkDir(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) | |||
1108 | int | 1118 | int |
1109 | CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, | 1119 | CIFSSMBRename(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 | ||
1184 | int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, | 1192 | int 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, | |||
1263 | int | 1274 | int |
1264 | CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, | 1275 | CIFSSMBCopy(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: | |||
1425 | int | 1434 | int |
1426 | CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, | 1435 | CIFSUnixCreateHardLink(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: | |||
1512 | int | 1519 | int |
1513 | CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, | 1520 | CIFSCreateHardLink(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 */ |
1796 | static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area) | 1802 | static 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 | |||
1912 | CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 1919 | CIFSSMBGetPosixACL(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: | |||
1997 | int | 2004 | int |
1998 | CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, | 2005 | CIFSSMBSetPosixACL(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 */ |
2084 | int | ||
2085 | CIFSGetExtAttr(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 | |||
2098 | GetExtAttrRetry: | ||
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 | } | ||
2158 | GetExtAttrOut: | ||
2159 | cifs_buf_release(pSMB); | ||
2160 | if (rc == -EAGAIN) | ||
2161 | goto GetExtAttrRetry; | ||
2162 | return rc; | ||
2163 | } | ||
2164 | |||
2165 | |||
2166 | #endif /* CONFIG_POSIX */ | ||
2076 | 2167 | ||
2077 | int | 2168 | int |
2078 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2169 | CIFSSMBQPathInfo(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 | |||
2160 | CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2250 | CIFSSMBUnixQPathInfo(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 | ||
2341 | findFirstRetry: | 2430 | findFirstRetry: |
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 | |||
2608 | CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 2705 | CIFSGetSrvInodeNumber(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 | ||
2873 | int | 2968 | int |
2874 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 2969 | CIFSSMBQFSInfo(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 | ||
2957 | int | 3051 | int |
2958 | CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon, | 3052 | CIFSSMBQFSAttributeInfo(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 | ||
3026 | int | 3119 | int |
3027 | CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, | 3120 | CIFSSMBQFSDeviceInfo(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 | ||
3096 | int | 3188 | int |
3097 | CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, | 3189 | CIFSSMBQFSUnixInfo(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 | ||
3167 | int | 3258 | int |
3168 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3259 | CIFSSMBQFSPosixInfo(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 | ||
3259 | int | 3350 | int |
3260 | CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 3351 | CIFSSMBSetEOF(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 | |||
3512 | int | 3607 | int |
3513 | CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 3608 | CIFSSMBSetTimes(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 | ||
3645 | int | 3739 | int |
3646 | CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, | 3740 | CIFSSMBUnixSetPerms(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 | |||
3789 | CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 3883 | CIFSSMBQAllEAs(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: | |||
3934 | ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, | 4027 | ssize_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: | |||
4082 | int | 4174 | int |
4083 | CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 4175 | CIFSSMBSetEA(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 | */ | ||
203 | static 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 | |||
245 | static 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 | |||
193 | static int | 311 | static int |
194 | cifs_demultiplex_thread(struct TCP_Server_Info *server) | 312 | cifs_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; | ||
579 | multi_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 | ||
472 | static void * | ||
473 | cifs_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 | |||
482 | static int | 718 | static int |
483 | cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | 719 | cifs_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 | ||
919 | int | 1172 | int |
920 | connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 1173 | connect_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, | |||
940 | int | 1194 | int |
941 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 1195 | get_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 | 2064 | sesssetup_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) |
105 | char * | ||
106 | build_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 | |||
117 | cifs_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 | 112 | BB 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 | 277 | cifs_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 | ||
456 | int | ||
457 | cifs_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 | |||
487 | static int | 406 | static int |
488 | cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | 407 | cifs_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 | ||
30 | int cifs_ioctl (struct inode * inode, struct file * filep, | 34 | int 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 | ||
32 | extern mempool_t *cifs_sm_req_poolp; | 33 | extern mempool_t *cifs_sm_req_poolp; |
33 | extern mempool_t *cifs_req_poolp; | 34 | extern 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 */ | ||
539 | int | ||
540 | cifs_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 | } | ||
589 | cUCS_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 */ | ||
598 | int | ||
599 | cifsConvertToUCS(__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 | |||
658 | ctoUCS_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 | ||
107 | static void fill_in_inode(struct inode *tmp_inode, | 107 | static 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 | ||
199 | static void unix_fill_in_inode(struct inode *tmp_inode, | 218 | static 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 | ||
365 | ffirst_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 |
78 | class.*/ | 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 | ||
183 | int | 186 | int |
184 | smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, | 187 | smb_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 | } |
88 | remove_ea_exit: | 89 | remove_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 | ||
810 | struct compat_nfs_string { | 810 | struct 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 | ||
815 | static inline void compat_nfs_string(struct nfs_string *dst, | 815 | static 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 | ||
843 | static int do_nfs4_super_data_conv(void *raw_data) | 843 | static 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 | ||
462 | static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4], | 461 | static 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 | ||
593 | static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, | 584 | static 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 | ||
660 | changed: | ||
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 | |||
668 | err_out: | 645 | err_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 | ||
719 | reread: | ||
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); |
725 | got_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) |
736 | cleanup: | 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); |
743 | out: | 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; | 769 | got_it: |
797 | 770 | map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); | |
798 | changed: | 771 | if (boundary) |
772 | set_buffer_boundary(bh_result); | ||
773 | /* Clean up and exit */ | ||
774 | partial = chain + depth - 1; /* the whole chain */ | ||
775 | cleanup: | ||
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"); |
782 | out: | ||
783 | return err; | ||
806 | } | 784 | } |
807 | 785 | ||
808 | static int ext3_get_block(struct inode *inode, sector_t iblock, | 786 | static 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. */ |
334 | void hfs_mdb_put(struct super_block *sb) | 334 | void 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); |
341 | bail_no_root: | 341 | bail_no_root: |
342 | hfs_warn("hfs_fs: get root inode failed.\n"); | 342 | hfs_warn("hfs_fs: get root inode failed.\n"); |
343 | bail: | ||
343 | hfs_mdb_put(sb); | 344 | hfs_mdb_put(sb); |
344 | bail2: | ||
345 | bail3: | ||
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) | |||
208 | static void hfsplus_put_super(struct super_block *sb) | 208 | static 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 | ||
231 | static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) | 235 | static 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, | |||
521 | static struct address_space_operations hostfs_aops = { | 521 | static 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 | */ | ||
1060 | void 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); | |||
506 | extern int lmLogInit(struct jfs_log * log); | 508 | extern int lmLogInit(struct jfs_log * log); |
507 | extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize); | 509 | extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize); |
508 | extern void jfs_flush_journal(struct jfs_log * log, int wait); | 510 | extern void jfs_flush_journal(struct jfs_log * log, int wait); |
511 | extern 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 | ||
32 | static DEFINE_SPINLOCK(meta_lock); | ||
33 | |||
34 | #ifdef CONFIG_JFS_STATISTICS | 33 | #ifdef CONFIG_JFS_STATISTICS |
35 | static struct { | 34 | static 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) | ||
45 | static struct metapage **hash_table = NULL; | ||
46 | static unsigned long hash_order; | ||
47 | |||
48 | |||
49 | static inline int metapage_locked(struct metapage *mp) | ||
50 | { | ||
51 | return test_bit(META_locked, &mp->flag); | ||
52 | } | ||
53 | |||
54 | static inline int trylock_metapage(struct metapage *mp) | ||
55 | { | ||
56 | return test_and_set_bit(META_locked, &mp->flag); | ||
57 | } | ||
58 | 43 | ||
59 | static inline void unlock_metapage(struct metapage *mp) | 44 | static 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 | ||
65 | static void __lock_metapage(struct metapage *mp) | 50 | static 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 | */ | ||
85 | static inline void lock_metapage(struct metapage *mp) | 70 | static 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) | |||
92 | static kmem_cache_t *metapage_cache; | 77 | static kmem_cache_t *metapage_cache; |
93 | static mempool_t *metapage_mempool; | 78 | static mempool_t *metapage_mempool; |
94 | 79 | ||
80 | #define MPS_PER_PAGE (PAGE_CACHE_SIZE >> L2PSIZE) | ||
81 | |||
82 | #if MPS_PER_PAGE > 1 | ||
83 | |||
84 | struct 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 | |||
91 | static 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 | |||
98 | static 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 | |||
126 | static 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 | |||
145 | static inline void inc_io(struct page *page) | ||
146 | { | ||
147 | atomic_inc(&mp_anchor(page)->io_count); | ||
148 | } | ||
149 | |||
150 | static 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 | ||
157 | static inline struct metapage *page_to_mp(struct page *page, uint offset) | ||
158 | { | ||
159 | return PagePrivate(page) ? (struct metapage *)page->private : NULL; | ||
160 | } | ||
161 | |||
162 | static 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 | |||
172 | static 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 | |||
95 | static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) | 184 | static 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 | ||
241 | static 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 | */ |
165 | static struct metapage **meta_hash(struct address_space *mapping, | 254 | |
166 | unsigned long index) | 255 | static 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 | ||
176 | static struct metapage *search_hash(struct metapage ** hash_ptr, | 280 | static 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 | |||
287 | static 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 | ||
190 | static void add_to_hash(struct metapage * mp, struct metapage ** hash_ptr) | 306 | static 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; | 328 | static 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 | ||
200 | static void remove_from_hash(struct metapage * mp, struct metapage ** hash_ptr) | 348 | static 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 | |||
367 | static 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; | ||
468 | add_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; | ||
472 | dump_bio: | ||
473 | dump_mem("bio", bio, sizeof(*bio)); | ||
474 | skip: | ||
475 | bio_put(bio); | ||
476 | unlock_page(page); | ||
477 | dec_io(page, last_write_complete); | ||
478 | |||
479 | return -EIO; | ||
480 | } | ||
481 | |||
482 | static 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) | 530 | add_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 | ||
537 | static 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 | |||
577 | static 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 | |||
587 | struct 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 | |||
213 | struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, | 596 | struct 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)) { |
241 | again: | 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 | ||
366 | freeit: | 700 | unlock: |
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 | ||
374 | void hold_metapage(struct metapage * mp, int force) | 705 | void 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 | ||
390 | static void __write_metapage(struct metapage * mp) | 715 | void 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 | ||
729 | extern 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); | 734 | extern 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 | |||
428 | static 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 | ||
443 | void release_metapage(struct metapage * mp) | 748 | void 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 | ||
507 | void __invalidate_metapages(struct inode *ip, s64 addr, int len) | 803 | void __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); |
524 | again: | 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 | ||
82 | extern void release_metapage(struct metapage *); | 71 | extern void release_metapage(struct metapage *); |
83 | extern void hold_metapage(struct metapage *, int); | 72 | extern void grab_metapage(struct metapage *); |
73 | extern 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 | */ | ||
80 | extern void hold_metapage(struct metapage *); | ||
81 | extern void put_metapage(struct metapage *); | ||
84 | 82 | ||
85 | static inline void write_metapage(struct metapage *mp) | 83 | static 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 | ||
102 | static 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 | */ | ||
118 | static 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 | */ | ||
127 | static inline void _metapage_homeok(struct metapage *mp) | ||
128 | { | ||
129 | if (!--mp->nohomeok) | ||
130 | page_cache_release(mp->page); | ||
131 | } | ||
132 | |||
133 | static inline void metapage_homeok(struct metapage *mp) | ||
134 | { | ||
135 | hold_metapage(mp); | ||
136 | _metapage_homeok(mp); | ||
137 | put_metapage(mp); | ||
138 | } | ||
139 | |||
140 | extern 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 | ||
228 | static void txLockFree(lid_t lid) | 228 | static 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(); | ||
588 | wakeup: | ||
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 | */ |
50 | int jfs_umount(struct super_block *sb) | 50 | int 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 | ||
141 | int jfs_umount_rw(struct super_block *sb) | 137 | int 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 | */ |
114 | static int xtSearch(struct inode *ip, | 114 | static 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 | ||
117 | static int xtSplitUp(tid_t tid, | 117 | static 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 | */ |
500 | static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ | 505 | static 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 | } |
509 | out_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; | ||
485 | out_kfree: | 516 | out_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 | */ | ||
209 | static struct bio * | 163 | static struct bio * |
210 | do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, | 164 | do_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 | */ | ||
323 | int | 323 | int |
324 | mpage_readpages(struct address_space *mapping, struct list_head *pages, | 324 | mpage_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; | |||
1419 | static struct inode_operations proc_tgid_attr_inode_operations; | 1419 | static struct inode_operations proc_tgid_attr_inode_operations; |
1420 | #endif | 1420 | #endif |
1421 | 1421 | ||
1422 | static int get_tid_list(int index, unsigned int *tids, struct inode *dir); | ||
1423 | |||
1422 | /* SMP-safe */ | 1424 | /* SMP-safe */ |
1423 | static struct dentry *proc_pident_lookup(struct inode *dir, | 1425 | static 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 | */ |
263 | u32 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 |
737 | static inline void displace_new_packing_locality (reiserfs_blocknr_hint_t *hint) | 738 | static 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 | ||
778 | static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint) | 779 | static 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 */ |
212 | void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, | 212 | void 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 */ |
245 | void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, | 245 | void 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 */ |
174 | static inline int allocation_needed (int retval, b_blocknr_t allocated, | 174 | static 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) | |||
296 | static void indirect_print_item (struct item_head * ih, char * item) | 296 | static 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 | ||
20 | static void check_objectid_map (struct super_block * s, __u32 * map) | 20 | static 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 |
30 | static void check_objectid_map (struct super_block * s, __u32 * map) | 30 | static 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, | |||
87 | inline int comp_short_keys (const struct reiserfs_key * le_key, | 87 | inline 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 | ||
153 | inline void le_key2cpu_key (struct cpu_key * to, const struct reiserfs_key * from) | 151 | inline 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; | |||
228 | const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; | 223 | const 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. */ |
231 | const struct reiserfs_key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; | 226 | const 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 | ||
233 | const 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 | ||
113 | extern const struct reiserfs_key MAX_KEY; | 113 | extern 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); |