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

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