📄 nfs4proc.c
字号:
* opens the file O_RDONLY. This will all be resolved with the VFS changes. */static intnfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, int flags, struct nameidata *nd){ struct path path = { .mnt = nd->mnt, .dentry = dentry, }; struct nfs4_state *state; struct rpc_cred *cred; int status = 0; cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); if (IS_ERR(cred)) { status = PTR_ERR(cred); goto out; } state = nfs4_do_open(dir, &path, flags, sattr, cred); put_rpccred(cred); d_drop(dentry); if (IS_ERR(state)) { status = PTR_ERR(state); goto out; } d_add(dentry, igrab(state->inode)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); if (flags & O_EXCL) { struct nfs_fattr fattr; status = nfs4_do_setattr(state->inode, &fattr, sattr, state); if (status == 0) nfs_setattr_update_inode(state->inode, sattr); nfs_post_op_update_inode(state->inode, &fattr); } if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) status = nfs4_intent_set_file(nd, &path, state); else nfs4_close_sync(&path, state, flags);out: return status;}static int _nfs4_proc_remove(struct inode *dir, struct qstr *name){ struct nfs_server *server = NFS_SERVER(dir); struct nfs_removeargs args = { .fh = NFS_FH(dir), .name.len = name->len, .name.name = name->name, .bitmask = server->attr_bitmask, }; struct nfs_removeres res = { .server = server, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], .rpc_argp = &args, .rpc_resp = &res, }; int status; nfs_fattr_init(&res.dir_attr); status = rpc_call_sync(server->client, &msg, 0); if (status == 0) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, &res.dir_attr); } return status;}static int nfs4_proc_remove(struct inode *dir, struct qstr *name){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_remove(dir, name), &exception); } while (exception.retry); return err;}static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir){ struct nfs_server *server = NFS_SERVER(dir); struct nfs_removeargs *args = msg->rpc_argp; struct nfs_removeres *res = msg->rpc_resp; args->bitmask = server->attr_bitmask; res->server = server; msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];}static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir){ struct nfs_removeres *res = task->tk_msg.rpc_resp; if (nfs4_async_handle_error(task, res->server) == -EAGAIN) return 0; update_changeattr(dir, &res->cinfo); nfs_post_op_update_inode(dir, &res->dir_attr); return 1;}static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, struct inode *new_dir, struct qstr *new_name){ struct nfs_server *server = NFS_SERVER(old_dir); struct nfs4_rename_arg arg = { .old_dir = NFS_FH(old_dir), .new_dir = NFS_FH(new_dir), .old_name = old_name, .new_name = new_name, .bitmask = server->attr_bitmask, }; struct nfs_fattr old_fattr, new_fattr; struct nfs4_rename_res res = { .server = server, .old_fattr = &old_fattr, .new_fattr = &new_fattr, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME], .rpc_argp = &arg, .rpc_resp = &res, }; int status; nfs_fattr_init(res.old_fattr); nfs_fattr_init(res.new_fattr); status = rpc_call_sync(server->client, &msg, 0); if (!status) { update_changeattr(old_dir, &res.old_cinfo); nfs_post_op_update_inode(old_dir, res.old_fattr); update_changeattr(new_dir, &res.new_cinfo); nfs_post_op_update_inode(new_dir, res.new_fattr); } return status;}static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, struct inode *new_dir, struct qstr *new_name){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(old_dir), _nfs4_proc_rename(old_dir, old_name, new_dir, new_name), &exception); } while (exception.retry); return err;}static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name){ struct nfs_server *server = NFS_SERVER(inode); struct nfs4_link_arg arg = { .fh = NFS_FH(inode), .dir_fh = NFS_FH(dir), .name = name, .bitmask = server->attr_bitmask, }; struct nfs_fattr fattr, dir_attr; struct nfs4_link_res res = { .server = server, .fattr = &fattr, .dir_attr = &dir_attr, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], .rpc_argp = &arg, .rpc_resp = &res, }; int status; nfs_fattr_init(res.fattr); nfs_fattr_init(res.dir_attr); status = rpc_call_sync(server->client, &msg, 0); if (!status) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); nfs_post_op_update_inode(inode, res.fattr); } return status;}static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(inode), _nfs4_proc_link(inode, dir, name), &exception); } while (exception.retry); return err;}static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, unsigned int len, struct iattr *sattr){ struct nfs_server *server = NFS_SERVER(dir); struct nfs_fh fhandle; struct nfs_fattr fattr, dir_fattr; struct nfs4_create_arg arg = { .dir_fh = NFS_FH(dir), .server = server, .name = &dentry->d_name, .attrs = sattr, .ftype = NF4LNK, .bitmask = server->attr_bitmask, }; struct nfs4_create_res res = { .server = server, .fh = &fhandle, .fattr = &fattr, .dir_fattr = &dir_fattr, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], .rpc_argp = &arg, .rpc_resp = &res, }; int status; if (len > NFS4_MAXPATHLEN) return -ENAMETOOLONG; arg.u.symlink.pages = &page; arg.u.symlink.len = len; nfs_fattr_init(&fattr); nfs_fattr_init(&dir_fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); if (!status) { update_changeattr(dir, &res.dir_cinfo); nfs_post_op_update_inode(dir, res.dir_fattr); status = nfs_instantiate(dentry, &fhandle, &fattr); } return status;}static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, unsigned int len, struct iattr *sattr){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_symlink(dir, dentry, page, len, sattr), &exception); } while (exception.retry); return err;}static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr){ struct nfs_server *server = NFS_SERVER(dir); struct nfs_fh fhandle; struct nfs_fattr fattr, dir_fattr; struct nfs4_create_arg arg = { .dir_fh = NFS_FH(dir), .server = server, .name = &dentry->d_name, .attrs = sattr, .ftype = NF4DIR, .bitmask = server->attr_bitmask, }; struct nfs4_create_res res = { .server = server, .fh = &fhandle, .fattr = &fattr, .dir_fattr = &dir_fattr, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], .rpc_argp = &arg, .rpc_resp = &res, }; int status; nfs_fattr_init(&fattr); nfs_fattr_init(&dir_fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); if (!status) { update_changeattr(dir, &res.dir_cinfo); nfs_post_op_update_inode(dir, res.dir_fattr); status = nfs_instantiate(dentry, &fhandle, &fattr); } return status;}static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_mkdir(dir, dentry, sattr), &exception); } while (exception.retry); return err;}static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page *page, unsigned int count, int plus){ struct inode *dir = dentry->d_inode; struct nfs4_readdir_arg args = { .fh = NFS_FH(dir), .pages = &page, .pgbase = 0, .count = count, .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask, }; struct nfs4_readdir_res res; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READDIR], .rpc_argp = &args, .rpc_resp = &res, .rpc_cred = cred, }; int status; dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __FUNCTION__, dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long long)cookie); nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); res.pgbase = args.pgbase; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); if (status == 0) memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); nfs_invalidate_atime(dir); dprintk("%s: returns %d\n", __FUNCTION__, status); return status;}static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page *page, unsigned int count, int plus){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), _nfs4_proc_readdir(dentry, cred, cookie, page, count, plus), &exception); } while (exception.retry); return err;}static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dev_t rdev){ struct nfs_server *server = NFS_SERVER(dir); struct nfs_fh fh; struct nfs_fattr fattr, dir_fattr; struct nfs4_create_arg arg = { .dir_fh = NFS_FH(dir), .server = server, .name = &dentry->d_name, .attrs = sattr, .bitmask = server->attr_bitmask, }; struct nfs4_create_res res = { .server = server, .fh = &fh, .fattr = &fattr, .dir_fattr = &dir_fattr, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], .rpc_argp = &arg, .rpc_resp = &res, }; int status; int mode = sattr->ia_mode; nfs_fattr_init(&fattr); nfs_fattr_init(&dir_fattr); BUG_ON(!(sattr->ia_valid & ATTR_MODE)); BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); if (S_ISFIFO(mode)) arg.ftype = NF4FIFO; else if (S_ISBLK(mode)) { arg.ftype = NF4BLK; arg.u.device.specdata1 = MAJOR(rdev); arg.u.device.specdata2 = MINOR(rdev); } else if (S_ISCHR(mode)) { arg.ftype = NF4CHR; arg.u.device.specdata1 = MAJOR(rdev); arg.u.device.specdata2 = MINOR(rdev); } else arg.ftype = NF4SOCK; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); if (status == 0) { update_changeattr(dir, &res.dir_cinfo); nfs_post_op_update_inode(dir, res.dir_fattr); status = nfs_instantiate(dentry, &fh, &fattr); } return status;}static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dev_t rdev){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_mknod(dir, dentry, sattr, rdev), &exception); } while (exception.retry); return err;}static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat){ struct nfs4_statfs_arg args = { .fh = fhandle, .bitmask = server->attr_bitmask, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS], .rpc_argp = &args, .rpc_resp = fsstat, }; nfs_fattr_init(fsstat->fattr); return rpc_call_sync(server->client, &msg, 0);}static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(server, _nfs4_proc_statfs(server, fhandle, fsstat), &exception); } while (exception.retry); return err;}static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo){ s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -