The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/smbfs/inode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/config.h>
   11 #include <linux/module.h>
   12 #include <linux/sched.h>
   13 #include <linux/kernel.h>
   14 #include <linux/mm.h>
   15 #include <linux/string.h>
   16 #include <linux/stat.h>
   17 #include <linux/errno.h>
   18 #include <linux/locks.h>
   19 #include <linux/slab.h>
   20 #include <linux/init.h>
   21 #include <linux/file.h>
   22 #include <linux/dcache.h>
   23 #include <linux/smp_lock.h>
   24 #include <linux/nls.h>
   25 #include <linux/seq_file.h>
   26 
   27 #include <linux/smb_fs.h>
   28 #include <linux/smbno.h>
   29 #include <linux/smb_mount.h>
   30 
   31 #include <asm/system.h>
   32 #include <asm/uaccess.h>
   33 
   34 #include "smb_debug.h"
   35 #include "getopt.h"
   36 #include "proto.h"
   37 
   38 /* Always pick a default string */
   39 #ifdef CONFIG_SMB_NLS_REMOTE
   40 #define SMB_NLS_REMOTE CONFIG_SMB_NLS_REMOTE
   41 #else
   42 #define SMB_NLS_REMOTE ""
   43 #endif
   44 
   45 #define SMB_TTL_DEFAULT 1000
   46 #define SMB_TIMEO_DEFAULT 30
   47 
   48 static void smb_delete_inode(struct inode *);
   49 static void smb_put_super(struct super_block *);
   50 static int  smb_statfs(struct super_block *, struct statfs *);
   51 static int  smb_show_options(struct seq_file *, struct vfsmount *);
   52 
   53 static struct super_operations smb_sops =
   54 {
   55         put_inode:      force_delete,
   56         delete_inode:   smb_delete_inode,
   57         put_super:      smb_put_super,
   58         statfs:         smb_statfs,
   59         show_options:   smb_show_options,
   60 };
   61 
   62 
   63 /* We are always generating a new inode here */
   64 struct inode *
   65 smb_iget(struct super_block *sb, struct smb_fattr *fattr)
   66 {
   67         struct inode *result;
   68 
   69         DEBUG1("smb_iget: %p\n", fattr);
   70 
   71         result = new_inode(sb);
   72         if (!result)
   73                 return result;
   74         result->i_ino = fattr->f_ino;
   75         memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i));
   76         smb_set_inode_attr(result, fattr);
   77         if (S_ISREG(result->i_mode)) {
   78                 result->i_op = &smb_file_inode_operations;
   79                 result->i_fop = &smb_file_operations;
   80                 result->i_data.a_ops = &smb_file_aops;
   81         } else if (S_ISDIR(result->i_mode)) {
   82                 result->i_op = &smb_dir_inode_operations;
   83                 result->i_fop = &smb_dir_operations;
   84         }
   85         insert_inode_hash(result);
   86         return result;
   87 }
   88 
   89 /*
   90  * Copy the inode data to a smb_fattr structure.
   91  */
   92 void
   93 smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr)
   94 {
   95         memset(fattr, 0, sizeof(struct smb_fattr));
   96         fattr->f_mode   = inode->i_mode;
   97         fattr->f_nlink  = inode->i_nlink;
   98         fattr->f_ino    = inode->i_ino;
   99         fattr->f_uid    = inode->i_uid;
  100         fattr->f_gid    = inode->i_gid;
  101         fattr->f_rdev   = inode->i_rdev;
  102         fattr->f_size   = inode->i_size;
  103         fattr->f_mtime  = inode->i_mtime;
  104         fattr->f_ctime  = inode->i_ctime;
  105         fattr->f_atime  = inode->i_atime;
  106         fattr->f_blksize= inode->i_blksize;
  107         fattr->f_blocks = inode->i_blocks;
  108 
  109         fattr->attr     = inode->u.smbfs_i.attr;
  110         /*
  111          * Keep the attributes in sync with the inode permissions.
  112          */
  113         if (fattr->f_mode & S_IWUSR)
  114                 fattr->attr &= ~aRONLY;
  115         else
  116                 fattr->attr |= aRONLY;
  117 }
  118 
  119 /*
  120  * Update the inode, possibly causing it to invalidate its pages if mtime/size
  121  * is different from last time.
  122  */
  123 void
  124 smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
  125 {
  126         /*
  127          * A size change should have a different mtime, or same mtime
  128          * but different size.
  129          */
  130         time_t last_time = inode->i_mtime;
  131         loff_t last_sz = inode->i_size;
  132 
  133         inode->i_mode   = fattr->f_mode;
  134         inode->i_nlink  = fattr->f_nlink;
  135         inode->i_uid    = fattr->f_uid;
  136         inode->i_gid    = fattr->f_gid;
  137         inode->i_rdev   = fattr->f_rdev;
  138         inode->i_ctime  = fattr->f_ctime;
  139         inode->i_blksize= fattr->f_blksize;
  140         inode->i_blocks = fattr->f_blocks;
  141         inode->i_size   = fattr->f_size;
  142         inode->i_mtime  = fattr->f_mtime;
  143         inode->i_atime  = fattr->f_atime;
  144         inode->u.smbfs_i.attr = fattr->attr;
  145         /*
  146          * Update the "last time refreshed" field for revalidation.
  147          */
  148         inode->u.smbfs_i.oldmtime = jiffies;
  149 
  150         if (inode->i_mtime != last_time || inode->i_size != last_sz) {
  151                 VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
  152                         inode->i_ino,
  153                         (long) last_time, (long) inode->i_mtime,
  154                         (long) last_sz, (long) inode->i_size);
  155 
  156                 if (!S_ISDIR(inode->i_mode))
  157                         invalidate_inode_pages(inode);
  158         }
  159 }
  160 
  161 /*
  162  * This is called if the connection has gone bad ...
  163  * try to kill off all the current inodes.
  164  */
  165 void
  166 smb_invalidate_inodes(struct smb_sb_info *server)
  167 {
  168         VERBOSE("\n");
  169         shrink_dcache_sb(SB_of(server));
  170         invalidate_inodes(SB_of(server));
  171 }
  172 
  173 /*
  174  * This is called to update the inode attributes after
  175  * we've made changes to a file or directory.
  176  */
  177 static int
  178 smb_refresh_inode(struct dentry *dentry)
  179 {
  180         struct inode *inode = dentry->d_inode;
  181         int error;
  182         struct smb_fattr fattr;
  183 
  184         error = smb_proc_getattr(dentry, &fattr);
  185         if (!error) {
  186                 smb_renew_times(dentry);
  187                 /*
  188                  * Check whether the type part of the mode changed,
  189                  * and don't update the attributes if it did.
  190                  */
  191                 if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT)) {
  192                         smb_set_inode_attr(inode, &fattr);
  193                 } else {
  194                         /*
  195                          * Big trouble! The inode has become a new object,
  196                          * so any operations attempted on it are invalid.
  197                          *
  198                          * To limit damage, mark the inode as bad so that
  199                          * subsequent lookup validations will fail.
  200                          */
  201                         PARANOIA("%s/%s changed mode, %07o to %07o\n",
  202                                  DENTRY_PATH(dentry),
  203                                  inode->i_mode, fattr.f_mode);
  204 
  205                         fattr.f_mode = inode->i_mode; /* save mode */
  206                         make_bad_inode(inode);
  207                         inode->i_mode = fattr.f_mode; /* restore mode */
  208                         /*
  209                          * No need to worry about unhashing the dentry: the
  210                          * lookup validation will see that the inode is bad.
  211                          * But we do want to invalidate the caches ...
  212                          */
  213                         if (!S_ISDIR(inode->i_mode))
  214                                 invalidate_inode_pages(inode);
  215                         else
  216                                 smb_invalid_dir_cache(inode);
  217                         error = -EIO;
  218                 }
  219         }
  220         return error;
  221 }
  222 
  223 /*
  224  * This is called when we want to check whether the inode
  225  * has changed on the server.  If it has changed, we must
  226  * invalidate our local caches.
  227  */
  228 int
  229 smb_revalidate_inode(struct dentry *dentry)
  230 {
  231         struct smb_sb_info *s = server_from_dentry(dentry);
  232         struct inode *inode = dentry->d_inode;
  233         int error = 0;
  234 
  235         DEBUG1("smb_revalidate_inode\n");
  236         lock_kernel();
  237 
  238         /*
  239          * Check whether we've recently refreshed the inode.
  240          */
  241         if (time_before(jiffies, inode->u.smbfs_i.oldmtime + SMB_MAX_AGE(s))) {
  242                 VERBOSE("up-to-date, ino=%ld, jiffies=%lu, oldtime=%lu\n",
  243                         inode->i_ino, jiffies, inode->u.smbfs_i.oldmtime);
  244                 goto out;
  245         }
  246 
  247         error = smb_refresh_inode(dentry);
  248 out:
  249         unlock_kernel();
  250         return error;
  251 }
  252 
  253 /*
  254  * This routine is called when i_nlink == 0 and i_count goes to 0.
  255  * All blocking cleanup operations need to go here to avoid races.
  256  */
  257 static void
  258 smb_delete_inode(struct inode *ino)
  259 {
  260         DEBUG1("ino=%ld\n", ino->i_ino);
  261         lock_kernel();
  262         if (smb_close(ino))
  263                 PARANOIA("could not close inode %ld\n", ino->i_ino);
  264         unlock_kernel();
  265         clear_inode(ino);
  266 }
  267 
  268 static struct option opts[] = {
  269         { "version",    0, 'v' },
  270         { "win95",      SMB_MOUNT_WIN95, 1 },
  271         { "oldattr",    SMB_MOUNT_OLDATTR, 1 },
  272         { "dirattr",    SMB_MOUNT_DIRATTR, 1 },
  273         { "case",       SMB_MOUNT_CASE, 1 },
  274         { "uid",        0, 'u' },
  275         { "gid",        0, 'g' },
  276         { "file_mode",  0, 'f' },
  277         { "dir_mode",   0, 'd' },
  278         { "iocharset",  0, 'i' },
  279         { "codepage",   0, 'c' },
  280         { "ttl",        0, 't' },
  281         { "timeo",      0, 'o' },
  282         { NULL,         0, 0}
  283 };
  284 
  285 static int
  286 parse_options(struct smb_mount_data_kernel *mnt, char *options)
  287 {
  288         int c;
  289         unsigned long flags;
  290         unsigned long value;
  291         char *optarg;
  292         char *optopt;
  293 
  294         flags = 0;
  295         while ( (c = smb_getopt("smbfs", &options, opts,
  296                                 &optopt, &optarg, &flags, &value)) > 0) {
  297 
  298                 VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");
  299 
  300                 switch (c) {
  301                 case 1:
  302                         /* got a "flag" option */
  303                         break;
  304                 case 'v':
  305                         if (value != SMB_MOUNT_VERSION) {
  306                         printk ("smbfs: Bad mount version %ld, expected %d\n",
  307                                 value, SMB_MOUNT_VERSION);
  308                                 return 0;
  309                         }
  310                         mnt->version = value;
  311                         break;
  312                 case 'u':
  313                         mnt->uid = value;
  314                         break;
  315                 case 'g':
  316                         mnt->gid = value;
  317                         break;
  318                 case 'f':
  319                         mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
  320                         break;
  321                 case 'd':
  322                         mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
  323                         break;
  324                 case 'i':
  325                         strncpy(mnt->codepage.local_name, optarg, 
  326                                 SMB_NLS_MAXNAMELEN);
  327                         break;
  328                 case 'c':
  329                         strncpy(mnt->codepage.remote_name, optarg,
  330                                 SMB_NLS_MAXNAMELEN);
  331                         break;
  332                 case 't':
  333                         mnt->ttl = value;
  334                         break;
  335                 case 'o':
  336                         mnt->timeo = value;
  337                         break;
  338                 default:
  339                         printk ("smbfs: Unrecognized mount option %s\n",
  340                                 optopt);
  341                         return -1;
  342                 }
  343         }
  344         mnt->flags = flags;
  345         return c;
  346 }
  347 
  348 /*
  349  * smb_show_options() is for displaying mount options in /proc/mounts.
  350  * It tries to avoid showing settings that were not changed from their
  351  * defaults.
  352  */
  353 static int
  354 smb_show_options(struct seq_file *s, struct vfsmount *m)
  355 {
  356         struct smb_mount_data_kernel *mnt = m->mnt_sb->u.smbfs_sb.mnt;
  357         int i;
  358 
  359         for (i = 0; opts[i].name != NULL; i++)
  360                 if (mnt->flags & opts[i].flag)
  361                         seq_printf(s, ",%s", opts[i].name);
  362 
  363         if (mnt->uid != 0)
  364                 seq_printf(s, ",uid=%d", mnt->uid);
  365         if (mnt->gid != 0)
  366                 seq_printf(s, ",gid=%d", mnt->gid);
  367         if (mnt->mounted_uid != 0)
  368                 seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
  369 
  370         /* 
  371          * Defaults for file_mode and dir_mode are unknown to us; they
  372          * depend on the current umask of the user doing the mount.
  373          */
  374         seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
  375         seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
  376 
  377         if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
  378                 seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
  379         if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
  380                 seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
  381 
  382         if (mnt->ttl != SMB_TTL_DEFAULT)
  383                 seq_printf(s, ",ttl=%d", mnt->ttl);
  384         if (mnt->timeo != SMB_TIMEO_DEFAULT)
  385                 seq_printf(s, ",timeo=%d", mnt->timeo);
  386 
  387         return 0;
  388 }
  389 
  390 static void
  391 smb_put_super(struct super_block *sb)
  392 {
  393         struct smb_sb_info *server = &(sb->u.smbfs_sb);
  394 
  395         if (server->sock_file) {
  396                 smb_dont_catch_keepalive(server);
  397                 fput(server->sock_file);
  398         }
  399 
  400         if (server->conn_pid)
  401                kill_proc(server->conn_pid, SIGTERM, 1);
  402 
  403         smb_kfree(server->mnt);
  404         smb_kfree(server->temp_buf);
  405         if (server->packet)
  406                 smb_vfree(server->packet);
  407 
  408         if (server->remote_nls) {
  409                 unload_nls(server->remote_nls);
  410                 server->remote_nls = NULL;
  411         }
  412         if (server->local_nls) {
  413                 unload_nls(server->local_nls);
  414                 server->local_nls = NULL;
  415         }
  416 }
  417 
  418 struct super_block *
  419 smb_read_super(struct super_block *sb, void *raw_data, int silent)
  420 {
  421         struct smb_sb_info *server = &sb->u.smbfs_sb;
  422         struct smb_mount_data_kernel *mnt;
  423         struct smb_mount_data *oldmnt;
  424         struct inode *root_inode;
  425         struct smb_fattr root;
  426         int ver;
  427 
  428         if (!raw_data)
  429                 goto out_no_data;
  430 
  431         oldmnt = (struct smb_mount_data *) raw_data;
  432         ver = oldmnt->version;
  433         if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII)
  434                 goto out_wrong_data;
  435 
  436         sb->s_blocksize = 1024; /* Eh...  Is this correct? */
  437         sb->s_blocksize_bits = 10;
  438         sb->s_magic = SMB_SUPER_MAGIC;
  439         sb->s_op = &smb_sops;
  440 
  441         server->mnt = NULL;
  442         server->sock_file = NULL;
  443         init_MUTEX(&server->sem);
  444         init_waitqueue_head(&server->wait);
  445         server->conn_pid = 0;
  446         server->state = CONN_INVALID; /* no connection yet */
  447         server->generation = 0;
  448         server->packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);
  449         server->packet = smb_vmalloc(server->packet_size);
  450         if (!server->packet)
  451                 goto out_no_mem;
  452 
  453         /* Allocate the global temp buffer */
  454         server->temp_buf = smb_kmalloc(2*SMB_MAXPATHLEN+20, GFP_KERNEL);
  455         if (!server->temp_buf)
  456                 goto out_no_temp;
  457 
  458         /* Setup NLS stuff */
  459         server->remote_nls = NULL;
  460         server->local_nls = NULL;
  461         server->name_buf = server->temp_buf + SMB_MAXPATHLEN + 20;
  462 
  463         /* Allocate the mount data structure */
  464         /* FIXME: merge this with the other malloc and get a whole page? */
  465         mnt = smb_kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
  466         if (!mnt)
  467                 goto out_no_mount;
  468         server->mnt = mnt;
  469 
  470         memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
  471         strncpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
  472                 SMB_NLS_MAXNAMELEN);
  473         strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
  474                 SMB_NLS_MAXNAMELEN);
  475 
  476         mnt->ttl = SMB_TTL_DEFAULT;
  477         mnt->timeo = SMB_TIMEO_DEFAULT;
  478         if (ver == SMB_MOUNT_OLDVERSION) {
  479                 mnt->version = oldmnt->version;
  480 
  481                 /* FIXME: is this enough to convert uid/gid's ? */
  482                 mnt->mounted_uid = oldmnt->mounted_uid;
  483                 mnt->uid = oldmnt->uid;
  484                 mnt->gid = oldmnt->gid;
  485 
  486                 mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
  487                 mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
  488 
  489                 mnt->flags = (oldmnt->file_mode >> 9);
  490         } else {
  491                 if (parse_options(mnt, raw_data))
  492                         goto out_bad_option;
  493 
  494                 mnt->mounted_uid = current->uid;
  495         }
  496         smb_setcodepage(server, &mnt->codepage);
  497 
  498         /*
  499          * Display the enabled options
  500          * Note: smb_proc_getattr uses these in 2.4 (but was changed in 2.2)
  501          */
  502         if (mnt->flags & SMB_MOUNT_OLDATTR)
  503                 printk("SMBFS: Using core getattr (Win 95 speedup)\n");
  504         else if (mnt->flags & SMB_MOUNT_DIRATTR)
  505                 printk("SMBFS: Using dir ff getattr\n");
  506 
  507         /*
  508          * Keep the super block locked while we get the root inode.
  509          */
  510         smb_init_root_dirent(server, &root);
  511         root_inode = smb_iget(sb, &root);
  512         if (!root_inode)
  513                 goto out_no_root;
  514 
  515         sb->s_root = d_alloc_root(root_inode);
  516         if (!sb->s_root)
  517                 goto out_no_root;
  518         smb_new_dentry(sb->s_root);
  519 
  520         return sb;
  521 
  522 out_no_root:
  523         iput(root_inode);
  524 out_bad_option:
  525         smb_kfree(server->mnt);
  526 out_no_mount:
  527         smb_kfree(server->temp_buf);
  528 out_no_temp:
  529         smb_vfree(server->packet);
  530 out_no_mem:
  531         if (!server->mnt)
  532                 printk(KERN_ERR "smb_read_super: allocation failure\n");
  533         goto out_fail;
  534 out_wrong_data:
  535         printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
  536         goto out_fail;
  537 out_no_data:
  538         printk(KERN_ERR "smb_read_super: missing data argument\n");
  539 out_fail:
  540         return NULL;
  541 }
  542 
  543 static int
  544 smb_statfs(struct super_block *sb, struct statfs *buf)
  545 {
  546         int result = smb_proc_dskattr(sb, buf);
  547 
  548         buf->f_type = SMB_SUPER_MAGIC;
  549         buf->f_namelen = SMB_MAXPATHLEN;
  550         return result;
  551 }
  552 
  553 int
  554 smb_notify_change(struct dentry *dentry, struct iattr *attr)
  555 {
  556         struct inode *inode = dentry->d_inode;
  557         struct smb_sb_info *server = server_from_dentry(dentry);
  558         unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
  559         int error, changed, refresh = 0;
  560         struct smb_fattr fattr;
  561 
  562         error = smb_revalidate_inode(dentry);
  563         if (error)
  564                 goto out;
  565 
  566         if ((error = inode_change_ok(inode, attr)) < 0)
  567                 goto out;
  568 
  569         error = -EPERM;
  570         if ((attr->ia_valid & ATTR_UID) && (attr->ia_uid != server->mnt->uid))
  571                 goto out;
  572 
  573         if ((attr->ia_valid & ATTR_GID) && (attr->ia_uid != server->mnt->gid))
  574                 goto out;
  575 
  576         if ((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~mask))
  577                 goto out;
  578 
  579         if ((attr->ia_valid & ATTR_SIZE) != 0) {
  580                 VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
  581                         DENTRY_PATH(dentry),
  582                         (long) inode->i_size, (long) attr->ia_size);
  583 
  584                 filemap_fdatasync(inode->i_mapping);
  585                 filemap_fdatawait(inode->i_mapping);
  586 
  587                 error = smb_open(dentry, O_WRONLY);
  588                 if (error)
  589                         goto out;
  590                 error = smb_proc_trunc(server, inode->u.smbfs_i.fileid,
  591                                          attr->ia_size);
  592                 if (error)
  593                         goto out;
  594                 error = vmtruncate(inode, attr->ia_size);
  595                 if (error)
  596                         goto out;
  597                 refresh = 1;
  598         }
  599 
  600         /*
  601          * Initialize the fattr and check for changed fields.
  602          * Note: CTIME under SMB is creation time rather than
  603          * change time, so we don't attempt to change it.
  604          */
  605         smb_get_inode_attr(inode, &fattr);
  606 
  607         changed = 0;
  608         if ((attr->ia_valid & ATTR_MTIME) != 0) {
  609                 fattr.f_mtime = attr->ia_mtime;
  610                 changed = 1;
  611         }
  612         if ((attr->ia_valid & ATTR_ATIME) != 0) {
  613                 fattr.f_atime = attr->ia_atime;
  614                 /* Earlier protocols don't have an access time */
  615                 if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
  616                         changed = 1;
  617         }
  618         if (changed) {
  619                 error = smb_proc_settime(dentry, &fattr);
  620                 if (error)
  621                         goto out;
  622                 refresh = 1;
  623         }
  624 
  625         /*
  626          * Check for mode changes ... we're extremely limited in
  627          * what can be set for SMB servers: just the read-only bit.
  628          */
  629         if ((attr->ia_valid & ATTR_MODE) != 0) {
  630                 VERBOSE("%s/%s mode change, old=%x, new=%x\n",
  631                         DENTRY_PATH(dentry), fattr.f_mode, attr->ia_mode);
  632                 changed = 0;
  633                 if (attr->ia_mode & S_IWUSR) {
  634                         if (fattr.attr & aRONLY) {
  635                                 fattr.attr &= ~aRONLY;
  636                                 changed = 1;
  637                         }
  638                 } else {
  639                         if (!(fattr.attr & aRONLY)) {
  640                                 fattr.attr |= aRONLY;
  641                                 changed = 1;
  642                         }
  643                 }
  644                 if (changed) {
  645                         error = smb_proc_setattr(dentry, &fattr);
  646                         if (error)
  647                                 goto out;
  648                         refresh = 1;
  649                 }
  650         }
  651         error = 0;
  652 
  653 out:
  654         if (refresh)
  655                 smb_refresh_inode(dentry);
  656         return error;
  657 }
  658 
  659 #ifdef DEBUG_SMB_MALLOC
  660 int smb_malloced;
  661 int smb_current_kmalloced;
  662 int smb_current_vmalloced;
  663 #endif
  664 
  665 static DECLARE_FSTYPE( smb_fs_type, "smbfs", smb_read_super, 0);
  666 
  667 static int __init init_smb_fs(void)
  668 {
  669         DEBUG1("registering ...\n");
  670 
  671 #ifdef DEBUG_SMB_MALLOC
  672         smb_malloced = 0;
  673         smb_current_kmalloced = 0;
  674         smb_current_vmalloced = 0;
  675 #endif
  676 
  677         return register_filesystem(&smb_fs_type);
  678 }
  679 
  680 static void __exit exit_smb_fs(void)
  681 {
  682         DEBUG1("unregistering ...\n");
  683         unregister_filesystem(&smb_fs_type);
  684 #ifdef DEBUG_SMB_MALLOC
  685         printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced);
  686         printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced);
  687         printk(KERN_DEBUG "smb_current_vmalloced: %d\n",smb_current_vmalloced);
  688 #endif
  689 }
  690 
  691 EXPORT_NO_SYMBOLS;
  692 
  693 module_init(init_smb_fs)
  694 module_exit(exit_smb_fs)
  695 MODULE_LICENSE("GPL");

Cache object: 345d05f6889e23e8121bd4de33d95927


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.