root/fs/nfs/inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. nfs_put_inode
  2. nfs_put_super
  3. nfs_read_super
  4. nfs_statfs
  5. nfs_fhget
  6. nfs_notify_change
  7. init_module
  8. 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 #ifdef MODULE
  17 #include <linux/module.h>
  18 #include <linux/version.h>
  19 #else
  20 #define MOD_INC_USE_COUNT
  21 #define MOD_DEC_USE_COUNT
  22 #endif
  23 
  24 #include <asm/system.h>
  25 #include <asm/segment.h>
  26 
  27 #include <linux/sched.h>
  28 #include <linux/nfs_fs.h>
  29 #include <linux/kernel.h>
  30 #include <linux/mm.h>
  31 #include <linux/string.h>
  32 #include <linux/stat.h>
  33 #include <linux/errno.h>
  34 #include <linux/locks.h>
  35 
  36 extern int close_fp(struct file *filp);
  37 
  38 static int nfs_notify_change(struct inode *, struct iattr *);
  39 static void nfs_put_inode(struct inode *);
  40 static void nfs_put_super(struct super_block *);
  41 static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz);
  42 
  43 static struct super_operations nfs_sops = { 
  44         NULL,                   /* read inode */
  45         nfs_notify_change,      /* notify change */
  46         NULL,                   /* write inode */
  47         nfs_put_inode,          /* put inode */
  48         nfs_put_super,          /* put superblock */
  49         NULL,                   /* write superblock */
  50         nfs_statfs,             /* stat filesystem */
  51         NULL
  52 };
  53 
  54 static void nfs_put_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  55 {
  56         clear_inode(inode);
  57 }
  58 
  59 void nfs_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61         close_fp(sb->u.nfs_sb.s_server.file);
  62         rpc_closesock(sb->u.nfs_sb.s_server.rsock);
  63         lock_super(sb);
  64         sb->s_dev = 0;
  65         unlock_super(sb);
  66         MOD_DEC_USE_COUNT;
  67 }
  68 
  69 /*
  70  * The way this works is that the mount process passes a structure
  71  * in the data argument which contains an open socket to the NFS
  72  * server and the root file handle obtained from the server's mount
  73  * daemon.  We stash theses away in the private superblock fields.
  74  * Later we can add other mount parameters like caching values.
  75  */
  76 
  77 struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
     /* [previous][next][first][last][top][bottom][index][help] */
  78                                    int silent)
  79 {
  80         struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data;
  81         struct nfs_server *server;
  82         unsigned int fd;
  83         struct file *filp;
  84 
  85         kdev_t dev = sb->s_dev;
  86 
  87         MOD_INC_USE_COUNT;
  88         if (!data) {
  89                 printk("nfs_read_super: missing data argument\n");
  90                 sb->s_dev = 0;
  91                 MOD_DEC_USE_COUNT;
  92                 return NULL;
  93         }
  94         fd = data->fd;
  95         if (data->version != NFS_MOUNT_VERSION) {
  96                 printk("nfs warning: mount version %s than kernel\n",
  97                         data->version < NFS_MOUNT_VERSION ? "older" : "newer");
  98         }
  99         if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) {
 100                 printk("nfs_read_super: invalid file descriptor\n");
 101                 sb->s_dev = 0;
 102                 MOD_DEC_USE_COUNT;
 103                 return NULL;
 104         }
 105         if (!S_ISSOCK(filp->f_inode->i_mode)) {
 106                 printk("nfs_read_super: not a socket\n");
 107                 sb->s_dev = 0;
 108                 MOD_DEC_USE_COUNT;
 109                 return NULL;
 110         }
 111         filp->f_count++;
 112         lock_super(sb);
 113 
 114         sb->s_blocksize = 1024; /* XXX */
 115         sb->s_blocksize_bits = 10;
 116         sb->s_magic = NFS_SUPER_MAGIC;
 117         sb->s_dev = dev;
 118         sb->s_op = &nfs_sops;
 119         server = &sb->u.nfs_sb.s_server;
 120         server->file = filp;
 121         server->lock = 0;
 122         server->wait = NULL;
 123         server->flags = data->flags;
 124         server->rsize = data->rsize;
 125         if (server->rsize <= 0)
 126                 server->rsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
 127         else if (server->rsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)
 128                 server->rsize = NFS_MAX_FILE_IO_BUFFER_SIZE;
 129         server->wsize = data->wsize;
 130         if (server->wsize <= 0)
 131                 server->wsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
 132         else if (server->wsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)
 133                 server->wsize = NFS_MAX_FILE_IO_BUFFER_SIZE;
 134         server->timeo = data->timeo*HZ/10;
 135         server->retrans = data->retrans;
 136         server->acregmin = data->acregmin*HZ;
 137         server->acregmax = data->acregmax*HZ;
 138         server->acdirmin = data->acdirmin*HZ;
 139         server->acdirmax = data->acdirmax*HZ;
 140         strcpy(server->hostname, data->hostname);
 141 
 142         /* Start of JSP NFS patch */
 143         /* Check if passed address in data->addr */
 144         if (data->addr.sin_addr.s_addr == INADDR_ANY) {  /* No address passed */
 145           if (((struct sockaddr_in *)(&server->toaddr))->sin_addr.s_addr == INADDR_ANY) {
 146             printk("NFS: Error passed unconnected socket and no address\n") ;
 147             MOD_DEC_USE_COUNT;
 148             return NULL ;
 149           } else {
 150             /* Need access to socket internals  JSP */
 151             struct socket *sock;
 152             int dummylen ;
 153 
 154          /*   printk("NFS: using socket address\n") ;*/
 155 
 156             sock = &((filp->f_inode)->u.socket_i);
 157 
 158             /* extract the other end of the socket into server->toaddr */
 159             sock->ops->getname(sock, &(server->toaddr), &dummylen, 1) ;
 160           }
 161         } else {
 162         /*  printk("NFS: coppying passed addr to server->toaddr\n") ;*/
 163           memcpy((char *)&(server->toaddr),(char *)(&data->addr),sizeof(server->toaddr));
 164         }
 165         /* End of JSP NFS patch */
 166 
 167         if ((server->rsock = rpc_makesock(filp)) == NULL) {
 168                 printk("NFS: cannot create RPC socket.\n");
 169                 MOD_DEC_USE_COUNT;
 170                 return NULL;
 171         }
 172 
 173         sb->u.nfs_sb.s_root = data->root;
 174         unlock_super(sb);
 175         if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
 176                 sb->s_dev = 0;
 177                 printk("nfs_read_super: get root inode failed\n");
 178                 MOD_DEC_USE_COUNT;
 179                 return NULL;
 180         }
 181         return sb;
 182 }
 183 
 184 void nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186         int error;
 187         struct nfs_fsinfo res;
 188         struct statfs tmp;
 189 
 190         error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root,
 191                 &res);
 192         if (error) {
 193                 printk("nfs_statfs: statfs error = %d\n", -error);
 194                 res.bsize = res.blocks = res.bfree = res.bavail = 0;
 195         }
 196         tmp.f_type = NFS_SUPER_MAGIC;
 197         tmp.f_bsize = res.bsize;
 198         tmp.f_blocks = res.blocks;
 199         tmp.f_bfree = res.bfree;
 200         tmp.f_bavail = res.bavail;
 201         tmp.f_files = 0;
 202         tmp.f_ffree = 0;
 203         tmp.f_namelen = NAME_MAX;
 204         memcpy_tofs(buf, &tmp, bufsiz);
 205 }
 206 
 207 /*
 208  * This is our own version of iget that looks up inodes by file handle
 209  * instead of inode number.  We use this technique instead of using
 210  * the vfs read_inode function because there is no way to pass the
 211  * file handle or current attributes into the read_inode function.
 212  * We just have to be careful not to subvert iget's special handling
 213  * of mount points.
 214  */
 215 
 216 struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
     /* [previous][next][first][last][top][bottom][index][help] */
 217                         struct nfs_fattr *fattr)
 218 {
 219         struct nfs_fattr newfattr;
 220         int error;
 221         struct inode *inode;
 222 
 223         if (!sb) {
 224                 printk("nfs_fhget: super block is NULL\n");
 225                 return NULL;
 226         }
 227         if (!fattr) {
 228                 error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,
 229                         &newfattr);
 230                 if (error) {
 231                         printk("nfs_fhget: getattr error = %d\n", -error);
 232                         return NULL;
 233                 }
 234                 fattr = &newfattr;
 235         }
 236         if (!(inode = iget(sb, fattr->fileid))) {
 237                 printk("nfs_fhget: iget failed\n");
 238                 return NULL;
 239         }
 240         if (inode->i_dev == sb->s_dev) {
 241                 if (inode->i_ino != fattr->fileid) {
 242                         printk("nfs_fhget: unexpected inode from iget\n");
 243                         return inode;
 244                 }
 245                 *NFS_FH(inode) = *fhandle;
 246                 nfs_refresh_inode(inode, fattr);
 247         }
 248         return inode;
 249 }
 250 
 251 int nfs_notify_change(struct inode *inode, struct iattr *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 252 {
 253         struct nfs_sattr sattr;
 254         struct nfs_fattr fattr;
 255         int error;
 256 
 257         if (attr->ia_valid & ATTR_MODE) 
 258                 sattr.mode = attr->ia_mode;
 259         else
 260                 sattr.mode = (unsigned) -1;
 261 
 262         if (attr->ia_valid & ATTR_UID)
 263                 sattr.uid = attr->ia_uid;
 264         else
 265                 sattr.uid = (unsigned) -1;
 266 
 267         if (attr->ia_valid & ATTR_GID)
 268                 sattr.gid = attr->ia_gid;
 269         else
 270                 sattr.gid = (unsigned) -1;
 271 
 272         if (attr->ia_valid & ATTR_SIZE)
 273                 sattr.size = S_ISREG(inode->i_mode) ? attr->ia_size : -1;
 274         else
 275                 sattr.size = (unsigned) -1;
 276 
 277         if (attr->ia_valid & ATTR_MTIME) {
 278                 sattr.mtime.seconds = attr->ia_mtime;
 279                 sattr.mtime.useconds = 0;
 280         } else 
 281                 sattr.mtime.seconds = sattr.mtime.useconds = (unsigned) -1;
 282 
 283         if (attr->ia_valid & ATTR_ATIME) {
 284                 sattr.atime.seconds = attr->ia_atime;
 285                 sattr.atime.useconds = 0;
 286         } else
 287                 sattr.atime.seconds = sattr.atime.useconds = (unsigned) -1;
 288 
 289         error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
 290                 &sattr, &fattr);
 291         if (!error)
 292                 nfs_refresh_inode(inode, &fattr);
 293         inode->i_dirt = 0;
 294         return error;
 295 }
 296 
 297 #ifdef MODULE
 298 
 299 /* Every kernel module contains stuff like this. */
 300 
 301 char kernel_version[] = UTS_RELEASE;
 302 
 303 static struct file_system_type nfs_fs_type = {
 304         nfs_read_super, "nfs", 0, NULL
 305 };
 306 
 307 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309         register_filesystem(&nfs_fs_type);
 310         return 0;
 311 }
 312 
 313 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 314 {
 315         unregister_filesystem(&nfs_fs_type);
 316         nfs_kfree_cache();
 317 }
 318 
 319 #endif

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