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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/ufs/ufs_dir.c
  3.  *
  4.  * Copyright (C) 1996
  5.  * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
  6.  * Laboratory for Computer Science Research Computing Facility
  7.  * Rutgers, The State University of New Jersey
  8.  *
  9.  * swab support by Francois-Rene Rideau <fare@tunes.org> 19970406
  10.  *
  11.  * 4.4BSD (FreeBSD) support added on February 1st 1998 by
  12.  * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
  13.  * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
  14.  */
  15. #include <linux/sched.h>
  16. #include <linux/locks.h>
  17. #include <linux/fs.h>
  18. #include <linux/ufs_fs.h>
  19. #include "swab.h"
  20. #include "util.h"
  21. #undef UFS_DIR_DEBUG
  22. #ifdef UFS_DIR_DEBUG
  23. #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
  24. #else
  25. #define UFSD(x)
  26. #endif
  27. /*
  28.  * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
  29.  *
  30.  * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
  31.  */
  32. static inline int ufs_match(struct super_block *sb, int len,
  33. const char * const name, struct ufs_dir_entry * de)
  34. {
  35. if (len != ufs_get_de_namlen(sb, de))
  36. return 0;
  37. if (!de->d_ino)
  38. return 0;
  39. return !memcmp(name, de->d_name, len);
  40. }
  41. /*
  42.  * This is blatantly stolen from ext2fs
  43.  */
  44. static int
  45. ufs_readdir (struct file * filp, void * dirent, filldir_t filldir)
  46. {
  47. struct inode *inode = filp->f_dentry->d_inode;
  48. int error = 0;
  49. unsigned long offset, lblk, blk;
  50. int i, stored;
  51. struct buffer_head * bh;
  52. struct ufs_dir_entry * de;
  53. struct super_block * sb;
  54. int de_reclen;
  55. unsigned flags;
  56. sb = inode->i_sb;
  57. flags = sb->u.ufs_sb.s_flags;
  58. UFSD(("ENTER, ino %lu  f_pos %lun", inode->i_ino, (unsigned long) filp->f_pos))
  59. stored = 0;
  60. bh = NULL;
  61. offset = filp->f_pos & (sb->s_blocksize - 1);
  62. while (!error && !stored && filp->f_pos < inode->i_size) {
  63. lblk = (filp->f_pos) >> sb->s_blocksize_bits;
  64. blk = ufs_frag_map(inode, lblk);
  65. if (!blk || !(bh = sb_bread(sb, blk))) {
  66. /* XXX - error - skip to the next block */
  67. printk("ufs_readdir: "
  68.        "dir inode %lu has a hole at offset %lun",
  69.        inode->i_ino, (unsigned long int)filp->f_pos);
  70. filp->f_pos += sb->s_blocksize - offset;
  71. continue;
  72. }
  73. revalidate:
  74. /* If the dir block has changed since the last call to
  75.  * readdir(2), then we might be pointing to an invalid
  76.  * dirent right now.  Scan from the start of the block
  77.  * to make sure. */
  78. if (filp->f_version != inode->i_version) {
  79. for (i = 0; i < sb->s_blocksize && i < offset; ) {
  80. de = (struct ufs_dir_entry *)(bh->b_data + i);
  81. /* It's too expensive to do a full
  82.  * dirent test each time round this
  83.  * loop, but we do have to test at
  84.  * least that it is non-zero.  A
  85.  * failure will be detected in the
  86.  * dirent test below. */
  87. de_reclen = fs16_to_cpu(sb, de->d_reclen);
  88. if (de_reclen < 1)
  89. break;
  90. i += de_reclen;
  91. }
  92. offset = i;
  93. filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
  94. | offset;
  95. filp->f_version = inode->i_version;
  96. }
  97. while (!error && filp->f_pos < inode->i_size
  98.        && offset < sb->s_blocksize) {
  99. de = (struct ufs_dir_entry *) (bh->b_data + offset);
  100. /* XXX - put in a real ufs_check_dir_entry() */
  101. if ((de->d_reclen == 0) || (ufs_get_de_namlen(sb, de) == 0)) {
  102. filp->f_pos = (filp->f_pos &
  103.               (sb->s_blocksize - 1)) +
  104.                sb->s_blocksize;
  105. brelse(bh);
  106. return stored;
  107. }
  108. if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
  109.    bh, offset)) {
  110. /* On error, skip the f_pos to the
  111.    next block. */
  112. filp->f_pos = (filp->f_pos |
  113.               (sb->s_blocksize - 1)) +
  114.        1;
  115. brelse (bh);
  116. return stored;
  117. }
  118. offset += fs16_to_cpu(sb, de->d_reclen);
  119. if (de->d_ino) {
  120. /* We might block in the next section
  121.  * if the data destination is
  122.  * currently swapped out.  So, use a
  123.  * version stamp to detect whether or
  124.  * not the directory has been modified
  125.  * during the copy operation. */
  126. unsigned long version = filp->f_version;
  127. unsigned char d_type = DT_UNKNOWN;
  128. UFSD(("filldir(%s,%u)n", de->d_name,
  129. fs32_to_cpu(sb, de->d_ino)))
  130. UFSD(("namlen %un", ufs_get_de_namlen(sb, de)))
  131. if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
  132. d_type = de->d_u.d_44.d_type;
  133. error = filldir(dirent, de->d_name,
  134. ufs_get_de_namlen(sb, de), filp->f_pos,
  135. fs32_to_cpu(sb, de->d_ino), d_type);
  136. if (error)
  137. break;
  138. if (version != filp->f_version)
  139. goto revalidate;
  140. stored ++;
  141. }
  142. filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
  143. }
  144. offset = 0;
  145. brelse (bh);
  146. }
  147. UPDATE_ATIME(inode);
  148. return 0;
  149. }
  150. /*
  151.  * define how far ahead to read directories while searching them.
  152.  */
  153. #define NAMEI_RA_CHUNKS  2
  154. #define NAMEI_RA_BLOCKS  4
  155. #define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
  156. #define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
  157. /*
  158.  * ufs_find_entry()
  159.  *
  160.  * finds an entry in the specified directory with the wanted name. It
  161.  * returns the cache buffer in which the entry was found, and the entry
  162.  * itself (as a parameter - res_bh). It does NOT read the inode of the
  163.  * entry - you'll have to do that yourself if you want to.
  164.  */
  165. struct ufs_dir_entry * ufs_find_entry (struct dentry *dentry,
  166. struct buffer_head ** res_bh)
  167. {
  168. struct super_block * sb;
  169. struct buffer_head * bh_use[NAMEI_RA_SIZE];
  170. struct buffer_head * bh_read[NAMEI_RA_SIZE];
  171. unsigned long offset;
  172. int block, toread, i, err;
  173. struct inode *dir = dentry->d_parent->d_inode;
  174. const char *name = dentry->d_name.name;
  175. int namelen = dentry->d_name.len;
  176. UFSD(("ENTER, dir_ino %lu, name %s, namlen %un", dir->i_ino, name, namelen))
  177. *res_bh = NULL;
  178. sb = dir->i_sb;
  179. if (namelen > UFS_MAXNAMLEN)
  180. return NULL;
  181. memset (bh_use, 0, sizeof (bh_use));
  182. toread = 0;
  183. for (block = 0; block < NAMEI_RA_SIZE; ++block) {
  184. struct buffer_head * bh;
  185. if ((block << sb->s_blocksize_bits) >= dir->i_size)
  186. break;
  187. bh = ufs_getfrag (dir, block, 0, &err);
  188. bh_use[block] = bh;
  189. if (bh && !buffer_uptodate(bh))
  190. bh_read[toread++] = bh;
  191. }
  192. for (block = 0, offset = 0; offset < dir->i_size; block++) {
  193. struct buffer_head * bh;
  194. struct ufs_dir_entry * de;
  195. char * dlimit;
  196. if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
  197. ll_rw_block (READ, toread, bh_read);
  198. toread = 0;
  199. }
  200. bh = bh_use[block % NAMEI_RA_SIZE];
  201. if (!bh) {
  202. ufs_error (sb, "ufs_find_entry", 
  203. "directory #%lu contains a hole at offset %lu",
  204. dir->i_ino, offset);
  205. offset += sb->s_blocksize;
  206. continue;
  207. }
  208. wait_on_buffer (bh);
  209. if (!buffer_uptodate(bh)) {
  210. /*
  211.  * read error: all bets are off
  212.  */
  213. break;
  214. }
  215. de = (struct ufs_dir_entry *) bh->b_data;
  216. dlimit = bh->b_data + sb->s_blocksize;
  217. while ((char *) de < dlimit && offset < dir->i_size) {
  218. /* this code is executed quadratically often */
  219. /* do minimal checking by hand */
  220. int de_len;
  221. if ((char *) de + namelen <= dlimit &&
  222.     ufs_match(sb, namelen, name, de)) {
  223. /* found a match -
  224. just to be sure, do a full check */
  225. if (!ufs_check_dir_entry("ufs_find_entry",
  226.     dir, de, bh, offset))
  227. goto failed;
  228. for (i = 0; i < NAMEI_RA_SIZE; ++i) {
  229. if (bh_use[i] != bh)
  230. brelse (bh_use[i]);
  231. }
  232. *res_bh = bh;
  233. return de;
  234. }
  235.                         /* prevent looping on a bad block */
  236. de_len = fs16_to_cpu(sb, de->d_reclen);
  237. if (de_len <= 0)
  238. goto failed;
  239. offset += de_len;
  240. de = (struct ufs_dir_entry *) ((char *) de + de_len);
  241. }
  242. brelse (bh);
  243. if (((block + NAMEI_RA_SIZE) << sb->s_blocksize_bits ) >=
  244.     dir->i_size)
  245. bh = NULL;
  246. else
  247. bh = ufs_getfrag (dir, block + NAMEI_RA_SIZE, 0, &err);
  248. bh_use[block % NAMEI_RA_SIZE] = bh;
  249. if (bh && !buffer_uptodate(bh))
  250. bh_read[toread++] = bh;
  251. }
  252. failed:
  253. for (i = 0; i < NAMEI_RA_SIZE; ++i) brelse (bh_use[i]);
  254. UFSD(("EXITn"))
  255. return NULL;
  256. }
  257. int ufs_check_dir_entry (const char * function, struct inode * dir,
  258. struct ufs_dir_entry * de, struct buffer_head * bh, 
  259. unsigned long offset)
  260. {
  261. struct super_block *sb = dir->i_sb;
  262. const char *error_msg = NULL;
  263. int rlen = fs16_to_cpu(sb, de->d_reclen);
  264. if (rlen < UFS_DIR_REC_LEN(1))
  265. error_msg = "reclen is smaller than minimal";
  266. else if (rlen % 4 != 0)
  267. error_msg = "reclen % 4 != 0";
  268. else if (rlen < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)))
  269. error_msg = "reclen is too small for namlen";
  270. else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
  271. error_msg = "directory entry across blocks";
  272. else if (fs32_to_cpu(sb, de->d_ino) > (sb->u.ufs_sb.s_uspi->s_ipg *
  273.       sb->u.ufs_sb.s_uspi->s_ncg))
  274. error_msg = "inode out of bounds";
  275. if (error_msg != NULL)
  276. ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - "
  277.     "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
  278.     dir->i_ino, dir->i_size, error_msg, offset,
  279.     (unsigned long)fs32_to_cpu(sb, de->d_ino),
  280.     rlen, ufs_get_de_namlen(sb, de));
  281. return (error_msg == NULL ? 1 : 0);
  282. }
  283. struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct buffer_head **p)
  284. {
  285. int err;
  286. struct buffer_head *bh = ufs_bread (dir, 0, 0, &err);
  287. struct ufs_dir_entry *res = NULL;
  288. if (bh) {
  289. res = (struct ufs_dir_entry *) bh->b_data;
  290. res = (struct ufs_dir_entry *)((char *)res +
  291. fs16_to_cpu(dir->i_sb, res->d_reclen));
  292. }
  293. *p = bh;
  294. return res;
  295. }
  296. ino_t ufs_inode_by_name(struct inode * dir, struct dentry *dentry)
  297. {
  298. ino_t res = 0;
  299. struct ufs_dir_entry * de;
  300. struct buffer_head *bh;
  301. de = ufs_find_entry (dentry, &bh);
  302. if (de) {
  303. res = fs32_to_cpu(dir->i_sb, de->d_ino);
  304. brelse(bh);
  305. }
  306. return res;
  307. }
  308. void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
  309. struct buffer_head *bh, struct inode *inode)
  310. {
  311. dir->i_version = ++event;
  312. de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
  313. mark_buffer_dirty(bh);
  314. if (IS_SYNC(dir)) {
  315. ll_rw_block (WRITE, 1, &bh);
  316. wait_on_buffer(bh);
  317. }
  318. brelse (bh);
  319. }
  320. /*
  321.  * ufs_add_entry()
  322.  *
  323.  * adds a file entry to the specified directory, using the same
  324.  * semantics as ufs_find_entry(). It returns NULL if it failed.
  325.  */
  326. int ufs_add_link(struct dentry *dentry, struct inode *inode)
  327. {
  328. struct super_block * sb;
  329. struct ufs_sb_private_info * uspi;
  330. unsigned long offset;
  331. unsigned fragoff;
  332. unsigned short rec_len;
  333. struct buffer_head * bh;
  334. struct ufs_dir_entry * de, * de1;
  335. struct inode *dir = dentry->d_parent->d_inode;
  336. const char *name = dentry->d_name.name;
  337. int namelen = dentry->d_name.len;
  338. int err;
  339. UFSD(("ENTER, name %s, namelen %un", name, namelen))
  340. sb = dir->i_sb;
  341. uspi = sb->u.ufs_sb.s_uspi;
  342. if (!namelen)
  343. return -EINVAL;
  344. bh = ufs_bread (dir, 0, 0, &err);
  345. if (!bh)
  346. return err;
  347. rec_len = UFS_DIR_REC_LEN(namelen);
  348. offset = 0;
  349. de = (struct ufs_dir_entry *) bh->b_data;
  350. while (1) {
  351. if ((char *)de >= UFS_SECTOR_SIZE + bh->b_data) {
  352. fragoff = offset & ~uspi->s_fmask;
  353. if (fragoff != 0 && fragoff != UFS_SECTOR_SIZE)
  354. ufs_error (sb, "ufs_add_entry", "internal error"
  355. " fragoff %u", fragoff);
  356. if (!fragoff) {
  357. brelse (bh);
  358. bh = ufs_bread (dir, offset >> sb->s_blocksize_bits, 1, &err);
  359. if (!bh)
  360. return err;
  361. }
  362. if (dir->i_size <= offset) {
  363. if (dir->i_size == 0) {
  364. brelse(bh);
  365. return -ENOENT;
  366. }
  367. de = (struct ufs_dir_entry *) (bh->b_data + fragoff);
  368. de->d_ino = 0;
  369. de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
  370. ufs_set_de_namlen(sb, de, 0);
  371. dir->i_size = offset + UFS_SECTOR_SIZE;
  372. mark_inode_dirty(dir);
  373. } else {
  374. de = (struct ufs_dir_entry *) bh->b_data;
  375. }
  376. }
  377. if (!ufs_check_dir_entry ("ufs_add_entry", dir, de, bh, offset)) {
  378. brelse (bh);
  379. return -ENOENT;
  380. }
  381. if (ufs_match(sb, namelen, name, de)) {
  382. brelse (bh);
  383. return -EEXIST;
  384. }
  385. if (de->d_ino == 0 && fs16_to_cpu(sb, de->d_reclen) >= rec_len)
  386. break;
  387. if (fs16_to_cpu(sb, de->d_reclen) >=
  388.      UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)) + rec_len)
  389. break;
  390. offset += fs16_to_cpu(sb, de->d_reclen);
  391. de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen));
  392. }
  393. if (de->d_ino) {
  394. de1 = (struct ufs_dir_entry *) ((char *) de +
  395. UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  396. de1->d_reclen =
  397. cpu_to_fs16(sb, fs16_to_cpu(sb, de->d_reclen) -
  398. UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  399. de->d_reclen =
  400. cpu_to_fs16(sb, UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  401. de = de1;
  402. }
  403. de->d_ino = 0;
  404. ufs_set_de_namlen(sb, de, namelen);
  405. memcpy (de->d_name, name, namelen + 1);
  406. de->d_ino = cpu_to_fs32(sb, inode->i_ino);
  407. ufs_set_de_type(sb, de, inode->i_mode);
  408. mark_buffer_dirty(bh);
  409. if (IS_SYNC(dir)) {
  410. ll_rw_block (WRITE, 1, &bh);
  411. wait_on_buffer (bh);
  412. }
  413. brelse (bh);
  414. dir->i_mtime = dir->i_ctime = CURRENT_TIME;
  415. dir->i_version = ++event;
  416. mark_inode_dirty(dir);
  417. UFSD(("EXITn"))
  418. return 0;
  419. }
  420. /*
  421.  * ufs_delete_entry deletes a directory entry by merging it with the
  422.  * previous entry.
  423.  */
  424. int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir,
  425. struct buffer_head * bh )
  426. {
  427. struct super_block * sb;
  428. struct ufs_dir_entry * de, * pde;
  429. unsigned i;
  430. UFSD(("ENTERn"))
  431. sb = inode->i_sb;
  432. i = 0;
  433. pde = NULL;
  434. de = (struct ufs_dir_entry *) bh->b_data;
  435. UFSD(("ino %u, reclen %u, namlen %u, name %sn",
  436. fs32_to_cpu(sb, de->d_ino),
  437. fs16to_cpu(sb, de->d_reclen),
  438. ufs_get_de_namlen(sb, de), de->d_name))
  439. while (i < bh->b_size) {
  440. if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) {
  441. brelse(bh);
  442. return -EIO;
  443. }
  444. if (de == dir)  {
  445. if (pde)
  446. fs16_add(sb, &pde->d_reclen,
  447. fs16_to_cpu(sb, dir->d_reclen));
  448. dir->d_ino = 0;
  449. inode->i_version = ++event;
  450. inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  451. mark_inode_dirty(inode);
  452. mark_buffer_dirty(bh);
  453. if (IS_SYNC(inode)) {
  454. ll_rw_block(WRITE, 1, &bh);
  455. wait_on_buffer(bh);
  456. }
  457. brelse(bh);
  458. UFSD(("EXITn"))
  459. return 0;
  460. }
  461. i += fs16_to_cpu(sb, de->d_reclen);
  462. if (i == UFS_SECTOR_SIZE) pde = NULL;
  463. else pde = de;
  464. de = (struct ufs_dir_entry *)
  465.     ((char *) de + fs16_to_cpu(sb, de->d_reclen));
  466. if (i == UFS_SECTOR_SIZE && de->d_reclen == 0)
  467. break;
  468. }
  469. UFSD(("EXITn"))
  470. brelse(bh);
  471. return -ENOENT;
  472. }
  473. int ufs_make_empty(struct inode * inode, struct inode *dir)
  474. {
  475. struct super_block * sb = dir->i_sb;
  476. struct buffer_head * dir_block;
  477. struct ufs_dir_entry * de;
  478. int err;
  479. dir_block = ufs_bread (inode, 0, 1, &err);
  480. if (!dir_block)
  481. return err;
  482. inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;
  483. de = (struct ufs_dir_entry *) dir_block->b_data;
  484. de->d_ino = cpu_to_fs32(sb, inode->i_ino);
  485. ufs_set_de_type(sb, de, inode->i_mode);
  486. ufs_set_de_namlen(sb, de, 1);
  487. de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1));
  488. strcpy (de->d_name, ".");
  489. de = (struct ufs_dir_entry *)
  490. ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  491. de->d_ino = cpu_to_fs32(sb, dir->i_ino);
  492. ufs_set_de_type(sb, de, dir->i_mode);
  493. de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
  494. ufs_set_de_namlen(sb, de, 2);
  495. strcpy (de->d_name, "..");
  496. mark_buffer_dirty(dir_block);
  497. brelse (dir_block);
  498. mark_inode_dirty(inode);
  499. return 0;
  500. }
  501. /*
  502.  * routine to check that the specified directory is empty (for rmdir)
  503.  */
  504. int ufs_empty_dir (struct inode * inode)
  505. {
  506. struct super_block * sb;
  507. unsigned long offset;
  508. struct buffer_head * bh;
  509. struct ufs_dir_entry * de, * de1;
  510. int err;
  511. sb = inode->i_sb;
  512. if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||
  513.     !(bh = ufs_bread (inode, 0, 0, &err))) {
  514.      ufs_warning (inode->i_sb, "empty_dir",
  515.       "bad directory (dir #%lu) - no data block",
  516.       inode->i_ino);
  517. return 1;
  518. }
  519. de = (struct ufs_dir_entry *) bh->b_data;
  520. de1 = (struct ufs_dir_entry *)
  521. ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  522. if (fs32_to_cpu(sb, de->d_ino) != inode->i_ino || de1->d_ino == 0 ||
  523.      strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
  524.      ufs_warning (inode->i_sb, "empty_dir",
  525.       "bad directory (dir #%lu) - no `.' or `..'",
  526.       inode->i_ino);
  527. return 1;
  528. }
  529. offset = fs16_to_cpu(sb, de->d_reclen) + fs16_to_cpu(sb, de1->d_reclen);
  530. de = (struct ufs_dir_entry *)
  531. ((char *)de1 + fs16_to_cpu(sb, de1->d_reclen));
  532. while (offset < inode->i_size ) {
  533. if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
  534. brelse (bh);
  535. bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err);
  536.   if (!bh) {
  537. ufs_error (sb, "empty_dir",
  538.     "directory #%lu contains a hole at offset %lu",
  539.     inode->i_ino, offset);
  540. offset += sb->s_blocksize;
  541. continue;
  542. }
  543. de = (struct ufs_dir_entry *) bh->b_data;
  544. }
  545. if (!ufs_check_dir_entry ("empty_dir", inode, de, bh, offset)) {
  546. brelse (bh);
  547. return 1;
  548. }
  549. if (de->d_ino) {
  550. brelse (bh);
  551. return 0;
  552. }
  553. offset += fs16_to_cpu(sb, de->d_reclen);
  554. de = (struct ufs_dir_entry *)
  555. ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  556. }
  557. brelse (bh);
  558. return 1;
  559. }
  560. struct file_operations ufs_dir_operations = {
  561. read: generic_read_dir,
  562. readdir: ufs_readdir,
  563. fsync: file_fsync,
  564. };