}
/**
+ * When setting a lease on a file, we take ownership of the lli_mds_*_och
+ * and save it as fd->fd_och so as to force client to reopen the file even
+ * if it has an open lock in cache already.
+ */
+static int ll_lease_och_acquire(struct inode *inode, struct file *file,
+ struct lustre_handle *old_handle)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct obd_client_handle **och_p;
+ __u64 *och_usecount;
+ int rc = 0;
+ ENTRY;
+
+ /* Get the openhandle of the file */
+ mutex_lock(&lli->lli_och_mutex);
+ if (fd->fd_lease_och != NULL)
+ GOTO(out_unlock, rc = -EBUSY);
+
+ if (fd->fd_och == NULL) {
+ if (file->f_mode & FMODE_WRITE) {
+ LASSERT(lli->lli_mds_write_och != NULL);
+ och_p = &lli->lli_mds_write_och;
+ och_usecount = &lli->lli_open_fd_write_count;
+ } else {
+ LASSERT(lli->lli_mds_read_och != NULL);
+ och_p = &lli->lli_mds_read_och;
+ och_usecount = &lli->lli_open_fd_read_count;
+ }
+
+ if (*och_usecount > 1)
+ GOTO(out_unlock, rc = -EBUSY);
+
+ fd->fd_och = *och_p;
+ *och_usecount = 0;
+ *och_p = NULL;
+ }
+
+ *old_handle = fd->fd_och->och_fh;
+
+ EXIT;
+out_unlock:
+ mutex_unlock(&lli->lli_och_mutex);
+ return rc;
+}
+
+/**
+ * Release ownership on lli_mds_*_och when putting back a file lease.
+ */
+static int ll_lease_och_release(struct inode *inode, struct file *file)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct obd_client_handle **och_p;
+ struct obd_client_handle *old_och = NULL;
+ __u64 *och_usecount;
+ int rc = 0;
+ ENTRY;
+
+ mutex_lock(&lli->lli_och_mutex);
+ if (file->f_mode & FMODE_WRITE) {
+ och_p = &lli->lli_mds_write_och;
+ och_usecount = &lli->lli_open_fd_write_count;
+ } else {
+ och_p = &lli->lli_mds_read_och;
+ och_usecount = &lli->lli_open_fd_read_count;
+ }
+
+ /* The file may have been open by another process (broken lease) so
+ * *och_p is not NULL. In this case we should simply increase usecount
+ * and close fd_och.
+ */
+ if (*och_p != NULL) {
+ old_och = fd->fd_och;
+ (*och_usecount)++;
+ } else {
+ *och_p = fd->fd_och;
+ *och_usecount = 1;
+ }
+ fd->fd_och = NULL;
+ mutex_unlock(&lli->lli_och_mutex);
+
+ if (old_och != NULL)
+ rc = ll_close_inode_openhandle(inode, old_och, 0, NULL);
+
+ RETURN(rc);
+}
+
+/**
* Acquire a lease and open the file.
*/
static struct obd_client_handle *
RETURN(ERR_PTR(-EINVAL));
if (file != NULL) {
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
- struct obd_client_handle **och_p;
- __u64 *och_usecount;
-
if (!(fmode & file->f_mode) || (file->f_mode & FMODE_EXEC))
RETURN(ERR_PTR(-EPERM));
- /* Get the openhandle of the file */
- rc = -EBUSY;
- mutex_lock(&lli->lli_och_mutex);
- if (fd->fd_lease_och != NULL) {
- mutex_unlock(&lli->lli_och_mutex);
- RETURN(ERR_PTR(rc));
- }
-
- if (fd->fd_och == NULL) {
- if (file->f_mode & FMODE_WRITE) {
- LASSERT(lli->lli_mds_write_och != NULL);
- och_p = &lli->lli_mds_write_och;
- och_usecount = &lli->lli_open_fd_write_count;
- } else {
- LASSERT(lli->lli_mds_read_och != NULL);
- och_p = &lli->lli_mds_read_och;
- och_usecount = &lli->lli_open_fd_read_count;
- }
- if (*och_usecount == 1) {
- fd->fd_och = *och_p;
- *och_p = NULL;
- *och_usecount = 0;
- rc = 0;
- }
- }
- mutex_unlock(&lli->lli_och_mutex);
- if (rc < 0) /* more than 1 opener */
+ rc = ll_lease_och_acquire(inode, file, &old_handle);
+ if (rc)
RETURN(ERR_PTR(rc));
-
- LASSERT(fd->fd_och != NULL);
- old_handle = fd->fd_och->och_fh;
}
OBD_ALLOC_PTR(och);
}
CDEBUG(D_INODE, "lease for "DFID" broken? %d\n",
- PFID(&ll_i2info(inode)->lli_fid), cancelled);
+ PFID(&ll_i2info(inode)->lli_fid), cancelled);
if (!cancelled)
ldlm_cli_cancel(&och->och_lease_handle, 0);
+
if (lease_broken != NULL)
*lease_broken = cancelled;
if (rc < 0)
RETURN(rc);
+ rc = ll_lease_och_release(inode, file);
+ if (rc < 0)
+ RETURN(rc);
+
if (lease_broken)
fmode = 0;
ASSERTF(rc == 0,
"invalid lease type on '%s': %s", filename, strerror(-rc));
-#if 0
- /* BUG! This returns EBUSY but there's no lease. */
rc = llapi_lease_get(fd, LL_LEASE_RDLCK);
ASSERTF(rc == 0, "cannot get lease '%s': %s", filename, strerror(-rc));
-#endif
close(fd);
ASSERTF(rc == 0,
"invalid lease type on '%s': %s", filename, strerror(-rc));
-#if 0
- /* BUG! This returns EBUSY but there's no lease. */
rc = llapi_lease_get(fd, LL_LEASE_WRLCK);
ASSERTF(rc == 0, "cannot get lease '%s': %s", filename, strerror(-rc));
-#endif
close(fd);
ASSERTF(fd >= 0, "open failed for '%s': %s", filename, strerror(errno));
for (i = 0; i < 1000; i++) {
-#if 0
- /* BUG! Same as above */
rc = llapi_lease_get(fd, LL_LEASE_WRLCK);
ASSERTF(rc == 0, "cannot get lease '%s': %s",
filename, strerror(-rc));
ASSERTF(rc == LL_LEASE_RDLCK,
"was not able to put back lease '%s': %s",
filename, strerror(-rc));
-#endif
}
close(fd);
+ /* Get a write lease, release and take a read one */
+ fd = open(filename, O_RDWR);
+ ASSERTF(fd >= 0, "open failed for '%s': %s", filename, strerror(errno));
+
+ rc = llapi_lease_get(fd, LL_LEASE_WRLCK);
+ ASSERTF(rc == 0, "cannot get lease '%s': %s", filename, strerror(-rc));
+
+ rc = llapi_lease_check(fd);
+ ASSERTF(rc == LL_LEASE_WRLCK,
+ "invalid lease type on '%s': %s", filename, strerror(-rc));
+
+ rc = llapi_lease_put(fd);
+ ASSERTF(rc == LL_LEASE_WRLCK, "was not able to put back lease '%s': %s",
+ filename, strerror(-rc));
+
+ rc = llapi_lease_check(fd);
+ ASSERTF(rc == 0,
+ "invalid lease type on '%s': %s", filename, strerror(-rc));
+
+ rc = llapi_lease_get(fd, LL_LEASE_RDLCK);
+ ASSERTF(rc == 0, "cannot get lease '%s': %s", filename, strerror(-rc));
+
+ close(fd);
+
+ /* Get a read lease, release and take a write one */
+ fd = open(filename, O_RDWR);
+ ASSERTF(fd >= 0, "open failed for '%s': %s", filename, strerror(errno));
+
+ rc = llapi_lease_get(fd, LL_LEASE_RDLCK);
+ ASSERTF(rc == 0, "cannot get lease '%s': %s", filename, strerror(-rc));
+
+ rc = llapi_lease_check(fd);
+ ASSERTF(rc == LL_LEASE_RDLCK,
+ "invalid lease type on '%s': %s", filename, strerror(-rc));
+
+ rc = llapi_lease_put(fd);
+ ASSERTF(rc == LL_LEASE_RDLCK, "was not able to put back lease '%s': %s",
+ filename, strerror(-rc));
+
+ rc = llapi_lease_check(fd);
+ ASSERTF(rc == 0,
+ "invalid lease type on '%s': %s", filename, strerror(-rc));
+
+ rc = llapi_lease_get(fd, LL_LEASE_WRLCK);
+ ASSERTF(rc == 0, "cannot get lease '%s': %s", filename, strerror(-rc));
+
+ close(fd);
+
free(filename);
}