+
+/*
+ * Unlock a group of NFS nodes
+ */
+void
+nfs_unlock4(nfsnode_t np1, nfsnode_t np2, nfsnode_t np3, nfsnode_t np4)
+{
+ nfsnode_t list[4];
+ int i, k = 0;
+
+ if (np1) {
+ nfs_unlock(np1);
+ list[k++] = np1;
+ }
+ if (np2) {
+ for (i = 0; i < k; ++i)
+ if (list[i] == np2)
+ goto skip2;
+ nfs_unlock(np2);
+ list[k++] = np2;
+ }
+skip2:
+ if (np3) {
+ for (i = 0; i < k; ++i)
+ if (list[i] == np3)
+ goto skip3;
+ nfs_unlock(np3);
+ list[k++] = np3;
+ }
+skip3:
+ if (np4) {
+ for (i = 0; i < k; ++i)
+ if (list[i] == np4)
+ return;
+ nfs_unlock(np4);
+ }
+}
+
+/*
+ * Acquire an NFS node data lock
+ */
+void
+nfs_data_lock(nfsnode_t np, int locktype)
+{
+ nfs_data_lock2(np, locktype, 1);
+}
+void
+nfs_data_lock2(nfsnode_t np, int locktype, int updatesize)
+{
+ FSDBG_TOP(270, np, locktype, np->n_datalockowner, 0);
+ if (locktype == NFS_NODE_LOCK_SHARED) {
+ if (updatesize && ISSET(np->n_flag, NUPDATESIZE))
+ nfs_data_update_size(np, 0);
+ lck_rw_lock_shared(&np->n_datalock);
+ } else {
+ lck_rw_lock_exclusive(&np->n_datalock);
+ np->n_datalockowner = current_thread();
+ if (updatesize && ISSET(np->n_flag, NUPDATESIZE))
+ nfs_data_update_size(np, 1);
+ }
+ FSDBG_BOT(270, np, locktype, np->n_datalockowner, 0);
+}
+
+/*
+ * Release an NFS node data lock
+ */
+void
+nfs_data_unlock(nfsnode_t np)
+{
+ nfs_data_unlock2(np, 1);
+}
+void
+nfs_data_unlock2(nfsnode_t np, int updatesize)
+{
+ int mine = (np->n_datalockowner == current_thread());
+ FSDBG_TOP(271, np, np->n_datalockowner, current_thread(), 0);
+ if (updatesize && mine && ISSET(np->n_flag, NUPDATESIZE))
+ nfs_data_update_size(np, 1);
+ np->n_datalockowner = NULL;
+ lck_rw_done(&np->n_datalock);
+ if (updatesize && !mine && ISSET(np->n_flag, NUPDATESIZE))
+ nfs_data_update_size(np, 0);
+ FSDBG_BOT(271, np, np->n_datalockowner, current_thread(), 0);
+}
+
+
+/*
+ * update an NFS node's size
+ */
+void
+nfs_data_update_size(nfsnode_t np, int datalocked)
+{
+ int error;
+
+ FSDBG_TOP(272, np, np->n_flag, np->n_size, np->n_newsize);
+ if (!datalocked) {
+ nfs_data_lock(np, NFS_NODE_LOCK_EXCLUSIVE);
+ /* grabbing data lock will automatically update size */
+ nfs_data_unlock(np);
+ FSDBG_BOT(272, np, np->n_flag, np->n_size, np->n_newsize);
+ return;
+ }
+ error = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE);
+ if (error || !ISSET(np->n_flag, NUPDATESIZE)) {
+ if (!error)
+ nfs_unlock(np);
+ FSDBG_BOT(272, np, np->n_flag, np->n_size, np->n_newsize);
+ return;
+ }
+ CLR(np->n_flag, NUPDATESIZE);
+ np->n_size = np->n_newsize;
+ /* make sure we invalidate buffers the next chance we get */
+ SET(np->n_flag, NNEEDINVALIDATE);
+ nfs_unlock(np);
+ ubc_setsize(NFSTOV(np), (off_t)np->n_size); /* XXX error? */
+ FSDBG_BOT(272, np, np->n_flag, np->n_size, np->n_newsize);
+}
+