Print this page
NEX-3758 Support for remote stale lock detection
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/flock.c
          +++ new/usr/src/uts/common/os/flock.c
↓ open down ↓ 20 lines elided ↑ open up ↑
  21   21  
  22   22  /*
  23   23   * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  28   28  /*      All Rights Reserved */
  29   29  
  30   30  /*
  31      - * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
       31 + * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  32   32   * Copyright 2015 Joyent, Inc.
  33   33   */
  34   34  
  35   35  #include <sys/flock_impl.h>
  36   36  #include <sys/vfs.h>
  37   37  #include <sys/t_lock.h>         /* for <sys/callb.h> */
  38   38  #include <sys/callb.h>
  39   39  #include <sys/clconf.h>
  40   40  #include <sys/cladm.h>
  41   41  #include <sys/nbmlock.h>
  42   42  #include <sys/cred.h>
  43   43  #include <sys/policy.h>
       44 +#include <sys/list.h>
       45 +#include <sys/sysmacros.h>
       46 +#include <sys/socket.h>
       47 +#include <inet/ip.h>
  44   48  
  45   49  /*
  46   50   * The following four variables are for statistics purposes and they are
  47   51   * not protected by locks. They may not be accurate but will at least be
  48   52   * close to the actual value.
  49   53   */
  50   54  
  51   55  int     flk_lock_allocs;
  52   56  int     flk_lock_frees;
  53   57  int     edge_allocs;
↓ open down ↓ 98 lines elided ↑ open up ↑
 152  156   * requests.  The global copy is used to initialize the per-graph field when a
 153  157   * new graph is created.
 154  158   */
 155  159  struct flock_globals {
 156  160          flk_lockmgr_status_t flk_lockmgr_status;
 157  161          flk_lockmgr_status_t lockmgr_status[HASH_SIZE];
 158  162  };
 159  163  
 160  164  zone_key_t flock_zone_key;
 161  165  
      166 +/*
      167 + * Support for the remote stale lock detection
      168 + *
      169 + * The sysid_to_host_translator_lock readers/writer lock protects
      170 + * sysid_to_host_translator_list.
      171 + *
      172 + * The sysid_to_host_translator_list is a list of sysid to host name translator
      173 + * functions.  The new translators are added using the public
      174 + * flk_add_sysid_to_host_translator() call.
      175 + *
      176 + * The stale_lock_timeout is in seconds and it determines the interval for the
      177 + * remote stale lock checking.  When set to 0, the remote stale lock checking
      178 + * is disabled.
      179 + */
      180 +struct sysid_to_host_translator_entry {
      181 +        sysid_to_host_translator_t translator;
      182 +        list_node_t node;
      183 +};
      184 +static krwlock_t sysid_to_host_translator_lock;
      185 +static list_t sysid_to_host_translator_list;
      186 +volatile int stale_lock_timeout = 3600;         /* one hour, in seconds */
      187 +
 162  188  static void create_flock(lock_descriptor_t *, flock64_t *);
 163  189  static lock_descriptor_t        *flk_get_lock(void);
 164  190  static void     flk_free_lock(lock_descriptor_t *lock);
 165      -static void     flk_get_first_blocking_lock(lock_descriptor_t *request);
      191 +static void     flk_get_first_blocking_lock(lock_descriptor_t *);
 166  192  static int flk_process_request(lock_descriptor_t *);
 167  193  static int flk_add_edge(lock_descriptor_t *, lock_descriptor_t *, int, int);
 168  194  static edge_t *flk_get_edge(void);
 169  195  static int flk_wait_execute_request(lock_descriptor_t *);
 170  196  static int flk_relation(lock_descriptor_t *, lock_descriptor_t *);
 171  197  static void flk_insert_active_lock(lock_descriptor_t *);
 172  198  static void flk_delete_active_lock(lock_descriptor_t *, int);
 173  199  static void flk_insert_sleeping_lock(lock_descriptor_t *);
 174  200  static void flk_graph_uncolor(graph_t *);
 175  201  static void flk_wakeup(lock_descriptor_t *, int);
