aboutsummaryrefslogtreecommitdiffstats
path: root/fs/smbfs/inode.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-10-04 16:55:57 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-05 12:08:21 -0400
commit2116b7a473bf1c8d26998b477c294e7fe294921f (patch)
tree5f06aca6b425916f763d83fa4516bca51c8f9a60 /fs/smbfs/inode.c
parent5af74aa5e97fcc0cc3955bc2a7ff6f3a13fa41cb (diff)
smbfs: move to drivers/staging
smbfs has been scheduled for removal in 2.6.27, so maybe we can now move it to drivers/staging on the way out. smbfs still uses the big kernel lock and nobody is going to fix that, so we should be getting rid of it soon. This removes the 32 bit compat mount and ioctl handling code, which is implemented in common fs code, and moves all smbfs related files into drivers/staging/smbfs. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/smbfs/inode.c')
-rw-r--r--fs/smbfs/inode.c839
1 files changed, 0 insertions, 839 deletions
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
deleted file mode 100644
index 450c91941988..000000000000
--- a/fs/smbfs/inode.c
+++ /dev/null
@@ -1,839 +0,0 @@
1/*
2 * inode.c
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10#include <linux/module.h>
11#include <linux/time.h>
12#include <linux/kernel.h>
13#include <linux/mm.h>
14#include <linux/string.h>
15#include <linux/stat.h>
16#include <linux/errno.h>
17#include <linux/slab.h>
18#include <linux/init.h>
19#include <linux/file.h>
20#include <linux/dcache.h>
21#include <linux/smp_lock.h>
22#include <linux/nls.h>
23#include <linux/seq_file.h>
24#include <linux/mount.h>
25#include <linux/net.h>
26#include <linux/vfs.h>
27#include <linux/highuid.h>
28#include <linux/sched.h>
29#include <linux/smb_fs.h>
30#include <linux/smbno.h>
31#include <linux/smb_mount.h>
32
33#include <asm/system.h>
34#include <asm/uaccess.h>
35
36#include "smb_debug.h"
37#include "getopt.h"
38#include "proto.h"
39
40/* Always pick a default string */
41#ifdef CONFIG_SMB_NLS_REMOTE
42#define SMB_NLS_REMOTE CONFIG_SMB_NLS_REMOTE
43#else
44#define SMB_NLS_REMOTE ""
45#endif
46
47#define SMB_TTL_DEFAULT 1000
48
49static void smb_evict_inode(struct inode *);
50static void smb_put_super(struct super_block *);
51static int smb_statfs(struct dentry *, struct kstatfs *);
52static int smb_show_options(struct seq_file *, struct vfsmount *);
53
54static struct kmem_cache *smb_inode_cachep;
55
56static struct inode *smb_alloc_inode(struct super_block *sb)
57{
58 struct smb_inode_info *ei;
59 ei = (struct smb_inode_info *)kmem_cache_alloc(smb_inode_cachep, GFP_KERNEL);
60 if (!ei)
61 return NULL;
62 return &ei->vfs_inode;
63}
64
65static void smb_destroy_inode(struct inode *inode)
66{
67 kmem_cache_free(smb_inode_cachep, SMB_I(inode));
68}
69
70static void init_once(void *foo)
71{
72 struct smb_inode_info *ei = (struct smb_inode_info *) foo;
73
74 inode_init_once(&ei->vfs_inode);
75}
76
77static int init_inodecache(void)
78{
79 smb_inode_cachep = kmem_cache_create("smb_inode_cache",
80 sizeof(struct smb_inode_info),
81 0, (SLAB_RECLAIM_ACCOUNT|
82 SLAB_MEM_SPREAD),
83 init_once);
84 if (smb_inode_cachep == NULL)
85 return -ENOMEM;
86 return 0;
87}
88
89static void destroy_inodecache(void)
90{
91 kmem_cache_destroy(smb_inode_cachep);
92}
93
94static int smb_remount(struct super_block *sb, int *flags, char *data)
95{
96 *flags |= MS_NODIRATIME;
97 return 0;
98}
99
100static const struct super_operations smb_sops =
101{
102 .alloc_inode = smb_alloc_inode,
103 .destroy_inode = smb_destroy_inode,
104 .drop_inode = generic_delete_inode,
105 .evict_inode = smb_evict_inode,
106 .put_super = smb_put_super,
107 .statfs = smb_statfs,
108 .show_options = smb_show_options,
109 .remount_fs = smb_remount,
110};
111
112
113/* We are always generating a new inode here */
114struct inode *
115smb_iget(struct super_block *sb, struct smb_fattr *fattr)
116{
117 struct smb_sb_info *server = SMB_SB(sb);
118 struct inode *result;
119
120 DEBUG1("smb_iget: %p\n", fattr);
121
122 result = new_inode(sb);
123 if (!result)
124 return result;
125 result->i_ino = fattr->f_ino;
126 SMB_I(result)->open = 0;
127 SMB_I(result)->fileid = 0;
128 SMB_I(result)->access = 0;
129 SMB_I(result)->flags = 0;
130 SMB_I(result)->closed = 0;
131 SMB_I(result)->openers = 0;
132 smb_set_inode_attr(result, fattr);
133 if (S_ISREG(result->i_mode)) {
134 result->i_op = &smb_file_inode_operations;
135 result->i_fop = &smb_file_operations;
136 result->i_data.a_ops = &smb_file_aops;
137 } else if (S_ISDIR(result->i_mode)) {
138 if (server->opt.capabilities & SMB_CAP_UNIX)
139 result->i_op = &smb_dir_inode_operations_unix;
140 else
141 result->i_op = &smb_dir_inode_operations;
142 result->i_fop = &smb_dir_operations;
143 } else if (S_ISLNK(result->i_mode)) {
144 result->i_op = &smb_link_inode_operations;
145 } else {
146 init_special_inode(result, result->i_mode, fattr->f_rdev);
147 }
148 insert_inode_hash(result);
149 return result;
150}
151
152/*
153 * Copy the inode data to a smb_fattr structure.
154 */
155void
156smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr)
157{
158 memset(fattr, 0, sizeof(struct smb_fattr));
159 fattr->f_mode = inode->i_mode;
160 fattr->f_nlink = inode->i_nlink;
161 fattr->f_ino = inode->i_ino;
162 fattr->f_uid = inode->i_uid;
163 fattr->f_gid = inode->i_gid;
164 fattr->f_size = inode->i_size;
165 fattr->f_mtime = inode->i_mtime;
166 fattr->f_ctime = inode->i_ctime;
167 fattr->f_atime = inode->i_atime;
168 fattr->f_blocks = inode->i_blocks;
169
170 fattr->attr = SMB_I(inode)->attr;
171 /*
172 * Keep the attributes in sync with the inode permissions.
173 */
174 if (fattr->f_mode & S_IWUSR)
175 fattr->attr &= ~aRONLY;
176 else
177 fattr->attr |= aRONLY;
178}
179
180/*
181 * Update the inode, possibly causing it to invalidate its pages if mtime/size
182 * is different from last time.
183 */
184void
185smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
186{
187 struct smb_inode_info *ei = SMB_I(inode);
188
189 /*
190 * A size change should have a different mtime, or same mtime
191 * but different size.
192 */
193 time_t last_time = inode->i_mtime.tv_sec;
194 loff_t last_sz = inode->i_size;
195
196 inode->i_mode = fattr->f_mode;
197 inode->i_nlink = fattr->f_nlink;
198 inode->i_uid = fattr->f_uid;
199 inode->i_gid = fattr->f_gid;
200 inode->i_ctime = fattr->f_ctime;
201 inode->i_blocks = fattr->f_blocks;
202 inode->i_size = fattr->f_size;
203 inode->i_mtime = fattr->f_mtime;
204 inode->i_atime = fattr->f_atime;
205 ei->attr = fattr->attr;
206
207 /*
208 * Update the "last time refreshed" field for revalidation.
209 */
210 ei->oldmtime = jiffies;
211
212 if (inode->i_mtime.tv_sec != last_time || inode->i_size != last_sz) {
213 VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
214 inode->i_ino,
215 (long) last_time, (long) inode->i_mtime.tv_sec,
216 (long) last_sz, (long) inode->i_size);
217
218 if (!S_ISDIR(inode->i_mode))
219 invalidate_remote_inode(inode);
220 }
221}
222
223/*
224 * This is called if the connection has gone bad ...
225 * try to kill off all the current inodes.
226 */
227void
228smb_invalidate_inodes(struct smb_sb_info *server)
229{
230 VERBOSE("\n");
231 shrink_dcache_sb(SB_of(server));
232 invalidate_inodes(SB_of(server));
233}
234
235/*
236 * This is called to update the inode attributes after
237 * we've made changes to a file or directory.
238 */
239static int
240smb_refresh_inode(struct dentry *dentry)
241{
242 struct inode *inode = dentry->d_inode;
243 int error;
244 struct smb_fattr fattr;
245
246 error = smb_proc_getattr(dentry, &fattr);
247 if (!error) {
248 smb_renew_times(dentry);
249 /*
250 * Check whether the type part of the mode changed,
251 * and don't update the attributes if it did.
252 *
253 * And don't dick with the root inode
254 */
255 if (inode->i_ino == 2)
256 return error;
257 if (S_ISLNK(inode->i_mode))
258 return error; /* VFS will deal with it */
259
260 if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT)) {
261 smb_set_inode_attr(inode, &fattr);
262 } else {
263 /*
264 * Big trouble! The inode has become a new object,
265 * so any operations attempted on it are invalid.
266 *
267 * To limit damage, mark the inode as bad so that
268 * subsequent lookup validations will fail.
269 */
270 PARANOIA("%s/%s changed mode, %07o to %07o\n",
271 DENTRY_PATH(dentry),
272 inode->i_mode, fattr.f_mode);
273
274 fattr.f_mode = inode->i_mode; /* save mode */
275 make_bad_inode(inode);
276 inode->i_mode = fattr.f_mode; /* restore mode */
277 /*
278 * No need to worry about unhashing the dentry: the
279 * lookup validation will see that the inode is bad.
280 * But we do want to invalidate the caches ...
281 */
282 if (!S_ISDIR(inode->i_mode))
283 invalidate_remote_inode(inode);
284 else
285 smb_invalid_dir_cache(inode);
286 error = -EIO;
287 }
288 }
289 return error;
290}
291
292/*
293 * This is called when we want to check whether the inode
294 * has changed on the server. If it has changed, we must
295 * invalidate our local caches.
296 */
297int
298smb_revalidate_inode(struct dentry *dentry)
299{
300 struct smb_sb_info *s = server_from_dentry(dentry);
301 struct inode *inode = dentry->d_inode;
302 int error = 0;
303
304 DEBUG1("smb_revalidate_inode\n");
305 lock_kernel();
306
307 /*
308 * Check whether we've recently refreshed the inode.
309 */
310 if (time_before(jiffies, SMB_I(inode)->oldmtime + SMB_MAX_AGE(s))) {
311 VERBOSE("up-to-date, ino=%ld, jiffies=%lu, oldtime=%lu\n",
312 inode->i_ino, jiffies, SMB_I(inode)->oldmtime);
313 goto out;
314 }
315
316 error = smb_refresh_inode(dentry);
317out:
318 unlock_kernel();
319 return error;
320}
321
322/*
323 * This routine is called when i_nlink == 0 and i_count goes to 0.
324 * All blocking cleanup operations need to go here to avoid races.
325 */
326static void
327smb_evict_inode(struct inode *ino)
328{
329 DEBUG1("ino=%ld\n", ino->i_ino);
330 truncate_inode_pages(&ino->i_data, 0);
331 end_writeback(ino);
332 lock_kernel();
333 if (smb_close(ino))
334 PARANOIA("could not close inode %ld\n", ino->i_ino);
335 unlock_kernel();
336}
337
338static struct option opts[] = {
339 { "version", 0, 'v' },
340 { "win95", SMB_MOUNT_WIN95, 1 },
341 { "oldattr", SMB_MOUNT_OLDATTR, 1 },
342 { "dirattr", SMB_MOUNT_DIRATTR, 1 },
343 { "case", SMB_MOUNT_CASE, 1 },
344 { "uid", 0, 'u' },
345 { "gid", 0, 'g' },
346 { "file_mode", 0, 'f' },
347 { "dir_mode", 0, 'd' },
348 { "iocharset", 0, 'i' },
349 { "codepage", 0, 'c' },
350 { "ttl", 0, 't' },
351 { NULL, 0, 0}
352};
353
354static int
355parse_options(struct smb_mount_data_kernel *mnt, char *options)
356{
357 int c;
358 unsigned long flags;
359 unsigned long value;
360 char *optarg;
361 char *optopt;
362
363 flags = 0;
364 while ( (c = smb_getopt("smbfs", &options, opts,
365 &optopt, &optarg, &flags, &value)) > 0) {
366
367 VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");
368 switch (c) {
369 case 1:
370 /* got a "flag" option */
371 break;
372 case 'v':
373 if (value != SMB_MOUNT_VERSION) {
374 printk ("smbfs: Bad mount version %ld, expected %d\n",
375 value, SMB_MOUNT_VERSION);
376 return 0;
377 }
378 mnt->version = value;
379 break;
380 case 'u':
381 mnt->uid = value;
382 flags |= SMB_MOUNT_UID;
383 break;
384 case 'g':
385 mnt->gid = value;
386 flags |= SMB_MOUNT_GID;
387 break;
388 case 'f':
389 mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
390 flags |= SMB_MOUNT_FMODE;
391 break;
392 case 'd':
393 mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
394 flags |= SMB_MOUNT_DMODE;
395 break;
396 case 'i':
397 strlcpy(mnt->codepage.local_name, optarg,
398 SMB_NLS_MAXNAMELEN);
399 break;
400 case 'c':
401 strlcpy(mnt->codepage.remote_name, optarg,
402 SMB_NLS_MAXNAMELEN);
403 break;
404 case 't':
405 mnt->ttl = value;
406 break;
407 default:
408 printk ("smbfs: Unrecognized mount option %s\n",
409 optopt);
410 return -1;
411 }
412 }
413 mnt->flags = flags;
414 return c;
415}
416
417/*
418 * smb_show_options() is for displaying mount options in /proc/mounts.
419 * It tries to avoid showing settings that were not changed from their
420 * defaults.
421 */
422static int
423smb_show_options(struct seq_file *s, struct vfsmount *m)
424{
425 struct smb_mount_data_kernel *mnt = SMB_SB(m->mnt_sb)->mnt;
426 int i;
427
428 for (i = 0; opts[i].name != NULL; i++)
429 if (mnt->flags & opts[i].flag)
430 seq_printf(s, ",%s", opts[i].name);
431
432 if (mnt->flags & SMB_MOUNT_UID)
433 seq_printf(s, ",uid=%d", mnt->uid);
434 if (mnt->flags & SMB_MOUNT_GID)
435 seq_printf(s, ",gid=%d", mnt->gid);
436 if (mnt->mounted_uid != 0)
437 seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
438
439 /*
440 * Defaults for file_mode and dir_mode are unknown to us; they
441 * depend on the current umask of the user doing the mount.
442 */
443 if (mnt->flags & SMB_MOUNT_FMODE)
444 seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
445 if (mnt->flags & SMB_MOUNT_DMODE)
446 seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
447
448 if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
449 seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
450 if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
451 seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
452
453 if (mnt->ttl != SMB_TTL_DEFAULT)
454 seq_printf(s, ",ttl=%d", mnt->ttl);
455
456 return 0;
457}
458
459static void
460smb_unload_nls(struct smb_sb_info *server)
461{
462 unload_nls(server->remote_nls);
463 unload_nls(server->local_nls);
464}
465
466static void
467smb_put_super(struct super_block *sb)
468{
469 struct smb_sb_info *server = SMB_SB(sb);
470
471 lock_kernel();
472
473 smb_lock_server(server);
474 server->state = CONN_INVALID;
475 smbiod_unregister_server(server);
476
477 smb_close_socket(server);
478
479 if (server->conn_pid)
480 kill_pid(server->conn_pid, SIGTERM, 1);
481
482 bdi_destroy(&server->bdi);
483 kfree(server->ops);
484 smb_unload_nls(server);
485 sb->s_fs_info = NULL;
486 smb_unlock_server(server);
487 put_pid(server->conn_pid);
488 kfree(server);
489
490 unlock_kernel();
491}
492
493static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
494{
495 struct smb_sb_info *server;
496 struct smb_mount_data_kernel *mnt;
497 struct smb_mount_data *oldmnt;
498 struct inode *root_inode;
499 struct smb_fattr root;
500 int ver;
501 void *mem;
502 static int warn_count;
503
504 if (warn_count < 5) {
505 warn_count++;
506 printk(KERN_EMERG "smbfs is deprecated and will be removed"
507 " from the 2.6.27 kernel. Please migrate to cifs\n");
508 }
509
510 if (!raw_data)
511 goto out_no_data;
512
513 oldmnt = (struct smb_mount_data *) raw_data;
514 ver = oldmnt->version;
515 if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII)
516 goto out_wrong_data;
517
518 sb->s_flags |= MS_NODIRATIME;
519 sb->s_blocksize = 1024; /* Eh... Is this correct? */
520 sb->s_blocksize_bits = 10;
521 sb->s_magic = SMB_SUPER_MAGIC;
522 sb->s_op = &smb_sops;
523 sb->s_time_gran = 100;
524
525 server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL);
526 if (!server)
527 goto out_no_server;
528 sb->s_fs_info = server;
529
530 if (bdi_setup_and_register(&server->bdi, "smbfs", BDI_CAP_MAP_COPY))
531 goto out_bdi;
532
533 sb->s_bdi = &server->bdi;
534
535 server->super_block = sb;
536 server->mnt = NULL;
537 server->sock_file = NULL;
538 init_waitqueue_head(&server->conn_wq);
539 init_MUTEX(&server->sem);
540 INIT_LIST_HEAD(&server->entry);
541 INIT_LIST_HEAD(&server->xmitq);
542 INIT_LIST_HEAD(&server->recvq);
543 server->conn_error = 0;
544 server->conn_pid = NULL;
545 server->state = CONN_INVALID; /* no connection yet */
546 server->generation = 0;
547
548 /* Allocate the global temp buffer and some superblock helper structs */
549 /* FIXME: move these to the smb_sb_info struct */
550 VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) +
551 sizeof(struct smb_mount_data_kernel));
552 mem = kmalloc(sizeof(struct smb_ops) +
553 sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
554 if (!mem)
555 goto out_no_mem;
556
557 server->ops = mem;
558 smb_install_null_ops(server->ops);
559 server->mnt = mem + sizeof(struct smb_ops);
560
561 /* Setup NLS stuff */
562 server->remote_nls = NULL;
563 server->local_nls = NULL;
564
565 mnt = server->mnt;
566
567 memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
568 strlcpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
569 SMB_NLS_MAXNAMELEN);
570 strlcpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
571 SMB_NLS_MAXNAMELEN);
572
573 mnt->ttl = SMB_TTL_DEFAULT;
574 if (ver == SMB_MOUNT_OLDVERSION) {
575 mnt->version = oldmnt->version;
576
577 SET_UID(mnt->uid, oldmnt->uid);
578 SET_GID(mnt->gid, oldmnt->gid);
579
580 mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
581 mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
582
583 mnt->flags = (oldmnt->file_mode >> 9) | SMB_MOUNT_UID |
584 SMB_MOUNT_GID | SMB_MOUNT_FMODE | SMB_MOUNT_DMODE;
585 } else {
586 mnt->file_mode = S_IRWXU | S_IRGRP | S_IXGRP |
587 S_IROTH | S_IXOTH | S_IFREG;
588 mnt->dir_mode = S_IRWXU | S_IRGRP | S_IXGRP |
589 S_IROTH | S_IXOTH | S_IFDIR;
590 if (parse_options(mnt, raw_data))
591 goto out_bad_option;
592 }
593 mnt->mounted_uid = current_uid();
594 smb_setcodepage(server, &mnt->codepage);
595
596 /*
597 * Display the enabled options
598 * Note: smb_proc_getattr uses these in 2.4 (but was changed in 2.2)
599 */
600 if (mnt->flags & SMB_MOUNT_OLDATTR)
601 printk("SMBFS: Using core getattr (Win 95 speedup)\n");
602 else if (mnt->flags & SMB_MOUNT_DIRATTR)
603 printk("SMBFS: Using dir ff getattr\n");
604
605 if (smbiod_register_server(server) < 0) {
606 printk(KERN_ERR "smbfs: failed to start smbiod\n");
607 goto out_no_smbiod;
608 }
609
610 /*
611 * Keep the super block locked while we get the root inode.
612 */
613 smb_init_root_dirent(server, &root, sb);
614 root_inode = smb_iget(sb, &root);
615 if (!root_inode)
616 goto out_no_root;
617
618 sb->s_root = d_alloc_root(root_inode);
619 if (!sb->s_root)
620 goto out_no_root;
621
622 smb_new_dentry(sb->s_root);
623
624 return 0;
625
626out_no_root:
627 iput(root_inode);
628out_no_smbiod:
629 smb_unload_nls(server);
630out_bad_option:
631 kfree(mem);
632out_no_mem:
633 bdi_destroy(&server->bdi);
634out_bdi:
635 if (!server->mnt)
636 printk(KERN_ERR "smb_fill_super: allocation failure\n");
637 sb->s_fs_info = NULL;
638 kfree(server);
639 goto out_fail;
640out_wrong_data:
641 printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
642 goto out_fail;
643out_no_data:
644 printk(KERN_ERR "smb_fill_super: missing data argument\n");
645out_fail:
646 return -EINVAL;
647out_no_server:
648 printk(KERN_ERR "smb_fill_super: cannot allocate struct smb_sb_info\n");
649 return -ENOMEM;
650}
651
652static int
653smb_statfs(struct dentry *dentry, struct kstatfs *buf)
654{
655 int result;
656
657 lock_kernel();
658
659 result = smb_proc_dskattr(dentry, buf);
660
661 unlock_kernel();
662
663 buf->f_type = SMB_SUPER_MAGIC;
664 buf->f_namelen = SMB_MAXPATHLEN;
665 return result;
666}
667
668int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
669{
670 int err = smb_revalidate_inode(dentry);
671 if (!err)
672 generic_fillattr(dentry->d_inode, stat);
673 return err;
674}
675
676int
677smb_notify_change(struct dentry *dentry, struct iattr *attr)
678{
679 struct inode *inode = dentry->d_inode;
680 struct smb_sb_info *server = server_from_dentry(dentry);
681 unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
682 int error, changed, refresh = 0;
683 struct smb_fattr fattr;
684
685 lock_kernel();
686
687 error = smb_revalidate_inode(dentry);
688 if (error)
689 goto out;
690
691 if ((error = inode_change_ok(inode, attr)) < 0)
692 goto out;
693
694 error = -EPERM;
695 if ((attr->ia_valid & ATTR_UID) && (attr->ia_uid != server->mnt->uid))
696 goto out;
697
698 if ((attr->ia_valid & ATTR_GID) && (attr->ia_uid != server->mnt->gid))
699 goto out;
700
701 if ((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~mask))
702 goto out;
703
704 if ((attr->ia_valid & ATTR_SIZE) != 0) {
705 VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
706 DENTRY_PATH(dentry),
707 (long) inode->i_size, (long) attr->ia_size);
708
709 filemap_write_and_wait(inode->i_mapping);
710
711 error = smb_open(dentry, O_WRONLY);
712 if (error)
713 goto out;
714 error = server->ops->truncate(inode, attr->ia_size);
715 if (error)
716 goto out;
717 truncate_setsize(inode, attr->ia_size);
718 refresh = 1;
719 }
720
721 if (server->opt.capabilities & SMB_CAP_UNIX) {
722 /* For now we don't want to set the size with setattr_unix */
723 attr->ia_valid &= ~ATTR_SIZE;
724 /* FIXME: only call if we actually want to set something? */
725 error = smb_proc_setattr_unix(dentry, attr, 0, 0);
726 if (!error)
727 refresh = 1;
728
729 goto out;
730 }
731
732 /*
733 * Initialize the fattr and check for changed fields.
734 * Note: CTIME under SMB is creation time rather than
735 * change time, so we don't attempt to change it.
736 */
737 smb_get_inode_attr(inode, &fattr);
738
739 changed = 0;
740 if ((attr->ia_valid & ATTR_MTIME) != 0) {
741 fattr.f_mtime = attr->ia_mtime;
742 changed = 1;
743 }
744 if ((attr->ia_valid & ATTR_ATIME) != 0) {
745 fattr.f_atime = attr->ia_atime;
746 /* Earlier protocols don't have an access time */
747 if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
748 changed = 1;
749 }
750 if (changed) {
751 error = smb_proc_settime(dentry, &fattr);
752 if (error)
753 goto out;
754 refresh = 1;
755 }
756
757 /*
758 * Check for mode changes ... we're extremely limited in
759 * what can be set for SMB servers: just the read-only bit.
760 */
761 if ((attr->ia_valid & ATTR_MODE) != 0) {
762 VERBOSE("%s/%s mode change, old=%x, new=%x\n",
763 DENTRY_PATH(dentry), fattr.f_mode, attr->ia_mode);
764 changed = 0;
765 if (attr->ia_mode & S_IWUSR) {
766 if (fattr.attr & aRONLY) {
767 fattr.attr &= ~aRONLY;
768 changed = 1;
769 }
770 } else {
771 if (!(fattr.attr & aRONLY)) {
772 fattr.attr |= aRONLY;
773 changed = 1;
774 }
775 }
776 if (changed) {
777 error = smb_proc_setattr(dentry, &fattr);
778 if (error)
779 goto out;
780 refresh = 1;
781 }
782 }
783 error = 0;
784
785out:
786 if (refresh)
787 smb_refresh_inode(dentry);
788 unlock_kernel();
789 return error;
790}
791
792static int smb_get_sb(struct file_system_type *fs_type,
793 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
794{
795 return get_sb_nodev(fs_type, flags, data, smb_fill_super, mnt);
796}
797
798static struct file_system_type smb_fs_type = {
799 .owner = THIS_MODULE,
800 .name = "smbfs",
801 .get_sb = smb_get_sb,
802 .kill_sb = kill_anon_super,
803 .fs_flags = FS_BINARY_MOUNTDATA,
804};
805
806static int __init init_smb_fs(void)
807{
808 int err;
809 DEBUG1("registering ...\n");
810
811 err = init_inodecache();
812 if (err)
813 goto out_inode;
814 err = smb_init_request_cache();
815 if (err)
816 goto out_request;
817 err = register_filesystem(&smb_fs_type);
818 if (err)
819 goto out;
820 return 0;
821out:
822 smb_destroy_request_cache();
823out_request:
824 destroy_inodecache();
825out_inode:
826 return err;
827}
828
829static void __exit exit_smb_fs(void)
830{
831 DEBUG1("unregistering ...\n");
832 unregister_filesystem(&smb_fs_type);
833 smb_destroy_request_cache();
834 destroy_inodecache();
835}
836
837module_init(init_smb_fs)
838module_exit(exit_smb_fs)
839MODULE_LICENSE("GPL");