Print this page
Fix NFS design problems re. multiple zone keys
Make NFS server zone-specific data all have the same lifetime
Fix rfs4_clean_state_exi
Fix exi_cache_reclaim
Fix mistakes in zone keys work
More fixes re. exi_zoneid and exi_tree
(danmcd -> Keep some ASSERT()s around for readability.)


  74 typedef struct nfs3_srv {
  75         writeverf3      write3verf;
  76 } nfs3_srv_t;
  77 
  78 /*
  79  * These are the interface routines for the server side of the
  80  * Network File System.  See the NFS version 3 protocol specification
  81  * for a description of this interface.
  82  */
  83 
  84 static int      sattr3_to_vattr(sattr3 *, struct vattr *);
  85 static int      vattr_to_fattr3(struct vattr *, fattr3 *);
  86 static int      vattr_to_wcc_attr(struct vattr *, wcc_attr *);
  87 static void     vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
  88 static void     vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
  89 static int      rdma_setup_read_data3(READ3args *, READ3resok *);
  90 
  91 extern int nfs_loaned_buffers;
  92 
  93 u_longlong_t nfs3_srv_caller_id;
  94 static zone_key_t rfs3_zone_key;
  95 









  96 /* ARGSUSED */
  97 void
  98 rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
  99     struct svc_req *req, cred_t *cr, bool_t ro)
 100 {
 101         int error;
 102         vnode_t *vp;
 103         struct vattr va;
 104 
 105         vp = nfs3_fhtovp(&args->object, exi);
 106 
 107         DTRACE_NFSV3_5(op__getattr__start, struct svc_req *, req,
 108             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
 109             GETATTR3args *, args);
 110 
 111         if (vp == NULL) {
 112                 error = ESTALE;
 113                 goto out;
 114         }
 115 


1310         struct iovec *iovp;
1311         int iovcnt;
1312         int ioflag;
1313         cred_t *savecred;
1314         int in_crit = 0;
1315         int rwlock_ret = -1;
1316         caller_context_t ct;
1317 
1318         vp = nfs3_fhtovp(&args->file, exi);
1319 
1320         DTRACE_NFSV3_5(op__write__start, struct svc_req *, req,
1321             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1322             WRITE3args *, args);
1323 
1324         if (vp == NULL) {
1325                 error = ESTALE;
1326                 goto err;
1327         }
1328 
1329         ASSERT3P(curzone, ==, exi->exi_zone); /* exi is guaranteed non-NULL. */
1330         ns = zone_getspecific(rfs3_zone_key, curzone);

1331         if (is_system_labeled()) {
1332                 bslabel_t *clabel = req->rq_label;
1333 
1334                 ASSERT(clabel != NULL);
1335                 DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
1336                     "got client label from request(1)", struct svc_req *, req);
1337 
1338                 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1339                         if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1340                             exi)) {
1341                                 resp->status = NFS3ERR_ACCES;
1342                                 goto err1;
1343                         }
1344                 }
1345         }
1346 
1347         ct.cc_sysid = 0;
1348         ct.cc_pid = 0;
1349         ct.cc_caller_id = nfs3_srv_caller_id;
1350         ct.cc_flags = CC_DONTBLOCK;


4111         struct vattr *bvap;
4112         struct vattr bva;
4113         struct vattr *avap;
4114         struct vattr ava;
4115 
4116         bvap = NULL;
4117         avap = NULL;
4118 
4119         vp = nfs3_fhtovp(&args->file, exi);
4120 
4121         DTRACE_NFSV3_5(op__commit__start, struct svc_req *, req,
4122             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4123             COMMIT3args *, args);
4124 
4125         if (vp == NULL) {
4126                 error = ESTALE;
4127                 goto out;
4128         }
4129 
4130         ASSERT3P(curzone, ==, exi->exi_zone); /* exi is guaranteed non-NULL. */
4131         ns = zone_getspecific(rfs3_zone_key, curzone);
4132         bva.va_mask = AT_ALL;
4133         error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4134 
4135         /*
4136          * If we can't get the attributes, then we can't do the
4137          * right access checking.  So, we'll fail the request.
4138          */
4139         if (error)
4140                 goto out;
4141 
4142         bvap = &bva;
4143 
4144         if (rdonly(ro, vp)) {
4145                 resp->status = NFS3ERR_ROFS;
4146                 goto out1;
4147         }
4148 
4149         if (vp->v_type != VREG) {
4150                 resp->status = NFS3ERR_INVAL;
4151                 goto out1;


4364         vattr_to_post_op_attr(avap, &wccp->after);
4365 }
4366 
4367 static int
4368 rdma_setup_read_data3(READ3args *args, READ3resok *rok)
4369 {
4370         struct clist    *wcl;
4371         int             wlist_len;
4372         count3          count = rok->count;
4373 
4374         wcl = args->wlist;
4375         if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE)
4376                 return (FALSE);
4377 
4378         wcl = args->wlist;
4379         rok->wlist_len = wlist_len;
4380         rok->wlist = wcl;
4381         return (TRUE);
4382 }
4383 
4384 /* ARGSUSED */
4385 static void *
4386 rfs3_zone_init(zoneid_t zoneid)
4387 {
4388         nfs3_srv_t *ns;
4389         struct rfs3_verf_overlay {
4390                 uint_t id; /* a "unique" identifier */
4391                 int ts; /* a unique timestamp */
4392         } *verfp;
4393         timestruc_t now;
4394 
4395         ns = kmem_zalloc(sizeof (*ns), KM_SLEEP);
4396 
4397         /*
4398          * The following algorithm attempts to find a unique verifier
4399          * to be used as the write verifier returned from the server
4400          * to the client.  It is important that this verifier change
4401          * whenever the server reboots.  Of secondary importance, it
4402          * is important for the verifier to be unique between two
4403          * different servers.
4404          *
4405          * Thus, an attempt is made to use the system hostid and the
4406          * current time in seconds when the nfssrv kernel module is


4411          * time the server reboots and minimize the chances that two
4412          * different servers will have the same verifier.
4413          */
4414 
4415 #ifndef lint
4416         /*
4417          * We ASSERT that this constant logic expression is
4418          * always true because in the past, it wasn't.
4419          */
4420         ASSERT(sizeof (*verfp) <= sizeof (ns->write3verf));
4421 #endif
4422 
4423         gethrestime(&now);
4424         verfp = (struct rfs3_verf_overlay *)&ns->write3verf;
4425         verfp->ts = (int)now.tv_sec;
4426         verfp->id = zone_get_hostid(NULL);
4427 
4428         if (verfp->id == 0)
4429                 verfp->id = (uint_t)now.tv_nsec;
4430 
4431         return (ns);
4432 }
4433 
4434 /* ARGSUSED */
4435 static void
4436 rfs3_zone_fini(zoneid_t zoneid, void *data)
4437 {
4438         nfs3_srv_t *ns = data;
4439 


4440         kmem_free(ns, sizeof (*ns));
4441 }
4442 
4443 void
4444 rfs3_srvrinit(void)
4445 {
4446         nfs3_srv_caller_id = fs_new_caller_id();
4447         zone_key_create(&rfs3_zone_key, rfs3_zone_init, NULL, rfs3_zone_fini);
4448 }
4449 
4450 void
4451 rfs3_srvrfini(void)
4452 {
4453         /* Nothing to do */
4454 }


  74 typedef struct nfs3_srv {
  75         writeverf3      write3verf;
  76 } nfs3_srv_t;
  77 
  78 /*
  79  * These are the interface routines for the server side of the
  80  * Network File System.  See the NFS version 3 protocol specification
  81  * for a description of this interface.
  82  */
  83 
  84 static int      sattr3_to_vattr(sattr3 *, struct vattr *);
  85 static int      vattr_to_fattr3(struct vattr *, fattr3 *);
  86 static int      vattr_to_wcc_attr(struct vattr *, wcc_attr *);
  87 static void     vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
  88 static void     vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
  89 static int      rdma_setup_read_data3(READ3args *, READ3resok *);
  90 
  91 extern int nfs_loaned_buffers;
  92 
  93 u_longlong_t nfs3_srv_caller_id;

  94 
  95 static nfs3_srv_t *
  96 nfs3_get_srv(void)
  97 {
  98         nfs_globals_t *ng = zone_getspecific(nfssrv_zone_key, curzone);
  99         nfs3_srv_t *srv = ng->nfs3_srv;
 100         ASSERT(srv != NULL);
 101         return (srv);
 102 }
 103 
 104 /* ARGSUSED */
 105 void
 106 rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
 107     struct svc_req *req, cred_t *cr, bool_t ro)
 108 {
 109         int error;
 110         vnode_t *vp;
 111         struct vattr va;
 112 
 113         vp = nfs3_fhtovp(&args->object, exi);
 114 
 115         DTRACE_NFSV3_5(op__getattr__start, struct svc_req *, req,
 116             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
 117             GETATTR3args *, args);
 118 
 119         if (vp == NULL) {
 120                 error = ESTALE;
 121                 goto out;
 122         }
 123 


1318         struct iovec *iovp;
1319         int iovcnt;
1320         int ioflag;
1321         cred_t *savecred;
1322         int in_crit = 0;
1323         int rwlock_ret = -1;
1324         caller_context_t ct;
1325 
1326         vp = nfs3_fhtovp(&args->file, exi);
1327 
1328         DTRACE_NFSV3_5(op__write__start, struct svc_req *, req,
1329             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1330             WRITE3args *, args);
1331 
1332         if (vp == NULL) {
1333                 error = ESTALE;
1334                 goto err;
1335         }
1336 
1337         ASSERT3P(curzone, ==, exi->exi_zone); /* exi is guaranteed non-NULL. */
1338         ns = nfs3_get_srv();
1339 
1340         if (is_system_labeled()) {
1341                 bslabel_t *clabel = req->rq_label;
1342 
1343                 ASSERT(clabel != NULL);
1344                 DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
1345                     "got client label from request(1)", struct svc_req *, req);
1346 
1347                 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1348                         if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1349                             exi)) {
1350                                 resp->status = NFS3ERR_ACCES;
1351                                 goto err1;
1352                         }
1353                 }
1354         }
1355 
1356         ct.cc_sysid = 0;
1357         ct.cc_pid = 0;
1358         ct.cc_caller_id = nfs3_srv_caller_id;
1359         ct.cc_flags = CC_DONTBLOCK;