↓ open down ↓ 373 lines elided ↑ open up ↑
 549  575              (lckdat->l_type == F_WRLCK && (flag & FWRITE) == 0)))
 550  576                          return (EBADF);
 551  577  
 552  578          /*
 553  579           * for query and unlock we use the stack_lock_request
 554  580           */
 555  581  
 556  582          if ((lckdat->l_type == F_UNLCK) ||
 557  583              !((cmd & INOFLCK) || (cmd & SETFLCK))) {
 558  584                  lock_request = &stack_lock_request;
 559      -                (void) bzero((caddr_t)lock_request,
 560      -                    sizeof (lock_descriptor_t));
      585 +                bzero(lock_request, sizeof (lock_descriptor_t));
 561  586  
 562  587                  /*
 563  588                   * following is added to make the assertions in
 564  589                   * flk_execute_request() to pass through
 565  590                   */
 566  591  
 567  592                  lock_request->l_edge.edge_in_next = &lock_request->l_edge;
 568  593                  lock_request->l_edge.edge_in_prev = &lock_request->l_edge;
 569  594                  lock_request->l_edge.edge_adj_next = &lock_request->l_edge;
 570  595                  lock_request->l_edge.edge_adj_prev = &lock_request->l_edge;
↓ open down ↓ 372 lines elided ↑ open up ↑
 943  968          if (nlm_status_size != 0) {     /* booted as a cluster */
 944  969                  nlm_reg_status = (flk_nlm_status_t *)
 945  970                      kmem_alloc(sizeof (flk_nlm_status_t) * nlm_status_size,
 946  971                      KM_SLEEP);
 947  972  
 948  973                  /* initialize all NLM states in array to NLM_UNKNOWN */
 949  974                  for (i = 0; i < nlm_status_size; i++) {
 950  975                          nlm_reg_status[i] = FLK_NLM_UNKNOWN;
 951  976                  }
 952  977          }
      978 +
      979 +        mutex_init(&flock_lock, NULL, MUTEX_DEFAULT, NULL);
      980 +        mutex_init(&nlm_reg_lock, NULL, MUTEX_DEFAULT, NULL);
      981 +
      982 +        rw_init(&sysid_to_host_translator_lock, NULL, RW_DEFAULT, NULL);
      983 +        list_create(&sysid_to_host_translator_list,
      984 +            sizeof (struct sysid_to_host_translator_entry),
      985 +            offsetof(struct sysid_to_host_translator_entry, node));
 953  986  }
 954  987  
 955  988  /*
 956  989   * Zone constructor/destructor callbacks to be executed when a zone is
 957  990   * created/destroyed.
 958  991   */
 959  992  /* ARGSUSED */
 960  993  void *
 961  994  flk_zone_init(zoneid_t zoneid)
 962  995  {
↓ open down ↓ 41 lines elided ↑ open up ↑
1004 1037  /*
1005 1038   * Free a lock_descriptor structure. Just sets the DELETED_LOCK flag
1006 1039   * when some thread has a reference to it as in reclock().
1007 1040   */
1008 1041  
1009 1042  void
1010 1043  flk_free_lock(lock_descriptor_t *lock)
1011 1044  {
1012 1045          file_t *fp;
1013 1046  
     1047 +        ASSERT(lock->l_blocker >= 0);
1014 1048          ASSERT(IS_DEAD(lock));
1015 1049  
1016 1050          if ((fp = lock->l_ofd) != NULL && fp->f_filock == (struct filock *)lock)
1017 1051                  fp->f_filock = NULL;
1018 1052  
1019 1053          if (IS_REFERENCED(lock)) {
1020 1054                  lock->l_state |= DELETED_LOCK;
1021 1055                  return;
1022 1056          }
1023 1057          flk_lock_frees++;
1024      -        kmem_free((void *)lock, sizeof (lock_descriptor_t));
     1058 +        kmem_free(lock, sizeof (lock_descriptor_t));
1025 1059  }
1026 1060  
1027 1061  void
1028 1062  flk_set_state(lock_descriptor_t *lock, int new_state)
1029 1063  {
1030 1064          /*
1031 1065           * Locks in the sleeping list may be woken up in a number of ways,
1032 1066           * and more than once.  If a sleeping lock is signaled awake more
1033 1067           * than once, then it may or may not change state depending on its
1034 1068           * current state.
↓ open down ↓ 19 lines elided ↑ open up ↑
1054 1088                  }
1055 1089          }
1056 1090          CHECK_LOCK_TRANSITION(lock->l_status, new_state);
1057 1091          if (IS_PXFS(lock)) {
1058 1092                  cl_flk_state_transition_notify(lock, lock->l_status, new_state);
1059 1093          }
1060 1094          lock->l_status = new_state;
1061 1095  }
1062 1096  
1063 1097  /*
     1098 + * Support for the remote stale lock detection
     1099 + */
     1100 +
     1101 +void
     1102 +flk_add_sysid_to_host_translator(sysid_to_host_translator_t tr)
     1103 +{
     1104 +        struct sysid_to_host_translator_entry *te;
     1105 +
     1106 +        te = kmem_alloc(sizeof (struct sysid_to_host_translator_entry),
     1107 +            KM_SLEEP);
     1108 +
     1109 +        te->translator = tr;
     1110 +
     1111 +        rw_enter(&sysid_to_host_translator_lock, RW_WRITER);
     1112 +        list_insert_head(&sysid_to_host_translator_list, te);
     1113 +        rw_exit(&sysid_to_host_translator_lock);
     1114 +}
     1115 +
     1116 +static void
     1117 +translate_sysid_to_host(zoneid_t zoneid, sysid_t sysid, char *host, size_t hlen,
     1118 +    const char **type)
     1119 +{
     1120 +        struct sockaddr sa;
     1121 +        struct sysid_to_host_translator_entry *te;
     1122 +
     1123 +        /* Some defaults in a case the translation will fail */
     1124 +        *type = "?";
     1125 +        (void) strlcpy(host, "?", hlen);
     1126 +
     1127 +        rw_enter(&sysid_to_host_translator_lock, RW_READER);
     1128 +
     1129 +        for (te = list_head(&sysid_to_host_translator_list); te != NULL;
     1130 +            te = list_next(&sysid_to_host_translator_list, te)) {
     1131 +
     1132 +                if (te->translator(zoneid, sysid, &sa, type) != 0) {
     1133 +                        rw_exit(&sysid_to_host_translator_lock);
     1134 +
     1135 +                        switch (sa.sa_family) {
     1136 +                        case AF_INET:
     1137 +                                (void) inet_ntop(AF_INET,
     1138 +                                    &((struct sockaddr_in *)&sa)->sin_addr,
     1139 +                                    host, hlen);
     1140 +                                break;
     1141 +                        case AF_INET6:
     1142 +                                (void) inet_ntop(AF_INET6,
     1143 +                                    &((struct sockaddr_in6 *)&sa)->sin6_addr,
     1144 +                                    host, hlen);
     1145 +                                break;
     1146 +                        default:
     1147 +                                break;
     1148 +                        }
     1149 +
     1150 +                        return;
     1151 +                }
     1152 +        }
     1153 +
     1154 +        rw_exit(&sysid_to_host_translator_lock);
     1155 +}
     1156 +
     1157 +static char *
     1158 +get_vnode_path(vnode_t *vp)
     1159 +{
     1160 +        size_t len;
     1161 +        char *ret;
     1162 +
     1163 +        mutex_enter(&vp->v_lock);
     1164 +        if (vp->v_path == NULL) {
     1165 +                mutex_exit(&vp->v_lock);
     1166 +                return (NULL);
     1167 +        }
     1168 +        len = strlen(vp->v_path) + 1;
     1169 +        mutex_exit(&vp->v_lock);
     1170 +
     1171 +        ret = kmem_alloc(len, KM_SLEEP);
     1172 +
     1173 +        mutex_enter(&vp->v_lock);
     1174 +        if (vp->v_path == NULL || strlen(vp->v_path) + 1 != len) {
     1175 +                mutex_exit(&vp->v_lock);
     1176 +                kmem_free(ret, len);
     1177 +                return (NULL);
     1178 +        }
     1179 +        bcopy(vp->v_path, ret, len);
     1180 +        mutex_exit(&vp->v_lock);
     1181 +
     1182 +        return (ret);
     1183 +}
     1184 +
     1185 +static void
     1186 +flk_stale_lock_check(lock_descriptor_t *lock)
     1187 +{
     1188 +        char *path;
     1189 +
     1190 +        char host[INET6_ADDRSTRLEN];            /* host name */
     1191 +        const char *type;                       /* host type */
     1192 +
     1193 +        /* temporary variables for the cmn_err() call */
     1194 +        char *p, *t;            /* path, lock type */
     1195 +        pid_t pid;              /* pid */
     1196 +        void *v;                /* vnode */
     1197 +        u_offset_t s, e;        /* start, end */
     1198 +
     1199 +        ASSERT(MUTEX_HELD(&lock->l_graph->gp_mutex));
     1200 +
     1201 +        /*
     1202 +         * Either not a remote lock, or the stale lock checking is disabled, or
     1203 +         * the lock is already reported.
     1204 +         */
     1205 +        if (IS_LOCAL(lock) || stale_lock_timeout == 0 || lock->l_blocker < 0)
     1206 +                return;
     1207 +
     1208 +        /* Seen first time? */
     1209 +        if (lock->l_blocker == 0) {
     1210 +                lock->l_blocker = gethrtime();
     1211 +                return;
     1212 +        }
     1213 +
     1214 +        /* Old enough? */
     1215 +        if ((gethrtime() - lock->l_blocker) / NANOSEC < stale_lock_timeout)
     1216 +                return;
     1217 +
     1218 +        translate_sysid_to_host(lock->l_zoneid, lock->l_flock.l_sysid, host,
     1219 +            sizeof (host), &type);
     1220 +        path = get_vnode_path(lock->l_vnode);
     1221 +
     1222 +        pid = lock->l_flock.l_pid;
     1223 +        v = (void *)lock->l_vnode;
     1224 +        p = path == NULL ? "?" : path;
     1225 +        t = lock->l_type == F_WRLCK ? "WR" : "RD";
     1226 +        s = lock->l_start;
     1227 +        e = lock->l_end;
     1228 +
     1229 +        /* Report the blocker as stale */
     1230 +        cmn_err(CE_NOTE, "!Stale lock (host: %s (%s), pid: %d, vnode: %p, "
     1231 +            "path: %s, %sLCK: %llu:%llu)", host, type, pid, v, p, t, s, e);
     1232 +
     1233 +        if (path != NULL)
     1234 +                strfree(path);
     1235 +
     1236 +        /* Mark this blocker as reported */
     1237 +        lock->l_blocker = -lock->l_blocker;
     1238 +}
     1239 +
     1240 +static void
     1241 +flk_stale_lock_shrink(lock_descriptor_t *lock, lock_descriptor_t *new)
     1242 +{
     1243 +        char *path;
     1244 +
     1245 +        char host[INET6_ADDRSTRLEN];            /* host name */
     1246 +        const char *type;                       /* host type */
     1247 +
     1248 +        /* temporary variables for the cmn_err() call */
     1249 +        char *p, *t;            /* path, lock type */
     1250 +        pid_t pid;              /* pid */
     1251 +        void *v;                /* vnode */
     1252 +        u_offset_t s, e;        /* start, end */
     1253 +        u_offset_t ns, ne;      /* new start, new end */
     1254 +
     1255 +        ASSERT(MUTEX_HELD(&lock->l_graph->gp_mutex));
     1256 +
     1257 +        translate_sysid_to_host(lock->l_zoneid, lock->l_flock.l_sysid, host,
     1258 +            sizeof (host), &type);
     1259 +        path = get_vnode_path(lock->l_vnode);
     1260 +
     1261 +        pid = lock->l_flock.l_pid;
     1262 +        v = (void *)lock->l_vnode;
     1263 +        p = path == NULL ? "?" : path;
     1264 +        t = lock->l_type == F_WRLCK ? "WR" : "RD";
     1265 +        s = lock->l_start;
     1266 +        e = lock->l_end;
     1267 +        ns = new->l_start;
     1268 +        ne = new->l_end;
     1269 +
     1270 +        cmn_err(CE_NOTE, "!Stale lock SHRINK (host: %s (%s), pid: %d, "
     1271 +            "vnode: %p, path: %s, %sLCK: %llu:%llu -> %llu:%llu)", host, type,
     1272 +            pid, v, p, t, s, e, ns, ne);
     1273 +
     1274 +        if (path != NULL)
     1275 +                strfree(path);
     1276 +}
     1277 +
     1278 +static void
     1279 +flk_stale_lock_split(lock_descriptor_t *lock, lock_descriptor_t *new1,
     1280 +    lock_descriptor_t *new2)
     1281 +{
     1282 +        char *path;
     1283 +
     1284 +        char host[INET6_ADDRSTRLEN];            /* host name */
     1285 +        const char *type;                       /* host type */
     1286 +
     1287 +        /* temporary variables for the cmn_err() call */
     1288 +        char *p, *t;            /* path, lock type */
     1289 +        pid_t pid;              /* pid */
     1290 +        void *v;                /* vnode */
     1291 +        u_offset_t s, e;        /* start, end */
     1292 +        u_offset_t n1s, n1e;    /* new1 start, new1 end */
     1293 +        u_offset_t n2s, n2e;    /* new2 start, new2 end */
     1294 +
     1295 +        ASSERT(MUTEX_HELD(&lock->l_graph->gp_mutex));
     1296 +
     1297 +        translate_sysid_to_host(lock->l_zoneid, lock->l_flock.l_sysid, host,
     1298 +            sizeof (host), &type);
     1299 +        path = get_vnode_path(lock->l_vnode);
     1300 +
     1301 +        pid = lock->l_flock.l_pid;
     1302 +        v = (void *)lock->l_vnode;
     1303 +        p = path == NULL ? "?" : path;
     1304 +        t = lock->l_type == F_WRLCK ? "WR" : "RD";
     1305 +        s = lock->l_start;
     1306 +        e = lock->l_end;
     1307 +        n1s = new1->l_start;
     1308 +        n1e = new1->l_end;
     1309 +        n2s = new2->l_start;
     1310 +        n2e = new2->l_end;
     1311 +
     1312 +        cmn_err(CE_NOTE, "!Stale lock SPLIT (host: %s (%s), pid: %d, "
     1313 +            "vnode: %p, path: %s, %sLCK: %llu:%llu -> %llu:%llu and %llu:%llu)",
     1314 +            host, type, pid, v, p, t, s, e, n1s, n1e, n2s, n2e);
     1315 +
     1316 +        if (path != NULL)
     1317 +                strfree(path);
     1318 +}
     1319 +
     1320 +static void
     1321 +flk_stale_lock_release(lock_descriptor_t *lock)
     1322 +{
     1323 +        char *path;
     1324 +
     1325 +        char host[INET6_ADDRSTRLEN];            /* host name */
     1326 +        const char *type;                       /* host type */
     1327 +
     1328 +        /* temporary variables for the cmn_err() call */
     1329 +        char *p, *t;            /* path, lock type */
     1330 +        pid_t pid;              /* pid */
     1331 +        void *v;                /* vnode */
     1332 +        u_offset_t s, e;        /* start, end */
     1333 +
     1334 +        ASSERT(MUTEX_HELD(&lock->l_graph->gp_mutex));
     1335 +
     1336 +        translate_sysid_to_host(lock->l_zoneid, lock->l_flock.l_sysid, host,
     1337 +            sizeof (host), &type);
     1338 +        path = get_vnode_path(lock->l_vnode);
     1339 +
     1340 +        pid = lock->l_flock.l_pid;
     1341 +        v = (void *)lock->l_vnode;
     1342 +        p = path == NULL ? "?" : path;
     1343 +        t = lock->l_type == F_WRLCK ? "WR" : "RD";
     1344 +        s = lock->l_start;
     1345 +        e = lock->l_end;
     1346 +
     1347 +        cmn_err(CE_NOTE, "!Stale lock RELEASE (host: %s (%s), pid: %d, "
     1348 +            "vnode: %p, path: %s, %sLCK: %llu:%llu)", host, type, pid, v, p, t,
     1349 +            s, e);
     1350 +
     1351 +        if (path != NULL)
     1352 +                strfree(path);
     1353 +}
     1354 +
     1355 +/*
1064 1356   * Routine that checks whether there are any blocking locks in the system.
1065 1357   *
1066 1358   * The policy followed is if a write lock is sleeping we don't allow read
1067 1359   * locks before this write lock even though there may not be any active
1068 1360   * locks corresponding to the read locks' region.
1069 1361   *
1070 1362   * flk_add_edge() function adds an edge between l1 and l2 iff there
1071 1363   * is no path between l1 and l2. This is done to have a "minimum
1072 1364   * storage representation" of the dependency graph.
1073 1365   *
↓ open down ↓ 18 lines elided ↑ open up ↑
1092 1384  
1093 1385          ASSERT(MUTEX_HELD(&gp->gp_mutex));
1094 1386          request_will_wait = IS_WILLING_TO_SLEEP(request);
1095 1387  
1096 1388          /*
1097 1389           * check active locks
1098 1390           */
1099 1391  
1100 1392          SET_LOCK_TO_FIRST_ACTIVE_VP(gp, lock, vp);
1101 1393  
1102      -
1103 1394          if (lock) {
1104 1395                  do {
1105 1396                          if (BLOCKS(lock, request)) {
1106      -                                if (!request_will_wait)
     1397 +                                if (!request_will_wait) {
     1398 +                                        flk_stale_lock_check(lock);
1107 1399                                          return (EAGAIN);
     1400 +                                }
1108 1401                                  request_blocked_by_active = 1;
1109 1402                                  break;
1110 1403                          }
1111 1404                          /*
1112 1405                           * Grant lock if it is for the same owner holding active
1113 1406                           * lock that covers the request.
1114 1407                           */
1115 1408  
1116 1409                          if (SAME_OWNER(lock, request) &&
1117 1410                              COVERS(lock, request) &&
1118 1411                              (request->l_type == F_RDLCK))
1119 1412                                  return (flk_execute_request(request));
1120 1413                          lock = lock->l_next;
1121 1414                  } while (lock->l_vnode == vp);
1122 1415          }
1123 1416  
1124 1417          if (!request_blocked_by_active) {
1125      -                        lock_descriptor_t *lk[1];
1126      -                        lock_descriptor_t *first_glock = NULL;
     1418 +                lock_descriptor_t *lk[1];
     1419 +                lock_descriptor_t *first_glock = NULL;
     1420 +
1127 1421                  /*
1128 1422                   * Shall we grant this?! NO!!
1129 1423                   * What about those locks that were just granted and still
1130 1424                   * in sleep queue. Those threads are woken up and so locks
1131 1425                   * are almost active.
1132 1426                   */
1133 1427                  SET_LOCK_TO_FIRST_SLEEP_VP(gp, lock, vp);
1134 1428                  if (lock) {
1135 1429                          do {
1136 1430                                  if (BLOCKS(lock, request)) {
↓ open down ↓ 36 lines elided ↑ open up ↑
1173 1467                  if (lock) {
1174 1468                          do {
1175 1469                                  flk_recompute_dependencies(lock, lk, 1, 0);
1176 1470                                  lock = lock->l_next;
1177 1471                          } while (lock->l_vnode == vp);
1178 1472                  }
1179 1473                  lock = first_glock;
1180 1474                  if (lock) {
1181 1475                          do {
1182 1476                                  if (IS_GRANTED(lock)) {
1183      -                                flk_recompute_dependencies(lock, lk, 1, 0);
     1477 +                                        flk_recompute_dependencies(lock, lk, 1,
     1478 +                                            0);
1184 1479                                  }
1185 1480                                  lock = lock->l_prev;
1186 1481                          } while ((lock->l_vnode == vp));
1187 1482                  }
1188 1483                  request->l_state &= ~RECOMPUTE_LOCK;
1189 1484                  if (!NO_DEPENDENTS(request) && flk_check_deadlock(request))
1190 1485                          return (EDEADLK);
1191 1486                  return (flk_execute_request(request));
1192 1487          }
1193 1488  
↓ open down ↓ 41 lines elided ↑ open up ↑
1235 1530                                          continue;
1236 1531                                  }
1237 1532                                  if ((error = flk_add_edge(request, lock,
1238 1533                                      !found_covering_lock, 0)))
1239 1534                                          return (error);
1240 1535                          }
1241 1536                          lock = lock->l_next;
1242 1537                  } while (lock->l_vnode == vp);
1243 1538          }
1244 1539  
1245      -/*
1246      - * found_covering_lock == 2 iff at this point 'request' has paths
1247      - * to all locks that blocks 'request'. found_covering_lock == 1 iff at this
1248      - * point 'request' has paths to all locks that blocks 'request' whose owners
1249      - * are not same as the one that covers 'request' (covered_by above) and
1250      - * we can have locks whose owner is same as covered_by in the active list.
1251      - */
     1540 +        /*
     1541 +         * found_covering_lock == 2 iff at this point 'request' has paths to
     1542 +         * all locks that blocks 'request'. found_covering_lock == 1 iff at
     1543 +         * this point 'request' has paths to all locks that blocks 'request'
     1544 +         * whose owners are not same as the one that covers 'request'
     1545 +         * (covered_by above) and we can have locks whose owner is same as
     1546 +         * covered_by in the active list.
     1547 +         */
1252 1548  
1253 1549          if (request_blocked_by_active && found_covering_lock != 2) {
1254 1550                  SET_LOCK_TO_FIRST_ACTIVE_VP(gp, lock, vp);
1255 1551                  ASSERT(lock != NULL);
1256 1552                  do {
1257 1553                          if (BLOCKS(lock, request)) {
1258 1554                                  if (found_covering_lock &&
1259 1555                                      !SAME_OWNER(lock, covered_by)) {
1260 1556                                          lock = lock->l_next;
1261 1557                                          continue;
↓ open down ↓ 52 lines elided ↑ open up ↑
1314 1610  
1315 1611          ASSERT(NOT_BLOCKED(request));
1316 1612  
1317 1613          /* IO_LOCK requests are only to check status */
1318 1614  
1319 1615          if (IS_IO_LOCK(request))
1320 1616                  return (0);
1321 1617  
1322 1618          SET_LOCK_TO_FIRST_ACTIVE_VP(gp, lock, vp);
1323 1619  
1324      -        if (lock == NULL && request->l_type == F_UNLCK)
1325      -                return (0);
1326      -        if (lock == NULL) {
1327      -                flk_insert_active_lock(request);
1328      -                return (0);
     1620 +        if (lock != NULL) {
     1621 +                /*
     1622 +                 * There are some active locks so check for relations
     1623 +                 */
     1624 +                do {
     1625 +                        lock1 = lock->l_next;
     1626 +                        if (SAME_OWNER(request, lock)) {
     1627 +                                done_searching = flk_relation(lock, request);
     1628 +                        }
     1629 +                        lock = lock1;
     1630 +                } while (lock->l_vnode == vp && !done_searching);
1329 1631          }
1330 1632  
1331      -        do {
1332      -                lock1 = lock->l_next;
1333      -                if (SAME_OWNER(request, lock)) {
1334      -                        done_searching = flk_relation(lock, request);
1335      -                }
1336      -                lock = lock1;
1337      -        } while (lock->l_vnode == vp && !done_searching);
1338      -
1339 1633          /*
1340 1634           * insert in active queue
1341 1635           */
1342 1636  
1343 1637          if (request->l_type != F_UNLCK)
1344 1638                  flk_insert_active_lock(request);
1345 1639  
1346 1640          return (0);
1347 1641  }
1348 1642  
↓ open down ↓ 243 lines elided ↑ open up ↑
1592 1886   */
1593 1887  
1594 1888  static void
1595 1889  flk_free_edge(edge_t *ep)
1596 1890  {
1597 1891          edge_frees++;
1598 1892          kmem_cache_free(flk_edge_cache, (void *)ep);
1599 1893  }
1600 1894  
1601 1895  /*
1602      - * Check the relationship of request with lock and perform the
1603      - * recomputation of dependencies, break lock if required, and return
1604      - * 1 if request cannot have any more relationship with the next
     1896 + * Check the relationship of 'request' with 'lock' and perform the
     1897 + * recomputation of dependencies, break 'lock' if required, and return
     1898 + * 1 if 'request' cannot have any more relationship with the next
1605 1899   * active locks.
     1900 + *
1606 1901   * The 'lock' and 'request' are compared and in case of overlap we
1607 1902   * delete the 'lock' and form new locks to represent the non-overlapped
1608 1903   * portion of original 'lock'. This function has side effects such as
1609 1904   * 'lock' will be freed, new locks will be added to the active list.
1610 1905   */
1611 1906  
1612 1907  static int
1613 1908  flk_relation(lock_descriptor_t *lock, lock_descriptor_t *request)
1614 1909  {
1615 1910          int lock_effect;
1616      -        lock_descriptor_t *lock1, *lock2;
1617 1911          lock_descriptor_t *topology[3];
1618 1912          int nvertex = 0;
1619 1913          int i;
1620 1914          edge_t  *ep;
1621      -        graph_t *gp = (lock->l_graph);
     1915 +        graph_t *gp = lock->l_graph;
     1916 +        boolean_t mergeable;
1622 1917  
     1918 +        ASSERT(request->l_blocker == 0);
1623 1919  
1624 1920          CHECK_SLEEPING_LOCKS(gp);
1625 1921          CHECK_ACTIVE_LOCKS(gp);
1626 1922  
1627 1923          ASSERT(MUTEX_HELD(&gp->gp_mutex));
1628 1924  
1629 1925          topology[0] = topology[1] = topology[2] = NULL;
1630 1926  
1631 1927          if (request->l_type == F_UNLCK)
1632 1928                  lock_effect = FLK_UNLOCK;
1633 1929          else if (request->l_type == F_RDLCK &&
1634 1930              lock->l_type == F_WRLCK)
1635 1931                  lock_effect = FLK_DOWNGRADE;
1636 1932          else if (request->l_type == F_WRLCK &&
1637 1933              lock->l_type == F_RDLCK)
1638 1934                  lock_effect = FLK_UPGRADE;
1639 1935          else
1640 1936                  lock_effect = FLK_STAY_SAME;
1641 1937  
     1938 +        /*
     1939 +         * The 'lock' and 'request' are merged only in a case the effect of
     1940 +         * both locks is same (FLK_STAY_SAME) and their blocker status
     1941 +         * (l_blocker) is same as well.  We do not merge 'lock' and 'request'
     1942 +         * with different l_blocker values because such merge might affect the
     1943 +         * stale lock detection.  It might cause either false positives, or
     1944 +         * miss some stale locks.
     1945 +         */
     1946 +        mergeable = lock_effect == FLK_STAY_SAME &&
     1947 +            lock->l_blocker == request->l_blocker;
     1948 +
1642 1949          if (lock->l_end < request->l_start) {
1643      -                if (lock->l_end == request->l_start - 1 &&
1644      -                    lock_effect == FLK_STAY_SAME) {
1645      -                        topology[0] = request;
     1950 +                /* If the 'lock' is just next to 'request', try to merge them */
     1951 +                if (lock->l_end == request->l_start - 1 && mergeable) {
1646 1952                          request->l_start = lock->l_start;
1647      -                        nvertex = 1;
1648 1953                          goto recompute;
1649      -                } else {
1650      -                        return (0);
1651 1954                  }
     1955 +
     1956 +                /* Otherwise, they do not overlap, so return immediately */
     1957 +                return (0);
1652 1958          }
1653 1959  
1654      -        if (lock->l_start > request->l_end) {
1655      -                if (request->l_end == lock->l_start - 1 &&
1656      -                    lock_effect == FLK_STAY_SAME) {
1657      -                        topology[0] = request;
     1960 +        if (request->l_end < lock->l_start) {
     1961 +                /* If the 'request' is just next to 'lock', try to merge them */
     1962 +                if (request->l_end == lock->l_start - 1 && mergeable) {
1658 1963                          request->l_end = lock->l_end;
1659      -                        nvertex = 1;
1660 1964                          goto recompute;
     1965 +                }
     1966 +
     1967 +                /* Otherwise, they do not overlap, so return immediately */
     1968 +                return (1);
     1969 +        }
     1970 +
     1971 +        /*
     1972 +         * Here we are sure the 'lock' and 'request' overlaps, so the 'request'
     1973 +         * will replace the 'lock' (either fully, or at least partially).
     1974 +         */
     1975 +
     1976 +        /*
     1977 +         * If the 'request' does not fully cover the 'lock' at the start,
     1978 +         * either move the start of the 'request' to cover the 'lock', or split
     1979 +         * the 'lock'.
     1980 +         */
     1981 +        if (lock->l_start < request->l_start) {
     1982 +                if (mergeable) {
     1983 +                        request->l_start = lock->l_start;
1661 1984                  } else {
1662      -                        return (1);
     1985 +                        lock_descriptor_t *new_lock = flk_get_lock();
     1986 +
     1987 +                        COPY(new_lock, lock);
     1988 +                        new_lock->l_end = request->l_start - 1;
     1989 +
     1990 +                        topology[nvertex++] = new_lock;
1663 1991                  }
1664 1992          }
1665 1993  
     1994 +        /*
     1995 +         * If the 'request' does not fully cover the 'lock' at the end, either
     1996 +         * move the end of the 'request' to cover the 'lock', or split the
     1997 +         * 'lock'.
     1998 +         */
1666 1999          if (request->l_end < lock->l_end) {
1667      -                if (request->l_start > lock->l_start) {
1668      -                        if (lock_effect == FLK_STAY_SAME) {
1669      -                                request->l_start = lock->l_start;
1670      -                                request->l_end = lock->l_end;
1671      -                                topology[0] = request;
1672      -                                nvertex = 1;
1673      -                        } else {
1674      -                                lock1 = flk_get_lock();
1675      -                                lock2 = flk_get_lock();
1676      -                                COPY(lock1, lock);
1677      -                                COPY(lock2, lock);
1678      -                                lock1->l_start = lock->l_start;
1679      -                                lock1->l_end = request->l_start - 1;
1680      -                                lock2->l_start = request->l_end + 1;
1681      -                                lock2->l_end = lock->l_end;
1682      -                                topology[0] = lock1;
1683      -                                topology[1] = lock2;
1684      -                                topology[2] = request;
1685      -                                nvertex = 3;
1686      -                        }
1687      -                } else if (request->l_start < lock->l_start) {
1688      -                        if (lock_effect == FLK_STAY_SAME) {
1689      -                                request->l_end = lock->l_end;
1690      -                                topology[0] = request;
1691      -                                nvertex = 1;
1692      -                        } else {
1693      -                                lock1 = flk_get_lock();
1694      -                                COPY(lock1, lock);
1695      -                                lock1->l_start = request->l_end + 1;
1696      -                                topology[0] = lock1;
1697      -                                topology[1] = request;
1698      -                                nvertex = 2;
1699      -                        }
1700      -                } else  {
1701      -                        if (lock_effect == FLK_STAY_SAME) {
1702      -                                request->l_start = lock->l_start;
1703      -                                request->l_end = lock->l_end;
1704      -                                topology[0] = request;
1705      -                                nvertex = 1;
1706      -                        } else {
1707      -                                lock1 = flk_get_lock();
1708      -                                COPY(lock1, lock);
1709      -                                lock1->l_start = request->l_end + 1;
1710      -                                topology[0] = lock1;
1711      -                                topology[1] = request;
1712      -                                nvertex = 2;
1713      -                        }
1714      -                }
1715      -        } else if (request->l_end > lock->l_end) {
1716      -                if (request->l_start > lock->l_start)  {
1717      -                        if (lock_effect == FLK_STAY_SAME) {
1718      -                                request->l_start = lock->l_start;
1719      -                                topology[0] = request;
1720      -                                nvertex = 1;
1721      -                        } else {
1722      -                                lock1 = flk_get_lock();
1723      -                                COPY(lock1, lock);
1724      -                                lock1->l_end = request->l_start - 1;
1725      -                                topology[0] = lock1;
1726      -                                topology[1] = request;
1727      -                                nvertex = 2;
1728      -                        }
1729      -                } else if (request->l_start < lock->l_start)  {
1730      -                        topology[0] = request;
1731      -                        nvertex = 1;
     2000 +                if (mergeable) {
     2001 +                        request->l_end = lock->l_end;
1732 2002                  } else {
1733      -                        topology[0] = request;
1734      -                        nvertex = 1;
     2003 +                        lock_descriptor_t *new_lock = flk_get_lock();
     2004 +
     2005 +                        COPY(new_lock, lock);
     2006 +                        new_lock->l_start = request->l_end + 1;
     2007 +
     2008 +                        topology[nvertex++] = new_lock;
1735 2009                  }
1736      -        } else {
1737      -                if (request->l_start > lock->l_start) {
1738      -                        if (lock_effect == FLK_STAY_SAME) {
1739      -                                request->l_start = lock->l_start;
1740      -                                topology[0] = request;
1741      -                                nvertex = 1;
1742      -                        } else {
1743      -                                lock1 = flk_get_lock();
1744      -                                COPY(lock1, lock);
1745      -                                lock1->l_end = request->l_start - 1;
1746      -                                topology[0] = lock1;
1747      -                                topology[1] = request;
1748      -                                nvertex = 2;
1749      -                        }
1750      -                } else if (request->l_start < lock->l_start) {
1751      -                        topology[0] = request;
1752      -                        nvertex = 1;
1753      -                } else {
1754      -                        if (lock_effect !=  FLK_UNLOCK) {
1755      -                                topology[0] = request;
1756      -                                nvertex = 1;
1757      -                        } else {
1758      -                                flk_delete_active_lock(lock, 0);
1759      -                                flk_wakeup(lock, 1);
1760      -                                flk_free_lock(lock);
1761      -                                CHECK_SLEEPING_LOCKS(gp);
1762      -                                CHECK_ACTIVE_LOCKS(gp);
1763      -                                return (1);
1764      -                        }
1765      -                }
1766 2010          }
1767 2011  
1768      -recompute:
     2012 +        /*
     2013 +         * Log the blocker change
     2014 +         */
     2015 +        if (nvertex > 0 && lock->l_blocker < 0) {
     2016 +                if (nvertex == 1)
     2017 +                        flk_stale_lock_shrink(lock, topology[0]);
     2018 +                if (nvertex == 2)
     2019 +                        flk_stale_lock_split(lock, topology[0], topology[1]);
1769 2020  
     2021 +                lock->l_blocker = 0;
     2022 +        }
     2023 +
     2024 +recompute:
1770 2025          /*
1771 2026           * For unlock we don't send the 'request' to for recomputing
1772 2027           * dependencies because no lock will add an edge to this.
1773 2028           */
     2029 +        if (lock_effect != FLK_UNLOCK)
     2030 +                topology[nvertex++] = request;
1774 2031  
1775      -        if (lock_effect == FLK_UNLOCK) {
1776      -                topology[nvertex-1] = NULL;
1777      -                nvertex--;
1778      -        }
1779 2032          for (i = 0; i < nvertex; i++) {
1780 2033                  topology[i]->l_state |= RECOMPUTE_LOCK;
1781 2034                  topology[i]->l_color = NO_COLOR;
1782 2035          }
1783 2036  
1784 2037          ASSERT(FIRST_ADJ(lock) == HEAD(lock));
1785 2038  
1786 2039          /*
1787 2040           * we remove the adjacent edges for all vertices' to this vertex
1788 2041           * 'lock'.
1789 2042           */
1790      -
1791 2043          ep = FIRST_IN(lock);
1792 2044          while (ep != HEAD(lock)) {
1793 2045                  ADJ_LIST_REMOVE(ep);
1794 2046                  ep = NEXT_IN(ep);
1795 2047          }
1796 2048  
1797 2049          flk_delete_active_lock(lock, 0);
1798 2050  
1799 2051          /* We are ready for recomputing the dependencies now */
1800      -
1801 2052          flk_recompute_dependencies(lock, topology, nvertex, 1);
1802 2053  
1803 2054          for (i = 0; i < nvertex; i++) {
1804 2055                  topology[i]->l_state &= ~RECOMPUTE_LOCK;
1805 2056                  topology[i]->l_color = NO_COLOR;
1806 2057          }
1807 2058  
1808      -
1809 2059          if (lock_effect == FLK_UNLOCK) {
1810 2060                  nvertex++;
1811 2061          }
1812 2062          for (i = 0; i < nvertex - 1; i++) {
1813 2063                  flk_insert_active_lock(topology[i]);
1814 2064          }
1815 2065  
1816      -
1817 2066          if (lock_effect == FLK_DOWNGRADE || lock_effect == FLK_UNLOCK) {
1818 2067                  flk_wakeup(lock, 0);
1819 2068          } else {
1820 2069                  ep = FIRST_IN(lock);
1821 2070                  while (ep != HEAD(lock)) {
1822 2071                          lock->l_sedge = NEXT_IN(ep);
1823 2072                          IN_LIST_REMOVE(ep);
1824 2073                          flk_update_proc_graph(ep, 1);
1825 2074                          flk_free_edge(ep);
1826 2075                          ep = lock->l_sedge;
↓ open down ↓ 58 lines elided ↑ open up ↑
1885 2134          graph_t *gp = lock->l_graph;
1886 2135  
1887 2136          ASSERT(MUTEX_HELD(&gp->gp_mutex));
1888 2137          if (free_lock)
1889 2138                  ASSERT(NO_DEPENDENTS(lock));
1890 2139          ASSERT(NOT_BLOCKED(lock));
1891 2140          ASSERT(IS_ACTIVE(lock));
1892 2141  
1893 2142          ASSERT((vp->v_filocks != NULL));
1894 2143  
     2144 +        if (lock->l_blocker < 0) {
     2145 +                /* Log the blocker release */
     2146 +                flk_stale_lock_release(lock);
     2147 +                lock->l_blocker = 0;
     2148 +        }
     2149 +
1895 2150          if (vp->v_filocks == (struct filock *)lock) {
1896 2151                  vp->v_filocks = (struct filock *)
1897 2152                      ((lock->l_next->l_vnode == vp) ? lock->l_next :
1898 2153                      NULL);
1899 2154          }
1900 2155          lock->l_next->l_prev = lock->l_prev;
1901 2156          lock->l_prev->l_next = lock->l_next;
1902 2157          lock->l_next = lock->l_prev = NULL;
1903 2158          flk_set_state(lock, FLK_DEAD_STATE);
1904 2159          lock->l_state &= ~ACTIVE_LOCK;
↓ open down ↓ 26 lines elided ↑ open up ↑
1931 2186          request->l_prev = lock->l_prev;
1932 2187          lock->l_prev = request;
1933 2188          request->l_next = lock;
1934 2189          flk_set_state(request, FLK_SLEEPING_STATE);
1935 2190          request->l_state |= SLEEPING_LOCK;
1936 2191  }
1937 2192  
1938 2193  /*
1939 2194   * Cancelling a sleeping lock implies removing a vertex from the
1940 2195   * dependency graph and therefore we should recompute the dependencies
1941      - * of all vertices that have a path  to this vertex, w.r.t. all
     2196 + * of all vertices that have a path to this vertex, w.r.t. all
1942 2197   * vertices reachable from this vertex.
1943 2198   */
1944 2199  
1945 2200  void
1946 2201  flk_cancel_sleeping_lock(lock_descriptor_t *request, int remove_from_queue)
1947 2202  {
1948 2203          graph_t *gp = request->l_graph;
1949 2204          vnode_t *vp = request->l_vnode;
1950 2205          lock_descriptor_t **topology = NULL;
1951 2206          edge_t  *ep;
↓ open down ↓ 101 lines elided ↑ open up ↑
2053 2308           */
2054 2309  
2055 2310          for (i = 0; i < nvertex; i++) {
2056 2311                  topology[i]->l_state &= ~RECOMPUTE_LOCK;
2057 2312          }
2058 2313  
2059 2314          /*
2060 2315           * free the topology
2061 2316           */
2062 2317          if (nvertex)
2063      -                kmem_free((void *)topology,
     2318 +                kmem_free(topology,
2064 2319                      (nvertex * sizeof (lock_descriptor_t *)));
2065 2320          /*
2066 2321           * Possibility of some locks unblocked now
2067 2322           */
2068 2323  
2069 2324          flk_wakeup(request, 0);
2070 2325  
2071 2326          /*
2072 2327           * we expect to have a correctly recomputed graph  now.
2073 2328           */
↓ open down ↓ 915 lines elided ↑ open up ↑
2989 3244  
2990 3245  /*
2991 3246   * Called from 'fs' read and write routines for files that have mandatory
2992 3247   * locking enabled.
2993 3248   */
2994 3249  
2995 3250  int
2996 3251  chklock(struct vnode *vp, int iomode, u_offset_t offset, ssize_t len, int fmode,
2997 3252      caller_context_t *ct)
2998 3253  {
2999      -        register int    i;
     3254 +        int             i;
3000 3255          struct flock64  bf;
3001 3256          int             error = 0;
3002 3257  
3003 3258          bf.l_type = (iomode & FWRITE) ? F_WRLCK : F_RDLCK;
3004 3259          bf.l_whence = 0;
3005 3260          bf.l_start = offset;
3006 3261          bf.l_len = len;
3007 3262          if (ct == NULL) {
3008 3263                  bf.l_pid = curproc->p_pid;
3009 3264                  bf.l_sysid = 0;
↓ open down ↓ 310 lines elided ↑ open up ↑
3320 3575  }
3321 3576  
3322 3577  /*
3323 3578   * Free the proc edge. Called whenever its reference count goes to zero.
3324 3579   */
3325 3580  
3326 3581  static void
3327 3582  flk_free_proc_edge(proc_edge_t *pep)
3328 3583  {
3329 3584          ASSERT(pep->refcount == 0);
3330      -        kmem_free((void *)pep, sizeof (proc_edge_t));
     3585 +        kmem_free(pep, sizeof (proc_edge_t));
3331 3586          flk_proc_edge_frees++;
3332 3587  }
3333 3588  
3334 3589  /*
3335 3590   * Color the graph explicitly done only when the mark value hits max value.
3336 3591   */
3337 3592  
3338 3593  static void
3339 3594  flk_proc_graph_uncolor()
3340 3595  {
↓ open down ↓ 721 lines elided ↑ open up ↑
4062 4317                                  ASSERT(IS_ACTIVE(lock));
4063 4318                                  flk_delete_active_lock(lock, 0);
4064 4319                                  flk_wakeup(lock, 1);
4065 4320                                  flk_free_lock(lock);
4066 4321                          }
4067 4322                  }
4068 4323                  mutex_exit(&gp->gp_mutex);
4069 4324          }
4070 4325  }
4071 4326  
4072      -
4073 4327  /*
4074 4328   * Wait until a lock is granted, cancelled, or interrupted.
4075 4329   */
4076 4330  
4077 4331  static void
4078 4332  wait_for_lock(lock_descriptor_t *request)
4079 4333  {
4080 4334          graph_t *gp = request->l_graph;
     4335 +        vnode_t *vp = request->l_vnode;
4081 4336  
4082 4337          ASSERT(MUTEX_HELD(&gp->gp_mutex));
4083 4338  
4084 4339          while (!(IS_GRANTED(request)) && !(IS_CANCELLED(request)) &&
4085 4340              !(IS_INTERRUPTED(request))) {
4086      -                if (!cv_wait_sig(&request->l_cv, &gp->gp_mutex)) {
     4341 +                lock_descriptor_t *lock;
     4342 +
     4343 +                if (stale_lock_timeout == 0) {
     4344 +                        /* The stale lock detection is disabled */
     4345 +                        if (cv_wait_sig(&request->l_cv, &gp->gp_mutex) == 0) {
     4346 +                                flk_set_state(request, FLK_INTERRUPTED_STATE);
     4347 +                                request->l_state |= INTERRUPTED_LOCK;
     4348 +                        }
     4349 +
     4350 +                        continue;
     4351 +                }
     4352 +
     4353 +                SET_LOCK_TO_FIRST_ACTIVE_VP(gp, lock, vp);
     4354 +
     4355 +                if (lock != NULL) {
     4356 +                        do {
     4357 +                                if (BLOCKS(lock, request)) {
     4358 +                                        flk_stale_lock_check(lock);
     4359 +                                        break;
     4360 +                                }
     4361 +                                lock = lock->l_next;
     4362 +                        } while (lock->l_vnode == vp);
     4363 +                }
     4364 +
     4365 +                if (cv_timedwait_sig(&request->l_cv, &gp->gp_mutex,
     4366 +                    ddi_get_lbolt() + SEC_TO_TICK(stale_lock_timeout)) == 0) {
4087 4367                          flk_set_state(request, FLK_INTERRUPTED_STATE);
4088 4368                          request->l_state |= INTERRUPTED_LOCK;
4089 4369                  }
4090 4370          }
4091 4371  }
4092 4372  
4093 4373  /*
4094 4374   * Create an flock structure from the existing lock information
4095 4375   *
4096 4376   * This routine is used to create flock structures for the lock manager
↓ open down ↓ 35 lines elided ↑ open up ↑
4132 4412           */
4133 4413          switch (flp->l_whence) {
4134 4414          case 0:         /* SEEK_SET */
4135 4415                  *start = (u_offset_t)flp->l_start;
4136 4416                  break;
4137 4417          case 1:         /* SEEK_CUR */
4138 4418                  *start = (u_offset_t)(flp->l_start + offset);
4139 4419                  break;
4140 4420          case 2:         /* SEEK_END */
4141 4421                  vattr.va_mask = AT_SIZE;
4142      -                if (error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL))
     4422 +                if ((error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)) != 0)
4143 4423                          return (error);
4144 4424                  *start = (u_offset_t)(flp->l_start + vattr.va_size);
4145 4425                  break;
4146 4426          default:
4147 4427                  return (EINVAL);
4148 4428          }
4149 4429  
4150 4430          /*
4151 4431           * Determine the range covered by the request.
4152 4432           */
↓ open down ↓ 12 lines elided ↑ open up ↑
4165 4445                  (*start)++;
4166 4446          }
4167 4447          return (0);
4168 4448  }
4169 4449  
4170 4450  /*
4171 4451   * Check the validity of lock data.  This can used by the NFS
4172 4452   * frlock routines to check data before contacting the server.  The
4173 4453   * server must support semantics that aren't as restrictive as
4174 4454   * the UNIX API, so the NFS client is required to check.
4175      - * The maximum is now passed in by the caller.
     4455 + * The maximum is passed in by the caller.
4176 4456   */
4177 4457  
4178 4458  int
4179 4459  flk_check_lock_data(u_offset_t start, u_offset_t end, offset_t max)
4180 4460  {
4181 4461          /*
4182 4462           * The end (length) for local locking should never be greater
4183      -         * than MAXEND. However, the representation for
     4463 +         * than max. However, the representation for
4184 4464           * the entire file is MAX_U_OFFSET_T.
4185 4465           */
4186 4466          if ((start > max) ||
4187 4467              ((end > max) && (end != MAX_U_OFFSET_T))) {
4188 4468                  return (EINVAL);
4189 4469          }
4190 4470          if (start > end) {
4191 4471                  return (EINVAL);
4192 4472          }
4193 4473          return (0);
↓ open down ↓ 412 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX