📄 nfs.c
字号:
sem_acquire(v->sem, 1); err = _nfs_readdir(fs, v, cookie, buf, len); sem_acquire(v->sem, 1); return err;}int nfs_open(fs_cookie fs, fs_vnode _v, file_cookie *_cookie, int oflags){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; nfs_cookie *cookie; int err; TOUCH(nfs); TRACE("nfs_open: fsid 0x%x, vnid 0x%Lx, oflags 0x%x\n", nfs->id, VNODETOVNID(v), oflags); if(v->st == STREAM_TYPE_DIR) { err = ERR_VFS_IS_DIR; goto err; } cookie = kmalloc(sizeof(nfs_cookie)); if(cookie == NULL) { err = ERR_NO_MEMORY; goto err; } cookie->v = v; cookie->u.file.pos = 0; cookie->u.file.oflags = oflags; *_cookie = (file_cookie)cookie; err = NO_ERROR;err: return err;}int nfs_close(fs_cookie fs, fs_vnode _v, file_cookie _cookie){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; TOUCH(nfs);TOUCH(v); TRACE("nfs_close: fsid 0x%x, vnid 0x%Lx\n", nfs->id, VNODETOVNID(v)); return NO_ERROR;}int nfs_freecookie(fs_cookie fs, fs_vnode _v, file_cookie _cookie){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; nfs_cookie *cookie = (nfs_cookie *)_cookie; TOUCH(nfs);TOUCH(v); TRACE("nfs_freecookie: fsid 0x%x, vnid 0x%Lx\n", nfs->id, VNODETOVNID(v)); kfree(cookie); return NO_ERROR;}int nfs_fsync(fs_cookie fs, fs_vnode _v){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; TOUCH(nfs);TOUCH(v); TRACE("nfs_fsync: fsid 0x%x, vnid 0x%Lx\n", nfs->id, VNODETOVNID(v)); return NO_ERROR;}#define READ_BUF_SIZE 1024static ssize_t nfs_readfile(nfs_fs *nfs, nfs_vnode *v, nfs_cookie *cookie, void *buf, off_t pos, ssize_t len){ uint8 abuf[4 + sizeof(nfs_fattr) + READ_BUF_SIZE]; nfs_readargs *args = (nfs_readargs *)abuf; nfs_readres *res = (nfs_readres *)abuf; int err; ssize_t total_read = 0; /* check args */ if(pos < 0) pos = cookie->u.file.pos; /* can't do more than 32-bit offsets right now */ if(pos > 0xffffffff) return 0; /* negative or zero length means nothing */ if(len <= 0) return 0; while(len > 0) { ssize_t to_read = min(len, READ_BUF_SIZE); /* put together the message */ memcpy(&args->file, &v->nfs_handle, sizeof(args->file)); args->offset = htonl(pos); args->count = htonl(to_read); args->totalcount = 0; // unused err = rpc_call(&nfs->rpc, NFSPROG, NFSVERS, NFSPROC_READ, args, sizeof(*args), abuf, sizeof(abuf)); if(err < 0) break; /* get response */ if(ntohl(res->status) != NFS_OK) break; /* see how much we read */ err = user_memcpy((uint8 *)buf + total_read, res->data, ntohl(res->len)); if(err < 0) { total_read = err; // bad user give me bad buffer break; } pos += ntohl(res->len); len -= ntohl(res->len); total_read += ntohl(res->len); /* short read, we're done */ if((ssize_t)ntohl(res->len) != to_read) break; } cookie->u.file.pos = pos; return total_read;}ssize_t nfs_read(fs_cookie fs, fs_vnode _v, file_cookie _cookie, void *buf, off_t pos, ssize_t len){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; nfs_cookie *cookie = (nfs_cookie *)_cookie; ssize_t err; TRACE("nfs_read: fsid 0x%x, vnid 0x%Lx, buf %p, pos 0x%Lx, len %ld\n", nfs->id, VNODETOVNID(v), buf, pos, len); if(v->st == STREAM_TYPE_DIR) return ERR_VFS_IS_DIR; sem_acquire(v->sem, 1); err = nfs_readfile(nfs, v, cookie, buf, pos, len); sem_release(v->sem, 1); return err;}#define WRITE_BUF_SIZE 1024static ssize_t nfs_writefile(nfs_fs *nfs, nfs_vnode *v, nfs_cookie *cookie, const void *buf, off_t pos, ssize_t len){ uint8 abuf[sizeof(nfs_writeargs) + WRITE_BUF_SIZE]; nfs_writeargs *args = (nfs_writeargs *)abuf; nfs_attrstat *res = (nfs_attrstat *)abuf; int err; ssize_t total_written = 0; /* check args */ if(pos < 0) pos = cookie->u.file.pos; /* can't do more than 32-bit offsets right now */ if(pos > 0xffffffff) return 0; /* negative or zero length means nothing */ if(len <= 0) return 0; while(len > 0) { ssize_t to_write = min(len, WRITE_BUF_SIZE); /* put together the message */ memcpy(&args->file, &v->nfs_handle, sizeof(args->file)); args->beginoffset = 0; // unused args->offset = htonl(pos); args->totalcount = 0; // unused args->len = htonl(to_write); err = user_memcpy(args->data, (const uint8 *)buf + total_written, to_write); if(err < 0) { total_written = err; break; } err = rpc_call(&nfs->rpc, NFSPROG, NFSVERS, NFSPROC_WRITE, args, sizeof(*args) + to_write, abuf, sizeof(abuf)); if(err < 0) break; /* get response */ if(ntohl(res->status) != NFS_OK) break; pos += to_write; len -= to_write; total_written += to_write; } cookie->u.file.pos = pos; return total_written;}ssize_t nfs_write(fs_cookie fs, fs_vnode _v, file_cookie _cookie, const void *buf, off_t pos, ssize_t len){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; nfs_cookie *cookie = (nfs_cookie *)_cookie; ssize_t err; TRACE("nfs_write: fsid 0x%x, vnid 0x%Lx, buf %p, pos 0x%Lx, len %ld\n", nfs->id, VNODETOVNID(v), buf, pos, len); sem_acquire(v->sem, 1); switch(v->st) { case STREAM_TYPE_FILE: err = nfs_writefile(nfs, v, cookie, buf, pos, len); break; case STREAM_TYPE_DIR: err = ERR_NOT_ALLOWED; break; default: err = ERR_GENERAL; } sem_release(v->sem, 1); return err;}int nfs_seek(fs_cookie fs, fs_vnode _v, file_cookie _cookie, off_t pos, seek_type st){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; nfs_cookie *cookie = (nfs_cookie *)_cookie; int err = NO_ERROR; TRACE("nfs_seek: fsid 0x%x, vnid 0x%Lx, pos 0x%Lx, seek_type %d\n", nfs->id, VNODETOVNID(v), pos, st); sem_acquire(v->sem, 1); switch(v->st) { case STREAM_TYPE_FILE: { nfs_attrstat attrstat; off_t file_len; err = nfs_getattr(nfs, v, &attrstat); if(err < 0) goto out; file_len = ntohl(attrstat.attributes.size); switch(st) { case _SEEK_SET: if(pos < 0) pos = 0; if(pos > file_len) pos = file_len; cookie->u.file.pos = pos; break; case _SEEK_CUR: if(pos + cookie->u.file.pos > file_len) cookie->u.file.pos = file_len; else if(pos + cookie->u.file.pos < 0) cookie->u.file.pos = 0; else cookie->u.file.pos += pos; break; case _SEEK_END: if(pos > 0) cookie->u.file.pos = file_len; else if(pos + file_len < 0) cookie->u.file.pos = 0; else cookie->u.file.pos = pos + file_len; break; default: err = ERR_INVALID_ARGS; } break; } case STREAM_TYPE_DIR: switch(st) { // only valid args are seek_type _SEEK_SET, pos 0. // this rewinds to beginning of directory case _SEEK_SET: if(pos == 0) { cookie->u.dir.nfscookie = 0; cookie->u.dir.at_end = false; } else { err = ERR_INVALID_ARGS; } break; case _SEEK_CUR: case _SEEK_END: default: err = ERR_INVALID_ARGS; } default: err = ERR_INVALID_ARGS; }out: sem_release(v->sem, 1); return err;}int nfs_ioctl(fs_cookie fs, fs_vnode _v, file_cookie cookie, int op, void *buf, size_t len){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; TOUCH(nfs);TOUCH(v); TRACE("nfs_ioctl: fsid 0x%x, vnid 0x%Lx, op %d, buf %p, len %ld\n", nfs->id, VNODETOVNID(v), op, buf, len); return ERR_UNIMPLEMENTED;}int nfs_canpage(fs_cookie fs, fs_vnode _v){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; TOUCH(nfs);TOUCH(v); TRACE("nfs_canpage: fsid 0x%x, vnid 0x%Lx\n", nfs->id, VNODETOVNID(v)); return ERR_UNIMPLEMENTED;}ssize_t nfs_readpage(fs_cookie fs, fs_vnode _v, iovecs *vecs, off_t pos){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; TOUCH(nfs);TOUCH(v); TRACE("nfs_readpage: fsid 0x%x, vnid 0x%Lx, vecs %p, pos 0x%Lx\n", nfs->id, VNODETOVNID(v), vecs, pos); return ERR_UNIMPLEMENTED;}ssize_t nfs_writepage(fs_cookie fs, fs_vnode _v, iovecs *vecs, off_t pos){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; TOUCH(nfs);TOUCH(v); TRACE("nfs_writepage: fsid 0x%x, vnid 0x%Lx, vecs %p, pos 0x%Lx\n", nfs->id, VNODETOVNID(v), vecs, pos); return ERR_UNIMPLEMENTED;}int nfs_create(fs_cookie fs, fs_vnode _dir, const char *name, void *create_args, vnode_id *new_vnid){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *dir = (nfs_vnode *)_dir; TOUCH(nfs);TOUCH(dir); TRACE("nfs_create: fsid 0x%x, vnid 0x%Lx, name '%s'\n", nfs->id, VNODETOVNID(dir), name); return ERR_UNIMPLEMENTED;}int nfs_unlink(fs_cookie fs, fs_vnode _dir, const char *name){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *dir = (nfs_vnode *)_dir; TOUCH(nfs);TOUCH(dir); TRACE("nfs_unlink: fsid 0x%x, vnid 0x%Lx, name '%s'\n", nfs->id, VNODETOVNID(dir), name); return ERR_UNIMPLEMENTED;}int nfs_rename(fs_cookie fs, fs_vnode _olddir, const char *oldname, fs_vnode _newdir, const char *newname){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *olddir = (nfs_vnode *)_olddir; nfs_vnode *newdir = (nfs_vnode *)_newdir; TOUCH(nfs);TOUCH(olddir);TOUCH(newdir); TRACE("nfs_rename: fsid 0x%x, vnid 0x%Lx, oldname '%s', newdir 0x%Lx, newname '%s'\n", nfs->id, VNODETOVNID(olddir), oldname, VNODETOVNID(newdir), newname); return ERR_UNIMPLEMENTED;}int nfs_mkdir(fs_cookie _fs, fs_vnode _base_dir, const char *name){ nfs_fs *nfs = (nfs_fs *)_fs; nfs_vnode *dir = (nfs_vnode *)_base_dir; TOUCH(nfs);TOUCH(dir); TRACE("nfs_mkdir: fsid 0x%x, vnid 0x%Lx, name '%s'\n", nfs->id, VNODETOVNID(dir), name); return ERR_UNIMPLEMENTED;}int nfs_rmdir(fs_cookie _fs, fs_vnode _base_dir, const char *name){ nfs_fs *nfs = (nfs_fs *)_fs; nfs_vnode *dir = (nfs_vnode *)_base_dir; TOUCH(nfs);TOUCH(dir); TRACE("nfs_rmdir: fsid 0x%x, vnid 0x%Lx, name '%s'\n", nfs->id, VNODETOVNID(dir), name); return ERR_UNIMPLEMENTED;}static int nfs_getattr(nfs_fs *nfs, nfs_vnode *v, nfs_attrstat *attrstat){ return rpc_call(&nfs->rpc, NFSPROG, NFSVERS, NFSPROC_GETATTR, &v->nfs_handle, sizeof(v->nfs_handle), attrstat, sizeof(nfs_attrstat));}int nfs_rstat(fs_cookie fs, fs_vnode _v, struct file_stat *stat){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; nfs_attrstat attrstat; int err; TRACE("nfs_rstat: fsid 0x%x, vnid 0x%Lx, stat %p\n", nfs->id, VNODETOVNID(v), stat); sem_acquire(v->sem, 1); err = nfs_getattr(nfs, v, &attrstat); if(err < 0) goto out; if(ntohl(attrstat.status) != NFS_OK) { err = ERR_IO_ERROR; goto out; } /* copy the stat over from the nfs attrstat */ stat->vnid = VNODETOVNID(v); stat->size = ntohl(attrstat.attributes.size); switch(ntohl(attrstat.attributes.ftype)) { case NFREG: stat->type = STREAM_TYPE_FILE; break; case NFDIR: stat->type = STREAM_TYPE_DIR; break; default: stat->type = STREAM_TYPE_DEVICE; // XXX should have unknown type break; } err = NO_ERROR;out: sem_release(v->sem, 1); return err;}int nfs_wstat(fs_cookie fs, fs_vnode _v, struct file_stat *stat, int stat_mask){ nfs_fs *nfs = (nfs_fs *)fs; nfs_vnode *v = (nfs_vnode *)_v; TOUCH(nfs);TOUCH(v); TRACE("nfs_wstat: fsid 0x%x, vnid 0x%Lx, stat %p, stat_mask 0x%x\n", nfs->id, VNODETOVNID(v), stat, stat_mask); return ERR_UNIMPLEMENTED;}static struct fs_calls nfs_calls = { &nfs_mount, &nfs_unmount, &nfs_sync, &nfs_lookup, &nfs_getvnode, &nfs_putvnode, &nfs_removevnode, &nfs_opendir, &nfs_closedir, &nfs_rewinddir, &nfs_readdir, &nfs_open, &nfs_close, &nfs_freecookie, &nfs_fsync, &nfs_read, &nfs_write, &nfs_seek, &nfs_ioctl, &nfs_canpage, &nfs_readpage, &nfs_writepage, &nfs_create, &nfs_unlink, &nfs_rename, &nfs_mkdir, &nfs_rmdir, &nfs_rstat, &nfs_wstat};int fs_bootstrap(void);int fs_bootstrap(void){ dprintf("bootstrap_nfs: entry\n"); return vfs_register_filesystem("nfs", &nfs_calls);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -