struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs_fattr newfattr; int error; struct inode *inode; if (!sb) { printk("nfs_fhget: super block is NULL\n"); return NULL; } if (!fattr) { error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle, &newfattr); if (error) { printk("nfs_fhget: getattr error = %d\n", -error); return NULL; } fattr = &newfattr; } if (!(inode = iget(sb, fattr->fileid))) { printk("nfs_fhget: iget failed\n"); return NULL; } if (inode->i_dev == sb->s_dev) { if (inode->i_ino != fattr->fileid) { printk("nfs_fhget: unexpected inode from iget\n"); return inode; } *NFS_FH(inode) = *fhandle; nfs_refresh_inode(inode, fattr); } return inode; }
int nfs_chmod(struct file *filp, mode_t mode) { struct nfs_fh *fhandle; struct nfs_fattr temp_fattr; struct nfs_sattr temp_sattr; int status; DPRINTF(CLU_LEVEL,("nfs_chmod:\n")); demand(filp, bogus filp); fhandle = GETFHANDLE(filp); k2printf("nfs_chmod: nfs_proc_getattr\n"); status = nfs_proc_getattr(fhandle,&temp_fattr); if (status == 0) { /* ALLPERMS is 07777 */ temp_sattr.mode = ((temp_fattr.mode & ~ALLPERMS) | (mode & ALLPERMS)); DPRINTF(CLU_LEVEL,("nfs_chmod: nfs_proc_getattr returned %d, " "new mode %08x, old %08x, setmode: %08x\n", status,mode,temp_fattr.mode,temp_sattr.mode)); /* do only permissions, also should use macro definitions */ temp_sattr.uid = -1; temp_sattr.gid = -1; temp_sattr.size = -1; temp_sattr.atime.seconds = -1; temp_sattr.atime.useconds = -1; temp_sattr.mtime.seconds = -1; temp_sattr.mtime.useconds = -1; status = nfs_proc_setattr(fhandle, &temp_sattr, &temp_fattr); DPRINTF(CLU_LEVEL,("nfs_chmod: nfs_proc_setattr returned %d\n",status)); if (status == 0) { filp->f_mode = temp_sattr.mode; nfs_fill_stat(&temp_fattr, GETNFSCE(filp)); } return(status);} else { fprintf(stderr,"warning: nfs_chmod, was not able to do getattr\n" "on a NFS filp\n"); errno = EACCES; return -1; } }
int nfs_truncate(struct file *filp, off_t length) { struct nfs_fh *fhandle; struct nfs_fattr temp_fattr; struct nfs_sattr temp_sattr; int status; /* make sure you interact with bc to drop unneeded page */ DPRINTF(CLU_LEVEL,("nfs_truncate:\n")); demand(filp, bogus filp); fhandle = GETFHANDLE(filp); /* HBXX this is OVERKILL, should not flush all things. */ nfsc_sync(GETNFSCE(filp)); /* just to be sure the size if proper */ k2printf("nfs_truncate: nfs_proc_getattr\n"); status = nfs_proc_getattr(fhandle,&temp_fattr); if (status == 0) { temp_sattr.mode = temp_fattr.mode; /* do only permissions, also should use macro definitions */ temp_sattr.uid = -1; temp_sattr.gid = -1; temp_sattr.size = length; temp_sattr.atime.seconds = -1; temp_sattr.atime.useconds = -1; temp_sattr.mtime.seconds = -1; temp_sattr.mtime.useconds = -1; status = nfs_proc_setattr(fhandle, &temp_sattr, &temp_fattr); if (status == 0) { /* note that the f_pos is not changed */ nfs_flush_filp(filp); nfs_fill_stat(&temp_fattr, GETNFSCE(filp)); return(0); } errno = status; return(-1); } else { fprintf(stderr,"warning: nfs_truncate, was not able to do getattr\n" "on a NFS filp\n"); errno = status; return -1; } }
int nfs_mkdir(struct file *dir_filp, const char *name, mode_t mode) { struct nfs_fh *dhandle, temp_fhandle; struct nfs_fattr temp_fattr; struct nfs_sattr temp_sattr; int status; DPRINTF(CLU_LEVEL,("nfs_mkdir:\n")); demand(dir_filp, bogus dir_filp); demand(name, empty name given to nfs_mkdir); dhandle = GETFHANDLE(dir_filp); k2printf("nfs_mkdir: nfs_proc_getattr\n"); status = nfs_proc_getattr(dhandle,&temp_fattr); if (status != 0) { fprintf(stderr,"nfs_mkdir, was not able to do getattr\n" "on a NFS filp\n"); errno = status; return -1; } temp_sattr.mode = ((temp_fattr.mode & 0xfffffe00) | (mode & 0x000001ff)); temp_sattr.uid = __current->uid; temp_sattr.gid = (temp_fattr.gid) ? temp_fattr.gid : __current->egid; temp_sattr.size = 1024; temp_sattr.atime.seconds = -1; temp_sattr.atime.useconds = -1; temp_sattr.mtime.seconds = -1; temp_sattr.mtime.useconds = -1; status = nfs_proc_mkdir(dhandle, name, &temp_sattr, &temp_fhandle, &temp_fattr); nfs_flush_filp(dir_filp); nfs_cache_remove(dir_filp,name); if (status == 0) { nfs_cache_add_devino(FHGETDEV(dhandle),temp_fattr.fileid,"..", GETNFSCE(dir_filp)); return 0; } else { errno = status; return -1; } }
int nfs_chown(struct file *filp, uid_t owner, gid_t group) { struct nfs_fh *fhandle; struct nfs_fattr temp_fattr; struct nfs_sattr temp_sattr; int status; kprintf("nfs_chown: bogusly returning success for ease of use.\n"); return 0; /* XXX */ DPRINTF(CLU_LEVEL,("nfs_chown:\n")); demand(filp, bogus filp); fhandle = GETFHANDLE(filp); #if 0 k2printf("nfs_chown: nfs_proc_getattr\n"); status = nfs_proc_getattr(fhandle,&temp_fattr); #else status = 0; #endif if (status == 0) { temp_sattr.mode = -1; temp_sattr.uid = (owner == -1) ? -1 : owner; temp_sattr.gid = (group == -1) ? -1 : group; temp_sattr.size = -1; temp_sattr.atime.seconds = -1; temp_sattr.atime.useconds = -1; temp_sattr.mtime.seconds = -1; temp_sattr.mtime.useconds = -1; status = nfs_proc_setattr( fhandle, &temp_sattr, &temp_fattr); if (status == 0) { nfs_fill_stat(&temp_fattr, GETNFSCE(filp)); } return(status);} else { fprintf(stderr,"nfs_chown, was not able to do getattr\n" "on a NFS filp\n"); errno = EACCES; return -1; } }
inline int nfs_stat_fh(struct nfs_fh *fhandle, nfsc_p e) { struct nfs_fattr temp_fattr; int status; k2printf("nfs_stat_fh : nfs_proc_getattr\n"); status = nfs_proc_getattr(fhandle,&temp_fattr); if (status != 0) { k1printf("nfs_stat_fh, was not able to do getattr\n" "on a NFS filp status: %d\n",status); errno = status; return -1; } nfs_fill_stat(&temp_fattr, e); return(0); }
static inline void revalidate_dir(struct nfs_server * server, struct inode * dir) { struct nfs_fattr fattr; if (jiffies - NFS_READTIME(dir) < NFS_ATTRTIMEO(dir)) return; NFS_READTIME(dir) = jiffies; if (nfs_proc_getattr(server, NFS_FH(dir), &fattr) == 0) { nfs_refresh_inode(dir, &fattr); if (fattr.mtime.seconds == NFS_OLDMTIME(dir)) { if ((NFS_ATTRTIMEO(dir) <<= 1) > server->acdirmax) NFS_ATTRTIMEO(dir) = server->acdirmax; return; } NFS_OLDMTIME(dir) = fattr.mtime.seconds; } /* invalidate directory cache here when we _really_ start caching */ }
/* * The way this works is that the mount process passes a structure * in the data argument which contains the server's IP address * and the root file handle obtained from the server's mount * daemon. We stash these away in the private superblock fields. */ struct super_block * nfs_read_super(struct super_block *sb, void *raw_data, int silent) { struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data; struct nfs_server *server; struct rpc_xprt *xprt; struct rpc_clnt *clnt; struct nfs_fh *root_fh; struct inode *root_inode; unsigned int authflavor; int tcp; struct sockaddr_in srvaddr; struct rpc_timeout timeparms; struct nfs_fattr fattr; MOD_INC_USE_COUNT; if (!data) goto out_miss_args; /* No NFS V3. */ if (data->flags & NFS_MOUNT_VER3) goto out_fail; /* Don't complain if "mount" is newer. */ if (data->version < NFS_MOUNT_VERSION) { printk("nfs warning: mount version %s than kernel\n", data->version < NFS_MOUNT_VERSION ? "older" : "newer"); if (data->version < 2) data->namlen = 0; if (data->version < 3) data->bsize = 0; } /* We now require that the mount process passes the remote address */ memcpy(&srvaddr, &data->addr, sizeof(srvaddr)); if (srvaddr.sin_addr.s_addr == INADDR_ANY) goto out_no_remote; lock_super(sb); sb->s_flags |= MS_ODD_RENAME; /* This should go away */ sb->s_magic = NFS_SUPER_MAGIC; sb->s_op = &nfs_sops; sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); sb->u.nfs_sb.s_root = data->root; server = &sb->u.nfs_sb.s_server; server->rsize = nfs_block_size(data->rsize, NULL); server->wsize = nfs_block_size(data->wsize, NULL); server->flags = data->flags; if (data->flags & NFS_MOUNT_NOAC) { data->acregmin = data->acregmax = 0; data->acdirmin = data->acdirmax = 0; } server->acregmin = data->acregmin*HZ; server->acregmax = data->acregmax*HZ; server->acdirmin = data->acdirmin*HZ; server->acdirmax = data->acdirmax*HZ; server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL); if (!server->hostname) goto out_unlock; strcpy(server->hostname, data->hostname); /* Which protocol do we use? */ tcp = (data->flags & NFS_MOUNT_TCP); /* Initialize timeout values */ timeparms.to_initval = data->timeo * HZ / 10; timeparms.to_retries = data->retrans; timeparms.to_maxval = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT; timeparms.to_exponential = 1; /* Now create transport and client */ xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP, &srvaddr, &timeparms); if (xprt == NULL) goto out_no_xprt; /* Choose authentication flavor */ authflavor = RPC_AUTH_UNIX; if (data->flags & NFS_MOUNT_SECURE) authflavor = RPC_AUTH_DES; else if (data->flags & NFS_MOUNT_KERBEROS) authflavor = RPC_AUTH_KRB; clnt = rpc_create_client(xprt, server->hostname, &nfs_program, NFS_VERSION, authflavor); if (clnt == NULL) goto out_no_client; clnt->cl_intr = (data->flags & NFS_MOUNT_INTR)? 1 : 0; clnt->cl_softrtry = (data->flags & NFS_MOUNT_SOFT)? 1 : 0; clnt->cl_chatty = 1; server->client = clnt; /* Fire up rpciod if not yet running */ if (rpciod_up() != 0) goto out_no_iod; /* * Keep the super block locked while we try to get * the root fh attributes. */ root_fh = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); if (!root_fh) goto out_no_fh; *root_fh = data->root; if (nfs_proc_getattr(server, root_fh, &fattr) != 0) goto out_no_fattr; clnt->cl_to_err = 1; root_inode = __nfs_fhget(sb, &fattr); if (!root_inode) goto out_no_root; sb->s_root = d_alloc_root(root_inode, NULL); if (!sb->s_root) goto out_no_root; sb->s_root->d_op = &nfs_dentry_operations; sb->s_root->d_fsdata = root_fh; /* We're airborne */ unlock_super(sb); /* Check whether to start the lockd process */ if (!(server->flags & NFS_MOUNT_NONLM)) lockd_up(); return sb; /* Yargs. It didn't work out. */ out_no_root: printk("nfs_read_super: get root inode failed\n"); iput(root_inode); goto out_free_fh; out_no_fattr: printk("nfs_read_super: get root fattr failed\n"); out_free_fh: kfree(root_fh); out_no_fh: rpciod_down(); goto out_shutdown; out_no_iod: printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); out_shutdown: rpc_shutdown_client(server->client); goto out_free_host; out_no_client: printk(KERN_WARNING "NFS: cannot create RPC client.\n"); xprt_destroy(xprt); goto out_free_host; out_no_xprt: printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); out_free_host: kfree(server->hostname); out_unlock: unlock_super(sb); goto out_fail; out_no_remote: printk("NFS: mount program didn't pass remote address!\n"); goto out_fail; out_miss_args: printk("nfs_read_super: missing data argument\n"); out_fail: sb->s_dev = 0; MOD_DEC_USE_COUNT; return NULL; }
int nfs_utimes(struct file *filp, const struct timeval *times) { struct nfs_fh *fhandle; struct nfs_fattr temp_fattr; struct nfs_sattr temp_sattr; int status; DPRINTF(CLU_LEVEL,("nfs_utimes:\n")); demand(filp, bogus filp); fhandle = GETFHANDLE(filp); #if 0 fprintf(stderr,"nfs_utimes: nfs_proc_getattr\n"); status = nfs_proc_getattr(fhandle,&temp_fattr); #else status = 0; #endif if (status == 0) { temp_sattr.mode = -1; temp_sattr.uid = -1; temp_sattr.gid = -1; temp_sattr.size = -1; if (times) { //fprintf(stderr,"time passed in\n"); temp_sattr.atime.seconds = times[0].tv_sec; temp_sattr.atime.useconds = times[0].tv_usec; temp_sattr.mtime.seconds = times[1].tv_sec; temp_sattr.mtime.useconds = times[1].tv_usec; } else { struct timeval times2; gettimeofday(×2,(struct timezone *)0); //fprintf(stderr,"times2.tv_sec = %ld\n",times2.tv_sec); temp_sattr.atime.seconds = times2.tv_sec; temp_sattr.atime.useconds = times2.tv_usec; temp_sattr.mtime.seconds = times2.tv_sec; temp_sattr.mtime.useconds = times2.tv_usec; } /* the owner will be the only one allowed to change the file */ status = nfs_proc_setattr(fhandle, &temp_sattr, &temp_fattr); //fprintf(stderr,"status: %d errno %d\n",status,errno); if (status == 0) { nfsc_p e = GETNFSCE(filp); nfs_fill_stat(&temp_fattr,e); nfs_flush_filp(filp); } return(status); } else { fprintf(stderr,"warning: nfs_utimes, was not able to do getattr\n" "on a NFS filp\n"); errno = EACCES; return -1; } }