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