4120         struct vattr *bvap;
4121         struct vattr bva;
4122         struct vattr *avap;
4123         struct vattr ava;
4124 
4125         bvap = NULL;
4126         avap = NULL;
4127 
4128         vp = nfs3_fhtovp(&args->file, exi);
4129 
4130         DTRACE_NFSV3_5(op__commit__start, struct svc_req *, req,
4131             cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4132             COMMIT3args *, args);
4133 
4134         if (vp == NULL) {
4135                 error = ESTALE;
4136                 goto out;
4137         }
4138 
4139         ASSERT3P(curzone, ==, exi->exi_zone); /* exi is guaranteed non-NULL. */
4140         ns = nfs3_get_srv();
4141         bva.va_mask = AT_ALL;
4142         error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4143 
4144         /*
4145          * If we can't get the attributes, then we can't do the
4146          * right access checking.  So, we'll fail the request.
4147          */
4148         if (error)
4149                 goto out;
4150 
4151         bvap = &bva;
4152 
4153         if (rdonly(ro, vp)) {
4154                 resp->status = NFS3ERR_ROFS;
4155                 goto out1;
4156         }
4157 
4158         if (vp->v_type != VREG) {
4159                 resp->status = NFS3ERR_INVAL;
4160                 goto out1;


4373         vattr_to_post_op_attr(avap, &wccp->after);
4374 }
4375 
4376 static int
4377 rdma_setup_read_data3(READ3args *args, READ3resok *rok)
4378 {
4379         struct clist    *wcl;
4380         int             wlist_len;
4381         count3          count = rok->count;
4382 
4383         wcl = args->wlist;
4384         if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE)
4385                 return (FALSE);
4386 
4387         wcl = args->wlist;
4388         rok->wlist_len = wlist_len;
4389         rok->wlist = wcl;
4390         return (TRUE);
4391 }
4392 
4393 void
4394 rfs3_srv_zone_init(nfs_globals_t *ng)

4395 {
4396         nfs3_srv_t *ns;
4397         struct rfs3_verf_overlay {
4398                 uint_t id; /* a "unique" identifier */
4399                 int ts; /* a unique timestamp */
4400         } *verfp;
4401         timestruc_t now;
4402 
4403         ns = kmem_zalloc(sizeof (*ns), KM_SLEEP);
4404 
4405         /*
4406          * The following algorithm attempts to find a unique verifier
4407          * to be used as the write verifier returned from the server
4408          * to the client.  It is important that this verifier change
4409          * whenever the server reboots.  Of secondary importance, it
4410          * is important for the verifier to be unique between two
4411          * different servers.
4412          *
4413          * Thus, an attempt is made to use the system hostid and the
4414          * current time in seconds when the nfssrv kernel module is


4419          * time the server reboots and minimize the chances that two
4420          * different servers will have the same verifier.
4421          */
4422 
4423 #ifndef lint
4424         /*
4425          * We ASSERT that this constant logic expression is
4426          * always true because in the past, it wasn't.
4427          */
4428         ASSERT(sizeof (*verfp) <= sizeof (ns->write3verf));
4429 #endif
4430 
4431         gethrestime(&now);
4432         verfp = (struct rfs3_verf_overlay *)&ns->write3verf;
4433         verfp->ts = (int)now.tv_sec;
4434         verfp->id = zone_get_hostid(NULL);
4435 
4436         if (verfp->id == 0)
4437                 verfp->id = (uint_t)now.tv_nsec;
4438 
4439         ng->nfs3_srv = ns;
4440 }
4441 
4442 void
4443 rfs3_srv_zone_fini(nfs_globals_t *ng)

4444 {
4445         nfs3_srv_t *ns = ng->nfs3_srv;
4446 
4447         ng->nfs3_srv = NULL;
4448 
4449         kmem_free(ns, sizeof (*ns));
4450 }
4451 
4452 void
4453 rfs3_srvrinit(void)
4454 {
4455         nfs3_srv_caller_id = fs_new_caller_id();

4456 }
4457 
4458 void
4459 rfs3_srvrfini(void)
4460 {
4461         /* Nothing to do */
4462 }