Print this page
6879933 Let SMBFS support extensible attributes per. PSARC 2007/315


  51 #include <sys/signal.h>
  52 #include <sys/list.h>
  53 #include <sys/zone.h>
  54 
  55 #include <netsmb/smb.h>
  56 #include <netsmb/smb_conn.h>
  57 #include <netsmb/smb_subr.h>
  58 
  59 #include <smbfs/smbfs.h>
  60 #include <smbfs/smbfs_node.h>
  61 #include <smbfs/smbfs_subr.h>
  62 
  63 #include <vm/hat.h>
  64 #include <vm/as.h>
  65 #include <vm/page.h>
  66 #include <vm/pvn.h>
  67 #include <vm/seg.h>
  68 #include <vm/seg_map.h>
  69 #include <vm/seg_vn.h>
  70 
  71 static int smbfs_getattr_cache(vnode_t *, struct smbfattr *);
  72 static int smbfattr_to_vattr(vnode_t *, struct smbfattr *,
  73         struct vattr *);
  74 
  75 /*
  76  * The following code provide zone support in order to perform an action
  77  * for each smbfs mount in a zone.  This is also where we would add
  78  * per-zone globals and kernel threads for the smbfs module (since
  79  * they must be terminated by the shutdown callback).
  80  */
  81 
  82 struct smi_globals {
  83         kmutex_t        smg_lock;  /* lock protecting smg_list */
  84         list_t          smg_list;  /* list of SMBFS mounts in zone */
  85         boolean_t       smg_destructor_called;
  86 };
  87 typedef struct smi_globals smi_globals_t;
  88 
  89 static zone_key_t smi_list_key;
  90 
  91 /*
  92  * Attributes caching:
  93  *


 424          */
 425         mask = AT_ALL;
 426         if (vap->va_mask & (AT_UID | AT_GID)) {
 427                 if (smi->smi_flags & SMI_ACL)
 428                         (void) smbfs_acl_getids(vp, cr);
 429                 /* else leave as set in make_smbnode */
 430         } else {
 431                 mask &= ~(AT_UID | AT_GID);
 432         }
 433 
 434         /*
 435          * If we've got cached attributes, just use them;
 436          * otherwise go to the server to get attributes,
 437          * which will update the cache in the process.
 438          */
 439         error = smbfs_getattr_cache(vp, &fa);
 440         if (error)
 441                 error = smbfs_getattr_otw(vp, &fa, cr);
 442         if (error)
 443                 return (error);

 444 
 445         /*
 446          * Re. client's view of the file size, see:
 447          * smbfs_attrcache_fa, smbfs_getattr_otw
 448          */



 449 
 450         error = smbfattr_to_vattr(vp, &fa, vap);
 451         vap->va_mask = mask;
 452 
 453         return (error);
 454 }
 455 
 456 
 457 /*
 458  * Convert SMB over the wire attributes to vnode form.
 459  * Returns 0 for success, error if failed (overflow, etc).
 460  * From NFS: nattr_to_vattr()
 461  */
 462 int
 463 smbfattr_to_vattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap)
 464 {
 465         struct smbnode *np = VTOSMB(vp);
 466 
 467         /* Set va_mask in caller */
 468 
 469         /*
 470          * Take type, mode, uid, gid from the smbfs node,
 471          * which has have been updated by _getattr_otw.
 472          */
 473         vap->va_type = vp->v_type;
 474         vap->va_mode = np->n_mode;
 475 
 476         vap->va_uid = np->n_uid;
 477         vap->va_gid = np->n_gid;
 478 
 479         vap->va_fsid = vp->v_vfsp->vfs_dev;
 480         vap->va_nodeid = np->n_ino;
 481         vap->va_nlink = 1;
 482 
 483         /*
 484          * Difference from NFS here:  We cache attributes as
 485          * reported by the server, so r_attr.fa_size is the
 486          * server's idea of the file size.  This is called
 487          * for getattr, so we want to return the client's
 488          * idea of the file size.  NFS deals with that in
 489          * nfsgetattr(), the equivalent of our caller.
 490          */
 491         vap->va_size = np->r_size;
 492 
 493         /*
 494          * Times.  Note, already converted from NT to
 495          * Unix form (in the unmarshalling code).
 496          */
 497         vap->va_atime = fa->fa_atime;
 498         vap->va_mtime = fa->fa_mtime;
 499         vap->va_ctime = fa->fa_ctime;
 500 
 501         /*
 502          * rdev, blksize, seq are made up.
 503          * va_nblocks is 512 byte blocks.
 504          */
 505         vap->va_rdev = vp->v_rdev;
 506         vap->va_blksize = MAXBSIZE;
 507         vap->va_nblocks = (fsblkcnt64_t)btod(np->r_attr.fa_allocsz);
 508         vap->va_seq = 0;
 509 
 510         return (0);
 511 }
 512 










 513 

































 514 /*
 515  * SMB Client initialization and cleanup.
 516  * Much of it is per-zone now.
 517  */
 518 
 519 
 520 /* ARGSUSED */
 521 static void *
 522 smbfs_zone_init(zoneid_t zoneid)
 523 {
 524         smi_globals_t *smg;
 525 
 526         smg = kmem_alloc(sizeof (*smg), KM_SLEEP);
 527         mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL);
 528         list_create(&smg->smg_list, sizeof (smbmntinfo_t),
 529             offsetof(smbmntinfo_t, smi_zone_node));
 530         smg->smg_destructor_called = B_FALSE;
 531         return (smg);
 532 }
 533 




  51 #include <sys/signal.h>
  52 #include <sys/list.h>
  53 #include <sys/zone.h>
  54 
  55 #include <netsmb/smb.h>
  56 #include <netsmb/smb_conn.h>
  57 #include <netsmb/smb_subr.h>
  58 
  59 #include <smbfs/smbfs.h>
  60 #include <smbfs/smbfs_node.h>
  61 #include <smbfs/smbfs_subr.h>
  62 
  63 #include <vm/hat.h>
  64 #include <vm/as.h>
  65 #include <vm/page.h>
  66 #include <vm/pvn.h>
  67 #include <vm/seg.h>
  68 #include <vm/seg_map.h>
  69 #include <vm/seg_vn.h>
  70 
  71 static int smbfs_getattr_cache(vnode_t *, smbfattr_t *);
  72 static void smbfattr_to_vattr(vnode_t *, smbfattr_t *, vattr_t *);
  73 static void smbfattr_to_xvattr(vnode_t *, smbfattr_t *, vattr_t *);
  74 
  75 /*
  76  * The following code provide zone support in order to perform an action
  77  * for each smbfs mount in a zone.  This is also where we would add
  78  * per-zone globals and kernel threads for the smbfs module (since
  79  * they must be terminated by the shutdown callback).
  80  */
  81 
  82 struct smi_globals {
  83         kmutex_t        smg_lock;  /* lock protecting smg_list */
  84         list_t          smg_list;  /* list of SMBFS mounts in zone */
  85         boolean_t       smg_destructor_called;
  86 };
  87 typedef struct smi_globals smi_globals_t;
  88 
  89 static zone_key_t smi_list_key;
  90 
  91 /*
  92  * Attributes caching:
  93  *


 424          */
 425         mask = AT_ALL;
 426         if (vap->va_mask & (AT_UID | AT_GID)) {
 427                 if (smi->smi_flags & SMI_ACL)
 428                         (void) smbfs_acl_getids(vp, cr);
 429                 /* else leave as set in make_smbnode */
 430         } else {
 431                 mask &= ~(AT_UID | AT_GID);
 432         }
 433 
 434         /*
 435          * If we've got cached attributes, just use them;
 436          * otherwise go to the server to get attributes,
 437          * which will update the cache in the process.
 438          */
 439         error = smbfs_getattr_cache(vp, &fa);
 440         if (error)
 441                 error = smbfs_getattr_otw(vp, &fa, cr);
 442         if (error)
 443                 return (error);
 444         vap->va_mask |= mask;
 445 
 446         /*
 447          * Re. client's view of the file size, see:
 448          * smbfs_attrcache_fa, smbfs_getattr_otw
 449          */
 450         smbfattr_to_vattr(vp, &fa, vap);
 451         if (vap->va_mask & AT_XVATTR)
 452                 smbfattr_to_xvattr(vp, &fa, vap);
 453                 
 454         return (0);



 455 }
 456 
 457 
 458 /*
 459  * Convert SMB over the wire attributes to vnode form.
 460  * Returns 0 for success, error if failed (overflow, etc).
 461  * From NFS: nattr_to_vattr()
 462  */
 463 void
 464 smbfattr_to_vattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap)
 465 {
 466         struct smbnode *np = VTOSMB(vp);
 467 


 468         /*
 469          * Take type, mode, uid, gid from the smbfs node,
 470          * which has have been updated by _getattr_otw.
 471          */
 472         vap->va_type = vp->v_type;
 473         vap->va_mode = np->n_mode;
 474 
 475         vap->va_uid = np->n_uid;
 476         vap->va_gid = np->n_gid;
 477 
 478         vap->va_fsid = vp->v_vfsp->vfs_dev;
 479         vap->va_nodeid = np->n_ino;
 480         vap->va_nlink = 1;
 481 
 482         /*
 483          * Difference from NFS here:  We cache attributes as
 484          * reported by the server, so r_attr.fa_size is the
 485          * server's idea of the file size.  This is called
 486          * for getattr, so we want to return the client's
 487          * idea of the file size.  NFS deals with that in
 488          * nfsgetattr(), the equivalent of our caller.
 489          */
 490         vap->va_size = np->r_size;
 491 
 492         /*
 493          * Times.  Note, already converted from NT to
 494          * Unix form (in the unmarshalling code).
 495          */
 496         vap->va_atime = fa->fa_atime;
 497         vap->va_mtime = fa->fa_mtime;
 498         vap->va_ctime = fa->fa_ctime;
 499 
 500         /*
 501          * rdev, blksize, seq are made up.
 502          * va_nblocks is 512 byte blocks.
 503          */
 504         vap->va_rdev = vp->v_rdev;
 505         vap->va_blksize = MAXBSIZE;
 506         vap->va_nblocks = (fsblkcnt64_t)btod(np->r_attr.fa_allocsz);
 507         vap->va_seq = 0;


 508 }
 509 
 510 /*
 511  * smbfattr_to_xvattr: like smbfattr_to_vattr but for
 512  * Extensible system attributes (PSARC 2007/315)
 513  */
 514 static void
 515 smbfattr_to_xvattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap)
 516 {
 517         struct smbnode *np = VTOSMB(vp);
 518         xvattr_t *xvap = (xvattr_t *)vap;       /* *vap may be xvattr_t */
 519         xoptattr_t *xoap = NULL;
 520 
 521         if ((xoap = xva_getxoptattr(xvap)) == NULL)
 522                 return;
 523 
 524         if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
 525                 xoap->xoa_createtime = fa->fa_createtime;
 526                 XVA_SET_RTN(xvap, XAT_CREATETIME);
 527         }
 528 
 529         if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
 530                 xoap->xoa_archive =
 531                     ((fa->fa_attr & SMB_FA_ARCHIVE) != 0);
 532                 XVA_SET_RTN(xvap, XAT_ARCHIVE);
 533         }
 534 
 535         if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
 536                 xoap->xoa_system =
 537                     ((fa->fa_attr & SMB_FA_SYSTEM) != 0);
 538                 XVA_SET_RTN(xvap, XAT_SYSTEM);
 539         }
 540 
 541         if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
 542                 xoap->xoa_readonly =
 543                     ((fa->fa_attr & SMB_FA_RDONLY) != 0);
 544                 XVA_SET_RTN(xvap, XAT_READONLY);
 545         }
 546 
 547         if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
 548                 xoap->xoa_hidden =
 549                     ((fa->fa_attr & SMB_FA_HIDDEN) != 0);
 550                 XVA_SET_RTN(xvap, XAT_HIDDEN);
 551         }
 552 }
 553 
 554 /*
 555  * SMB Client initialization and cleanup.
 556  * Much of it is per-zone now.
 557  */
 558 
 559 
 560 /* ARGSUSED */
 561 static void *
 562 smbfs_zone_init(zoneid_t zoneid)
 563 {
 564         smi_globals_t *smg;
 565 
 566         smg = kmem_alloc(sizeof (*smg), KM_SLEEP);
 567         mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL);
 568         list_create(&smg->smg_list, sizeof (smbmntinfo_t),
 569             offsetof(smbmntinfo_t, smi_zone_node));
 570         smg->smg_destructor_called = B_FALSE;
 571         return (smg);
 572 }
 573