root/fs/smbfs/inode.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. smb_read_inode
  2. smb_put_inode
  3. smb_put_super
  4. smb_read_super
  5. smb_statfs
  6. smb_notify_change
  7. init_module
  8. cleanup_module

   1 /*
   2  *  inode.c
   3  *
   4  *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
   5  *
   6  */
   7 
   8 #include <linux/config.h>
   9 #ifdef MODULE
  10 #include <linux/module.h>
  11 #include <linux/version.h>
  12 #else
  13 #define MOD_INC_USE_COUNT
  14 #define MOD_DEC_USE_COUNT
  15 #endif
  16 
  17 #include <asm/system.h>
  18 #include <asm/segment.h>
  19 
  20 #include <linux/sched.h>
  21 #include <linux/smb_fs.h>
  22 #include <linux/smbno.h>
  23 #include <linux/kernel.h>
  24 #include <linux/mm.h>
  25 #include <linux/string.h>
  26 #include <linux/stat.h>
  27 #include <linux/errno.h>
  28 #include <linux/locks.h>
  29 #include <linux/fcntl.h>
  30 #include <linux/malloc.h>
  31 
  32 extern int close_fp(struct file *filp);
  33 
  34 static void smb_put_inode(struct inode *);
  35 static void smb_read_inode(struct inode *);
  36 static void smb_put_super(struct super_block *);
  37 static void smb_statfs(struct super_block *, struct statfs *, int bufsiz);
  38 
  39 static struct super_operations smb_sops = {
  40         smb_read_inode,         /* read inode */
  41         smb_notify_change,      /* notify change */
  42         NULL,                   /* write inode */
  43         smb_put_inode,          /* put inode */
  44         smb_put_super,          /* put superblock */
  45         NULL,                   /* write superblock */
  46         smb_statfs,             /* stat filesystem */
  47         NULL
  48         };
  49 
  50 /* smb_read_inode: Called from iget, it only traverses the allocated
  51    smb_inode_info's and initializes the inode from the data found
  52    there.  It does not allocate or deallocate anything. */
  53 
  54 static void
  55 smb_read_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57         /* Our task should be extremely simple here. We only have to
  58            look up the infomation somebody else (smb_iget) put into
  59            the inode tree. The address of this information is the
  60            inode->i_ino. Just to make sure everything went well, we
  61            check it's there. */
  62 
  63         struct smb_inode_info *inode_info
  64                 = (struct smb_inode_info *)(inode->i_ino);
  65 
  66 #if 1
  67         struct smb_inode_info *root = &(SMB_SERVER(inode)->root);
  68         struct smb_inode_info *check_info = root;
  69 
  70         do {
  71                 if (inode_info == check_info) {
  72                         if (check_info->state == INODE_LOOKED_UP) {
  73                                 DDPRINTK("smb_read_inode: found it!\n");
  74                                 goto good;
  75                         }
  76                         else {
  77                                 printk("smb_read_inode: "
  78                                        "state != INODE_LOOKED_UP\n");
  79                                 return;
  80                         }
  81                 }
  82                 check_info = check_info->next;
  83         } while (check_info != root);
  84 
  85         /* Ok, now we're in trouble. The inode info is not there. What
  86            should we do now??? */
  87         printk("smb_read_inode: inode info not found\n");
  88         return;
  89 
  90  good:
  91 #endif
  92         inode_info->state = INODE_VALID;
  93 
  94         SMB_INOP(inode) = inode_info;
  95 
  96         if (SMB_INOP(inode)->finfo.attr & aDIR)
  97                 inode->i_mode = SMB_SERVER(inode)->m.dir_mode;
  98         else
  99                 inode->i_mode = SMB_SERVER(inode)->m.file_mode;
 100 
 101         DDPRINTK("smb_read_inode: inode->i_mode = %u\n", inode->i_mode);
 102 
 103         inode->i_nlink   = 1;
 104         inode->i_uid     = SMB_SERVER(inode)->m.uid;
 105         inode->i_gid     = SMB_SERVER(inode)->m.gid;
 106         inode->i_size    = SMB_INOP(inode)->finfo.size;
 107         inode->i_blksize = 1024;
 108         inode->i_rdev    = 0;
 109         if ((inode->i_blksize != 0) && (inode->i_size != 0))
 110                 inode->i_blocks =
 111                         (inode->i_size - 1) / inode->i_blksize + 1;
 112         else
 113                 inode->i_blocks = 0;
 114 
 115         inode->i_mtime = SMB_INOP(inode)->finfo.mtime;
 116         inode->i_ctime = SMB_INOP(inode)->finfo.ctime;
 117         inode->i_atime = SMB_INOP(inode)->finfo.atime;
 118 
 119         if (S_ISREG(inode->i_mode))
 120                 inode->i_op = &smb_file_inode_operations;
 121         else if (S_ISDIR(inode->i_mode))
 122                 inode->i_op = &smb_dir_inode_operations;
 123         else
 124                 inode->i_op = NULL;
 125 
 126 }
 127 
 128 static void
 129 smb_put_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         struct smb_dirent *finfo = SMB_FINFO(inode);
 132 
 133         if (finfo->opened != 0) {
 134 
 135                 /* smb_proc_close wants mtime in finfo */
 136                 finfo->mtime = inode->i_mtime;
 137                 
 138                 if (smb_proc_close(SMB_SERVER(inode), finfo)) {
 139                         /* We can't do anything but complain. */
 140                         printk("smb_put_inode: could not close\n");
 141                 }
 142         }
 143         
 144         smb_free_inode_info(SMB_INOP(inode));
 145 
 146         if (S_ISDIR(inode->i_mode)) {
 147                 DDPRINTK("smb_put_inode: put directory %ld\n",
 148                          inode->i_ino);
 149                 smb_invalid_dir_cache(inode->i_ino);
 150         }                
 151 
 152         clear_inode(inode);
 153 }
 154 
 155 static void
 156 smb_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         struct smb_server *server = &(SMB_SBP(sb)->s_server);
 159 
 160         smb_proc_disconnect(server);
 161         close_fp(server->sock_file);
 162 
 163         lock_super(sb);
 164 
 165         smb_free_all_inodes(server);
 166 
 167         smb_kfree_s(server->packet, server->max_xmit);
 168 
 169         sb->s_dev = 0;
 170         smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
 171 
 172         unlock_super(sb);
 173 
 174         MOD_DEC_USE_COUNT;
 175 }
 176 
 177 
 178 /* Hmm, should we do this like the NFS mount command does? Guess so.. */
 179 struct super_block *
 180 smb_read_super(struct super_block *sb, void *raw_data, int silent)
     /* [previous][next][first][last][top][bottom][index][help] */
 181 {
 182         struct smb_mount_data *data = (struct smb_mount_data *) raw_data;
 183         struct smb_server *server;
 184         struct smb_sb_info *smb_sb;
 185         unsigned int fd;
 186         struct file *filp;
 187         kdev_t dev = sb->s_dev;
 188         int error;
 189 
 190         if (!data) {
 191                 printk("smb_read_super: missing data argument\n");
 192                 sb->s_dev = 0;
 193                 return NULL;
 194         }
 195         fd = data->fd;
 196         if (data->version != SMB_MOUNT_VERSION) {
 197                 printk("smb warning: mount version %s than kernel\n",
 198                        (data->version < SMB_MOUNT_VERSION) ?
 199                        "older" : "newer");
 200         }
 201         if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) {
 202                 printk("smb_read_super: invalid file descriptor\n");
 203                 sb->s_dev = 0;
 204                 return NULL;
 205         }
 206         if (!S_ISSOCK(filp->f_inode->i_mode)) {
 207                 printk("smb_read_super: not a socket!\n");
 208                 sb->s_dev = 0;
 209                 return NULL;
 210         }
 211 
 212         /* We must malloc our own super-block info */
 213         smb_sb = (struct smb_sb_info *)smb_kmalloc(sizeof(struct smb_sb_info),
 214                                                    GFP_KERNEL);
 215 
 216         if (smb_sb == NULL) {
 217                 printk("smb_read_super: could not alloc smb_sb_info\n");
 218                 return NULL;
 219         }
 220 
 221         filp->f_count += 1; 
 222 
 223         lock_super(sb);
 224 
 225         SMB_SBP(sb) = smb_sb;
 226         
 227         sb->s_blocksize = 1024; /* Eh...  Is this correct? */
 228         sb->s_blocksize_bits = 10;
 229         sb->s_magic = SMB_SUPER_MAGIC;
 230         sb->s_dev = dev;
 231         sb->s_op = &smb_sops;
 232 
 233         server = &(SMB_SBP(sb)->s_server);
 234         server->sock_file = filp;
 235         server->lock = 0;
 236         server->wait = NULL;
 237         server->packet = NULL;
 238         server->max_xmit = data->max_xmit;
 239         if (server->max_xmit <= 0)
 240                 server->max_xmit = SMB_DEF_MAX_XMIT;
 241    
 242         server->tid = 0;
 243         server->pid = current->pid;
 244         server->mid = current->pid + 20;
 245 
 246         server->m = *data;
 247         server->m.file_mode = (server->m.file_mode &
 248                              (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
 249         server->m.dir_mode  = (server->m.dir_mode &
 250                              (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
 251 
 252         smb_init_root(server);
 253 
 254         /*
 255          * Make the connection to the server
 256          */
 257         
 258         error = smb_proc_connect(server);
 259 
 260         unlock_super(sb);
 261 
 262         if (error < 0) {
 263                 sb->s_dev = 0;
 264                 printk("smb_read_super: Failed connection, bailing out "
 265                        "(error = %d).\n", -error);
 266                 goto fail;
 267         }
 268 
 269         if (server->protocol >= PROTOCOL_LANMAN2)
 270                 server->case_handling = CASE_DEFAULT;
 271         else
 272                 server->case_handling = CASE_LOWER;
 273 
 274         if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0) {
 275                 sb->s_dev = 0;
 276                 printk("smb_read_super: could not get super block "
 277                        "attributes\n");
 278                 smb_kfree_s(server->packet, server->max_xmit);
 279                 goto fail;
 280         }
 281 
 282         if ((error = smb_stat_root(server)) < 0) {
 283                 sb->s_dev = 0;
 284                 printk("smb_read_super: could not get root dir attributes\n");
 285                 smb_kfree_s(server->packet, server->max_xmit);
 286                 goto fail;
 287         }
 288 
 289         DPRINTK("smb_read_super : %u %u %u %u\n",
 290                 SMB_SBP(sb)->s_attr.total,
 291                 SMB_SBP(sb)->s_attr.blocksize,
 292                 SMB_SBP(sb)->s_attr.allocblocks,
 293                 SMB_SBP(sb)->s_attr.free);
 294 
 295         DPRINTK("smb_read_super: SMB_SBP(sb) = %x\n", (int)SMB_SBP(sb));
 296 
 297         if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) {
 298                 sb->s_dev = 0;
 299                 printk("smb_read_super: get root inode failed\n");
 300                 smb_kfree_s(server->packet, server->max_xmit);
 301                 goto fail;
 302         }
 303 
 304         MOD_INC_USE_COUNT;
 305         return sb;
 306 
 307  fail:
 308         filp->f_count -= 1; 
 309         smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
 310         return NULL;
 311 }
 312 
 313 static void 
 314 smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 315 {
 316         int error;
 317         struct smb_dskattr attr;
 318         struct statfs tmp;
 319         
 320         error = smb_proc_dskattr(sb, &attr);
 321 
 322         if (error) {
 323                 printk("smb_statfs: dskattr error = %d\n", -error);
 324                 attr.total = attr.allocblocks = attr.blocksize =
 325                         attr.free = 0;
 326         }
 327 
 328         tmp.f_type = SMB_SUPER_MAGIC;
 329         tmp.f_bsize = attr.blocksize*attr.allocblocks;
 330         tmp.f_blocks = attr.total;
 331         tmp.f_bfree = attr.free;
 332         tmp.f_bavail = attr.free;
 333         tmp.f_files = -1;
 334         tmp.f_ffree = -1;
 335         tmp.f_namelen = SMB_MAXPATHLEN;
 336         memcpy_tofs(buf, &tmp, bufsiz);
 337 }
 338 
 339 /* DO MORE */
 340 int
 341 smb_notify_change(struct inode *inode, struct iattr *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 342 {
 343         int error = 0;
 344 
 345         if ((error = inode_change_ok(inode, attr)) < 0)
 346                 return error;
 347 
 348         if (((attr->ia_valid & ATTR_UID) && 
 349              (attr->ia_uid != SMB_SERVER(inode)->m.uid)))
 350                 return -EPERM;
 351 
 352         if (((attr->ia_valid & ATTR_GID) && 
 353              (attr->ia_uid != SMB_SERVER(inode)->m.gid)))
 354                 return -EPERM;
 355 
 356         if (((attr->ia_valid & ATTR_MODE) &&
 357              (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
 358                 return -EPERM;
 359 
 360         if ((attr->ia_valid & ATTR_SIZE) != 0) {
 361 
 362                 if ((error = smb_make_open(inode, O_WRONLY)) < 0)
 363                         goto fail;
 364 
 365                 if ((error = smb_proc_trunc(SMB_SERVER(inode),
 366                                             SMB_FINFO(inode)->fileid,
 367                                             attr->ia_size)) < 0)
 368                         goto fail;
 369 
 370         }
 371 
 372         if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0) {
 373 
 374                 struct smb_dirent finfo;
 375 
 376                 finfo.attr  = 0;
 377 
 378                 if ((attr->ia_valid & ATTR_CTIME) != 0)
 379                         finfo.ctime = attr->ia_ctime;
 380                 else
 381                         finfo.ctime = inode->i_ctime;
 382 
 383                 if ((attr->ia_valid & ATTR_MTIME) != 0)
 384                         finfo.mtime = attr->ia_mtime;
 385                 else
 386                         finfo.mtime = inode->i_mtime;
 387 
 388                 if ((attr->ia_valid & ATTR_ATIME) != 0)
 389                         finfo.atime = attr->ia_atime;
 390                 else
 391                         finfo.atime = inode->i_atime;
 392 
 393                 if ((error = smb_proc_setattr(SMB_SERVER(inode),
 394                                               inode, &finfo)) >= 0) {
 395                         inode->i_ctime = finfo.ctime;
 396                         inode->i_mtime = finfo.mtime;
 397                         inode->i_atime = finfo.atime;
 398                 }
 399         }
 400 
 401  fail:
 402         smb_invalid_dir_cache((unsigned long)(SMB_INOP(inode)->dir));
 403 
 404         return error;
 405 }
 406 
 407                 
 408 #ifdef DEBUG_SMB_MALLOC
 409 int smb_malloced;
 410 int smb_current_malloced;
 411 #endif
 412 
 413 #ifdef MODULE
 414 
 415 char kernel_version[] = UTS_RELEASE;
 416 
 417 /* looks ugly, taken from gcc-info */
 418 static void *shut_up_gcc = (&shut_up_gcc, kernel_version);
 419 
 420 static struct file_system_type smb_fs_type = {
 421         smb_read_super, "smbfs", 0, NULL
 422         };
 423 
 424 int
 425 init_module( void)
     /* [previous][next][first][last][top][bottom][index][help] */
 426 {
 427         DPRINTK("smbfs: init_module called\n");
 428 
 429 #ifdef DEBUG_SMB_MALLOC
 430         smb_malloced = 0;
 431         smb_current_malloced = 0;
 432 #endif
 433 
 434         smb_init_dir_cache();
 435         register_filesystem(&smb_fs_type);
 436         return 0;
 437 }
 438 
 439 void
 440 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 441 {
 442         DPRINTK("smbfs: cleanup_module called\n");
 443         smb_free_dir_cache();
 444         unregister_filesystem(&smb_fs_type);
 445 #ifdef DEBUG_SMB_MALLOC
 446         printk("smb_malloced: %d\n", smb_malloced);
 447         printk("smb_current_malloced: %d\n", smb_current_malloced);
 448 #endif
 449 }
 450 
 451 #endif
 452 
 453 /*
 454  * Overrides for Emacs so that we follow Linus's tabbing style.
 455  * Emacs will notice this stuff at the end of the file and automatically
 456  * adjust the settings for this buffer only.  This must remain at the end
 457  * of the file.
 458  * ---------------------------------------------------------------------------
 459  * Local variables:
 460  * c-indent-level: 8
 461  * c-brace-imaginary-offset: 0
 462  * c-brace-offset: -8
 463  * c-argdecl-indent: 8
 464  * c-label-offset: -8
 465  * c-continued-statement-offset: 8
 466  * c-continued-brace-offset: 0
 467  * End:
 468  */

/* [previous][next][first][last][top][bottom][index][help] */