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

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