"Fossies" - the Fresh Open Source Software Archive

Member "linux-coda-6.9/linux2.6/dir.c" (1 Dec 2009, 17109 Bytes) of package /linux/misc/old/linux-coda-6.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 
    2 /*
    3  * Directory operations for Coda filesystem
    4  * Original version: (C) 1996 P. Braam and M. Callahan
    5  * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
    6  * 
    7  * Carnegie Mellon encourages users to contribute improvements to
    8  * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
    9  */
   10 
   11 #include <linux/fs.h>
   12 #include <linux/smp_lock.h>
   13 
   14 #include <linux/coda_linux.h>
   15 #include <linux/coda_psdev.h>
   16 #include <linux/coda_fs_i.h>
   17 #include <linux/coda_cache.h>
   18 
   19 #include "coda_int.h"
   20 #include "compat.h"
   21 
   22 /* dir inode-ops */
   23 static int coda_create(struct inode *dir, struct dentry *new, int mode, struct nameidata *nd);
   24 static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);
   25 static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, 
   26              struct dentry *entry);
   27 static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
   28 static int coda_symlink(struct inode *dir_inode, struct dentry *entry,
   29             const char *symname);
   30 static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);
   31 static int coda_rmdir(struct inode *dir_inode, struct dentry *entry);
   32 static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, 
   33                        struct inode *new_inode, struct dentry *new_dentry);
   34 
   35 /* dir file-ops */
   36 static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
   37 
   38 /* dentry ops */
   39 static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
   40 static int coda_dentry_delete(struct dentry *);
   41 
   42 /* support routines */
   43 static int coda_venus_readdir(struct file *filp, filldir_t filldir,
   44                   void *dirent, struct dentry *dir);
   45 
   46 /* same as fs/bad_inode.c */
   47 static int coda_return_EIO(void)
   48 {
   49     return -EIO;
   50 }
   51 #define CODA_EIO_ERROR ((void *) (coda_return_EIO))
   52 
   53 static const struct dentry_operations coda_dentry_operations =
   54 {
   55     .d_revalidate   = coda_dentry_revalidate,
   56     .d_delete   = coda_dentry_delete,
   57 };
   58 
   59 struct inode_operations coda_dir_inode_operations =
   60 {
   61     .create     = coda_create,
   62     .lookup     = coda_lookup,
   63     .link       = coda_link,
   64     .unlink     = coda_unlink,
   65     .symlink    = coda_symlink,
   66     .mkdir      = coda_mkdir,
   67     .rmdir      = coda_rmdir,
   68     .mknod      = CODA_EIO_ERROR,
   69     .rename     = coda_rename,
   70     .permission = coda_permission,
   71     .getattr    = coda_getattr,
   72     .setattr    = coda_setattr,
   73 };
   74 
   75 struct file_operations coda_dir_operations = {
   76     .llseek     = generic_file_llseek,
   77     .read       = generic_read_dir,
   78     .readdir    = coda_readdir,
   79     .open       = coda_open,
   80     .release    = coda_release,
   81     .fsync      = coda_fsync,
   82 };
   83 
   84 
   85 /* inode operations for directories */
   86 /* access routines: lookup, readlink, permission */
   87 static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
   88 {
   89     struct inode *inode = NULL;
   90     struct CodaFid resfid = { { 0, } };
   91     int type = 0;
   92     int error = 0;
   93     const char *name = entry->d_name.name;
   94     size_t length = entry->d_name.len;
   95     
   96     if ( length > CODA_MAXNAMLEN ) {
   97             printk("name too long: lookup, %s (%*s)\n", 
   98                coda_i2s(dir), (int)length, name);
   99         return ERR_PTR(-ENAMETOOLONG);
  100     }
  101 
  102         /* control object, create inode on the fly */
  103         if (coda_isroot(dir) && coda_iscontrol(name, length)) {
  104             error = coda_cnode_makectl(&inode, dir->i_sb);
  105         type = CODA_NOCACHE;
  106                 goto exit;
  107         }
  108 
  109     lock_kernel();
  110 
  111     error = venus_lookup(dir->i_sb, coda_i2f(dir), 
  112                  name, length, &type, &resfid);
  113 
  114     if (!error)
  115             error = coda_cnode_make(&inode, &resfid, dir->i_sb);
  116 
  117     unlock_kernel();
  118 
  119     if (error && error != -ENOENT)
  120         return ERR_PTR(error);
  121 
  122 exit:
  123     entry->d_op = &coda_dentry_operations;
  124     if (inode && (type & CODA_NOCACHE))
  125         coda_flag_inode(inode, C_VATTR | C_PURGE);
  126 
  127     return d_splice_alias(inode, entry);
  128 }
  129 
  130 
  131 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) /* 2.6.27-rc1 */
  132 int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
  133 #else
  134 /* git commit e6305c43eda10ebfd2ad9e35d6e172ccc7bb3695 sanitize permission prototype */
  135 int coda_permission(struct inode *inode, int mask)
  136 #endif
  137 {
  138         int error = 0;
  139 
  140     mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
  141  
  142     if (!mask)
  143         return 0; 
  144 
  145     if ((mask & MAY_EXEC) && !execute_ok(inode))
  146         return -EACCES;
  147 
  148     lock_kernel();
  149 
  150     if (coda_cache_check(inode, mask))
  151         goto out; 
  152 
  153         error = venus_access(inode->i_sb, coda_i2f(inode), mask);
  154     
  155     if (!error)
  156         coda_cache_enter(inode, mask);
  157 
  158  out:
  159     unlock_kernel();
  160 
  161         return error; 
  162 }
  163 
  164 
  165 static inline void coda_dir_update_mtime(struct inode *dir)
  166 {
  167 #ifdef REQUERY_VENUS_FOR_MTIME
  168     /* invalidate the directory cnode's attributes so we refetch the
  169      * attributes from venus next time the inode is referenced */
  170     coda_flag_inode(dir, C_VATTR);
  171 #else
  172     /* optimistically we can also act as if our nose bleeds. The
  173      * granularity of the mtime is coarse anyways so we might actually be
  174      * right most of the time. Note: we only do this for directories. */
  175     dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
  176 #endif
  177 }
  178 
  179 /* we have to wrap inc_nlink/drop_nlink because sometimes userspace uses a
  180  * trick to fool GNU find's optimizations. If we can't be sure of the link
  181  * (because of volume mount points) we set i_nlink to 1 which forces find
  182  * to consider every child as a possible directory. We should also never
  183  * see an increment or decrement for deleted directories where i_nlink == 0 */
  184 static inline void coda_dir_inc_nlink(struct inode *dir)
  185 {
  186     if (dir->i_nlink >= 2)
  187         inc_nlink(dir);
  188 }
  189 static inline void coda_dir_drop_nlink(struct inode *dir)
  190 {
  191     if (dir->i_nlink > 2)
  192         drop_nlink(dir);
  193 }
  194 
  195 /* creation routines: create, mknod, mkdir, link, symlink */
  196 static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
  197 {
  198         int error=0;
  199     const char *name=de->d_name.name;
  200     int length=de->d_name.len;
  201     struct inode *inode;
  202     struct CodaFid newfid;
  203     struct coda_vattr attrs;
  204 
  205     lock_kernel();
  206 
  207     if (coda_isroot(dir) && coda_iscontrol(name, length)) {
  208         unlock_kernel();
  209         return -EPERM;
  210     }
  211 
  212     error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
  213                 0, mode, &newfid, &attrs);
  214 
  215         if ( error ) {
  216         unlock_kernel();
  217         d_drop(de);
  218         return error;
  219     }
  220 
  221     inode = coda_iget(dir->i_sb, &newfid, &attrs);
  222     if ( IS_ERR(inode) ) {
  223         unlock_kernel();
  224         d_drop(de);
  225         return PTR_ERR(inode);
  226     }
  227 
  228     /* invalidate the directory cnode's attributes */
  229     coda_dir_update_mtime(dir);
  230     unlock_kernel();
  231     d_instantiate(de, inode);
  232         return 0;
  233 }
  234 
  235 static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
  236 {
  237     struct inode *inode;
  238     struct coda_vattr attrs;
  239     const char *name = de->d_name.name;
  240     int len = de->d_name.len;
  241     int error;
  242     struct CodaFid newfid;
  243 
  244     lock_kernel();
  245 
  246     if (coda_isroot(dir) && coda_iscontrol(name, len)) {
  247         unlock_kernel();
  248         return -EPERM;
  249     }
  250 
  251     attrs.va_mode = mode;
  252     error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
  253                    name, len, &newfid, &attrs);
  254         
  255         if ( error ) {
  256         unlock_kernel();
  257         d_drop(de);
  258         return error;
  259         }
  260          
  261     inode = coda_iget(dir->i_sb, &newfid, &attrs);
  262     if ( IS_ERR(inode) ) {
  263         unlock_kernel();
  264         d_drop(de);
  265         return PTR_ERR(inode);
  266     }
  267     
  268     /* invalidate the directory cnode's attributes */
  269     coda_dir_inc_nlink(dir);
  270     coda_dir_update_mtime(dir);
  271     unlock_kernel();
  272     d_instantiate(de, inode);
  273         return 0;
  274 }
  275 
  276 /* try to make de an entry in dir_inodde linked to source_de */ 
  277 static int coda_link(struct dentry *source_de, struct inode *dir_inode, 
  278       struct dentry *de)
  279 {
  280     struct inode *inode = source_de->d_inode;
  281         const char * name = de->d_name.name;
  282     int len = de->d_name.len;
  283     int error;
  284 
  285     lock_kernel();
  286 
  287     if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
  288         unlock_kernel();
  289         return -EPERM;
  290     }
  291 
  292     error = venus_link(dir_inode->i_sb, coda_i2f(inode),
  293                coda_i2f(dir_inode), (const char *)name, len);
  294 
  295     if (error) { 
  296         d_drop(de);
  297         goto out;
  298     }
  299 
  300     coda_dir_update_mtime(dir_inode);
  301     atomic_inc(&inode->i_count);
  302     d_instantiate(de, inode);
  303     inc_nlink(inode);
  304 
  305 out:
  306     unlock_kernel();
  307     return(error);
  308 }
  309 
  310 
  311 static int coda_symlink(struct inode *dir_inode, struct dentry *de,
  312             const char *symname)
  313 {
  314         const char *name = de->d_name.name;
  315     int len = de->d_name.len;
  316     int symlen;
  317         int error=0;
  318         
  319     lock_kernel();
  320 
  321     if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
  322         unlock_kernel();
  323         return -EPERM;
  324     }
  325 
  326     symlen = strlen(symname);
  327     if ( symlen > CODA_MAXPATHLEN ) {
  328         unlock_kernel();
  329         return -ENAMETOOLONG;
  330     }
  331 
  332     /*
  333      * This entry is now negative. Since we do not create
  334      * an inode for the entry we have to drop it. 
  335      */
  336     d_drop(de);
  337     error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len, 
  338                   symname, symlen);
  339 
  340     /* mtime is no good anymore */
  341     if ( !error )
  342         coda_dir_update_mtime(dir_inode);
  343 
  344     unlock_kernel();
  345         return error;
  346 }
  347 
  348 /* destruction routines: unlink, rmdir */
  349 static int coda_unlink(struct inode *dir, struct dentry *de)
  350 {
  351     int error;
  352     const char *name = de->d_name.name;
  353     int len = de->d_name.len;
  354 
  355     lock_kernel();
  356 
  357     error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
  358     if ( error ) {
  359         unlock_kernel();
  360         return error;
  361     }
  362 
  363     coda_dir_update_mtime(dir);
  364     drop_nlink(de->d_inode);
  365     unlock_kernel();
  366 
  367     return 0;
  368 }
  369 
  370 static int coda_rmdir(struct inode *dir, struct dentry *de)
  371 {
  372     const char *name = de->d_name.name;
  373     int len = de->d_name.len;
  374     int error;
  375 
  376     lock_kernel();
  377 
  378     error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
  379     if (!error) {
  380         /* VFS can delete the child */
  381         if (de->d_inode)
  382             de->d_inode->i_nlink = 0;
  383 
  384         /* fix linkcount of the parent */
  385         coda_dir_drop_nlink(dir);
  386         coda_dir_update_mtime(dir);
  387     }
  388     unlock_kernel();
  389 
  390     return error;
  391 }
  392 
  393 /* rename */
  394 static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, 
  395                struct inode *new_dir, struct dentry *new_dentry)
  396 {
  397     const char *old_name = old_dentry->d_name.name;
  398     const char *new_name = new_dentry->d_name.name;
  399     int old_length = old_dentry->d_name.len;
  400     int new_length = new_dentry->d_name.len;
  401     int error;
  402 
  403     lock_kernel();
  404 
  405     error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
  406                  coda_i2f(new_dir), old_length, new_length,
  407                  (const char *) old_name, (const char *)new_name);
  408 
  409     if ( !error ) {
  410         if ( new_dentry->d_inode ) {
  411             if (S_ISDIR(new_dentry->d_inode->i_mode)) {
  412                 coda_dir_drop_nlink(old_dir);
  413                 coda_dir_inc_nlink(new_dir);
  414             }
  415             coda_dir_update_mtime(old_dir);
  416             coda_dir_update_mtime(new_dir);
  417             coda_flag_inode(new_dentry->d_inode, C_VATTR);
  418         } else {
  419             coda_flag_inode(old_dir, C_VATTR);
  420             coda_flag_inode(new_dir, C_VATTR);
  421         }
  422     }
  423     unlock_kernel();
  424 
  425     return error;
  426 }
  427 
  428 
  429 /* file operations for directories */
  430 static int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
  431 {
  432     struct dentry *coda_dentry = coda_file->f_dentry;
  433     struct file *host_file;
  434     struct inode *host_inode;
  435     int ret;
  436 
  437     host_file = CODA_FTOC(coda_file);
  438     BUG_ON(!host_file);
  439 
  440     host_inode = host_file->f_dentry->d_inode;
  441     mutex_lock(&host_inode->i_mutex);
  442     host_file->f_pos = coda_file->f_pos;
  443 
  444     if (!host_file->f_op->readdir) {
  445         /* Venus: we must read Venus dirents from the file */
  446         ret = coda_venus_readdir(host_file, filldir, dirent, coda_dentry);
  447     } else {
  448         /* potemkin case: we were handed a directory inode. */
  449         /* Yuk, we can't call vfs_readdir because we are already
  450          * holding the inode semaphore. */
  451         ret = -ENOTDIR;
  452         if (!host_file->f_op || !host_file->f_op->readdir)
  453             goto out;
  454 
  455         ret = -ENOENT;
  456         if (!IS_DEADDIR(host_inode)) {
  457             ret = host_file->f_op->readdir(host_file, filldir, dirent);
  458             file_accessed(host_file);
  459         }
  460     }
  461 out:
  462     coda_file->f_pos = host_file->f_pos;
  463     mutex_unlock(&host_inode->i_mutex);
  464 
  465     return ret;
  466 }
  467 
  468 static inline unsigned int CDT2DT(unsigned char cdt)
  469 {
  470     unsigned int dt;
  471 
  472     switch(cdt) {
  473     case CDT_UNKNOWN: dt = DT_UNKNOWN; break;
  474     case CDT_FIFO:    dt = DT_FIFO;    break;
  475     case CDT_CHR:     dt = DT_CHR;     break;
  476     case CDT_DIR:     dt = DT_DIR;     break;
  477     case CDT_BLK:     dt = DT_BLK;     break;
  478     case CDT_REG:     dt = DT_REG;     break;
  479     case CDT_LNK:     dt = DT_LNK;     break;
  480     case CDT_SOCK:    dt = DT_SOCK;    break;
  481     case CDT_WHT:     dt = DT_WHT;     break;
  482     default:      dt = DT_UNKNOWN; break;
  483     }
  484     return dt;
  485 }
  486 
  487 /* support routines */
  488 static int coda_venus_readdir(struct file *filp, filldir_t filldir,
  489                   void *dirent, struct dentry *dir)
  490 {
  491     int result = 0; /* # of entries returned */
  492     struct venus_dirent *vdir;
  493     unsigned long vdir_size =
  494         (unsigned long)(&((struct venus_dirent *)0)->d_name);
  495     unsigned int type;
  496     struct qstr name;
  497     ino_t ino;
  498     int ret;
  499 
  500     vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
  501     if (!vdir) return -ENOMEM;
  502 
  503     if (filp->f_pos == 0) {
  504         ret = filldir(dirent, ".", 1, 0, dir->d_inode->i_ino, DT_DIR);
  505         if (ret < 0)
  506             goto out;
  507         result++;
  508         filp->f_pos++;
  509     }
  510     if (filp->f_pos == 1) {
  511         ret = filldir(dirent, "..", 2, 1, dir->d_parent->d_inode->i_ino, DT_DIR);
  512         if (ret < 0)
  513             goto out;
  514         result++;
  515         filp->f_pos++;
  516     }
  517     while (1) {
  518         /* read entries from the directory file */
  519         ret = kernel_read(filp, filp->f_pos - 2, (char *)vdir,
  520                   sizeof(*vdir));
  521         if (ret < 0) {
  522             printk("coda_venus_readdir: read dir failed %d\n", ret);
  523             break;
  524         }
  525         if (ret == 0) break; /* end of directory file reached */
  526 
  527         /* catch truncated reads */
  528         if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
  529             printk("coda_venus_readdir: short read: %ld\n",
  530                    filp->f_dentry->d_inode->i_ino);
  531             ret = -EBADF;
  532             break;
  533         }
  534         /* validate whether the directory file actually makes sense */
  535         if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
  536             printk("coda_venus_readdir: Invalid dir: %ld\n",
  537                    filp->f_dentry->d_inode->i_ino);
  538             ret = -EBADF;
  539             break;
  540         }
  541 
  542         name.len = vdir->d_namlen;
  543         name.name = vdir->d_name;
  544 
  545         /* Make sure we skip '.' and '..', we already got those */
  546         if (name.name[0] == '.' && (name.len == 1 ||
  547             (vdir->d_name[1] == '.' && name.len == 2)))
  548             vdir->d_fileno = name.len = 0;
  549 
  550         /* skip null entries */
  551         if (vdir->d_fileno && name.len) {
  552             /* try to look up this entry in the dcache, that way
  553              * userspace doesn't have to worry about breaking
  554              * getcwd by having mismatched inode numbers for
  555              * internal volume mountpoints. */
  556             ino = find_inode_number(dir, &name);
  557             if (!ino) ino = vdir->d_fileno;
  558 
  559             type = CDT2DT(vdir->d_type);
  560             ret = filldir(dirent, name.name, name.len, filp->f_pos,
  561                       ino, type);
  562             /* failure means no space for filling in this round */
  563             if (ret < 0) break;
  564             result++;
  565         }
  566         /* we'll always have progress because d_reclen is unsigned and
  567          * we've already established it is non-zero. */
  568         filp->f_pos += vdir->d_reclen;
  569     }
  570 out:
  571     kfree(vdir);
  572     return result ? result : ret;
  573 }
  574 
  575 /* called when a cache lookup succeeds */
  576 static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
  577 {
  578     struct inode *inode = de->d_inode;
  579     struct coda_inode_info *cii;
  580 
  581     if (!inode)
  582         return 1;
  583     lock_kernel();
  584     if (coda_isroot(inode))
  585         goto out;
  586     if (is_bad_inode(inode))
  587         goto bad;
  588 
  589     cii = ITOC(de->d_inode);
  590     if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
  591         goto out;
  592 
  593     shrink_dcache_parent(de);
  594 
  595     /* propagate for a flush */
  596     if (cii->c_flags & C_FLUSH) 
  597         coda_flag_inode_children(inode, C_FLUSH);
  598 
  599     if (atomic_read(&de->d_count) > 1)
  600         /* pretend it's valid, but don't change the flags */
  601         goto out;
  602 
  603     /* clear the flags. */
  604     cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
  605 
  606 bad:
  607     unlock_kernel();
  608     return 0;
  609 out:
  610     unlock_kernel();
  611     return 1;
  612 }
  613 
  614 /*
  615  * This is the callback from dput() when d_count is going to 0.
  616  * We use this to unhash dentries with bad inodes.
  617  */
  618 static int coda_dentry_delete(struct dentry * dentry)
  619 {
  620     int flags;
  621 
  622     if (!dentry->d_inode) 
  623         return 0;
  624 
  625     flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
  626     if (is_bad_inode(dentry->d_inode) || flags) {
  627         return 1;
  628     }
  629     return 0;
  630 }
  631 
  632 
  633 
  634 /*
  635  * This is called when we want to check if the inode has
  636  * changed on the server.  Coda makes this easy since the
  637  * cache manager Venus issues a downcall to the kernel when this 
  638  * happens 
  639  */
  640 int coda_revalidate_inode(struct dentry *dentry)
  641 {
  642     struct coda_vattr attr;
  643     int error = 0;
  644     int old_mode;
  645     ino_t old_ino;
  646     struct inode *inode = dentry->d_inode;
  647     struct coda_inode_info *cii = ITOC(inode);
  648 
  649     lock_kernel();
  650     if ( !cii->c_flags )
  651         goto ok;
  652 
  653     if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
  654         error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
  655         if ( error )
  656             goto return_bad;
  657 
  658         /* this inode may be lost if:
  659            - it's ino changed 
  660            - type changes must be permitted for repair and
  661            missing mount points.
  662         */
  663         old_mode = inode->i_mode;
  664         old_ino = inode->i_ino;
  665         coda_vattr_to_iattr(inode, &attr);
  666 
  667         if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
  668             printk("Coda: inode %ld, fid %s changed type!\n",
  669                    inode->i_ino, coda_f2s(&(cii->c_fid)));
  670         }
  671 
  672         /* the following can happen when a local fid is replaced 
  673            with a global one, here we lose and declare the inode bad */
  674         if (inode->i_ino != old_ino)
  675             goto return_bad;
  676         
  677         coda_flag_inode_children(inode, C_FLUSH);
  678         cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
  679     }
  680 
  681 ok:
  682     unlock_kernel();
  683     return 0;
  684 
  685 return_bad:
  686     unlock_kernel();
  687     return -EIO;
  688 }