rdu.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*
  2. * Copyright (C) 2009 Junjiro Okajima
  3. *
  4. * This program, aufs is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #define _ATFILE_SOURCE
  19. #define _GNU_SOURCE
  20. #define _REENTRANT
  21. #include <linux/aufs_type.h>
  22. #include <sys/ioctl.h>
  23. #include <sys/stat.h>
  24. #include <sys/types.h>
  25. #include <sys/vfs.h> /* or <sys/statfs.h> */
  26. #include <assert.h>
  27. #include <dirent.h>
  28. #include <dlfcn.h>
  29. #include <errno.h>
  30. #include <fcntl.h>
  31. #include <pthread.h>
  32. #include <search.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include "compat.h"
  38. /* ---------------------------------------------------------------------- */
  39. struct rdu {
  40. #ifdef AuRDU_REENTRANT
  41. pthread_rwlock_t lock;
  42. #else
  43. struct dirent de;
  44. #endif
  45. int fd;
  46. unsigned long npos, idx;
  47. struct au_rdu_ent **pos;
  48. unsigned long nent, sz;
  49. struct au_rdu_ent *ent;
  50. int shwh;
  51. struct au_rdu_ent *real, *wh;
  52. };
  53. static struct rdu **rdu;
  54. #define RDU_STEP 8
  55. static int rdu_cur, rdu_lim = RDU_STEP;
  56. /* ---------------------------------------------------------------------- */
  57. /* #define RduLocalTest */
  58. #ifdef RduLocalTest
  59. static int rdu_test_data(struct rdu *p, int err)
  60. {
  61. struct au_rdu_ent *e = p->ent;
  62. static int i;
  63. if (!i++) {
  64. err = 3;
  65. e->ino = e->type = e->nlen = 1;
  66. strcpy(e->name, ".");
  67. e += au_rdu_len(e->nlen);
  68. e->ino = e->type = e->nlen = 2;
  69. strcpy(e->name, "..");
  70. e += au_rdu_len(e->nlen);
  71. e->ino = e->type = e->nlen = 3;
  72. strcpy(e->name, "foo");
  73. } else
  74. err = 0;
  75. return err;
  76. }
  77. #else
  78. static int rdu_test_data(struct rdu *p, int err)
  79. {
  80. return err;
  81. }
  82. #endif
  83. /* #define RduDebug */
  84. #ifdef RduDebug
  85. #define DPri(fmt, args...) fprintf(stderr, "%s:%d: " fmt, \
  86. __func__, __LINE__, ##args)
  87. #else
  88. #define DPri(fmt, args...) do {} while (0)
  89. #endif
  90. /* ---------------------------------------------------------------------- */
  91. #ifdef AuRDU_REENTRANT
  92. static void rdu_rwlock_init(struct rdu *p)
  93. {
  94. pthread_rwlock_init(&p->lock);
  95. }
  96. static void rdu_read_lock(struct rdu *p)
  97. {
  98. pthread_rwlock_rdlock(&p->lock);
  99. }
  100. static void rdu_write_lock(struct rdu *p)
  101. {
  102. pthread_rwlock_wrlock(&p->lock);
  103. }
  104. static void rdu_unlock(struct rdu *p)
  105. {
  106. pthread_rwlock_unlock(&p->lock);
  107. }
  108. static pthread_mutex_t rdu_lib_mtx = PTHREAD_MUTEX_INITIALIZER;
  109. #define rdu_lib_lock() pthread_mutex_lock(&rdu_lib_mtx)
  110. #define rdu_lib_unlock() pthread_mutex_unlock(&rdu_lib_mtx)
  111. #define rdu_lib_must_lock() assert(pthread_mutex_trylock(&rdu_lib_mtx))
  112. #else
  113. static void rdu_rwlock_init(struct rdu *p)
  114. {
  115. /* empty */
  116. }
  117. static void rdu_read_lock(struct rdu *p)
  118. {
  119. /* empty */
  120. }
  121. static void rdu_write_lock(struct rdu *p)
  122. {
  123. /* empty */
  124. }
  125. static void rdu_unlock(struct rdu *p)
  126. {
  127. /* empty */
  128. }
  129. #define rdu_lib_lock() do {} while(0)
  130. #define rdu_lib_unlock() do {} while(0)
  131. #define rdu_lib_must_lock() do {} while(0)
  132. #endif
  133. /*
  134. * initialize this library, particularly global variables.
  135. */
  136. static int rdu_lib_init(void)
  137. {
  138. int err;
  139. err = 0;
  140. if (rdu)
  141. goto out;
  142. rdu_lib_lock();
  143. if (!rdu) {
  144. rdu = calloc(rdu_lim, sizeof(*rdu));
  145. err = !rdu;
  146. }
  147. rdu_lib_unlock();
  148. out:
  149. return err;
  150. }
  151. static int rdu_append(struct rdu *p)
  152. {
  153. int err, i;
  154. void *t;
  155. rdu_lib_must_lock();
  156. err = 0;
  157. if (rdu_cur < rdu_lim - 1)
  158. rdu[rdu_cur++] = p;
  159. else {
  160. t = realloc(rdu, rdu_lim + RDU_STEP * sizeof(*rdu));
  161. if (t) {
  162. rdu = t;
  163. rdu_lim += RDU_STEP;
  164. rdu[rdu_cur++] = p;
  165. for (i = 0; i < RDU_STEP - 1; i++)
  166. rdu[rdu_cur + i] = NULL;
  167. } else
  168. err = -1;
  169. }
  170. return err;
  171. }
  172. /* ---------------------------------------------------------------------- */
  173. static struct rdu *rdu_new(int fd)
  174. {
  175. struct rdu *p;
  176. int err;
  177. p = malloc(sizeof(*p));
  178. if (p) {
  179. rdu_rwlock_init(p);
  180. p->fd = fd;
  181. p->sz = BUFSIZ;
  182. p->ent = malloc(BUFSIZ);
  183. if (p->ent) {
  184. err = rdu_append(p);
  185. if (!err)
  186. goto out; /* success */
  187. }
  188. }
  189. free(p);
  190. p = NULL;
  191. out:
  192. return p;
  193. }
  194. static struct rdu *rdu_buf_lock(int fd)
  195. {
  196. struct rdu *p;
  197. int i;
  198. assert(rdu);
  199. assert(fd >= 0);
  200. p = NULL;
  201. rdu_lib_lock();
  202. for (i = 0; i < rdu_cur; i++)
  203. if (rdu[i] && rdu[i]->fd == fd) {
  204. p = rdu[i];
  205. goto out;
  206. }
  207. for (i = 0; i < rdu_cur; i++)
  208. if (rdu[i] && rdu[i]->fd == -1) {
  209. p = rdu[i];
  210. p->fd = fd;
  211. goto out;
  212. }
  213. if (!p)
  214. p = rdu_new(fd);
  215. out:
  216. if (p)
  217. rdu_write_lock(p);
  218. rdu_lib_unlock();
  219. return p;
  220. }
  221. static void rdu_free(int fd)
  222. {
  223. struct rdu *p;
  224. p = rdu_buf_lock(fd);
  225. if (p) {
  226. free(p->ent);
  227. free(p->pos);
  228. p->fd = -1;
  229. p->ent = NULL;
  230. p->pos = NULL;
  231. rdu_unlock(p);
  232. }
  233. }
  234. /* ---------------------------------------------------------------------- */
  235. static int rdu_do_store(int dirfd, struct au_rdu_ent *ent,
  236. struct au_rdu_ent **pos, struct rdu *p)
  237. {
  238. int err;
  239. unsigned char c;
  240. struct stat st;
  241. c = ent->name[ent->nlen];
  242. ent->name[ent->nlen] = 0;
  243. DPri("%s\n", ent->name);
  244. err = fstatat(dirfd, ent->name, &st, AT_SYMLINK_NOFOLLOW);
  245. ent->name[ent->nlen] = c;
  246. if (!err) {
  247. ent->ino = st.st_ino;
  248. pos[p->idx++] = ent;
  249. } else {
  250. DPri("err %d\n", err);
  251. if (errno == ENOENT)
  252. err = 0;
  253. }
  254. return err;
  255. }
  256. struct rdu_thread_arg {
  257. int pipefd;
  258. struct rdu *p;
  259. };
  260. static void *rdu_thread(void *_arg)
  261. {
  262. int err, pipefd, dirfd;
  263. ssize_t ssz;
  264. struct rdu_thread_arg *arg = _arg;
  265. struct au_rdu_ent *ent, **pos;
  266. struct rdu *p;
  267. pipefd = arg->pipefd;
  268. p = arg->p;
  269. dirfd = p->fd;
  270. pos = p->pos;
  271. while (1) {
  272. DPri("read\n");
  273. ssz = read(pipefd, &ent, sizeof(ent));
  274. DPri("ssz %zd\n", ssz);
  275. if (ssz != sizeof(ent) || !ent) {
  276. //perror("read");
  277. break;
  278. }
  279. //DPri("%p\n", ent);
  280. err = rdu_do_store(dirfd, ent, pos, p);
  281. }
  282. DPri("here\n");
  283. return NULL;
  284. }
  285. static int rdu_store(struct rdu *p, struct au_rdu_ent *ent, int pipefd)
  286. {
  287. #ifdef RduLocalTest
  288. if (ent)
  289. return rdu_do_store(p->fd, ent, p->pos, p);
  290. return 0;
  291. #else
  292. ssize_t ssz;
  293. //DPri("%p\n", ent);
  294. ssz = write(pipefd, &ent, sizeof(ent));
  295. DPri("ssz %zd\n", ssz);
  296. //sleep(1);
  297. return ssz != sizeof(ent);
  298. #endif
  299. }
  300. /* ---------------------------------------------------------------------- */
  301. /* the heart of this library */
  302. static void rdu_tfree(void *node)
  303. {
  304. /* empty */
  305. }
  306. static int rdu_ent_compar(const void *_a, const void *_b)
  307. {
  308. int ret;
  309. const struct au_rdu_ent *a = _a, *b = _b;
  310. ret = (int)a->nlen - b->nlen;
  311. if (!ret)
  312. ret = memcmp(a->name, b->name, a->nlen);
  313. return ret;
  314. }
  315. static int rdu_ent_compar_wh(const void *_a, const void *_b)
  316. {
  317. int ret;
  318. const struct au_rdu_ent *real = _a, *wh = _b;
  319. if (real->nlen >= AUFS_WH_PFX_LEN
  320. && !memcmp(real->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
  321. wh = _a;
  322. real = _b;
  323. }
  324. ret = (int)wh->nlen - AUFS_WH_PFX_LEN - real->nlen;
  325. if (!ret)
  326. ret = memcmp(wh->name + AUFS_WH_PFX_LEN, real->name,
  327. real->nlen);
  328. return ret;
  329. }
  330. /* tsearch(3) may not be thread-safe */
  331. static int rdu_ent_append(struct rdu *p, struct au_rdu_ent *ent, int pipefd)
  332. {
  333. int err;
  334. struct au_rdu_ent *e;
  335. err = 0;
  336. e = tfind(ent, (void *)&p->wh, rdu_ent_compar_wh);
  337. if (e)
  338. goto out;
  339. e = tsearch(ent, (void *)&p->real, rdu_ent_compar);
  340. if (e)
  341. err = rdu_store(p, ent, pipefd);
  342. else
  343. err = -1;
  344. out:
  345. return err;
  346. }
  347. static int rdu_ent_append_wh(struct rdu *p, struct au_rdu_ent *ent, int pipefd)
  348. {
  349. int err;
  350. struct au_rdu_ent *e;
  351. err = 0;
  352. e = tfind(ent, (void *)&p->wh, rdu_ent_compar);
  353. if (e)
  354. goto out;
  355. e = tsearch(ent, (void *)&p->wh, rdu_ent_compar);
  356. if (e) {
  357. if (p->shwh)
  358. err = rdu_store(p, ent, pipefd);
  359. } else
  360. err = -1;
  361. out:
  362. return err;
  363. }
  364. static int rdu_merge(struct rdu *p)
  365. {
  366. int err;
  367. unsigned long ul;
  368. pthread_t th;
  369. int fds[2];
  370. struct rdu_thread_arg arg;
  371. struct au_rdu_ent *ent;
  372. void *t;
  373. err = -1;
  374. p->pos = malloc(sizeof(*p->pos) * p->npos);
  375. if (!p->pos)
  376. goto out;
  377. /* pipe(2) may not be scheduled well in linux-2.6.23 and earlier */
  378. err = pipe(fds);
  379. if (err)
  380. goto out_free;
  381. arg.pipefd = fds[0];
  382. arg.p = p;
  383. #ifndef RduLocalTest
  384. err = pthread_create(&th, NULL, rdu_thread, &arg);
  385. #endif
  386. if (err)
  387. goto out_close;
  388. p->real = NULL;
  389. p->wh = NULL;
  390. ent = p->ent;
  391. for (ul = 0; !err && ul < p->npos; ul++) {
  392. if (ent->nlen <= AUFS_WH_PFX_LEN
  393. || strncmp(ent->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
  394. err = rdu_ent_append(p, ent, fds[1]);
  395. else
  396. err = rdu_ent_append_wh(p, ent, fds[1]);
  397. ent += au_rdu_len(ent->nlen);
  398. }
  399. rdu_store(p, /*ent*/NULL, fds[1]); /* terminate the thread */
  400. tdestroy(p->real, rdu_tfree);
  401. tdestroy(p->wh, rdu_tfree);
  402. #ifndef RduLocalTest
  403. pthread_join(th, NULL);
  404. #endif
  405. p->npos = p->idx;
  406. t = realloc(p->pos, sizeof(*p->pos) * p->npos);
  407. if (t)
  408. p->pos = t;
  409. /* t == NULL is not an error */
  410. out_close:
  411. close(fds[1]);
  412. close(fds[0]);
  413. if (!err)
  414. goto out; /* success */
  415. out_free:
  416. free(p->pos);
  417. p->pos = NULL;
  418. out:
  419. return err;
  420. }
  421. static int rdu_init(struct rdu *p)
  422. {
  423. int err;
  424. struct aufs_rdu param;
  425. char *t;
  426. memset(&param, 0, sizeof(param));
  427. param.ent = p->ent;
  428. param.sz = p->sz;
  429. t = getenv("AUFS_RDU_BLK");
  430. if (t)
  431. param.blk = strtoul(t + sizeof("AUFS_RDU_BLK"), NULL, 0);
  432. do {
  433. err = ioctl(p->fd, AUFS_CTL_RDU, &param);
  434. err = rdu_test_data(p, err);
  435. if (err > 0) {
  436. p->npos += err;
  437. if (!param.full)
  438. continue;
  439. assert(param.blk);
  440. t = realloc(p->ent, p->sz + param.blk);
  441. if (t) {
  442. param.sz = param.blk;
  443. param.ent = (void *)(t + p->sz);
  444. p->ent = (void *)t;
  445. p->sz += param.blk;
  446. } else
  447. err = -1;
  448. }
  449. } while (err > 0);
  450. p->shwh = param.shwh;
  451. if (!err)
  452. err = rdu_merge(p);
  453. if (err) {
  454. free(p->ent);
  455. p->ent = NULL;
  456. }
  457. return err;
  458. }
  459. static int rdu_pos(struct dirent *de, struct rdu *p, long pos)
  460. {
  461. int err;
  462. struct au_rdu_ent *ent;
  463. err = -1;
  464. if (pos <= p->npos) {
  465. ent = p->pos[pos];
  466. de->d_ino = ent->ino;
  467. de->d_off = pos;
  468. de->d_reclen = sizeof(*ent) + ent->nlen;
  469. de->d_type = ent->type;
  470. memcpy(de->d_name, ent->name, ent->nlen);
  471. de->d_name[ent->nlen] = 0;
  472. err = 0;
  473. }
  474. return err;
  475. }
  476. /* ---------------------------------------------------------------------- */
  477. static struct dirent *(*real_readdir)(DIR *dir);
  478. static int (*real_readdir_r)(DIR *dir, struct dirent *de, struct dirent **rde);
  479. static int (*real_closedir)(DIR *dir);
  480. static int rdu_dl(void **real, char *sym)
  481. {
  482. char *p;
  483. if (*real)
  484. return 0;
  485. dlerror(); /* clear */
  486. *real = dlsym(RTLD_NEXT, sym);
  487. p = dlerror();
  488. if (p)
  489. fprintf(stderr, "%s\n", p);
  490. return !!p;
  491. }
  492. #define RduDlFunc(sym) \
  493. static int rdu_dl_##sym(void) \
  494. { \
  495. return rdu_dl((void *)&real_##sym, #sym); \
  496. }
  497. RduDlFunc(readdir);
  498. RduDlFunc(closedir);
  499. #ifdef AuRDU_REENTRANT
  500. RduDlFunc(readdir_r);
  501. #else
  502. #define rdu_dl_readdir_r() 1
  503. #endif
  504. /* ---------------------------------------------------------------------- */
  505. static int rdu_readdir(DIR *dir, struct dirent *de, struct dirent **rde)
  506. {
  507. int err, fd;
  508. struct rdu *p;
  509. long pos;
  510. struct statfs stfs;
  511. if (rde)
  512. *rde = NULL;
  513. errno = EBADF;
  514. fd = dirfd(dir);
  515. err = fd;
  516. if (fd < 0)
  517. goto out;
  518. err = fstatfs(fd, &stfs);
  519. if (err)
  520. goto out;
  521. if (
  522. #ifdef RduLocalTest
  523. 1 ||
  524. #endif
  525. stfs.f_type == AUFS_SUPER_MAGIC) {
  526. err = rdu_lib_init();
  527. if (err)
  528. goto out;
  529. p = rdu_buf_lock(fd);
  530. if (!p)
  531. goto out;
  532. pos = telldir(dir);
  533. if (!pos || !p->npos) {
  534. err = rdu_init(p);
  535. rdu_unlock(p);
  536. }
  537. if (err)
  538. goto out;
  539. rdu_read_lock(p);
  540. if (!de)
  541. de = &p->de;
  542. err = rdu_pos(de, p, pos);
  543. rdu_unlock(p);
  544. if (!err) {
  545. *rde = de;
  546. seekdir(dir, pos + 1);
  547. }
  548. } else if (!de) {
  549. if (!rdu_dl_readdir()) {
  550. err = 0;
  551. *rde = real_readdir(dir);
  552. if (!*rde)
  553. err = -1;
  554. }
  555. } else {
  556. if (!rdu_dl_readdir_r())
  557. err = real_readdir_r(dir, de, rde);
  558. }
  559. out:
  560. return err;
  561. }
  562. struct dirent *readdir(DIR *dir)
  563. {
  564. struct dirent *de;
  565. int err;
  566. err = rdu_readdir(dir, NULL, &de);
  567. DPri("err %d\n", err);
  568. return de;
  569. }
  570. #ifdef AuRDU_REENTRANT
  571. int readdir_r(DIR *dirp, struct dirent *de, struct dirent **rde)
  572. {
  573. return rdu_readdir(dir, de, rde);
  574. }
  575. #endif
  576. int closedir(DIR *dir)
  577. {
  578. int err, fd;
  579. struct statfs stfs;
  580. errno = EBADF;
  581. fd = dirfd(dir);
  582. if (fd < 0)
  583. goto out;
  584. err = fstatfs(fd, &stfs);
  585. if (err)
  586. goto out;
  587. if (stfs.f_type == AUFS_SUPER_MAGIC)
  588. rdu_free(fd);
  589. if (!rdu_dl_closedir())
  590. err = real_closedir(dir);
  591. out:
  592. return err;
  593. }
  594. #if 0
  595. extern DIR *opendir (__const char *__name) __nonnull ((1));
  596. extern int closedir (DIR *__dirp) __nonnull ((1));
  597. extern struct dirent *__REDIRECT (readdir, (DIR *__dirp), readdir64)
  598. __nonnull ((1));
  599. extern struct dirent64 *readdir64 (DIR *__dirp) __nonnull ((1));
  600. extern int readdir_r (DIR *__restrict __dirp,
  601. struct dirent *__restrict __entry,
  602. struct dirent **__restrict __result)
  603. __nonnull ((1, 2, 3));
  604. extern int readdir64_r (DIR *__restrict __dirp,
  605. struct dirent64 *__restrict __entry,
  606. struct dirent64 **__restrict __result)
  607. __nonnull ((1, 2, 3));
  608. extern void rewinddir (DIR *__dirp) __THROW __nonnull ((1));
  609. extern void seekdir (DIR *__dirp, long int __pos) __THROW __nonnull ((1));
  610. extern long int telldir (DIR *__dirp) __THROW __nonnull ((1));
  611. extern int dirfd (DIR *__dirp) __THROW __nonnull ((1));
  612. extern int scandir (__const char *__restrict __dir,
  613. struct dirent ***__restrict __namelist,
  614. int (*__selector) (__const struct dirent *),
  615. int (*__cmp) (__const void *, __const void *))
  616. __nonnull ((1, 2));
  617. extern int scandir64 (__const char *__restrict __dir,
  618. struct dirent64 ***__restrict __namelist,
  619. int (*__selector) (__const struct dirent64 *),
  620. int (*__cmp) (__const void *, __const void *))
  621. __nonnull ((1, 2));
  622. extern int alphasort (__const void *__e1, __const void *__e2)
  623. __THROW __attribute_pure__ __nonnull ((1, 2));
  624. extern int alphasort64 (__const void *__e1, __const void *__e2)
  625. __THROW __attribute_pure__ __nonnull ((1, 2));
  626. extern int versionsort (__const void *__e1, __const void *__e2)
  627. __THROW __attribute_pure__ __nonnull ((1, 2));
  628. extern int versionsort64 (__const void *__e1, __const void *__e2)
  629. __THROW __attribute_pure__ __nonnull ((1, 2));
  630. extern __ssize_t getdirentries (int __fd, char *__restrict __buf,
  631. size_t __nbytes,
  632. __off_t *__restrict __basep)
  633. __THROW __nonnull ((2, 4));
  634. extern __ssize_t getdirentries64 (int __fd, char *__restrict __buf,
  635. size_t __nbytes,
  636. __off64_t *__restrict __basep)
  637. __THROW __nonnull ((2, 4));
  638. #endif