📄 nfs4proc.c
字号:
static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name){ struct nfs4_link_arg arg = { .fh = NFS_FH(inode), .dir_fh = NFS_FH(dir), .name = name, }; struct nfs4_change_info cinfo = { }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], .rpc_argp = &arg, .rpc_resp = &cinfo, }; int status; status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); if (!status) update_changeattr(dir, &cinfo); 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 qstr *name, struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, struct nfs_fattr *fattr){ struct nfs_server *server = NFS_SERVER(dir); struct nfs4_create_arg arg = { .dir_fh = NFS_FH(dir), .server = server, .name = name, .attrs = sattr, .ftype = NF4LNK, .bitmask = server->attr_bitmask, }; struct nfs4_create_res res = { .server = server, .fh = fhandle, .fattr = fattr, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], .rpc_argp = &arg, .rpc_resp = &res, }; int status; if (path->len > NFS4_MAXPATHLEN) return -ENAMETOOLONG; arg.u.symlink = path; fattr->valid = 0; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); if (!status) update_changeattr(dir, &res.dir_cinfo); return status;}static int nfs4_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, struct nfs_fattr *fattr){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_symlink(dir, name, path, sattr, fhandle, fattr), &exception); } while (exception.retry); return err;}static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr, struct nfs_fh *fhandle, struct nfs_fattr *fattr){ struct nfs_server *server = NFS_SERVER(dir); struct nfs4_create_arg arg = { .dir_fh = NFS_FH(dir), .server = server, .name = name, .attrs = sattr, .ftype = NF4DIR, .bitmask = server->attr_bitmask, }; struct nfs4_create_res res = { .server = server, .fh = fhandle, .fattr = fattr, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], .rpc_argp = &arg, .rpc_resp = &res, }; int status; fattr->valid = 0; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); if (!status) update_changeattr(dir, &res.dir_cinfo); return status;}static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr, struct nfs_fh *fhandle, struct nfs_fattr *fattr){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_mkdir(dir, name, sattr, fhandle, fattr), &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, }; 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; lock_kernel(); 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); unlock_kernel(); 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 qstr *name, struct iattr *sattr, dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr){ struct nfs_server *server = NFS_SERVER(dir); struct nfs4_create_arg arg = { .dir_fh = NFS_FH(dir), .server = server, .name = name, .attrs = sattr, .bitmask = server->attr_bitmask, }; struct nfs4_create_res res = { .server = server, .fh = fh, .fattr = 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; fattr->valid = 0; 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) update_changeattr(dir, &res.dir_cinfo); return status;}static int nfs4_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr, dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_mknod(dir, name, sattr, rdev, fh, fattr), &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, }; fsstat->fattr->valid = 0; 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){ struct nfs4_fsinfo_arg args = { .fh = fhandle, .bitmask = server->attr_bitmask, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO], .rpc_argp = &args, .rpc_resp = fsinfo, }; return rpc_call_sync(server->client, &msg, 0);}static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(server, _nfs4_do_fsinfo(server, fhandle, fsinfo), &exception); } while (exception.retry); return err;}static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo){ fsinfo->fattr->valid = 0; return nfs4_do_fsinfo(server, fhandle, fsinfo);}static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_pathconf *pathconf){ struct nfs4_pathconf_arg args = { .fh = fhandle, .bitmask = server->attr_bitmask, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF], .rpc_argp = &args, .rpc_resp = pathconf, }; /* None of the pathconf attributes are mandatory to implement */ if ((args.bitmask[0] & nfs4_pathconf_bitmap[0]) == 0) { memset(pathconf, 0, sizeof(*pathconf)); return 0; } pathconf->fattr->valid = 0; return rpc_call_sync(server->client, &msg, 0);}static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_pathconf *pathconf){ struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(server, _nfs4_proc_pathconf(server, fhandle, pathconf), &exception); } while (exception.retry); return err;}static voidnfs4_read_done(struct rpc_task *task){ struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct inode *inode = data->inode; if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { rpc_restart_call(task); return; } if (task->tk_status > 0) renew_lease(NFS_SERVER(inode), data->timestamp); /* Call back common NFS readpage processing */ nfs_readpage_result(task);}static voidnfs4_proc_read_setup(struct nfs_read_data *data){ struct rpc_task *task = &data->task; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], .rpc_argp = &data->args, .rpc_resp = &data->res, .rpc_cred = data->cred, }; struct inode *inode = data->inode; int flags; data->timestamp = jiffies; /* N.B. Do we need to test? Never called for swapfile inode */ flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); /* Finalize the task. */ rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags); rpc_call_setup(task, &msg, 0);}static voidnfs4_write_done(struct rpc_task *task){ struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; struct inode *inode = data->inode; if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { rpc_restart_call(task); return; } if (task->tk_status >= 0) renew_lease(NFS_SERVER(inode), data->timestamp); /* Call back common NFS writeback processing */ nfs_writeback_done(task);}static voidnfs4_proc_write_setup(struct nfs_write_data *data, int how){ struct rpc_task *task = &data->task; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], .rpc_argp = &data->args, .rpc_resp = &data->res, .rpc_cred = data->cred, }; struct inode *inode = data->inode; int stable; int flags; if (how & FLUSH_STABLE) { if (!NFS_I(inode)->ncommit) stable = NFS_FILE_SYNC; else stable = NFS_DATA_SYNC; } else stable = NFS_UNSTABLE; data->args.stable = stable; data->timestamp = jiffies; /* Set the initial flags for the task. */ flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags); rpc_call_setup(task, &msg, 0);}static voidnfs4_commit_done(struct rpc_task *task){ struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; struct inode *inode = data->inode; if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { rpc_restart_call(task); return; } /* Call back common NFS writeback processing */ nfs_commit_done(task);}static voidnfs4_proc_commit_setup(struct nfs_write_data *data, int how){ struct rpc_task *task = &data->task; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT], .rpc_argp = &data->args, .rpc_resp = &data->res, .rpc_cred = data->cred, }; struct inode *inode = data->inode; int flags; /* Set the initial flags for the task. */ flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags); rpc_call_setup(task, &msg, 0); }/* * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special * standalone procedure for queueing an asynchronous RENEW. */static voidrenew_done(struct rpc_task *task){ struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; unsigned long timestamp = (unsigned long)task->tk_calldata; if (task->tk_status < 0) { switch (task->tk_status) { case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_EXPIRED: case -NFS4ERR_CB_PATH_DOWN: nfs4_schedule_state_recovery(clp); } return; } spin_lock(&clp->cl_lock); if (time_before(clp->cl_last_renewal,timestamp)) clp->cl_last_renewal = timestamp; spin_unlock(&clp->cl_lock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -