dir.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. /*
  2. * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  3. * All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <linux/kernel.h>
  16. #include <linux/fs.h>
  17. #include <linux/jhash.h>
  18. #include <linux/namei.h>
  19. #include <linux/slab.h>
  20. #include <linux/pagemap.h>
  21. #include "netfs.h"
  22. static int pohmelfs_cmp_hash(struct pohmelfs_name *n, u32 hash)
  23. {
  24. if (n->hash > hash)
  25. return -1;
  26. if (n->hash < hash)
  27. return 1;
  28. return 0;
  29. }
  30. static struct pohmelfs_name *pohmelfs_search_hash_unprecise(struct pohmelfs_inode *pi, u32 hash)
  31. {
  32. struct rb_node *n = pi->hash_root.rb_node;
  33. struct pohmelfs_name *tmp = NULL;
  34. int cmp;
  35. while (n) {
  36. tmp = rb_entry(n, struct pohmelfs_name, hash_node);
  37. cmp = pohmelfs_cmp_hash(tmp, hash);
  38. if (cmp < 0)
  39. n = n->rb_left;
  40. else if (cmp > 0)
  41. n = n->rb_right;
  42. else
  43. break;
  44. }
  45. return tmp;
  46. }
  47. struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash)
  48. {
  49. struct pohmelfs_name *tmp;
  50. tmp = pohmelfs_search_hash_unprecise(pi, hash);
  51. if (tmp && (tmp->hash == hash))
  52. return tmp;
  53. return NULL;
  54. }
  55. static void __pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
  56. {
  57. rb_erase(&node->hash_node, &parent->hash_root);
  58. }
  59. /*
  60. * Remove name cache entry from its caches and free it.
  61. */
  62. static void pohmelfs_name_free(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
  63. {
  64. __pohmelfs_name_del(parent, node);
  65. list_del(&node->sync_create_entry);
  66. kfree(node);
  67. }
  68. static struct pohmelfs_name *pohmelfs_insert_hash(struct pohmelfs_inode *pi,
  69. struct pohmelfs_name *new)
  70. {
  71. struct rb_node **n = &pi->hash_root.rb_node, *parent = NULL;
  72. struct pohmelfs_name *ret = NULL, *tmp;
  73. int cmp;
  74. while (*n) {
  75. parent = *n;
  76. tmp = rb_entry(parent, struct pohmelfs_name, hash_node);
  77. cmp = pohmelfs_cmp_hash(tmp, new->hash);
  78. if (cmp < 0)
  79. n = &parent->rb_left;
  80. else if (cmp > 0)
  81. n = &parent->rb_right;
  82. else {
  83. ret = tmp;
  84. break;
  85. }
  86. }
  87. if (ret) {
  88. printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', "
  89. "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n",
  90. __func__, pi->ino,
  91. ret->ino, ret->hash, ret->len, ret->data,
  92. new->ino, new->hash, new->len, new->data);
  93. ret->ino = new->ino;
  94. return ret;
  95. }
  96. rb_link_node(&new->hash_node, parent, n);
  97. rb_insert_color(&new->hash_node, &pi->hash_root);
  98. return NULL;
  99. }
  100. /*
  101. * Free name cache for given inode.
  102. */
  103. void pohmelfs_free_names(struct pohmelfs_inode *parent)
  104. {
  105. struct rb_node *rb_node;
  106. struct pohmelfs_name *n;
  107. for (rb_node = rb_first(&parent->hash_root); rb_node;) {
  108. n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
  109. rb_node = rb_next(rb_node);
  110. pohmelfs_name_free(parent, n);
  111. }
  112. }
  113. static void pohmelfs_fix_offset(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
  114. {
  115. parent->total_len -= node->len;
  116. }
  117. /*
  118. * Free name cache entry helper.
  119. */
  120. void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
  121. {
  122. pohmelfs_fix_offset(parent, node);
  123. pohmelfs_name_free(parent, node);
  124. }
  125. /*
  126. * Insert new name cache entry into all hash cache.
  127. */
  128. static int pohmelfs_insert_name(struct pohmelfs_inode *parent, struct pohmelfs_name *n)
  129. {
  130. struct pohmelfs_name *name;
  131. name = pohmelfs_insert_hash(parent, n);
  132. if (name)
  133. return -EEXIST;
  134. parent->total_len += n->len;
  135. list_add_tail(&n->sync_create_entry, &parent->sync_create_list);
  136. return 0;
  137. }
  138. /*
  139. * Allocate new name cache entry.
  140. */
  141. static struct pohmelfs_name *pohmelfs_name_alloc(unsigned int len)
  142. {
  143. struct pohmelfs_name *n;
  144. n = kzalloc(sizeof(struct pohmelfs_name) + len, GFP_KERNEL);
  145. if (!n)
  146. return NULL;
  147. INIT_LIST_HEAD(&n->sync_create_entry);
  148. n->data = (char *)(n+1);
  149. return n;
  150. }
  151. /*
  152. * Add new name entry into directory's cache.
  153. */
  154. static int pohmelfs_add_dir(struct pohmelfs_sb *psb, struct pohmelfs_inode *parent,
  155. struct pohmelfs_inode *npi, struct qstr *str, unsigned int mode, int link)
  156. {
  157. int err = -ENOMEM;
  158. struct pohmelfs_name *n;
  159. n = pohmelfs_name_alloc(str->len + 1);
  160. if (!n)
  161. goto err_out_exit;
  162. n->ino = npi->ino;
  163. n->mode = mode;
  164. n->len = str->len;
  165. n->hash = str->hash;
  166. sprintf(n->data, "%s", str->name);
  167. mutex_lock(&parent->offset_lock);
  168. err = pohmelfs_insert_name(parent, n);
  169. mutex_unlock(&parent->offset_lock);
  170. if (err) {
  171. if (err != -EEXIST)
  172. goto err_out_free;
  173. kfree(n);
  174. }
  175. return 0;
  176. err_out_free:
  177. kfree(n);
  178. err_out_exit:
  179. return err;
  180. }
  181. /*
  182. * Create new inode for given parameters (name, inode info, parent).
  183. * This does not create object on the server, it will be synced there during writeback.
  184. */
  185. struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
  186. struct pohmelfs_inode *parent, struct qstr *str,
  187. struct netfs_inode_info *info, int link)
  188. {
  189. struct inode *new = NULL;
  190. struct pohmelfs_inode *npi;
  191. int err = -EEXIST;
  192. dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n",
  193. __func__, (parent) ? parent->ino : 0, info->ino, str);
  194. err = -ENOMEM;
  195. new = iget_locked(psb->sb, info->ino);
  196. if (!new)
  197. goto err_out_exit;
  198. npi = POHMELFS_I(new);
  199. npi->ino = info->ino;
  200. err = 0;
  201. if (new->i_state & I_NEW) {
  202. dprintk("%s: filling VFS inode: %lu/%llu.\n",
  203. __func__, new->i_ino, info->ino);
  204. pohmelfs_fill_inode(new, info);
  205. if (S_ISDIR(info->mode)) {
  206. struct qstr s;
  207. s.name = ".";
  208. s.len = 1;
  209. s.hash = jhash(s.name, s.len, 0);
  210. err = pohmelfs_add_dir(psb, npi, npi, &s, info->mode, 0);
  211. if (err)
  212. goto err_out_put;
  213. s.name = "..";
  214. s.len = 2;
  215. s.hash = jhash(s.name, s.len, 0);
  216. err = pohmelfs_add_dir(psb, npi, (parent) ? parent : npi, &s,
  217. (parent) ? parent->vfs_inode.i_mode : npi->vfs_inode.i_mode, 0);
  218. if (err)
  219. goto err_out_put;
  220. }
  221. }
  222. if (str) {
  223. if (parent) {
  224. err = pohmelfs_add_dir(psb, parent, npi, str, info->mode, link);
  225. dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n",
  226. __func__, (err) ? "unsuccessfully" : "successfully",
  227. str->name, parent->total_len, info->ino, parent->ino);
  228. if (err && err != -EEXIST)
  229. goto err_out_put;
  230. }
  231. }
  232. if (new->i_state & I_NEW) {
  233. if (parent)
  234. mark_inode_dirty(&parent->vfs_inode);
  235. mark_inode_dirty(new);
  236. }
  237. set_bit(NETFS_INODE_OWNED, &npi->state);
  238. npi->lock_type = POHMELFS_WRITE_LOCK;
  239. unlock_new_inode(new);
  240. return npi;
  241. err_out_put:
  242. printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__, new, npi, err);
  243. iput(new);
  244. err_out_exit:
  245. return ERR_PTR(err);
  246. }
  247. static int pohmelfs_remote_sync_complete(struct page **pages, unsigned int page_num,
  248. void *private, int err)
  249. {
  250. struct pohmelfs_inode *pi = private;
  251. struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
  252. dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
  253. if (err)
  254. pi->error = err;
  255. wake_up(&psb->wait);
  256. pohmelfs_put_inode(pi);
  257. return err;
  258. }
  259. /*
  260. * Receive directory content from the server.
  261. * This should be only done for objects, which were not created locally,
  262. * and which were not synced previously.
  263. */
  264. static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi)
  265. {
  266. struct inode *inode = &pi->vfs_inode;
  267. struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
  268. long ret = psb->wait_on_page_timeout;
  269. int err;
  270. dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
  271. __func__, pi->ino, pi->state, test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state));
  272. if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state))
  273. return 0;
  274. if (!igrab(inode)) {
  275. err = -ENOENT;
  276. goto err_out_exit;
  277. }
  278. err = pohmelfs_meta_command(pi, NETFS_READDIR, NETFS_TRANS_SINGLE_DST,
  279. pohmelfs_remote_sync_complete, pi, 0);
  280. if (err)
  281. goto err_out_exit;
  282. pi->error = 0;
  283. ret = wait_event_interruptible_timeout(psb->wait,
  284. test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state) || pi->error, ret);
  285. dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__, pi->ino, ret, pi->error);
  286. if (ret <= 0) {
  287. err = ret;
  288. if (!err)
  289. err = -ETIMEDOUT;
  290. goto err_out_exit;
  291. }
  292. if (pi->error)
  293. return pi->error;
  294. return 0;
  295. err_out_exit:
  296. clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
  297. return err;
  298. }
  299. static int pohmelfs_dir_open(struct inode *inode, struct file *file)
  300. {
  301. file->private_data = NULL;
  302. return 0;
  303. }
  304. /*
  305. * VFS readdir callback. Syncs directory content from server if needed,
  306. * and provides direntry info to the userspace.
  307. */
  308. static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir)
  309. {
  310. struct inode *inode = file->f_path.dentry->d_inode;
  311. struct pohmelfs_inode *pi = POHMELFS_I(inode);
  312. struct pohmelfs_name *n;
  313. struct rb_node *rb_node;
  314. int err = 0, mode;
  315. u64 len;
  316. dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
  317. __func__, pi->ino, (u64)file->f_pos,
  318. (unsigned long)file->private_data);
  319. #if 0
  320. err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
  321. if (err)
  322. return err;
  323. #endif
  324. err = pohmelfs_sync_remote_dir(pi);
  325. if (err)
  326. return err;
  327. if (file->private_data && (file->private_data == (void *)(unsigned long)file->f_pos))
  328. return 0;
  329. mutex_lock(&pi->offset_lock);
  330. n = pohmelfs_search_hash_unprecise(pi, (unsigned long)file->private_data);
  331. while (n) {
  332. mode = (n->mode >> 12) & 15;
  333. dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
  334. "mode: %o/%o, fpos: %llu, hash: %08x.\n",
  335. __func__, file->f_pos, pi->ino, n->data, n->len,
  336. n->ino, n->mode, mode, file->f_pos, n->hash);
  337. file->private_data = (void *)(unsigned long)n->hash;
  338. len = n->len;
  339. err = filldir(dirent, n->data, n->len, file->f_pos, n->ino, mode);
  340. if (err < 0) {
  341. dprintk("%s: err: %d.\n", __func__, err);
  342. err = 0;
  343. break;
  344. }
  345. file->f_pos += len;
  346. rb_node = rb_next(&n->hash_node);
  347. if (!rb_node || (rb_node == &n->hash_node)) {
  348. file->private_data = (void *)(unsigned long)file->f_pos;
  349. break;
  350. }
  351. n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
  352. }
  353. mutex_unlock(&pi->offset_lock);
  354. return err;
  355. }
  356. static loff_t pohmelfs_dir_lseek(struct file *file, loff_t offset, int origin)
  357. {
  358. file->f_pos = offset;
  359. file->private_data = NULL;
  360. return offset;
  361. }
  362. const struct file_operations pohmelfs_dir_fops = {
  363. .open = pohmelfs_dir_open,
  364. .read = generic_read_dir,
  365. .llseek = pohmelfs_dir_lseek,
  366. .readdir = pohmelfs_readdir,
  367. };
  368. /*
  369. * Lookup single object on server.
  370. */
  371. static int pohmelfs_lookup_single(struct pohmelfs_inode *parent,
  372. struct qstr *str, u64 ino)
  373. {
  374. struct pohmelfs_sb *psb = POHMELFS_SB(parent->vfs_inode.i_sb);
  375. long ret = msecs_to_jiffies(5000);
  376. int err;
  377. set_bit(NETFS_COMMAND_PENDING, &parent->state);
  378. err = pohmelfs_meta_command_data(parent, parent->ino, NETFS_LOOKUP,
  379. (char *)str->name, NETFS_TRANS_SINGLE_DST, NULL, NULL, ino);
  380. if (err)
  381. goto err_out_exit;
  382. err = 0;
  383. ret = wait_event_interruptible_timeout(psb->wait,
  384. !test_bit(NETFS_COMMAND_PENDING, &parent->state), ret);
  385. if (ret <= 0) {
  386. err = ret;
  387. if (!err)
  388. err = -ETIMEDOUT;
  389. }
  390. if (err)
  391. goto err_out_exit;
  392. return 0;
  393. err_out_exit:
  394. clear_bit(NETFS_COMMAND_PENDING, &parent->state);
  395. printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
  396. __func__, parent->ino, ino, str->name, err);
  397. return err;
  398. }
  399. /*
  400. * VFS lookup callback.
  401. * We first try to get inode number from local name cache, if we have one,
  402. * then inode can be found in inode cache. If there is no inode or no object in
  403. * local cache, try to lookup it on server. This only should be done for directories,
  404. * which were not created locally, otherwise remote server does not know about dir at all,
  405. * so no need to try to know that.
  406. */
  407. struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
  408. {
  409. struct pohmelfs_inode *parent = POHMELFS_I(dir);
  410. struct pohmelfs_name *n;
  411. struct inode *inode = NULL;
  412. unsigned long ino = 0;
  413. int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1;
  414. struct qstr str = dentry->d_name;
  415. if ((nd->intent.open.flags & O_ACCMODE) > 1)
  416. lock_type = POHMELFS_WRITE_LOCK;
  417. if (test_bit(NETFS_INODE_OWNED, &parent->state)) {
  418. if (lock_type == parent->lock_type)
  419. need_lock = 0;
  420. if ((lock_type == POHMELFS_READ_LOCK) && (parent->lock_type == POHMELFS_WRITE_LOCK))
  421. need_lock = 0;
  422. }
  423. if ((lock_type == POHMELFS_READ_LOCK) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state))
  424. need_lock = 1;
  425. str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
  426. mutex_lock(&parent->offset_lock);
  427. n = pohmelfs_search_hash(parent, str.hash);
  428. if (n)
  429. ino = n->ino;
  430. mutex_unlock(&parent->offset_lock);
  431. dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
  432. __func__, ino, inode, str.name, str.hash, parent->state, need_lock);
  433. if (ino) {
  434. inode = ilookup(dir->i_sb, ino);
  435. if (inode)
  436. goto out;
  437. }
  438. dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
  439. __func__, dir, parent->ino,
  440. str.name, str.len, parent->state, ino);
  441. if (!ino) {
  442. if (!need_lock)
  443. goto out;
  444. }
  445. err = pohmelfs_data_lock(parent, 0, ~0, lock_type);
  446. if (err)
  447. goto out;
  448. err = pohmelfs_lookup_single(parent, &str, ino);
  449. if (err)
  450. goto out;
  451. if (!ino) {
  452. mutex_lock(&parent->offset_lock);
  453. n = pohmelfs_search_hash(parent, str.hash);
  454. if (n)
  455. ino = n->ino;
  456. mutex_unlock(&parent->offset_lock);
  457. }
  458. if (ino) {
  459. inode = ilookup(dir->i_sb, ino);
  460. dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
  461. __func__, ino, inode, str.name, str.hash);
  462. if (!inode) {
  463. dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
  464. __func__, ino, str.name, str.hash);
  465. /* return NULL; */
  466. return ERR_PTR(-EACCES);
  467. }
  468. } else {
  469. printk("%s: No inode number : name: '%s', hash: %x.\n",
  470. __func__, str.name, str.hash);
  471. }
  472. out:
  473. return d_splice_alias(inode, dentry);
  474. }
  475. /*
  476. * Create new object in local cache. Object will be synced to server
  477. * during writeback for given inode.
  478. */
  479. struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
  480. struct pohmelfs_inode *parent, struct qstr *str, u64 start, int mode)
  481. {
  482. struct pohmelfs_inode *npi;
  483. int err = -ENOMEM;
  484. struct netfs_inode_info info;
  485. dprintk("%s: name: '%s', mode: %o, start: %llu.\n",
  486. __func__, str->name, mode, start);
  487. info.mode = mode;
  488. info.ino = start;
  489. if (!start)
  490. info.ino = pohmelfs_new_ino(psb);
  491. info.nlink = S_ISDIR(mode) ? 2 : 1;
  492. info.uid = current_fsuid();
  493. info.gid = current_fsgid();
  494. info.size = 0;
  495. info.blocksize = 512;
  496. info.blocks = 0;
  497. info.rdev = 0;
  498. info.version = 0;
  499. npi = pohmelfs_new_inode(psb, parent, str, &info, !!start);
  500. if (IS_ERR(npi)) {
  501. err = PTR_ERR(npi);
  502. goto err_out_unlock;
  503. }
  504. return npi;
  505. err_out_unlock:
  506. dprintk("%s: err: %d.\n", __func__, err);
  507. return ERR_PTR(err);
  508. }
  509. /*
  510. * Create local object and bind it to dentry.
  511. */
  512. static int pohmelfs_create_entry(struct inode *dir, struct dentry *dentry, u64 start, int mode)
  513. {
  514. struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
  515. struct pohmelfs_inode *npi, *parent;
  516. struct qstr str = dentry->d_name;
  517. int err;
  518. parent = POHMELFS_I(dir);
  519. err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
  520. if (err)
  521. return err;
  522. str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
  523. npi = pohmelfs_create_entry_local(psb, parent, &str, start, mode);
  524. if (IS_ERR(npi))
  525. return PTR_ERR(npi);
  526. d_instantiate(dentry, &npi->vfs_inode);
  527. dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
  528. __func__, parent->ino, npi->ino, dentry->d_name.name,
  529. (signed)dir->i_nlink, (signed)npi->vfs_inode.i_nlink);
  530. return 0;
  531. }
  532. /*
  533. * VFS create and mkdir callbacks.
  534. */
  535. static int pohmelfs_create(struct inode *dir, struct dentry *dentry, int mode,
  536. struct nameidata *nd)
  537. {
  538. return pohmelfs_create_entry(dir, dentry, 0, mode);
  539. }
  540. static int pohmelfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  541. {
  542. int err;
  543. inode_inc_link_count(dir);
  544. err = pohmelfs_create_entry(dir, dentry, 0, mode | S_IFDIR);
  545. if (err)
  546. inode_dec_link_count(dir);
  547. return err;
  548. }
  549. static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry)
  550. {
  551. struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
  552. struct inode *inode = dentry->d_inode;
  553. struct pohmelfs_inode *parent = POHMELFS_I(dir), *pi = POHMELFS_I(inode);
  554. struct pohmelfs_name *n;
  555. int err = -ENOENT;
  556. struct qstr str = dentry->d_name;
  557. err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
  558. if (err)
  559. return err;
  560. str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
  561. dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
  562. __func__, parent->ino, pi->ino,
  563. str.name, (signed)inode->i_nlink);
  564. BUG_ON(!inode);
  565. mutex_lock(&parent->offset_lock);
  566. n = pohmelfs_search_hash(parent, str.hash);
  567. if (n) {
  568. pohmelfs_fix_offset(parent, n);
  569. if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
  570. pohmelfs_remove_child(pi, n);
  571. pohmelfs_name_free(parent, n);
  572. err = 0;
  573. }
  574. mutex_unlock(&parent->offset_lock);
  575. if (!err) {
  576. psb->avail_size += inode->i_size;
  577. pohmelfs_inode_del_inode(psb, pi);
  578. mark_inode_dirty(dir);
  579. inode->i_ctime = dir->i_ctime;
  580. if (inode->i_nlink)
  581. inode_dec_link_count(inode);
  582. }
  583. return err;
  584. }
  585. /*
  586. * Unlink and rmdir VFS callbacks.
  587. */
  588. static int pohmelfs_unlink(struct inode *dir, struct dentry *dentry)
  589. {
  590. return pohmelfs_remove_entry(dir, dentry);
  591. }
  592. static int pohmelfs_rmdir(struct inode *dir, struct dentry *dentry)
  593. {
  594. int err;
  595. struct inode *inode = dentry->d_inode;
  596. dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
  597. __func__, POHMELFS_I(dir)->ino, POHMELFS_I(inode)->ino,
  598. dentry->d_name.name, (signed)dir->i_nlink, (signed)inode->i_nlink);
  599. err = pohmelfs_remove_entry(dir, dentry);
  600. if (!err) {
  601. inode_dec_link_count(dir);
  602. inode_dec_link_count(inode);
  603. }
  604. return err;
  605. }
  606. /*
  607. * Link creation is synchronous.
  608. * I'm lazy.
  609. * Earth is somewhat round.
  610. */
  611. static int pohmelfs_create_link(struct pohmelfs_inode *parent, struct qstr *obj,
  612. struct pohmelfs_inode *target, struct qstr *tstr)
  613. {
  614. struct super_block *sb = parent->vfs_inode.i_sb;
  615. struct pohmelfs_sb *psb = POHMELFS_SB(sb);
  616. struct netfs_cmd *cmd;
  617. struct netfs_trans *t;
  618. void *data;
  619. int err, parent_len, target_len = 0, cur_len, path_size = 0;
  620. err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
  621. if (err)
  622. return err;
  623. err = sb->s_op->write_inode(&parent->vfs_inode, 0);
  624. if (err)
  625. goto err_out_exit;
  626. if (tstr)
  627. target_len = tstr->len;
  628. parent_len = pohmelfs_path_length(parent);
  629. if (target)
  630. target_len += pohmelfs_path_length(target);
  631. if (parent_len < 0) {
  632. err = parent_len;
  633. goto err_out_exit;
  634. }
  635. if (target_len < 0) {
  636. err = target_len;
  637. goto err_out_exit;
  638. }
  639. t = netfs_trans_alloc(psb, parent_len + target_len + obj->len + 2, 0, 0);
  640. if (!t) {
  641. err = -ENOMEM;
  642. goto err_out_exit;
  643. }
  644. cur_len = netfs_trans_cur_len(t);
  645. cmd = netfs_trans_current(t);
  646. if (IS_ERR(cmd)) {
  647. err = PTR_ERR(cmd);
  648. goto err_out_free;
  649. }
  650. data = (void *)(cmd + 1);
  651. cur_len -= sizeof(struct netfs_cmd);
  652. err = pohmelfs_construct_path_string(parent, data, parent_len);
  653. if (err > 0) {
  654. /* Do not place null-byte before the slash */
  655. path_size = err - 1;
  656. cur_len -= path_size;
  657. err = snprintf(data + path_size, cur_len, "/%s|", obj->name);
  658. path_size += err;
  659. cur_len -= err;
  660. cmd->ext = path_size - 1; /* No | symbol */
  661. if (target) {
  662. err = pohmelfs_construct_path_string(target, data + path_size, target_len);
  663. if (err > 0) {
  664. path_size += err;
  665. cur_len -= err;
  666. }
  667. }
  668. }
  669. if (err < 0)
  670. goto err_out_free;
  671. cmd->start = 0;
  672. if (!target && tstr) {
  673. if (tstr->len > cur_len - 1) {
  674. err = -ENAMETOOLONG;
  675. goto err_out_free;
  676. }
  677. err = snprintf(data + path_size, cur_len, "%s", tstr->name) + 1; /* 0-byte */
  678. path_size += err;
  679. cur_len -= err;
  680. cmd->start = 1;
  681. }
  682. dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
  683. __func__, parent->ino, obj->name, (target) ? target->ino : 0, (tstr) ? tstr->name : NULL,
  684. (char *)data);
  685. cmd->cmd = NETFS_LINK;
  686. cmd->size = path_size;
  687. cmd->id = parent->ino;
  688. netfs_convert_cmd(cmd);
  689. netfs_trans_update(cmd, t, path_size);
  690. err = netfs_trans_finish(t, psb);
  691. if (err)
  692. goto err_out_exit;
  693. return 0;
  694. err_out_free:
  695. t->result = err;
  696. netfs_trans_put(t);
  697. err_out_exit:
  698. return err;
  699. }
  700. /*
  701. * VFS hard and soft link callbacks.
  702. */
  703. static int pohmelfs_link(struct dentry *old_dentry, struct inode *dir,
  704. struct dentry *dentry)
  705. {
  706. struct inode *inode = old_dentry->d_inode;
  707. struct pohmelfs_inode *pi = POHMELFS_I(inode);
  708. int err;
  709. struct qstr str = dentry->d_name;
  710. str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
  711. err = inode->i_sb->s_op->write_inode(inode, 0);
  712. if (err)
  713. return err;
  714. err = pohmelfs_create_link(POHMELFS_I(dir), &str, pi, NULL);
  715. if (err)
  716. return err;
  717. return pohmelfs_create_entry(dir, dentry, pi->ino, inode->i_mode);
  718. }
  719. static int pohmelfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
  720. {
  721. struct qstr sym_str;
  722. struct qstr str = dentry->d_name;
  723. struct inode *inode;
  724. int err;
  725. str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
  726. sym_str.name = symname;
  727. sym_str.len = strlen(symname);
  728. err = pohmelfs_create_link(POHMELFS_I(dir), &str, NULL, &sym_str);
  729. if (err)
  730. goto err_out_exit;
  731. err = pohmelfs_create_entry(dir, dentry, 0, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
  732. if (err)
  733. goto err_out_exit;
  734. inode = dentry->d_inode;
  735. err = page_symlink(inode, symname, sym_str.len + 1);
  736. if (err)
  737. goto err_out_put;
  738. return 0;
  739. err_out_put:
  740. iput(inode);
  741. err_out_exit:
  742. return err;
  743. }
  744. static int pohmelfs_send_rename(struct pohmelfs_inode *pi, struct pohmelfs_inode *parent,
  745. struct qstr *str)
  746. {
  747. int path_len, err, total_len = 0, inode_len, parent_len;
  748. char *path;
  749. struct netfs_trans *t;
  750. struct netfs_cmd *cmd;
  751. struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
  752. parent_len = pohmelfs_path_length(parent);
  753. inode_len = pohmelfs_path_length(pi);
  754. if (parent_len < 0 || inode_len < 0)
  755. return -EINVAL;
  756. path_len = parent_len + inode_len + str->len + 3;
  757. t = netfs_trans_alloc(psb, path_len, 0, 0);
  758. if (!t)
  759. return -ENOMEM;
  760. cmd = netfs_trans_current(t);
  761. path = (char *)(cmd + 1);
  762. err = pohmelfs_construct_path_string(pi, path, inode_len);
  763. if (err < 0)
  764. goto err_out_unlock;
  765. cmd->ext = err;
  766. path += err;
  767. total_len += err;
  768. path_len -= err;
  769. *path = '|';
  770. path++;
  771. total_len++;
  772. path_len--;
  773. err = pohmelfs_construct_path_string(parent, path, parent_len);
  774. if (err < 0)
  775. goto err_out_unlock;
  776. /*
  777. * Do not place a null-byte before the final slash and the name.
  778. */
  779. err--;
  780. path += err;
  781. total_len += err;
  782. path_len -= err;
  783. err = snprintf(path, path_len - 1, "/%s", str->name);
  784. total_len += err + 1; /* 0 symbol */
  785. path_len -= err + 1;
  786. cmd->cmd = NETFS_RENAME;
  787. cmd->id = pi->ino;
  788. cmd->start = parent->ino;
  789. cmd->size = total_len;
  790. netfs_convert_cmd(cmd);
  791. netfs_trans_update(cmd, t, total_len);
  792. return netfs_trans_finish(t, psb);
  793. err_out_unlock:
  794. netfs_trans_free(t);
  795. return err;
  796. }
  797. static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry,
  798. struct inode *new_dir, struct dentry *new_dentry)
  799. {
  800. struct inode *inode = old_dentry->d_inode;
  801. struct pohmelfs_inode *old_parent, *pi, *new_parent;
  802. struct qstr str = new_dentry->d_name;
  803. struct pohmelfs_name *n;
  804. unsigned int old_hash;
  805. int err = -ENOENT;
  806. pi = POHMELFS_I(inode);
  807. old_parent = POHMELFS_I(old_dir);
  808. if (new_dir)
  809. new_dir->i_sb->s_op->write_inode(new_dir, 0);
  810. old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0);
  811. str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
  812. str.len = new_dentry->d_name.len;
  813. str.name = new_dentry->d_name.name;
  814. str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
  815. if (new_dir) {
  816. new_parent = POHMELFS_I(new_dir);
  817. err = -ENOTEMPTY;
  818. if (S_ISDIR(inode->i_mode) &&
  819. new_parent->total_len <= 3)
  820. goto err_out_exit;
  821. } else {
  822. new_parent = old_parent;
  823. }
  824. dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
  825. __func__, pi->ino, old_parent->ino, old_dentry->d_name.name,
  826. new_parent->ino, new_dentry->d_name.name, inode->i_size);
  827. if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state) &&
  828. test_bit(NETFS_INODE_OWNED, &pi->state)) {
  829. err = pohmelfs_send_rename(pi, new_parent, &str);
  830. if (err)
  831. goto err_out_exit;
  832. }
  833. n = pohmelfs_name_alloc(str.len + 1);
  834. if (!n)
  835. goto err_out_exit;
  836. mutex_lock(&new_parent->offset_lock);
  837. n->ino = pi->ino;
  838. n->mode = inode->i_mode;
  839. n->len = str.len;
  840. n->hash = str.hash;
  841. sprintf(n->data, "%s", str.name);
  842. err = pohmelfs_insert_name(new_parent, n);
  843. mutex_unlock(&new_parent->offset_lock);
  844. if (err)
  845. goto err_out_exit;
  846. mutex_lock(&old_parent->offset_lock);
  847. n = pohmelfs_search_hash(old_parent, old_hash);
  848. if (n)
  849. pohmelfs_name_del(old_parent, n);
  850. mutex_unlock(&old_parent->offset_lock);
  851. mark_inode_dirty(inode);
  852. mark_inode_dirty(&new_parent->vfs_inode);
  853. WARN_ON_ONCE(list_empty(&inode->i_dentry));
  854. return 0;
  855. err_out_exit:
  856. clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
  857. return err;
  858. }
  859. /*
  860. * POHMELFS directory inode operations.
  861. */
  862. const struct inode_operations pohmelfs_dir_inode_ops = {
  863. .link = pohmelfs_link,
  864. .symlink = pohmelfs_symlink,
  865. .unlink = pohmelfs_unlink,
  866. .mkdir = pohmelfs_mkdir,
  867. .rmdir = pohmelfs_rmdir,
  868. .create = pohmelfs_create,
  869. .lookup = pohmelfs_lookup,
  870. .setattr = pohmelfs_setattr,
  871. .rename = pohmelfs_rename,
  872. };