nfs3proc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/nfs/nfs3proc.c
  3.  *
  4.  *  Client-side NFSv3 procedures stubs.
  5.  *
  6.  *  Copyright (C) 1997, Olaf Kirch
  7.  */
  8. #include <linux/mm.h>
  9. #include <linux/utsname.h>
  10. #include <linux/errno.h>
  11. #include <linux/string.h>
  12. #include <linux/sunrpc/clnt.h>
  13. #include <linux/nfs.h>
  14. #include <linux/nfs3.h>
  15. #include <linux/nfs_fs.h>
  16. #define NFSDBG_FACILITY NFSDBG_PROC
  17. /* A wrapper to handle the EJUKEBOX error message */
  18. static int
  19. nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
  20. {
  21. sigset_t oldset;
  22. int res;
  23. rpc_clnt_sigmask(clnt, &oldset);
  24. do {
  25. res = rpc_call_sync(clnt, msg, flags);
  26. if (res != -EJUKEBOX)
  27. break;
  28. set_current_state(TASK_INTERRUPTIBLE);
  29. schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
  30. res = -ERESTARTSYS;
  31. } while (!signalled());
  32. rpc_clnt_sigunmask(clnt, &oldset);
  33. return res;
  34. }
  35. static inline int
  36. nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
  37. {
  38. struct rpc_message msg = { proc, argp, resp, NULL };
  39. return nfs3_rpc_wrapper(clnt, &msg, flags);
  40. }
  41. #define rpc_call(clnt, proc, argp, resp, flags) 
  42. nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)
  43. #define rpc_call_sync(clnt, msg, flags) 
  44. nfs3_rpc_wrapper(clnt, msg, flags)
  45. /*
  46.  * Bare-bones access to getattr: this is for nfs_read_super.
  47.  */
  48. static int
  49. nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  50.    struct nfs_fattr *fattr)
  51. {
  52. int status;
  53. dprintk("NFS call  getrootn");
  54. fattr->valid = 0;
  55. status = rpc_call(server->client, NFS3PROC_GETATTR, fhandle, fattr, 0);
  56. dprintk("NFS reply getrootn");
  57. return status;
  58. }
  59. /*
  60.  * One function for each procedure in the NFS protocol.
  61.  */
  62. static int
  63. nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
  64. {
  65. int status;
  66. dprintk("NFS call  getattrn");
  67. fattr->valid = 0;
  68. status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
  69.   NFS_FH(inode), fattr, 0);
  70. dprintk("NFS reply getattrn");
  71. return status;
  72. }
  73. static int
  74. nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
  75. struct iattr *sattr)
  76. {
  77. struct nfs3_sattrargs arg = { NFS_FH(inode), sattr, 0, 0 };
  78. int status;
  79. dprintk("NFS call  setattrn");
  80. fattr->valid = 0;
  81. status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
  82. dprintk("NFS reply setattrn");
  83. return status;
  84. }
  85. static int
  86. nfs3_proc_lookup(struct inode *dir, struct qstr *name,
  87.  struct nfs_fh *fhandle, struct nfs_fattr *fattr)
  88. {
  89. struct nfs_fattr dir_attr;
  90. struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
  91. struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
  92. int status;
  93. dprintk("NFS call  lookup %sn", name->name);
  94. dir_attr.valid = 0;
  95. fattr->valid = 0;
  96. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
  97. if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
  98. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
  99.  fhandle, fattr, 0);
  100. dprintk("NFS reply lookup: %dn", status);
  101. if (status >= 0)
  102. status = nfs_refresh_inode(dir, &dir_attr);
  103. return status;
  104. }
  105. static int
  106. nfs3_proc_access(struct inode *inode, int mode, int ruid)
  107. {
  108. struct nfs_fattr fattr;
  109. struct nfs3_accessargs arg = { NFS_FH(inode), 0 };
  110. struct nfs3_accessres res = { &fattr, 0 };
  111. int status, flags;
  112. dprintk("NFS call  accessn");
  113. fattr.valid = 0;
  114. if (mode & MAY_READ)
  115. arg.access |= NFS3_ACCESS_READ;
  116. if (S_ISDIR(inode->i_mode)) {
  117. if (mode & MAY_WRITE)
  118. arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
  119. if (mode & MAY_EXEC)
  120. arg.access |= NFS3_ACCESS_LOOKUP;
  121. } else {
  122. if (mode & MAY_WRITE)
  123. arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND;
  124. if (mode & MAY_EXEC)
  125. arg.access |= NFS3_ACCESS_EXECUTE;
  126. }
  127. flags = (ruid) ? RPC_CALL_REALUID : 0;
  128. status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
  129. nfs_refresh_inode(inode, &fattr);
  130. dprintk("NFS reply accessn");
  131. if (status == 0 && (arg.access & res.access) != arg.access)
  132. status = -EACCES;
  133. return status;
  134. }
  135. static int
  136. nfs3_proc_readlink(struct inode *inode, struct page *page)
  137. {
  138. struct nfs_fattr fattr;
  139. struct nfs3_readlinkargs args = { NFS_FH(inode), PAGE_CACHE_SIZE, &page };
  140. int status;
  141. dprintk("NFS call  readlinkn");
  142. fattr.valid = 0;
  143. status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
  144. &args, &fattr, 0);
  145. nfs_refresh_inode(inode, &fattr);
  146. dprintk("NFS reply readlink: %dn", status);
  147. return status;
  148. }
  149. static int
  150. nfs3_proc_read(struct inode *inode, struct rpc_cred *cred,
  151.        struct nfs_fattr *fattr, int flags,
  152.        unsigned int base, unsigned int count, struct page *page,
  153.        int *eofp)
  154. {
  155. u64 offset = page_offset(page) + base;
  156. struct nfs_readargs arg = { NFS_FH(inode), offset, count,
  157. base, &page };
  158. struct nfs_readres res = { fattr, count, 0 };
  159. struct rpc_message msg = { NFS3PROC_READ, &arg, &res, cred };
  160. int status;
  161. dprintk("NFS call  read %d @ %Ldn", count, (long long)offset);
  162. fattr->valid = 0;
  163. status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
  164. dprintk("NFS reply read: %dn", status);
  165. *eofp = res.eof;
  166. return status;
  167. }
  168. static int
  169. nfs3_proc_write(struct inode *inode, struct rpc_cred *cred,
  170. struct nfs_fattr *fattr, int flags,
  171. unsigned int base, unsigned int count,
  172. struct page *page, struct nfs_writeverf *verf)
  173. {
  174. u64 offset = page_offset(page) + base;
  175. struct nfs_writeargs arg = { NFS_FH(inode), offset, count,
  176. NFS_FILE_SYNC, base, &page };
  177. struct nfs_writeres res = { fattr, verf, 0 };
  178. struct rpc_message msg = { NFS3PROC_WRITE, &arg, &res, cred };
  179. int status, rpcflags = 0;
  180. dprintk("NFS call  write %d @ %Ldn", count, (long long)offset);
  181. fattr->valid = 0;
  182. if (flags & NFS_RW_SWAP)
  183. rpcflags |= NFS_RPC_SWAPFLAGS;
  184. arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE;
  185. status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
  186. dprintk("NFS reply read: %dn", status);
  187. return status < 0? status : res.count;
  188. }
  189. /*
  190.  * Create a regular file.
  191.  * For now, we don't implement O_EXCL.
  192.  */
  193. static int
  194. nfs3_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
  195.  int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
  196. {
  197. struct nfs_fattr dir_attr;
  198. struct nfs3_createargs arg = { NFS_FH(dir), name->name, name->len,
  199. sattr, 0, { 0, 0 } };
  200. struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
  201. int status;
  202. dprintk("NFS call  create %sn", name->name);
  203. arg.createmode = NFS3_CREATE_UNCHECKED;
  204. if (flags & O_EXCL) {
  205. arg.createmode  = NFS3_CREATE_EXCLUSIVE;
  206. arg.verifier[0] = jiffies;
  207. arg.verifier[1] = current->pid;
  208. }
  209. again:
  210. dir_attr.valid = 0;
  211. fattr->valid = 0;
  212. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
  213. nfs_refresh_inode(dir, &dir_attr);
  214. /* If the server doesn't support the exclusive creation semantics,
  215.  * try again with simple 'guarded' mode. */
  216. if (status == NFSERR_NOTSUPP) {
  217. switch (arg.createmode) {
  218. case NFS3_CREATE_EXCLUSIVE:
  219. arg.createmode = NFS3_CREATE_GUARDED;
  220. break;
  221. case NFS3_CREATE_GUARDED:
  222. arg.createmode = NFS3_CREATE_UNCHECKED;
  223. break;
  224. case NFS3_CREATE_UNCHECKED:
  225. goto exit;
  226. }
  227. goto again;
  228. }
  229. exit:
  230. dprintk("NFS reply create: %dn", status);
  231. /* When we created the file with exclusive semantics, make
  232.  * sure we set the attributes afterwards. */
  233. if (status == 0 && arg.createmode == NFS3_CREATE_EXCLUSIVE) {
  234. struct nfs3_sattrargs arg = { fhandle, sattr, 0, 0 };
  235. dprintk("NFS call  setattr (post-create)n");
  236. /* Note: we could use a guarded setattr here, but I'm
  237.  * not sure this buys us anything (and I'd have
  238.  * to revamp the NFSv3 XDR code) */
  239. fattr->valid = 0;
  240. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
  241. &arg, fattr, 0);
  242. dprintk("NFS reply setattr (post-create): %dn", status);
  243. }
  244. return status;
  245. }
  246. static int
  247. nfs3_proc_remove(struct inode *dir, struct qstr *name)
  248. {
  249. struct nfs_fattr dir_attr;
  250. struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
  251. struct rpc_message msg = { NFS3PROC_REMOVE, &arg, &dir_attr, NULL };
  252. int status;
  253. dprintk("NFS call  remove %sn", name->name);
  254. dir_attr.valid = 0;
  255. status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
  256. nfs_refresh_inode(dir, &dir_attr);
  257. dprintk("NFS reply remove: %dn", status);
  258. return status;
  259. }
  260. static int
  261. nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
  262. {
  263. struct nfs3_diropargs *arg;
  264. struct nfs_fattr *res;
  265. arg = (struct nfs3_diropargs *)kmalloc(sizeof(*arg)+sizeof(*res), GFP_KERNEL);
  266. if (!arg)
  267. return -ENOMEM;
  268. res = (struct nfs_fattr*)(arg + 1);
  269. arg->fh = NFS_FH(dir->d_inode);
  270. arg->name = name->name;
  271. arg->len = name->len;
  272. res->valid = 0;
  273. msg->rpc_proc = NFS3PROC_REMOVE;
  274. msg->rpc_argp = arg;
  275. msg->rpc_resp = res;
  276. return 0;
  277. }
  278. static void
  279. nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
  280. {
  281. struct nfs_fattr *dir_attr;
  282. if (msg->rpc_argp) {
  283. dir_attr = (struct nfs_fattr*)msg->rpc_resp;
  284. nfs_refresh_inode(dir->d_inode, dir_attr);
  285. kfree(msg->rpc_argp);
  286. }
  287. }
  288. static int
  289. nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
  290.  struct inode *new_dir, struct qstr *new_name)
  291. {
  292. struct nfs_fattr old_dir_attr, new_dir_attr;
  293. struct nfs3_renameargs arg = { NFS_FH(old_dir),
  294. old_name->name, old_name->len,
  295. NFS_FH(new_dir),
  296. new_name->name, new_name->len };
  297. struct nfs3_renameres res = { &old_dir_attr, &new_dir_attr };
  298. int status;
  299. dprintk("NFS call  rename %s -> %sn", old_name->name, new_name->name);
  300. old_dir_attr.valid = 0;
  301. new_dir_attr.valid = 0;
  302. status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
  303. nfs_refresh_inode(old_dir, &old_dir_attr);
  304. nfs_refresh_inode(new_dir, &new_dir_attr);
  305. dprintk("NFS reply rename: %dn", status);
  306. return status;
  307. }
  308. static int
  309. nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
  310. {
  311. struct nfs_fattr dir_attr, fattr;
  312. struct nfs3_linkargs arg = { NFS_FH(inode), NFS_FH(dir),
  313. name->name, name->len };
  314. struct nfs3_linkres res = { &dir_attr, &fattr };
  315. int status;
  316. dprintk("NFS call  link %sn", name->name);
  317. dir_attr.valid = 0;
  318. fattr.valid = 0;
  319. status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
  320. nfs_refresh_inode(dir, &dir_attr);
  321. nfs_refresh_inode(inode, &fattr);
  322. dprintk("NFS reply link: %dn", status);
  323. return status;
  324. }
  325. static int
  326. nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
  327.   struct iattr *sattr, struct nfs_fh *fhandle,
  328.   struct nfs_fattr *fattr)
  329. {
  330. struct nfs_fattr dir_attr;
  331. struct nfs3_symlinkargs arg = { NFS_FH(dir), name->name, name->len,
  332. path->name, path->len, sattr };
  333. struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
  334. int status;
  335. dprintk("NFS call  symlink %s -> %sn", name->name, path->name);
  336. dir_attr.valid = 0;
  337. fattr->valid = 0;
  338. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
  339. nfs_refresh_inode(dir, &dir_attr);
  340. dprintk("NFS reply symlink: %dn", status);
  341. return status;
  342. }
  343. static int
  344. nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
  345. struct nfs_fh *fhandle, struct nfs_fattr *fattr)
  346. {
  347. struct nfs_fattr dir_attr;
  348. struct nfs3_mkdirargs arg = { NFS_FH(dir), name->name, name->len,
  349. sattr };
  350. struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
  351. int status;
  352. dprintk("NFS call  mkdir %sn", name->name);
  353. dir_attr.valid = 0;
  354. fattr->valid = 0;
  355. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
  356. nfs_refresh_inode(dir, &dir_attr);
  357. dprintk("NFS reply mkdir: %dn", status);
  358. return status;
  359. }
  360. static int
  361. nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
  362. {
  363. struct nfs_fattr dir_attr;
  364. struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
  365. int status;
  366. dprintk("NFS call  rmdir %sn", name->name);
  367. dir_attr.valid = 0;
  368. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
  369. nfs_refresh_inode(dir, &dir_attr);
  370. dprintk("NFS reply rmdir: %dn", status);
  371. return status;
  372. }
  373. /*
  374.  * The READDIR implementation is somewhat hackish - we pass the user buffer
  375.  * to the encode function, which installs it in the receive iovec.
  376.  * The decode function itself doesn't perform any decoding, it just makes
  377.  * sure the reply is syntactically correct.
  378.  *
  379.  * Also note that this implementation handles both plain readdir and
  380.  * readdirplus.
  381.  */
  382. static int
  383. nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred,
  384.   u64 cookie, struct page *page, unsigned int count, int plus)
  385. {
  386. struct nfs_fattr dir_attr;
  387. u32 *verf = NFS_COOKIEVERF(dir);
  388. struct nfs3_readdirargs arg = { NFS_FH(dir), cookie, {verf[0], verf[1]},
  389.         plus, count, &page };
  390. struct nfs3_readdirres res = { &dir_attr, verf, plus };
  391. struct rpc_message msg = { NFS3PROC_READDIR, &arg, &res, cred };
  392. int status;
  393. if (plus)
  394. msg.rpc_proc = NFS3PROC_READDIRPLUS;
  395. dprintk("NFS call  readdir%s %dn",
  396. plus? "plus" : "", (unsigned int) cookie);
  397. dir_attr.valid = 0;
  398. status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
  399. nfs_refresh_inode(dir, &dir_attr);
  400. dprintk("NFS reply readdir: %dn", status);
  401. return status;
  402. }
  403. static int
  404. nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
  405. dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
  406. {
  407. struct nfs_fattr dir_attr;
  408. struct nfs3_mknodargs arg = { NFS_FH(dir), name->name, name->len, 0,
  409. sattr, rdev };
  410. struct nfs3_diropres res = { &dir_attr, fh, fattr };
  411. int status;
  412. switch (sattr->ia_mode & S_IFMT) {
  413. case S_IFBLK: arg.type = NF3BLK;  break;
  414. case S_IFCHR: arg.type = NF3CHR;  break;
  415. case S_IFIFO: arg.type = NF3FIFO; break;
  416. case S_IFSOCK: arg.type = NF3SOCK; break;
  417. default: return -EINVAL;
  418. }
  419. dprintk("NFS call  mknod %s %xn", name->name, rdev);
  420. dir_attr.valid = 0;
  421. fattr->valid = 0;
  422. status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
  423. nfs_refresh_inode(dir, &dir_attr);
  424. dprintk("NFS reply mknod: %dn", status);
  425. return status;
  426. }
  427. /*
  428.  * This is a combo call of fsstat and fsinfo
  429.  */
  430. static int
  431. nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
  432.  struct nfs_fsinfo *info)
  433. {
  434. int status;
  435. dprintk("NFS call  fsstatn");
  436. memset((char *)info, 0, sizeof(*info));
  437. status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, info, 0);
  438. if (status < 0)
  439. goto error;
  440. status = rpc_call(server->client, NFS3PROC_FSINFO, fhandle, info, 0);
  441. error:
  442. dprintk("NFS reply statfs: %dn", status);
  443. return status;
  444. }
  445. extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
  446. struct nfs_rpc_ops nfs_v3_clientops = {
  447. 3, /* protocol version */
  448. nfs3_proc_get_root,
  449. nfs3_proc_getattr,
  450. nfs3_proc_setattr,
  451. nfs3_proc_lookup,
  452. nfs3_proc_access,
  453. nfs3_proc_readlink,
  454. nfs3_proc_read,
  455. nfs3_proc_write,
  456. NULL, /* commit */
  457. nfs3_proc_create,
  458. nfs3_proc_remove,
  459. nfs3_proc_unlink_setup,
  460. nfs3_proc_unlink_done,
  461. nfs3_proc_rename,
  462. nfs3_proc_link,
  463. nfs3_proc_symlink,
  464. nfs3_proc_mkdir,
  465. nfs3_proc_rmdir,
  466. nfs3_proc_readdir,
  467. nfs3_proc_mknod,
  468. nfs3_proc_statfs,
  469. nfs3_decode_dirent,
  470. };