root/fs/nfs/inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. nfs_read_inode
  2. nfs_put_inode
  3. nfs_put_super
  4. nfs_read_super
  5. nfs_statfs
  6. nfs_fhget
  7. nfs_notify_change
  8. run_nfsiod
  9. init_nfs_fs
  10. init_module
  11. cleanup_module

   1 /*
   2  *  linux/fs/nfs/inode.c
   3  *
   4  *  Copyright (C) 1992  Rick Sladkey
   5  *
   6  *  nfs inode and superblock handling functions
   7  *
   8  *  Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
   9  *  experimental NFS changes. Modularisation taken straight from SYS5 fs.
  10  *
  11  *  Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
  12  *  J.S.Peatfield@damtp.cam.ac.uk
  13  *
  14  */
  15 
  16 #include <linux/module.h>
  17 
  18 #include <linux/sched.h>
  19 #include <linux/nfs_fs.h>
  20 #include <linux/nfsiod.h>
  21 #include <linux/kernel.h>
  22 #include <linux/mm.h>
  23 #include <linux/string.h>
  24 #include <linux/stat.h>
  25 #include <linux/errno.h>
  26 #include <linux/locks.h>
  27 #include <linux/smp.h>
  28 #include <linux/smp_lock.h>
  29 
  30 #include <asm/system.h>
  31 #include <asm/segment.h>
  32 
  33 /* This is for kernel_thread */
  34 #define __KERNEL_SYSCALLS__
  35 #include <linux/unistd.h>
  36 
  37 extern int close_fp(struct file *filp);
  38 
  39 static int nfs_notify_change(struct inode *, struct iattr *);
  40 static void nfs_put_inode(struct inode *);
  41 static void nfs_put_super(struct super_block *);
  42 static void nfs_read_inode(struct inode *);
  43 static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz);
  44 
  45 static struct super_operations nfs_sops = { 
  46         nfs_read_inode,         /* read inode */
  47         nfs_notify_change,      /* notify change */
  48         NULL,                   /* write inode */
  49         nfs_put_inode,          /* put inode */
  50         nfs_put_super,          /* put superblock */
  51         NULL,                   /* write superblock */
  52         nfs_statfs,             /* stat filesystem */
  53         NULL
  54 };
  55 
  56 /*
  57  * The "read_inode" function doesn't actually do anything:
  58  * the real data is filled in later in nfs_fhget. Here we
  59  * just mark the cache times invalid, and zero out i_mode
  60  * (the latter makes "nfs_refresh_inode" do the right thing
  61  * wrt pipe inodes)
  62  */
  63 static void nfs_read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65         inode->i_mode = 0;
  66         inode->i_op = NULL;
  67         NFS_CACHEINV(inode);
  68 }
  69 
  70 static void nfs_put_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         if (NFS_RENAMED_DIR(inode))
  73                 nfs_sillyrename_cleanup(inode);
  74         if (inode->i_pipe)
  75                 clear_inode(inode);
  76 }
  77 
  78 void nfs_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         close_fp(sb->u.nfs_sb.s_server.file);
  81         rpc_closesock(sb->u.nfs_sb.s_server.rsock);
  82         lock_super(sb);
  83         sb->s_dev = 0;
  84         unlock_super(sb);
  85         MOD_DEC_USE_COUNT;
  86 }
  87 
  88 /*
  89  * The way this works is that the mount process passes a structure
  90  * in the data argument which contains an open socket to the NFS
  91  * server and the root file handle obtained from the server's mount
  92  * daemon.  We stash these away in the private superblock fields.
  93  * Later we can add other mount parameters like caching values.
  94  */
  95 
  96 struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
     /* [previous][next][first][last][top][bottom][index][help] */
  97                                    int silent)
  98 {
  99         struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data;
 100         struct nfs_server *server;
 101         unsigned int fd;
 102         struct file *filp;
 103 
 104         kdev_t dev = sb->s_dev;
 105 
 106         MOD_INC_USE_COUNT;
 107         if (!data) {
 108                 printk("nfs_read_super: missing data argument\n");
 109                 sb->s_dev = 0;
 110                 MOD_DEC_USE_COUNT;
 111                 return NULL;
 112         }
 113         fd = data->fd;
 114         if (data->version != NFS_MOUNT_VERSION) {
 115                 printk("nfs warning: mount version %s than kernel\n",
 116                         data->version < NFS_MOUNT_VERSION ? "older" : "newer");
 117         }
 118         if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) {
 119                 printk("nfs_read_super: invalid file descriptor\n");
 120                 sb->s_dev = 0;
 121                 MOD_DEC_USE_COUNT;
 122                 return NULL;
 123         }
 124         if (!S_ISSOCK(filp->f_inode->i_mode)) {
 125                 printk("nfs_read_super: not a socket\n");
 126                 sb->s_dev = 0;
 127                 MOD_DEC_USE_COUNT;
 128                 return NULL;
 129         }
 130         filp->f_count++;
 131         lock_super(sb);
 132 
 133         sb->s_blocksize = 1024; /* XXX */
 134         sb->s_blocksize_bits = 10;
 135         sb->s_magic = NFS_SUPER_MAGIC;
 136         sb->s_dev = dev;
 137         sb->s_op = &nfs_sops;
 138         server = &sb->u.nfs_sb.s_server;
 139         server->file = filp;
 140         server->lock = 0;
 141         server->wait = NULL;
 142         server->flags = data->flags;
 143         server->rsize = data->rsize;
 144         if (server->rsize <= 0)
 145                 server->rsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
 146         else if (server->rsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)
 147                 server->rsize = NFS_MAX_FILE_IO_BUFFER_SIZE;
 148         server->wsize = data->wsize;
 149         if (server->wsize <= 0)
 150                 server->wsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
 151         else if (server->wsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)
 152                 server->wsize = NFS_MAX_FILE_IO_BUFFER_SIZE;
 153         server->timeo = data->timeo*HZ/10;
 154         server->retrans = data->retrans;
 155         server->acregmin = data->acregmin*HZ;
 156         server->acregmax = data->acregmax*HZ;
 157         server->acdirmin = data->acdirmin*HZ;
 158         server->acdirmax = data->acdirmax*HZ;
 159         strcpy(server->hostname, data->hostname);
 160 
 161         /* Start of JSP NFS patch */
 162         /* Check if passed address in data->addr */
 163         if (data->addr.sin_addr.s_addr == INADDR_ANY) {  /* No address passed */
 164           if (((struct sockaddr_in *)(&server->toaddr))->sin_addr.s_addr == INADDR_ANY) {
 165             printk("NFS: Error passed unconnected socket and no address\n") ;
 166             MOD_DEC_USE_COUNT;
 167             return NULL ;
 168           } else {
 169             /* Need access to socket internals  JSP */
 170             struct socket *sock;
 171             int dummylen ;
 172 
 173          /*   printk("NFS: using socket address\n") ;*/
 174 
 175             sock = &((filp->f_inode)->u.socket_i);
 176 
 177             /* extract the other end of the socket into server->toaddr */
 178             sock->ops->getname(sock, &(server->toaddr), &dummylen, 1) ;
 179           }
 180         } else {
 181         /*  printk("NFS: copying passed addr to server->toaddr\n") ;*/
 182           memcpy((char *)&(server->toaddr),(char *)(&data->addr),sizeof(server->toaddr));
 183         }
 184         /* End of JSP NFS patch */
 185 
 186         if ((server->rsock = rpc_makesock(filp)) == NULL) {
 187                 printk("NFS: cannot create RPC socket.\n");
 188                 MOD_DEC_USE_COUNT;
 189                 return NULL;
 190         }
 191 
 192         sb->u.nfs_sb.s_root = data->root;
 193         unlock_super(sb);
 194         if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
 195                 sb->s_dev = 0;
 196                 printk("nfs_read_super: get root inode failed\n");
 197                 MOD_DEC_USE_COUNT;
 198                 return NULL;
 199         }
 200         return sb;
 201 }
 202 
 203 void nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205         int error;
 206         struct nfs_fsinfo res;
 207         struct statfs tmp;
 208 
 209         error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root,
 210                 &res);
 211         if (error) {
 212                 printk("nfs_statfs: statfs error = %d\n", -error);
 213                 res.bsize = res.blocks = res.bfree = res.bavail = 0;
 214         }
 215         tmp.f_type = NFS_SUPER_MAGIC;
 216         tmp.f_bsize = res.bsize;
 217         tmp.f_blocks = res.blocks;
 218         tmp.f_bfree = res.bfree;
 219         tmp.f_bavail = res.bavail;
 220         tmp.f_files = 0;
 221         tmp.f_ffree = 0;
 222         tmp.f_namelen = NAME_MAX;
 223         memcpy_tofs(buf, &tmp, bufsiz);
 224 }
 225 
 226 /*
 227  * This is our own version of iget that looks up inodes by file handle
 228  * instead of inode number.  We use this technique instead of using
 229  * the vfs read_inode function because there is no way to pass the
 230  * file handle or current attributes into the read_inode function.
 231  * We just have to be careful not to subvert iget's special handling
 232  * of mount points.
 233  */
 234 
 235 struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 236                         struct nfs_fattr *fattr)
 237 {
 238         struct nfs_fattr newfattr;
 239         int error;
 240         struct inode *inode;
 241 
 242         if (!sb) {
 243                 printk("nfs_fhget: super block is NULL\n");
 244                 return NULL;
 245         }
 246         if (!fattr) {
 247                 error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,
 248                         &newfattr);
 249                 if (error) {
 250                         printk("nfs_fhget: getattr error = %d\n", -error);
 251                         return NULL;
 252                 }
 253                 fattr = &newfattr;
 254         }
 255         if (!(inode = iget(sb, fattr->fileid))) {
 256                 printk("nfs_fhget: iget failed\n");
 257                 return NULL;
 258         }
 259         if (inode->i_dev == sb->s_dev) {
 260                 if (inode->i_ino != fattr->fileid) {
 261                         printk("nfs_fhget: unexpected inode from iget\n");
 262                         return inode;
 263                 }
 264                 *NFS_FH(inode) = *fhandle;
 265                 nfs_refresh_inode(inode, fattr);
 266         }
 267         return inode;
 268 }
 269 
 270 int nfs_notify_change(struct inode *inode, struct iattr *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272         struct nfs_sattr sattr;
 273         struct nfs_fattr fattr;
 274         int error;
 275 
 276         sattr.mode = (unsigned) -1;
 277         if (attr->ia_valid & ATTR_MODE) 
 278                 sattr.mode = attr->ia_mode;
 279 
 280         sattr.uid = (unsigned) -1;
 281         if (attr->ia_valid & ATTR_UID)
 282                 sattr.uid = attr->ia_uid;
 283 
 284         sattr.gid = (unsigned) -1;
 285         if (attr->ia_valid & ATTR_GID)
 286                 sattr.gid = attr->ia_gid;
 287 
 288 
 289         sattr.size = (unsigned) -1;
 290         if (attr->ia_valid & ATTR_SIZE)
 291                 sattr.size = S_ISREG(inode->i_mode) ? attr->ia_size : -1;
 292 
 293         sattr.mtime.seconds = sattr.mtime.useconds = (unsigned) -1;
 294         if (attr->ia_valid & ATTR_MTIME) {
 295                 sattr.mtime.seconds = attr->ia_mtime;
 296                 sattr.mtime.useconds = 0;
 297         }
 298 
 299         sattr.atime.seconds = sattr.atime.useconds = (unsigned) -1;
 300         if (attr->ia_valid & ATTR_ATIME) {
 301                 sattr.atime.seconds = attr->ia_atime;
 302                 sattr.atime.useconds = 0;
 303         }
 304 
 305         error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
 306                 &sattr, &fattr);
 307         if (!error)
 308                 nfs_refresh_inode(inode, &fattr);
 309         inode->i_dirt = 0;
 310         return error;
 311 }
 312 
 313 /* Every kernel module contains stuff like this. */
 314 
 315 static struct file_system_type nfs_fs_type = {
 316         nfs_read_super, "nfs", 0, NULL
 317 };
 318 
 319 /*
 320  * Start up an nfsiod process. This is an awful hack, because when running
 321  * as a module, we will keep insmod's memory. Besides, the current->comm
 322  * hack won't work in this case
 323  * The best would be to have a syscall for nfs client control that (among
 324  * other things) forks biod's.
 325  * Alternatively, we might want to have the idle task spawn biod's on demand.
 326  */
 327 static int run_nfsiod(void *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 328 {
 329         int     ret;
 330 
 331 #ifdef __SMP__
 332         lock_kernel();
 333         syscall_count++;
 334 #endif
 335 
 336         MOD_INC_USE_COUNT;
 337         current->session = 1;
 338         current->pgrp = 1;
 339         sprintf(current->comm, "nfsiod");
 340         ret = nfsiod();
 341         MOD_DEC_USE_COUNT;
 342         return ret;
 343 }
 344 
 345 int init_nfs_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 346 {
 347         /* Fork four biod's */
 348         kernel_thread(run_nfsiod, NULL, 0);
 349         kernel_thread(run_nfsiod, NULL, 0);
 350         kernel_thread(run_nfsiod, NULL, 0);
 351         kernel_thread(run_nfsiod, NULL, 0);
 352         return register_filesystem(&nfs_fs_type);
 353 }
 354 
 355 #ifdef MODULE
 356 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 357 {
 358         int status;
 359 
 360         if ((status = init_nfs_fs()) == 0)
 361                 register_symtab(0);
 362         return status;
 363 }
 364 
 365 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 366 {
 367         unregister_filesystem(&nfs_fs_type);
 368         nfs_kfree_cache();
 369 }
 370 
 371 #endif

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