Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
0003  */
0004 
0005 #include <linux/string.h>
0006 #include <linux/errno.h>
0007 #include <linux/fs.h>
0008 #include "reiserfs.h"
0009 #include <linux/stat.h>
0010 #include <linux/buffer_head.h>
0011 #include <linux/slab.h>
0012 #include <linux/uaccess.h>
0013 
0014 extern const struct reiserfs_key MIN_KEY;
0015 
0016 static int reiserfs_readdir(struct file *, struct dir_context *);
0017 static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
0018                   int datasync);
0019 
0020 const struct file_operations reiserfs_dir_operations = {
0021     .llseek = generic_file_llseek,
0022     .read = generic_read_dir,
0023     .iterate_shared = reiserfs_readdir,
0024     .fsync = reiserfs_dir_fsync,
0025     .unlocked_ioctl = reiserfs_ioctl,
0026 #ifdef CONFIG_COMPAT
0027     .compat_ioctl = reiserfs_compat_ioctl,
0028 #endif
0029 };
0030 
0031 static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
0032                   int datasync)
0033 {
0034     struct inode *inode = filp->f_mapping->host;
0035     int err;
0036 
0037     err = file_write_and_wait_range(filp, start, end);
0038     if (err)
0039         return err;
0040 
0041     inode_lock(inode);
0042     reiserfs_write_lock(inode->i_sb);
0043     err = reiserfs_commit_for_inode(inode);
0044     reiserfs_write_unlock(inode->i_sb);
0045     inode_unlock(inode);
0046     if (err < 0)
0047         return err;
0048     return 0;
0049 }
0050 
0051 #define store_ih(where,what) copy_item_head (where, what)
0052 
0053 static inline bool is_privroot_deh(struct inode *dir, struct reiserfs_de_head *deh)
0054 {
0055     struct dentry *privroot = REISERFS_SB(dir->i_sb)->priv_root;
0056     return (d_really_is_positive(privroot) &&
0057             deh->deh_objectid == INODE_PKEY(d_inode(privroot))->k_objectid);
0058 }
0059 
0060 int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
0061 {
0062 
0063     /* key of current position in the directory (key of directory entry) */
0064     struct cpu_key pos_key;
0065 
0066     INITIALIZE_PATH(path_to_entry);
0067     struct buffer_head *bh;
0068     int item_num, entry_num;
0069     const struct reiserfs_key *rkey;
0070     struct item_head *ih, tmp_ih;
0071     int search_res;
0072     char *local_buf;
0073     loff_t next_pos;
0074     char small_buf[32]; /* avoid kmalloc if we can */
0075     struct reiserfs_dir_entry de;
0076     int ret = 0;
0077     int depth;
0078 
0079     reiserfs_write_lock(inode->i_sb);
0080 
0081     reiserfs_check_lock_depth(inode->i_sb, "readdir");
0082 
0083     /*
0084      * form key for search the next directory entry using
0085      * f_pos field of file structure
0086      */
0087     make_cpu_key(&pos_key, inode, ctx->pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3);
0088     next_pos = cpu_key_k_offset(&pos_key);
0089 
0090     path_to_entry.reada = PATH_READA;
0091     while (1) {
0092 research:
0093         /*
0094          * search the directory item, containing entry with
0095          * specified key
0096          */
0097         search_res =
0098             search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry,
0099                     &de);
0100         if (search_res == IO_ERROR) {
0101             /*
0102              * FIXME: we could just skip part of directory
0103              * which could not be read
0104              */
0105             ret = -EIO;
0106             goto out;
0107         }
0108         entry_num = de.de_entry_num;
0109         bh = de.de_bh;
0110         item_num = de.de_item_num;
0111         ih = de.de_ih;
0112         store_ih(&tmp_ih, ih);
0113 
0114         /* we must have found item, that is item of this directory, */
0115         RFALSE(COMP_SHORT_KEYS(&ih->ih_key, &pos_key),
0116                "vs-9000: found item %h does not match to dir we readdir %K",
0117                ih, &pos_key);
0118         RFALSE(item_num > B_NR_ITEMS(bh) - 1,
0119                "vs-9005 item_num == %d, item amount == %d",
0120                item_num, B_NR_ITEMS(bh));
0121 
0122         /*
0123          * and entry must be not more than number of entries
0124          * in the item
0125          */
0126         RFALSE(ih_entry_count(ih) < entry_num,
0127                "vs-9010: entry number is too big %d (%d)",
0128                entry_num, ih_entry_count(ih));
0129 
0130         /*
0131          * go through all entries in the directory item beginning
0132          * from the entry, that has been found
0133          */
0134         if (search_res == POSITION_FOUND
0135             || entry_num < ih_entry_count(ih)) {
0136             struct reiserfs_de_head *deh =
0137                 B_I_DEH(bh, ih) + entry_num;
0138 
0139             for (; entry_num < ih_entry_count(ih);
0140                  entry_num++, deh++) {
0141                 int d_reclen;
0142                 char *d_name;
0143                 ino_t d_ino;
0144                 loff_t cur_pos = deh_offset(deh);
0145 
0146                 /* it is hidden entry */
0147                 if (!de_visible(deh))
0148                     continue;
0149                 d_reclen = entry_length(bh, ih, entry_num);
0150                 d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
0151 
0152                 if (d_reclen <= 0 ||
0153                     d_name + d_reclen > bh->b_data + bh->b_size) {
0154                     /*
0155                      * There is corrupted data in entry,
0156                      * We'd better stop here
0157                      */
0158                     pathrelse(&path_to_entry);
0159                     ret = -EIO;
0160                     goto out;
0161                 }
0162 
0163                 if (!d_name[d_reclen - 1])
0164                     d_reclen = strlen(d_name);
0165 
0166                 /* too big to send back to VFS */
0167                 if (d_reclen >
0168                     REISERFS_MAX_NAME(inode->i_sb->
0169                               s_blocksize)) {
0170                     continue;
0171                 }
0172 
0173                 /* Ignore the .reiserfs_priv entry */
0174                 if (is_privroot_deh(inode, deh))
0175                     continue;
0176 
0177                 ctx->pos = deh_offset(deh);
0178                 d_ino = deh_objectid(deh);
0179                 if (d_reclen <= 32) {
0180                     local_buf = small_buf;
0181                 } else {
0182                     local_buf = kmalloc(d_reclen,
0183                                 GFP_NOFS);
0184                     if (!local_buf) {
0185                         pathrelse(&path_to_entry);
0186                         ret = -ENOMEM;
0187                         goto out;
0188                     }
0189                     if (item_moved(&tmp_ih, &path_to_entry)) {
0190                         kfree(local_buf);
0191                         goto research;
0192                     }
0193                 }
0194 
0195                 /*
0196                  * Note, that we copy name to user space via
0197                  * temporary buffer (local_buf) because
0198                  * filldir will block if user space buffer is
0199                  * swapped out. At that time entry can move to
0200                  * somewhere else
0201                  */
0202                 memcpy(local_buf, d_name, d_reclen);
0203 
0204                 /*
0205                  * Since filldir might sleep, we can release
0206                  * the write lock here for other waiters
0207                  */
0208                 depth = reiserfs_write_unlock_nested(inode->i_sb);
0209                 if (!dir_emit
0210                     (ctx, local_buf, d_reclen, d_ino,
0211                      DT_UNKNOWN)) {
0212                     reiserfs_write_lock_nested(inode->i_sb, depth);
0213                     if (local_buf != small_buf) {
0214                         kfree(local_buf);
0215                     }
0216                     goto end;
0217                 }
0218                 reiserfs_write_lock_nested(inode->i_sb, depth);
0219                 if (local_buf != small_buf) {
0220                     kfree(local_buf);
0221                 }
0222 
0223                 /* deh_offset(deh) may be invalid now. */
0224                 next_pos = cur_pos + 1;
0225 
0226                 if (item_moved(&tmp_ih, &path_to_entry)) {
0227                     set_cpu_key_k_offset(&pos_key,
0228                                  next_pos);
0229                     goto research;
0230                 }
0231             }   /* for */
0232         }
0233 
0234         /* end of directory has been reached */
0235         if (item_num != B_NR_ITEMS(bh) - 1)
0236             goto end;
0237 
0238         /*
0239          * item we went through is last item of node. Using right
0240          * delimiting key check is it directory end
0241          */
0242         rkey = get_rkey(&path_to_entry, inode->i_sb);
0243         if (!comp_le_keys(rkey, &MIN_KEY)) {
0244             /*
0245              * set pos_key to key, that is the smallest and greater
0246              * that key of the last entry in the item
0247              */
0248             set_cpu_key_k_offset(&pos_key, next_pos);
0249             continue;
0250         }
0251 
0252         /* end of directory has been reached */
0253         if (COMP_SHORT_KEYS(rkey, &pos_key)) {
0254             goto end;
0255         }
0256 
0257         /* directory continues in the right neighboring block */
0258         set_cpu_key_k_offset(&pos_key,
0259                      le_key_k_offset(KEY_FORMAT_3_5, rkey));
0260 
0261     }           /* while */
0262 
0263 end:
0264     ctx->pos = next_pos;
0265     pathrelse(&path_to_entry);
0266     reiserfs_check_path(&path_to_entry);
0267 out:
0268     reiserfs_write_unlock(inode->i_sb);
0269     return ret;
0270 }
0271 
0272 static int reiserfs_readdir(struct file *file, struct dir_context *ctx)
0273 {
0274     return reiserfs_readdir_inode(file_inode(file), ctx);
0275 }
0276 
0277 /*
0278  * compose directory item containing "." and ".." entries (entries are
0279  * not aligned to 4 byte boundary)
0280  */
0281 void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid,
0282                 __le32 par_dirid, __le32 par_objid)
0283 {
0284     struct reiserfs_de_head *dot, *dotdot;
0285 
0286     memset(body, 0, EMPTY_DIR_SIZE_V1);
0287     dot = (struct reiserfs_de_head *)body;
0288     dotdot = dot + 1;
0289 
0290     /* direntry header of "." */
0291     put_deh_offset(dot, DOT_OFFSET);
0292     /* these two are from make_le_item_head, and are LE */
0293     dot->deh_dir_id = dirid;
0294     dot->deh_objectid = objid;
0295     dot->deh_state = 0; /* Endian safe if 0 */
0296     put_deh_location(dot, EMPTY_DIR_SIZE_V1 - strlen("."));
0297     mark_de_visible(dot);
0298 
0299     /* direntry header of ".." */
0300     put_deh_offset(dotdot, DOT_DOT_OFFSET);
0301     /* key of ".." for the root directory */
0302     /* these two are from the inode, and are LE */
0303     dotdot->deh_dir_id = par_dirid;
0304     dotdot->deh_objectid = par_objid;
0305     dotdot->deh_state = 0;  /* Endian safe if 0 */
0306     put_deh_location(dotdot, deh_location(dot) - strlen(".."));
0307     mark_de_visible(dotdot);
0308 
0309     /* copy ".." and "." */
0310     memcpy(body + deh_location(dot), ".", 1);
0311     memcpy(body + deh_location(dotdot), "..", 2);
0312 }
0313 
0314 /* compose directory item containing "." and ".." entries */
0315 void make_empty_dir_item(char *body, __le32 dirid, __le32 objid,
0316              __le32 par_dirid, __le32 par_objid)
0317 {
0318     struct reiserfs_de_head *dot, *dotdot;
0319 
0320     memset(body, 0, EMPTY_DIR_SIZE);
0321     dot = (struct reiserfs_de_head *)body;
0322     dotdot = dot + 1;
0323 
0324     /* direntry header of "." */
0325     put_deh_offset(dot, DOT_OFFSET);
0326     /* these two are from make_le_item_head, and are LE */
0327     dot->deh_dir_id = dirid;
0328     dot->deh_objectid = objid;
0329     dot->deh_state = 0; /* Endian safe if 0 */
0330     put_deh_location(dot, EMPTY_DIR_SIZE - ROUND_UP(strlen(".")));
0331     mark_de_visible(dot);
0332 
0333     /* direntry header of ".." */
0334     put_deh_offset(dotdot, DOT_DOT_OFFSET);
0335     /* key of ".." for the root directory */
0336     /* these two are from the inode, and are LE */
0337     dotdot->deh_dir_id = par_dirid;
0338     dotdot->deh_objectid = par_objid;
0339     dotdot->deh_state = 0;  /* Endian safe if 0 */
0340     put_deh_location(dotdot, deh_location(dot) - ROUND_UP(strlen("..")));
0341     mark_de_visible(dotdot);
0342 
0343     /* copy ".." and "." */
0344     memcpy(body + deh_location(dot), ".", 1);
0345     memcpy(body + deh_location(dotdot), "..", 2);
0346 }