The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/smbfs/dir.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  dir.c
    3  *
    4  *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
    5  *  Copyright (C) 1997 by Volker Lendecke
    6  *
    7  *  Please add a note about your changes to smbfs in the ChangeLog file.
    8  */
    9 
   10 #include <linux/sched.h>
   11 #include <linux/errno.h>
   12 #include <linux/kernel.h>
   13 #include <linux/smp_lock.h>
   14 #include <linux/ctype.h>
   15 
   16 #include <linux/smb_fs.h>
   17 #include <linux/smb_mount.h>
   18 #include <linux/smbno.h>
   19 
   20 #include "smb_debug.h"
   21 #include "proto.h"
   22 
   23 static int smb_readdir(struct file *, void *, filldir_t);
   24 static int smb_dir_open(struct inode *, struct file *);
   25 
   26 static struct dentry *smb_lookup(struct inode *, struct dentry *);
   27 static int smb_create(struct inode *, struct dentry *, int);
   28 static int smb_mkdir(struct inode *, struct dentry *, int);
   29 static int smb_rmdir(struct inode *, struct dentry *);
   30 static int smb_unlink(struct inode *, struct dentry *);
   31 static int smb_rename(struct inode *, struct dentry *,
   32                       struct inode *, struct dentry *);
   33 
   34 struct file_operations smb_dir_operations =
   35 {
   36         read:           generic_read_dir,
   37         readdir:        smb_readdir,
   38         ioctl:          smb_ioctl,
   39         open:           smb_dir_open,
   40 };
   41 
   42 struct inode_operations smb_dir_inode_operations =
   43 {
   44         create:         smb_create,
   45         lookup:         smb_lookup,
   46         unlink:         smb_unlink,
   47         mkdir:          smb_mkdir,
   48         rmdir:          smb_rmdir,
   49         rename:         smb_rename,
   50         revalidate:     smb_revalidate_inode,
   51         setattr:        smb_notify_change,
   52 };
   53 
   54 /*
   55  * Read a directory, using filldir to fill the dirent memory.
   56  * smb_proc_readdir does the actual reading from the smb server.
   57  *
   58  * The cache code is almost directly taken from ncpfs
   59  */
   60 static int 
   61 smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
   62 {
   63         struct dentry *dentry = filp->f_dentry;
   64         struct inode *dir = dentry->d_inode;
   65         struct smb_sb_info *server = server_from_dentry(dentry);
   66         union  smb_dir_cache *cache = NULL;
   67         struct smb_cache_control ctl;
   68         struct page *page = NULL;
   69         int result;
   70 
   71         ctl.page  = NULL;
   72         ctl.cache = NULL;
   73 
   74         VERBOSE("reading %s/%s, f_pos=%d\n",
   75                 DENTRY_PATH(dentry),  (int) filp->f_pos);
   76 
   77         result = 0;
   78         switch ((unsigned int) filp->f_pos) {
   79         case 0:
   80                 if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
   81                         goto out;
   82                 filp->f_pos = 1;
   83                 /* fallthrough */
   84         case 1:
   85                 if (filldir(dirent, "..", 2, 1,
   86                             dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
   87                         goto out;
   88                 filp->f_pos = 2;
   89         }
   90 
   91         /*
   92          * Make sure our inode is up-to-date.
   93          */
   94         result = smb_revalidate_inode(dentry);
   95         if (result)
   96                 goto out;
   97 
   98 
   99         page = grab_cache_page(&dir->i_data, 0);
  100         if (!page)
  101                 goto read_really;
  102 
  103         ctl.cache = cache = kmap(page);
  104         ctl.head  = cache->head;
  105 
  106         if (!Page_Uptodate(page) || !ctl.head.eof) {
  107                 VERBOSE("%s/%s, page uptodate=%d, eof=%d\n",
  108                          DENTRY_PATH(dentry), Page_Uptodate(page),ctl.head.eof);
  109                 goto init_cache;
  110         }
  111 
  112         if (filp->f_pos == 2) {
  113                 if (jiffies - ctl.head.time >= SMB_MAX_AGE(server))
  114                         goto init_cache;
  115 
  116                 /*
  117                  * N.B. ncpfs checks mtime of dentry too here, we don't.
  118                  *   1. common smb servers do not update mtime on dir changes
  119                  *   2. it requires an extra smb request
  120                  *      (revalidate has the same timeout as ctl.head.time)
  121                  *
  122                  * Instead smbfs invalidates its own cache on local changes
  123                  * and remote changes are not seen until timeout.
  124                  */
  125         }
  126 
  127         if (filp->f_pos > ctl.head.end)
  128                 goto finished;
  129 
  130         ctl.fpos = filp->f_pos + (SMB_DIRCACHE_START - 2);
  131         ctl.ofs  = ctl.fpos / SMB_DIRCACHE_SIZE;
  132         ctl.idx  = ctl.fpos % SMB_DIRCACHE_SIZE;
  133 
  134         for (;;) {
  135                 if (ctl.ofs != 0) {
  136                         ctl.page = find_lock_page(&dir->i_data, ctl.ofs);
  137                         if (!ctl.page)
  138                                 goto invalid_cache;
  139                         ctl.cache = kmap(ctl.page);
  140                         if (!Page_Uptodate(ctl.page))
  141                                 goto invalid_cache;
  142                 }
  143                 while (ctl.idx < SMB_DIRCACHE_SIZE) {
  144                         struct dentry *dent;
  145                         int res;
  146 
  147                         dent = smb_dget_fpos(ctl.cache->dentry[ctl.idx],
  148                                              dentry, filp->f_pos);
  149                         if (!dent)
  150                                 goto invalid_cache;
  151 
  152                         res = filldir(dirent, dent->d_name.name,
  153                                       dent->d_name.len, filp->f_pos,
  154                                       dent->d_inode->i_ino, DT_UNKNOWN);
  155                         dput(dent);
  156                         if (res)
  157                                 goto finished;
  158                         filp->f_pos += 1;
  159                         ctl.idx += 1;
  160                         if (filp->f_pos > ctl.head.end)
  161                                 goto finished;
  162                 }
  163                 if (ctl.page) {
  164                         kunmap(ctl.page);
  165                         SetPageUptodate(ctl.page);
  166                         UnlockPage(ctl.page);
  167                         page_cache_release(ctl.page);
  168                         ctl.page = NULL;
  169                 }
  170                 ctl.idx  = 0;
  171                 ctl.ofs += 1;
  172         }
  173 invalid_cache:
  174         if (ctl.page) {
  175                 kunmap(ctl.page);
  176                 UnlockPage(ctl.page);
  177                 page_cache_release(ctl.page);
  178                 ctl.page = NULL;
  179         }
  180         ctl.cache = cache;
  181 init_cache:
  182         smb_invalidate_dircache_entries(dentry);
  183         ctl.head.time = jiffies;
  184         ctl.head.eof = 0;
  185         ctl.fpos = 2;
  186         ctl.ofs = 0;
  187         ctl.idx = SMB_DIRCACHE_START;
  188         ctl.filled = 0;
  189         ctl.valid  = 1;
  190 read_really:
  191         result = smb_proc_readdir(filp, dirent, filldir, &ctl);
  192         if (ctl.idx == -1)
  193                 goto invalid_cache;     /* retry */
  194         ctl.head.end = ctl.fpos - 1;
  195         ctl.head.eof = ctl.valid;
  196 finished:
  197         if (page) {
  198                 cache->head = ctl.head;
  199                 kunmap(page);
  200                 SetPageUptodate(page);
  201                 UnlockPage(page);
  202                 page_cache_release(page);
  203         }
  204         if (ctl.page) {
  205                 kunmap(ctl.page);
  206                 SetPageUptodate(ctl.page);
  207                 UnlockPage(ctl.page);
  208                 page_cache_release(ctl.page);
  209         }
  210 out:
  211         return result;
  212 }
  213 
  214 static int
  215 smb_dir_open(struct inode *dir, struct file *file)
  216 {
  217         struct dentry *dentry = file->f_dentry;
  218         struct smb_sb_info *server;
  219         int error = 0;
  220 
  221         VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
  222                 file->f_dentry->d_name.name);
  223 
  224         /*
  225          * Directory timestamps in the core protocol aren't updated
  226          * when a file is added, so we give them a very short TTL.
  227          */
  228         lock_kernel();
  229         server = server_from_dentry(dentry);
  230         if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
  231                 unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
  232                 if (age > 2*HZ)
  233                         smb_invalid_dir_cache(dir);
  234         }
  235 
  236         /*
  237          * Note: in order to allow the smbmount process to open the
  238          * mount point, we only revalidate if the connection is valid or
  239          * if the process is trying to access something other than the root.
  240          */
  241         if (server->state == CONN_VALID || !IS_ROOT(dentry))
  242                 error = smb_revalidate_inode(dentry);
  243         unlock_kernel();
  244         return error;
  245 }
  246 
  247 /*
  248  * Dentry operations routines
  249  */
  250 static int smb_lookup_validate(struct dentry *, int);
  251 static int smb_hash_dentry(struct dentry *, struct qstr *);
  252 static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
  253 static int smb_delete_dentry(struct dentry *);
  254 
  255 static struct dentry_operations smbfs_dentry_operations =
  256 {
  257         d_revalidate:   smb_lookup_validate,
  258         d_hash:         smb_hash_dentry,
  259         d_compare:      smb_compare_dentry,
  260         d_delete:       smb_delete_dentry,
  261 };
  262 
  263 static struct dentry_operations smbfs_dentry_operations_case =
  264 {
  265         d_revalidate:   smb_lookup_validate,
  266         d_delete:       smb_delete_dentry,
  267 };
  268 
  269 
  270 /*
  271  * This is the callback when the dcache has a lookup hit.
  272  */
  273 static int
  274 smb_lookup_validate(struct dentry * dentry, int flags)
  275 {
  276         struct smb_sb_info *server = server_from_dentry(dentry);
  277         struct inode * inode = dentry->d_inode;
  278         unsigned long age = jiffies - dentry->d_time;
  279         int valid;
  280 
  281         /*
  282          * The default validation is based on dentry age:
  283          * we believe in dentries for a few seconds.  (But each
  284          * successful server lookup renews the timestamp.)
  285          */
  286         valid = (age <= SMB_MAX_AGE(server));
  287 #ifdef SMBFS_DEBUG_VERBOSE
  288         if (!valid)
  289                 VERBOSE("%s/%s not valid, age=%lu\n", 
  290                         DENTRY_PATH(dentry), age);
  291 #endif
  292 
  293         if (inode) {
  294                 lock_kernel();
  295                 if (is_bad_inode(inode)) {
  296                         PARANOIA("%s/%s has dud inode\n", DENTRY_PATH(dentry));
  297                         valid = 0;
  298                 } else if (!valid)
  299                         valid = (smb_revalidate_inode(dentry) == 0);
  300                 unlock_kernel();
  301         } else {
  302                 /*
  303                  * What should we do for negative dentries?
  304                  */
  305         }
  306         return valid;
  307 }
  308 
  309 static int 
  310 smb_hash_dentry(struct dentry *dir, struct qstr *this)
  311 {
  312         unsigned long hash;
  313         int i;
  314 
  315         hash = init_name_hash();
  316         for (i=0; i < this->len ; i++)
  317                 hash = partial_name_hash(tolower(this->name[i]), hash);
  318         this->hash = end_name_hash(hash);
  319   
  320         return 0;
  321 }
  322 
  323 static int
  324 smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
  325 {
  326         int i, result = 1;
  327 
  328         if (a->len != b->len)
  329                 goto out;
  330         for (i=0; i < a->len; i++) {
  331                 if (tolower(a->name[i]) != tolower(b->name[i]))
  332                         goto out;
  333         }
  334         result = 0;
  335 out:
  336         return result;
  337 }
  338 
  339 /*
  340  * This is the callback from dput() when d_count is going to 0.
  341  * We use this to unhash dentries with bad inodes.
  342  */
  343 static int
  344 smb_delete_dentry(struct dentry * dentry)
  345 {
  346         if (dentry->d_inode) {
  347                 if (is_bad_inode(dentry->d_inode)) {
  348                         PARANOIA("bad inode, unhashing %s/%s\n",
  349                                  DENTRY_PATH(dentry));
  350                         return 1;
  351                 }
  352         } else {
  353                 /* N.B. Unhash negative dentries? */
  354         }
  355         return 0;
  356 }
  357 
  358 /*
  359  * Initialize a new dentry
  360  */
  361 void
  362 smb_new_dentry(struct dentry *dentry)
  363 {
  364         struct smb_sb_info *server = server_from_dentry(dentry);
  365 
  366         if (server->mnt->flags & SMB_MOUNT_CASE)
  367                 dentry->d_op = &smbfs_dentry_operations_case;
  368         else
  369                 dentry->d_op = &smbfs_dentry_operations;
  370         dentry->d_time = jiffies;
  371 }
  372 
  373 
  374 /*
  375  * Whenever a lookup succeeds, we know the parent directories
  376  * are all valid, so we want to update the dentry timestamps.
  377  * N.B. Move this to dcache?
  378  */
  379 void
  380 smb_renew_times(struct dentry * dentry)
  381 {
  382         for (;;) {
  383                 dentry->d_time = jiffies;
  384                 if (IS_ROOT(dentry))
  385                         break;
  386                 dentry = dentry->d_parent;
  387         }
  388 }
  389 
  390 static struct dentry *
  391 smb_lookup(struct inode *dir, struct dentry *dentry)
  392 {
  393         struct smb_fattr finfo;
  394         struct inode *inode;
  395         int error;
  396         struct smb_sb_info *server;
  397 
  398         error = -ENAMETOOLONG;
  399         if (dentry->d_name.len > SMB_MAXNAMELEN)
  400                 goto out;
  401 
  402         error = smb_proc_getattr(dentry, &finfo);
  403 #ifdef SMBFS_PARANOIA
  404         if (error && error != -ENOENT)
  405                 PARANOIA("find %s/%s failed, error=%d\n",
  406                          DENTRY_PATH(dentry), error);
  407 #endif
  408 
  409         inode = NULL;
  410         if (error == -ENOENT)
  411                 goto add_entry;
  412         if (!error) {
  413                 error = -EACCES;
  414                 finfo.f_ino = iunique(dentry->d_sb, 2);
  415                 inode = smb_iget(dir->i_sb, &finfo);
  416                 if (inode) {
  417         add_entry:
  418                         server = server_from_dentry(dentry);
  419                         if (server->mnt->flags & SMB_MOUNT_CASE)
  420                                 dentry->d_op = &smbfs_dentry_operations_case;
  421                         else
  422                                 dentry->d_op = &smbfs_dentry_operations;
  423 
  424                         d_add(dentry, inode);
  425                         smb_renew_times(dentry);
  426                         error = 0;
  427                 }
  428         }
  429 out:
  430         return ERR_PTR(error);
  431 }
  432 
  433 /*
  434  * This code is common to all routines creating a new inode.
  435  */
  436 static int
  437 smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
  438 {
  439         struct smb_sb_info *server = server_from_dentry(dentry);
  440         struct inode *inode;
  441         int error;
  442         struct smb_fattr fattr;
  443 
  444         VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid);
  445 
  446         error = smb_proc_getattr(dentry, &fattr);
  447         if (error)
  448                 goto out_close;
  449 
  450         smb_renew_times(dentry);
  451         fattr.f_ino = iunique(dentry->d_sb, 2);
  452         inode = smb_iget(dentry->d_sb, &fattr);
  453         if (!inode)
  454                 goto out_no_inode;
  455 
  456         if (have_id) {
  457                 inode->u.smbfs_i.fileid = fileid;
  458                 inode->u.smbfs_i.access = SMB_O_RDWR;
  459                 inode->u.smbfs_i.open = server->generation;
  460         }
  461         d_instantiate(dentry, inode);
  462 out:
  463         return error;
  464 
  465 out_no_inode:
  466         error = -EACCES;
  467 out_close:
  468         if (have_id) {
  469                 PARANOIA("%s/%s failed, error=%d, closing %u\n",
  470                          DENTRY_PATH(dentry), error, fileid);
  471                 smb_close_fileid(dentry, fileid);
  472         }
  473         goto out;
  474 }
  475 
  476 /* N.B. How should the mode argument be used? */
  477 static int
  478 smb_create(struct inode *dir, struct dentry *dentry, int mode)
  479 {
  480         __u16 fileid;
  481         int error;
  482 
  483         VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode);
  484 
  485         smb_invalid_dir_cache(dir);
  486         error = smb_proc_create(dentry, 0, CURRENT_TIME, &fileid);
  487         if (!error) {
  488                 error = smb_instantiate(dentry, fileid, 1);
  489         } else {
  490                 PARANOIA("%s/%s failed, error=%d\n",
  491                          DENTRY_PATH(dentry), error);
  492         }
  493         return error;
  494 }
  495 
  496 /* N.B. How should the mode argument be used? */
  497 static int
  498 smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  499 {
  500         int error;
  501 
  502         smb_invalid_dir_cache(dir);
  503         error = smb_proc_mkdir(dentry);
  504         if (!error) {
  505                 error = smb_instantiate(dentry, 0, 0);
  506         }
  507         return error;
  508 }
  509 
  510 static int
  511 smb_rmdir(struct inode *dir, struct dentry *dentry)
  512 {
  513         struct inode *inode = dentry->d_inode;
  514         int error;
  515 
  516         /*
  517          * Close the directory if it's open.
  518          */
  519         smb_close(inode);
  520 
  521         /*
  522          * Check that nobody else is using the directory..
  523          */
  524         error = -EBUSY;
  525         if (!d_unhashed(dentry))
  526                 goto out;
  527 
  528         smb_invalid_dir_cache(dir);
  529         error = smb_proc_rmdir(dentry);
  530 
  531 out:
  532         return error;
  533 }
  534 
  535 static int
  536 smb_unlink(struct inode *dir, struct dentry *dentry)
  537 {
  538         int error;
  539 
  540         /*
  541          * Close the file if it's open.
  542          */
  543         smb_close(dentry->d_inode);
  544 
  545         smb_invalid_dir_cache(dir);
  546         error = smb_proc_unlink(dentry);
  547         if (!error)
  548                 smb_renew_times(dentry);
  549         return error;
  550 }
  551 
  552 static int
  553 smb_rename(struct inode *old_dir, struct dentry *old_dentry,
  554            struct inode *new_dir, struct dentry *new_dentry)
  555 {
  556         int error;
  557 
  558         /*
  559          * Close any open files, and check whether to delete the
  560          * target before attempting the rename.
  561          */
  562         if (old_dentry->d_inode)
  563                 smb_close(old_dentry->d_inode);
  564         if (new_dentry->d_inode) {
  565                 smb_close(new_dentry->d_inode);
  566                 error = smb_proc_unlink(new_dentry);
  567                 if (error) {
  568                         VERBOSE("unlink %s/%s, error=%d\n",
  569                                 DENTRY_PATH(new_dentry), error);
  570                         goto out;
  571                 }
  572                 /* FIXME */
  573                 d_delete(new_dentry);
  574         }
  575 
  576         smb_invalid_dir_cache(old_dir);
  577         smb_invalid_dir_cache(new_dir);
  578         error = smb_proc_mv(old_dentry, new_dentry);
  579         if (!error) {
  580                 smb_renew_times(old_dentry);
  581                 smb_renew_times(new_dentry);
  582         }
  583 out:
  584         return error;
  585 }

Cache object: a7e60ca5295541bbc98ebae1336d2f1e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.