fat: rcu-delay unloading nls and freeing sbi
[deliverable/linux.git] / fs / ncpfs / inode.c
CommitLineData
1da177e4
LT
1/*
2 * inode.c
3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified for big endian by J.F. Chadima and David S. Miller
6 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7 * Modified 1998 Wolfram Pienkoss for NLS
8 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
9 *
10 */
11
1da177e4
LT
12#include <linux/module.h>
13
1da177e4
LT
14#include <asm/uaccess.h>
15#include <asm/byteorder.h>
16
17#include <linux/time.h>
18#include <linux/kernel.h>
19#include <linux/mm.h>
20#include <linux/string.h>
21#include <linux/stat.h>
22#include <linux/errno.h>
23#include <linux/file.h>
24#include <linux/fcntl.h>
25#include <linux/slab.h>
26#include <linux/vmalloc.h>
27#include <linux/init.h>
1da177e4 28#include <linux/vfs.h>
564cd138
MS
29#include <linux/mount.h>
30#include <linux/seq_file.h>
34286d66 31#include <linux/namei.h>
1da177e4 32
1da177e4
LT
33#include <net/sock.h>
34
32c419d9 35#include "ncp_fs.h"
1da177e4
LT
36#include "getopt.h"
37
564cd138
MS
38#define NCP_DEFAULT_FILE_MODE 0600
39#define NCP_DEFAULT_DIR_MODE 0700
40#define NCP_DEFAULT_TIME_OUT 10
41#define NCP_DEFAULT_RETRY_COUNT 20
42
94ee8494 43static void ncp_evict_inode(struct inode *);
1da177e4 44static void ncp_put_super(struct super_block *);
726c3342 45static int ncp_statfs(struct dentry *, struct kstatfs *);
34c80b1d 46static int ncp_show_options(struct seq_file *, struct dentry *);
1da177e4 47
e18b890b 48static struct kmem_cache * ncp_inode_cachep;
1da177e4
LT
49
50static struct inode *ncp_alloc_inode(struct super_block *sb)
51{
52 struct ncp_inode_info *ei;
e94b1766 53 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
1da177e4
LT
54 if (!ei)
55 return NULL;
56 return &ei->vfs_inode;
57}
58
fa0d7e3d 59static void ncp_i_callback(struct rcu_head *head)
1da177e4 60{
fa0d7e3d 61 struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4
LT
62 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
63}
64
fa0d7e3d
NP
65static void ncp_destroy_inode(struct inode *inode)
66{
67 call_rcu(&inode->i_rcu, ncp_i_callback);
68}
69
51cc5068 70static void init_once(void *foo)
1da177e4
LT
71{
72 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
73
a35afb83
CL
74 mutex_init(&ei->open_mutex);
75 inode_init_once(&ei->vfs_inode);
1da177e4 76}
20c2df83 77
1da177e4
LT
78static int init_inodecache(void)
79{
80 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
81 sizeof(struct ncp_inode_info),
fffb60f9
PJ
82 0, (SLAB_RECLAIM_ACCOUNT|
83 SLAB_MEM_SPREAD),
20c2df83 84 init_once);
1da177e4
LT
85 if (ncp_inode_cachep == NULL)
86 return -ENOMEM;
87 return 0;
88}
89
90static void destroy_inodecache(void)
91{
8c0a8537
KS
92 /*
93 * Make sure all delayed rcu free inodes are flushed before we
94 * destroy cache.
95 */
96 rcu_barrier();
1a1d92c1 97 kmem_cache_destroy(ncp_inode_cachep);
1da177e4
LT
98}
99
100static int ncp_remount(struct super_block *sb, int *flags, char* data)
101{
102 *flags |= MS_NODIRATIME;
103 return 0;
104}
105
ee9b6d61 106static const struct super_operations ncp_sops =
1da177e4
LT
107{
108 .alloc_inode = ncp_alloc_inode,
109 .destroy_inode = ncp_destroy_inode,
110 .drop_inode = generic_delete_inode,
94ee8494 111 .evict_inode = ncp_evict_inode,
1da177e4
LT
112 .put_super = ncp_put_super,
113 .statfs = ncp_statfs,
114 .remount_fs = ncp_remount,
564cd138 115 .show_options = ncp_show_options,
1da177e4
LT
116};
117
1da177e4
LT
118/*
119 * Fill in the ncpfs-specific information in the inode.
120 */
121static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
122{
123 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
124 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
125 NCP_FINFO(inode)->volNumber = nwinfo->volume;
126}
127
128void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
129{
130 ncp_update_dirent(inode, nwinfo);
131 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
132 NCP_FINFO(inode)->access = nwinfo->access;
133 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
134 sizeof(nwinfo->file_handle));
135 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
136 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
137 NCP_FINFO(inode)->dirEntNum);
138}
139
140static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
141{
142 /* NFS namespace mode overrides others if it's set. */
143 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
144 nwi->entryName, nwi->nfs.mode);
145 if (nwi->nfs.mode) {
146 /* XXX Security? */
147 inode->i_mode = nwi->nfs.mode;
148 }
149
2e54eb96 150 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
1da177e4
LT
151
152 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
153 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
154 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
155 inode->i_atime.tv_nsec = 0;
156 inode->i_mtime.tv_nsec = 0;
157 inode->i_ctime.tv_nsec = 0;
158}
159
160static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
161{
162 struct nw_info_struct *nwi = &nwinfo->i;
163 struct ncp_server *server = NCP_SERVER(inode);
164
165 if (nwi->attributes & aDIR) {
166 inode->i_mode = server->m.dir_mode;
167 /* for directories dataStreamSize seems to be some
168 Object ID ??? */
2e54eb96 169 i_size_write(inode, NCP_BLOCK_SIZE);
1da177e4 170 } else {
2e54eb96
PV
171 u32 size;
172
1da177e4 173 inode->i_mode = server->m.file_mode;
2e54eb96
PV
174 size = le32_to_cpu(nwi->dataStreamSize);
175 i_size_write(inode, size);
1da177e4
LT
176#ifdef CONFIG_NCPFS_EXTRAS
177 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
178 && (nwi->attributes & aSHARED)) {
179 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
180 case aHIDDEN:
181 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
2e54eb96
PV
182 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
183 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
1da177e4
LT
184 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
185 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
186 break;
187 }
188 }
189 /* FALLTHROUGH */
190 case 0:
191 if (server->m.flags & NCP_MOUNT_EXTRAS)
192 inode->i_mode |= S_IRUGO;
193 break;
194 case aSYSTEM:
195 if (server->m.flags & NCP_MOUNT_EXTRAS)
196 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
197 break;
198 /* case aSYSTEM|aHIDDEN: */
199 default:
200 /* reserved combination */
201 break;
202 }
203 }
204#endif
205 }
206 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
207}
208
209void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
210{
211 NCP_FINFO(inode)->flags = 0;
212 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
213 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
214 ncp_update_attrs(inode, nwinfo);
215 }
216
217 ncp_update_dates(inode, &nwinfo->i);
218 ncp_update_dirent(inode, nwinfo);
219}
220
221/*
2e54eb96 222 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
1da177e4
LT
223 */
224static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
225{
226 struct ncp_server *server = NCP_SERVER(inode);
227
228 NCP_FINFO(inode)->flags = 0;
229
230 ncp_update_attrs(inode, nwinfo);
231
232 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
233
bfe86848 234 set_nlink(inode, 1);
1da177e4
LT
235 inode->i_uid = server->m.uid;
236 inode->i_gid = server->m.gid;
1da177e4
LT
237
238 ncp_update_dates(inode, &nwinfo->i);
239 ncp_update_inode(inode, nwinfo);
240}
241
242#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
92e1d5be 243static const struct inode_operations ncp_symlink_inode_operations = {
1da177e4
LT
244 .readlink = generic_readlink,
245 .follow_link = page_follow_link_light,
246 .put_link = page_put_link,
247 .setattr = ncp_notify_change,
248};
249#endif
250
251/*
252 * Get a new inode.
253 */
254struct inode *
255ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
256{
257 struct inode *inode;
258
259 if (info == NULL) {
260 printk(KERN_ERR "ncp_iget: info is NULL\n");
261 return NULL;
262 }
263
264 inode = new_inode(sb);
265 if (inode) {
266 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
267
2e54eb96 268 inode->i_mapping->backing_dev_info = sb->s_bdi;
1da177e4
LT
269 inode->i_ino = info->ino;
270 ncp_set_attr(inode, info);
271 if (S_ISREG(inode->i_mode)) {
272 inode->i_op = &ncp_file_inode_operations;
273 inode->i_fop = &ncp_file_operations;
274 } else if (S_ISDIR(inode->i_mode)) {
275 inode->i_op = &ncp_dir_inode_operations;
276 inode->i_fop = &ncp_dir_operations;
277#ifdef CONFIG_NCPFS_NFS_NS
278 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
279 init_special_inode(inode, inode->i_mode,
280 new_decode_dev(info->i.nfs.rdev));
281#endif
282#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
283 } else if (S_ISLNK(inode->i_mode)) {
284 inode->i_op = &ncp_symlink_inode_operations;
285 inode->i_data.a_ops = &ncp_symlink_aops;
286#endif
287 } else {
288 make_bad_inode(inode);
289 }
290 insert_inode_hash(inode);
291 } else
292 printk(KERN_ERR "ncp_iget: iget failed!\n");
293 return inode;
294}
295
296static void
94ee8494 297ncp_evict_inode(struct inode *inode)
1da177e4 298{
fef26658 299 truncate_inode_pages(&inode->i_data, 0);
dbd5768f 300 clear_inode(inode);
fef26658 301
1da177e4 302 if (S_ISDIR(inode->i_mode)) {
94ee8494 303 DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
1da177e4
LT
304 }
305
306 if (ncp_make_closed(inode) != 0) {
307 /* We can't do anything but complain. */
94ee8494 308 printk(KERN_ERR "ncp_evict_inode: could not close\n");
1da177e4 309 }
1da177e4
LT
310}
311
312static void ncp_stop_tasks(struct ncp_server *server) {
313 struct sock* sk = server->ncp_sock->sk;
2a4df5d3
PV
314
315 lock_sock(sk);
1da177e4
LT
316 sk->sk_error_report = server->error_report;
317 sk->sk_data_ready = server->data_ready;
318 sk->sk_write_space = server->write_space;
2a4df5d3 319 release_sock(sk);
1da177e4 320 del_timer_sync(&server->timeout_tm);
5d8e4bdd 321
43829731 322 flush_work(&server->rcv.tq);
5d8e4bdd 323 if (sk->sk_socket->type == SOCK_STREAM)
43829731 324 flush_work(&server->tx.tq);
5d8e4bdd 325 else
43829731 326 flush_work(&server->timeout_tq);
1da177e4
LT
327}
328
34c80b1d 329static int ncp_show_options(struct seq_file *seq, struct dentry *root)
564cd138 330{
34c80b1d 331 struct ncp_server *server = NCP_SBP(root->d_sb);
564cd138
MS
332 unsigned int tmp;
333
1ac7fd81
EB
334 if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID))
335 seq_printf(seq, ",uid=%u",
336 from_kuid_munged(&init_user_ns, server->m.uid));
337 if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID))
338 seq_printf(seq, ",gid=%u",
339 from_kgid_munged(&init_user_ns, server->m.gid));
340 if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID))
341 seq_printf(seq, ",owner=%u",
342 from_kuid_munged(&init_user_ns, server->m.mounted_uid));
564cd138
MS
343 tmp = server->m.file_mode & S_IALLUGO;
344 if (tmp != NCP_DEFAULT_FILE_MODE)
345 seq_printf(seq, ",mode=0%o", tmp);
346 tmp = server->m.dir_mode & S_IALLUGO;
347 if (tmp != NCP_DEFAULT_DIR_MODE)
348 seq_printf(seq, ",dirmode=0%o", tmp);
349 if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
350 tmp = server->m.time_out * 100 / HZ;
351 seq_printf(seq, ",timeout=%u", tmp);
352 }
353 if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
354 seq_printf(seq, ",retry=%u", server->m.retry_count);
355 if (server->m.flags != 0)
356 seq_printf(seq, ",flags=%lu", server->m.flags);
357 if (server->m.wdog_pid != NULL)
358 seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
359
360 return 0;
361}
362
1da177e4
LT
363static const struct ncp_option ncp_opts[] = {
364 { "uid", OPT_INT, 'u' },
365 { "gid", OPT_INT, 'g' },
366 { "owner", OPT_INT, 'o' },
367 { "mode", OPT_INT, 'm' },
368 { "dirmode", OPT_INT, 'd' },
369 { "timeout", OPT_INT, 't' },
370 { "retry", OPT_INT, 'r' },
371 { "flags", OPT_INT, 'f' },
372 { "wdogpid", OPT_INT, 'w' },
373 { "ncpfd", OPT_INT, 'n' },
374 { "infofd", OPT_INT, 'i' }, /* v5 */
375 { "version", OPT_INT, 'v' },
376 { NULL, 0, 0 } };
377
378static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
379 int optval;
380 char *optarg;
381 unsigned long optint;
382 int version = 0;
1de24126 383 int ret;
1da177e4
LT
384
385 data->flags = 0;
386 data->int_flags = 0;
1ac7fd81 387 data->mounted_uid = GLOBAL_ROOT_UID;
2154227a 388 data->wdog_pid = NULL;
1da177e4 389 data->ncp_fd = ~0;
564cd138
MS
390 data->time_out = NCP_DEFAULT_TIME_OUT;
391 data->retry_count = NCP_DEFAULT_RETRY_COUNT;
1ac7fd81
EB
392 data->uid = GLOBAL_ROOT_UID;
393 data->gid = GLOBAL_ROOT_GID;
564cd138
MS
394 data->file_mode = NCP_DEFAULT_FILE_MODE;
395 data->dir_mode = NCP_DEFAULT_DIR_MODE;
1da177e4
LT
396 data->info_fd = -1;
397 data->mounted_vol[0] = 0;
398
399 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
1de24126
EB
400 ret = optval;
401 if (ret < 0)
402 goto err;
1da177e4
LT
403 switch (optval) {
404 case 'u':
1ac7fd81 405 data->uid = make_kuid(current_user_ns(), optint);
4fbeb19d
WY
406 if (!uid_valid(data->uid)) {
407 ret = -EINVAL;
1ac7fd81 408 goto err;
4fbeb19d 409 }
1da177e4
LT
410 break;
411 case 'g':
1ac7fd81 412 data->gid = make_kgid(current_user_ns(), optint);
4fbeb19d
WY
413 if (!gid_valid(data->gid)) {
414 ret = -EINVAL;
1ac7fd81 415 goto err;
4fbeb19d 416 }
1da177e4
LT
417 break;
418 case 'o':
1ac7fd81 419 data->mounted_uid = make_kuid(current_user_ns(), optint);
4fbeb19d
WY
420 if (!uid_valid(data->mounted_uid)) {
421 ret = -EINVAL;
1ac7fd81 422 goto err;
4fbeb19d 423 }
1da177e4
LT
424 break;
425 case 'm':
426 data->file_mode = optint;
427 break;
428 case 'd':
429 data->dir_mode = optint;
430 break;
431 case 't':
432 data->time_out = optint;
433 break;
434 case 'r':
435 data->retry_count = optint;
436 break;
437 case 'f':
438 data->flags = optint;
439 break;
440 case 'w':
2154227a 441 data->wdog_pid = find_get_pid(optint);
1da177e4
LT
442 break;
443 case 'n':
444 data->ncp_fd = optint;
445 break;
446 case 'i':
447 data->info_fd = optint;
448 break;
449 case 'v':
1de24126
EB
450 ret = -ECHRNG;
451 if (optint < NCP_MOUNT_VERSION_V4)
452 goto err;
453 if (optint > NCP_MOUNT_VERSION_V5)
454 goto err;
1da177e4
LT
455 version = optint;
456 break;
457
458 }
459 }
460 return 0;
1de24126
EB
461err:
462 put_pid(data->wdog_pid);
463 data->wdog_pid = NULL;
464 return ret;
1da177e4
LT
465}
466
467static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
468{
469 struct ncp_mount_data_kernel data;
470 struct ncp_server *server;
471 struct file *ncp_filp;
472 struct inode *root_inode;
473 struct inode *sock_inode;
474 struct socket *sock;
475 int error;
476 int default_bufsize;
477#ifdef CONFIG_NCPFS_PACKET_SIGNING
478 int options;
479#endif
480 struct ncp_entry_info finfo;
481
2a5cac17 482 memset(&data, 0, sizeof(data));
f8314dc6 483 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
1da177e4
LT
484 if (!server)
485 return -ENOMEM;
486 sb->s_fs_info = server;
1da177e4
LT
487
488 error = -EFAULT;
489 if (raw_data == NULL)
490 goto out;
491 switch (*(int*)raw_data) {
492 case NCP_MOUNT_VERSION:
493 {
494 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
495
496 data.flags = md->flags;
497 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
1ac7fd81 498 data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
2154227a 499 data.wdog_pid = find_get_pid(md->wdog_pid);
1da177e4
LT
500 data.ncp_fd = md->ncp_fd;
501 data.time_out = md->time_out;
502 data.retry_count = md->retry_count;
1ac7fd81
EB
503 data.uid = make_kuid(current_user_ns(), md->uid);
504 data.gid = make_kgid(current_user_ns(), md->gid);
1da177e4
LT
505 data.file_mode = md->file_mode;
506 data.dir_mode = md->dir_mode;
507 data.info_fd = -1;
508 memcpy(data.mounted_vol, md->mounted_vol,
509 NCP_VOLNAME_LEN+1);
510 }
511 break;
512 case NCP_MOUNT_VERSION_V4:
513 {
514 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
515
516 data.flags = md->flags;
1ac7fd81 517 data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
2154227a 518 data.wdog_pid = find_get_pid(md->wdog_pid);
1da177e4
LT
519 data.ncp_fd = md->ncp_fd;
520 data.time_out = md->time_out;
521 data.retry_count = md->retry_count;
1ac7fd81
EB
522 data.uid = make_kuid(current_user_ns(), md->uid);
523 data.gid = make_kgid(current_user_ns(), md->gid);
1da177e4
LT
524 data.file_mode = md->file_mode;
525 data.dir_mode = md->dir_mode;
526 data.info_fd = -1;
1da177e4
LT
527 }
528 break;
529 default:
530 error = -ECHRNG;
531 if (memcmp(raw_data, "vers", 4) == 0) {
532 error = ncp_parse_options(&data, raw_data);
533 }
534 if (error)
535 goto out;
536 break;
537 }
1ac7fd81
EB
538 error = -EINVAL;
539 if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
540 !gid_valid(data.gid))
541 goto out;
1da177e4
LT
542 error = -EBADF;
543 ncp_filp = fget(data.ncp_fd);
544 if (!ncp_filp)
545 goto out;
546 error = -ENOTSOCK;
496ad9aa 547 sock_inode = file_inode(ncp_filp);
1da177e4
LT
548 if (!S_ISSOCK(sock_inode->i_mode))
549 goto out_fput;
550 sock = SOCKET_I(sock_inode);
551 if (!sock)
552 goto out_fput;
553
554 if (sock->type == SOCK_STREAM)
555 default_bufsize = 0xF000;
556 else
557 default_bufsize = 1024;
558
559 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
560 sb->s_maxbytes = 0xFFFFFFFFU;
561 sb->s_blocksize = 1024; /* Eh... Is this correct? */
562 sb->s_blocksize_bits = 10;
563 sb->s_magic = NCP_SUPER_MAGIC;
564 sb->s_op = &ncp_sops;
0378c405 565 sb->s_d_op = &ncp_dentry_operations;
f1970c73 566 sb->s_bdi = &server->bdi;
1da177e4
LT
567
568 server = NCP_SBP(sb);
569 memset(server, 0, sizeof(*server));
570
f1970c73
JA
571 error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
572 if (error)
759c361e 573 goto out_fput;
f1970c73 574
1da177e4
LT
575 server->ncp_filp = ncp_filp;
576 server->ncp_sock = sock;
577
578 if (data.info_fd != -1) {
579 struct socket *info_sock;
580
581 error = -EBADF;
582 server->info_filp = fget(data.info_fd);
583 if (!server->info_filp)
759c361e 584 goto out_bdi;
1da177e4 585 error = -ENOTSOCK;
496ad9aa 586 sock_inode = file_inode(server->info_filp);
1da177e4
LT
587 if (!S_ISSOCK(sock_inode->i_mode))
588 goto out_fput2;
589 info_sock = SOCKET_I(sock_inode);
590 if (!info_sock)
591 goto out_fput2;
592 error = -EBADFD;
593 if (info_sock->type != SOCK_STREAM)
594 goto out_fput2;
595 server->info_sock = info_sock;
596 }
597
598/* server->lock = 0; */
8e3f9045 599 mutex_init(&server->mutex);
1da177e4
LT
600 server->packet = NULL;
601/* server->buffer_size = 0; */
602/* server->conn_status = 0; */
603/* server->root_dentry = NULL; */
604/* server->root_setuped = 0; */
2e54eb96 605 mutex_init(&server->root_setup_lock);
1da177e4
LT
606#ifdef CONFIG_NCPFS_PACKET_SIGNING
607/* server->sign_wanted = 0; */
608/* server->sign_active = 0; */
609#endif
2e54eb96 610 init_rwsem(&server->auth_rwsem);
1da177e4
LT
611 server->auth.auth_type = NCP_AUTH_NONE;
612/* server->auth.object_name_len = 0; */
613/* server->auth.object_name = NULL; */
614/* server->auth.object_type = 0; */
615/* server->priv.len = 0; */
616/* server->priv.data = NULL; */
617
618 server->m = data;
25985edc 619 /* Although anything producing this is buggy, it happens
1da177e4
LT
620 now because of PATH_MAX changes.. */
621 if (server->m.time_out < 1) {
622 server->m.time_out = 10;
623 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
624 }
625 server->m.time_out = server->m.time_out * HZ / 100;
626 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
627 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
628
629#ifdef CONFIG_NCPFS_NLS
630 /* load the default NLS charsets */
631 server->nls_vol = load_nls_default();
632 server->nls_io = load_nls_default();
633#endif /* CONFIG_NCPFS_NLS */
634
2e54eb96 635 atomic_set(&server->dentry_ttl, 0); /* no caching */
1da177e4
LT
636
637 INIT_LIST_HEAD(&server->tx.requests);
8e3f9045 638 mutex_init(&server->rcv.creq_mutex);
1da177e4
LT
639 server->tx.creq = NULL;
640 server->rcv.creq = NULL;
1da177e4
LT
641
642 init_timer(&server->timeout_tm);
643#undef NCP_PACKET_SIZE
644#define NCP_PACKET_SIZE 131072
645 error = -ENOMEM;
646 server->packet_size = NCP_PACKET_SIZE;
647 server->packet = vmalloc(NCP_PACKET_SIZE);
648 if (server->packet == NULL)
649 goto out_nls;
c5f93cf1
PO
650 server->txbuf = vmalloc(NCP_PACKET_SIZE);
651 if (server->txbuf == NULL)
652 goto out_packet;
653 server->rxbuf = vmalloc(NCP_PACKET_SIZE);
654 if (server->rxbuf == NULL)
655 goto out_txbuf;
1da177e4 656
2a4df5d3
PV
657 lock_sock(sock->sk);
658 server->data_ready = sock->sk->sk_data_ready;
659 server->write_space = sock->sk->sk_write_space;
660 server->error_report = sock->sk->sk_error_report;
661 sock->sk->sk_user_data = server;
1da177e4
LT
662 sock->sk->sk_data_ready = ncp_tcp_data_ready;
663 sock->sk->sk_error_report = ncp_tcp_error_report;
664 if (sock->type == SOCK_STREAM) {
665 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
666 server->rcv.len = 10;
667 server->rcv.state = 0;
c4028958
DH
668 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
669 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
1da177e4
LT
670 sock->sk->sk_write_space = ncp_tcp_write_space;
671 } else {
c4028958
DH
672 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
673 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
1da177e4
LT
674 server->timeout_tm.data = (unsigned long)server;
675 server->timeout_tm.function = ncpdgram_timeout_call;
676 }
2a4df5d3 677 release_sock(sock->sk);
1da177e4
LT
678
679 ncp_lock_server(server);
680 error = ncp_connect(server);
681 ncp_unlock_server(server);
682 if (error < 0)
c5f93cf1 683 goto out_rxbuf;
1da177e4
LT
684 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
685
686 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
687#ifdef CONFIG_NCPFS_PACKET_SIGNING
688 if (ncp_negotiate_size_and_options(server, default_bufsize,
689 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
690 {
691 if (options != NCP_DEFAULT_OPTIONS)
692 {
693 if (ncp_negotiate_size_and_options(server,
694 default_bufsize,
695 options & 2,
696 &(server->buffer_size), &options) != 0)
697
698 {
699 goto out_disconnect;
700 }
701 }
2e54eb96 702 ncp_lock_server(server);
1da177e4
LT
703 if (options & 2)
704 server->sign_wanted = 1;
2e54eb96 705 ncp_unlock_server(server);
1da177e4
LT
706 }
707 else
708#endif /* CONFIG_NCPFS_PACKET_SIGNING */
709 if (ncp_negotiate_buffersize(server, default_bufsize,
710 &(server->buffer_size)) != 0)
711 goto out_disconnect;
712 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
713
714 memset(&finfo, 0, sizeof(finfo));
715 finfo.i.attributes = aDIR;
716 finfo.i.dataStreamSize = 0; /* ignored */
717 finfo.i.dirEntNum = 0;
718 finfo.i.DosDirNum = 0;
719#ifdef CONFIG_NCPFS_SMALLDOS
720 finfo.i.NSCreator = NW_NS_DOS;
721#endif
722 finfo.volume = NCP_NUMBER_OF_VOLUMES;
723 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
724 finfo.i.creationTime = finfo.i.modifyTime
725 = cpu_to_le16(0x0000);
726 finfo.i.creationDate = finfo.i.modifyDate
727 = finfo.i.lastAccessDate
728 = cpu_to_le16(0x0C21);
729 finfo.i.nameLen = 0;
730 finfo.i.entryName[0] = '\0';
731
732 finfo.opened = 0;
733 finfo.ino = 2; /* tradition */
734
735 server->name_space[finfo.volume] = NW_NS_DOS;
736
737 error = -ENOMEM;
738 root_inode = ncp_iget(sb, &finfo);
739 if (!root_inode)
740 goto out_disconnect;
741 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
48fde701 742 sb->s_root = d_make_root(root_inode);
1da177e4 743 if (!sb->s_root)
48fde701 744 goto out_disconnect;
1da177e4
LT
745 return 0;
746
1da177e4
LT
747out_disconnect:
748 ncp_lock_server(server);
749 ncp_disconnect(server);
750 ncp_unlock_server(server);
c5f93cf1 751out_rxbuf:
1da177e4 752 ncp_stop_tasks(server);
c5f93cf1
PO
753 vfree(server->rxbuf);
754out_txbuf:
755 vfree(server->txbuf);
756out_packet:
1da177e4
LT
757 vfree(server->packet);
758out_nls:
759#ifdef CONFIG_NCPFS_NLS
760 unload_nls(server->nls_io);
761 unload_nls(server->nls_vol);
762#endif
2e54eb96
PV
763 mutex_destroy(&server->rcv.creq_mutex);
764 mutex_destroy(&server->root_setup_lock);
765 mutex_destroy(&server->mutex);
1da177e4
LT
766out_fput2:
767 if (server->info_filp)
768 fput(server->info_filp);
f1970c73 769out_bdi:
759c361e
DH
770 bdi_destroy(&server->bdi);
771out_fput:
1da177e4
LT
772 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
773 *
e956b4b7
MW
774 * The previously used put_filp(ncp_filp); was bogus, since
775 * it doesn't perform proper unlocking.
1da177e4
LT
776 */
777 fput(ncp_filp);
778out:
1de24126 779 put_pid(data.wdog_pid);
1da177e4
LT
780 sb->s_fs_info = NULL;
781 kfree(server);
782 return error;
783}
784
785static void ncp_put_super(struct super_block *sb)
786{
787 struct ncp_server *server = NCP_SBP(sb);
788
789 ncp_lock_server(server);
790 ncp_disconnect(server);
791 ncp_unlock_server(server);
792
793 ncp_stop_tasks(server);
794
795#ifdef CONFIG_NCPFS_NLS
796 /* unload the NLS charsets */
6d729e44
TG
797 unload_nls(server->nls_vol);
798 unload_nls(server->nls_io);
1da177e4 799#endif /* CONFIG_NCPFS_NLS */
2e54eb96
PV
800 mutex_destroy(&server->rcv.creq_mutex);
801 mutex_destroy(&server->root_setup_lock);
802 mutex_destroy(&server->mutex);
1da177e4
LT
803
804 if (server->info_filp)
805 fput(server->info_filp);
806 fput(server->ncp_filp);
2154227a
EB
807 kill_pid(server->m.wdog_pid, SIGTERM, 1);
808 put_pid(server->m.wdog_pid);
1da177e4 809
f1970c73 810 bdi_destroy(&server->bdi);
44db77f3
PE
811 kfree(server->priv.data);
812 kfree(server->auth.object_name);
c5f93cf1
PO
813 vfree(server->rxbuf);
814 vfree(server->txbuf);
1da177e4
LT
815 vfree(server->packet);
816 sb->s_fs_info = NULL;
817 kfree(server);
818}
819
726c3342 820static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4
LT
821{
822 struct dentry* d;
823 struct inode* i;
824 struct ncp_inode_info* ni;
825 struct ncp_server* s;
826 struct ncp_volume_info vi;
726c3342 827 struct super_block *sb = dentry->d_sb;
1da177e4
LT
828 int err;
829 __u8 dh;
830
831 d = sb->s_root;
832 if (!d) {
833 goto dflt;
834 }
835 i = d->d_inode;
836 if (!i) {
837 goto dflt;
838 }
839 ni = NCP_FINFO(i);
840 if (!ni) {
841 goto dflt;
842 }
843 s = NCP_SBP(sb);
844 if (!s) {
845 goto dflt;
846 }
847 if (!s->m.mounted_vol[0]) {
848 goto dflt;
849 }
850
851 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
852 if (err) {
853 goto dflt;
854 }
855 err = ncp_get_directory_info(s, dh, &vi);
856 ncp_dirhandle_free(s, dh);
857 if (err) {
858 goto dflt;
859 }
860 buf->f_type = NCP_SUPER_MAGIC;
861 buf->f_bsize = vi.sectors_per_block * 512;
862 buf->f_blocks = vi.total_blocks;
863 buf->f_bfree = vi.free_blocks;
864 buf->f_bavail = vi.free_blocks;
865 buf->f_files = vi.total_dir_entries;
866 buf->f_ffree = vi.available_dir_entries;
867 buf->f_namelen = 12;
868 return 0;
869
870 /* We cannot say how much disk space is left on a mounted
871 NetWare Server, because free space is distributed over
872 volumes, and the current user might have disk quotas. So
873 free space is not that simple to determine. Our decision
874 here is to err conservatively. */
875
876dflt:;
877 buf->f_type = NCP_SUPER_MAGIC;
878 buf->f_bsize = NCP_BLOCK_SIZE;
879 buf->f_blocks = 0;
880 buf->f_bfree = 0;
881 buf->f_bavail = 0;
882 buf->f_namelen = 12;
883 return 0;
884}
885
886int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
887{
888 struct inode *inode = dentry->d_inode;
889 int result = 0;
890 __le32 info_mask;
891 struct nw_modify_dos_info info;
892 struct ncp_server *server;
893
894 result = -EIO;
895
1da177e4 896 server = NCP_SERVER(inode);
2e54eb96 897 if (!server) /* How this could happen? */
1da177e4
LT
898 goto out;
899
338b2f57
AV
900 result = -EPERM;
901 if (IS_DEADDIR(dentry->d_inode))
902 goto out;
903
1da177e4
LT
904 /* ageing the dentry to force validation */
905 ncp_age_dentry(server, dentry);
906
907 result = inode_change_ok(inode, attr);
908 if (result < 0)
909 goto out;
910
911 result = -EPERM;
1ac7fd81 912 if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
1da177e4
LT
913 goto out;
914
1ac7fd81 915 if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
1da177e4
LT
916 goto out;
917
918 if (((attr->ia_valid & ATTR_MODE) &&
919 (attr->ia_mode &
920 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
921 goto out;
922
923 info_mask = 0;
924 memset(&info, 0, sizeof(info));
925
926#if 1
927 if ((attr->ia_valid & ATTR_MODE) != 0)
928 {
929 umode_t newmode = attr->ia_mode;
930
931 info_mask |= DM_ATTRIBUTES;
932
933 if (S_ISDIR(inode->i_mode)) {
934 newmode &= server->m.dir_mode;
935 } else {
936#ifdef CONFIG_NCPFS_EXTRAS
937 if (server->m.flags & NCP_MOUNT_EXTRAS) {
938 /* any non-default execute bit set */
939 if (newmode & ~server->m.file_mode & S_IXUGO)
940 info.attributes |= aSHARED | aSYSTEM;
941 /* read for group/world and not in default file_mode */
942 else if (newmode & ~server->m.file_mode & S_IRUGO)
943 info.attributes |= aSHARED;
944 } else
945#endif
946 newmode &= server->m.file_mode;
947 }
948 if (newmode & S_IWUGO)
949 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
950 else
951 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
952
953#ifdef CONFIG_NCPFS_NFS_NS
954 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
955 result = ncp_modify_nfs_info(server,
956 NCP_FINFO(inode)->volNumber,
957 NCP_FINFO(inode)->dirEntNum,
958 attr->ia_mode, 0);
959 if (result != 0)
960 goto out;
961 info.attributes &= ~(aSHARED | aSYSTEM);
962 {
963 /* mark partial success */
964 struct iattr tmpattr;
965
966 tmpattr.ia_valid = ATTR_MODE;
967 tmpattr.ia_mode = attr->ia_mode;
968
1025774c
CH
969 setattr_copy(inode, &tmpattr);
970 mark_inode_dirty(inode);
1da177e4
LT
971 }
972 }
973#endif
974 }
975#endif
976
977 /* Do SIZE before attributes, otherwise mtime together with size does not work...
978 */
979 if ((attr->ia_valid & ATTR_SIZE) != 0) {
980 int written;
981
982 DPRINTK("ncpfs: trying to change size to %ld\n",
983 attr->ia_size);
984
985 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
986 result = -EACCES;
987 goto out;
988 }
989 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
990 attr->ia_size, 0, "", &written);
991
992 /* According to ndir, the changes only take effect after
993 closing the file */
994 ncp_inode_close(inode);
995 result = ncp_make_closed(inode);
996 if (result)
997 goto out;
1025774c
CH
998
999 if (attr->ia_size != i_size_read(inode)) {
3e7a8069 1000 truncate_setsize(inode, attr->ia_size);
1025774c 1001 mark_inode_dirty(inode);
1da177e4
LT
1002 }
1003 }
1004 if ((attr->ia_valid & ATTR_CTIME) != 0) {
1005 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
1006 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
1007 &info.creationTime, &info.creationDate);
1008 }
1009 if ((attr->ia_valid & ATTR_MTIME) != 0) {
1010 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
1011 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
1012 &info.modifyTime, &info.modifyDate);
1013 }
1014 if ((attr->ia_valid & ATTR_ATIME) != 0) {
1015 __le16 dummy;
1016 info_mask |= (DM_LAST_ACCESS_DATE);
1017 ncp_date_unix2dos(attr->ia_atime.tv_sec,
1018 &dummy, &info.lastAccessDate);
1019 }
1020 if (info_mask != 0) {
1021 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1022 inode, info_mask, &info);
1023 if (result != 0) {
1da177e4
LT
1024 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1025 /* NetWare seems not to allow this. I
1026 do not know why. So, just tell the
1027 user everything went fine. This is
1028 a terrible hack, but I do not know
1029 how to do this correctly. */
1030 result = 0;
1031 } else
1032 goto out;
1033 }
1034#ifdef CONFIG_NCPFS_STRONG
1035 if ((!result) && (info_mask & DM_ATTRIBUTES))
1036 NCP_FINFO(inode)->nwattr = info.attributes;
1037#endif
1038 }
1025774c
CH
1039 if (result)
1040 goto out;
1041
1042 setattr_copy(inode, attr);
1043 mark_inode_dirty(inode);
1044
1da177e4 1045out:
2e54eb96
PV
1046 if (result > 0)
1047 result = -EACCES;
1da177e4
LT
1048 return result;
1049}
1050
3c26ff6e
AV
1051static struct dentry *ncp_mount(struct file_system_type *fs_type,
1052 int flags, const char *dev_name, void *data)
1da177e4 1053{
3c26ff6e 1054 return mount_nodev(fs_type, flags, data, ncp_fill_super);
1da177e4
LT
1055}
1056
1057static struct file_system_type ncp_fs_type = {
1058 .owner = THIS_MODULE,
1059 .name = "ncpfs",
3c26ff6e 1060 .mount = ncp_mount,
1da177e4 1061 .kill_sb = kill_anon_super,
564cd138 1062 .fs_flags = FS_BINARY_MOUNTDATA,
1da177e4 1063};
7f78e035 1064MODULE_ALIAS_FS("ncpfs");
1da177e4
LT
1065
1066static int __init init_ncp_fs(void)
1067{
1068 int err;
7c28cbae 1069 DPRINTK("ncpfs: init_ncp_fs called\n");
1da177e4 1070
1da177e4
LT
1071 err = init_inodecache();
1072 if (err)
1073 goto out1;
1074 err = register_filesystem(&ncp_fs_type);
1075 if (err)
1076 goto out;
1077 return 0;
1078out:
1079 destroy_inodecache();
1080out1:
1081 return err;
1082}
1083
1084static void __exit exit_ncp_fs(void)
1085{
7c28cbae 1086 DPRINTK("ncpfs: exit_ncp_fs called\n");
1da177e4
LT
1087 unregister_filesystem(&ncp_fs_type);
1088 destroy_inodecache();
1da177e4
LT
1089}
1090
1091module_init(init_ncp_fs)
1092module_exit(exit_ncp_fs)
1093MODULE_LICENSE("GPL");
This page took 0.991832 seconds and 5 git commands to generate.