Whamcloud - gitweb
git://git.whamcloud.com
/
fs
/
lustre-release.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
| inline |
side by side
- added comment in mds_open() and GNS mount points.
[fs/lustre-release.git]
/
lustre
/
llite
/
llite_gns.c
diff --git
a/lustre/llite/llite_gns.c
b/lustre/llite/llite_gns.c
index
2cebcbc
..
a8e73c3
100644
(file)
--- a/
lustre/llite/llite_gns.c
+++ b/
lustre/llite/llite_gns.c
@@
-50,27
+50,23
@@
ll_gns_wait_for_mount(struct dentry *dentry,
{
struct l_wait_info lwi;
struct ll_sb_info *sbi;
- int rc;
ENTRY;
LASSERT(dentry != NULL);
LASSERT(!IS_ERR(dentry));
sbi = ll_s2sbi(dentry->d_sb);
- for (; !d_mountpoint(dentry) && tries > 0; tries--) {
- lwi = LWI_TIMEOUT(timeout * HZ, NULL, NULL);
+ lwi = LWI_TIMEOUT(timeout * HZ, NULL, NULL);
+ for (; !d_mountpoint(dentry) && tries > 0; tries--)
l_wait_event(sbi->ll_gns_waitq, d_mountpoint(dentry), &lwi);
- }
- if (
(rc = d_mountpoint(dentry) ? 1 : 0
)) {
+ if (
d_mountpoint(dentry
)) {
spin_lock(&sbi->ll_gns_lock);
- LASSERT(sbi->ll_gns_state == LL_GNS_MOUNTING);
sbi->ll_gns_state = LL_GNS_FINISHED;
spin_unlock(&sbi->ll_gns_lock);
+ RETURN(0);
}
-
- complete_all(&sbi->ll_gns_mount_finished);
- RETURN(rc);
+ RETURN(-ETIME);
}
/*
@@
-110,10
+106,9
@@
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
*/
spin_lock(&sbi->ll_gns_lock);
if (sbi->ll_gns_state == LL_GNS_MOUNTING ||
- sbi->ll_gns_state == LL_GNS_FINISHED)
- {
+ sbi->ll_gns_state == LL_GNS_FINISHED) {
spin_unlock(&sbi->ll_gns_lock);
- CDEBUG(D_INODE"GNS is in progress now, throwing "
+ CDEBUG(D_INODE
,
"GNS is in progress now, throwing "
"-ERESTARTSYS to restart syscall and let "
"it finish.\n");
RETURN(-ERESTARTSYS);
@@
-149,25
+144,44
@@
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
* mount object name is taken from sbi, where it is set in mount time or
* via /proc/fs... tunable. It may be ".mntinfo" or so.
*/
+
+ /*
+ * FIXME: lookup_one_len() requires dentry->d_inode->i_sem to be locked,
+ * but we can't use ll_lookup_one_len() as this function is called from
+ * different contol paths and some of them take dentry->d_inode->i_sem
+ * and others do not.
+ */
dchild = lookup_one_len(sbi->ll_gns_oname, dentry,
strlen(sbi->ll_gns_oname));
up(&sbi->ll_gns_sem);
- if (!dchild)
- GOTO(cleanup, rc = -ENOENT);
+ cleanup_phase = 2;
if (IS_ERR(dchild)) {
+ rc = PTR_ERR(dchild);
+
+ if (rc == -ERESTARTSYS) {
+ CDEBUG(D_INODE, "possible endless loop is detected "
+ "due to mount object is directory marked by "
+ "SUID bit.\n");
+ GOTO(cleanup, rc = -ELOOP);
+ }
+
CERROR("can't find mount object %*s/%*s err = %d.\n",
(int)dentry->d_name.len, dentry->d_name.name,
-
(int)dchild->d_name.len, dchild->d_name.
name,
-
(int)PTR_ERR(dchild)
);
- GOTO(cleanup, rc
= PTR_ERR(dchild)
);
+
strlen(sbi->ll_gns_oname), sbi->ll_gns_o
name,
+
rc
);
+ GOTO(cleanup, rc);
}
/* mount object is not found */
if (!dchild->d_inode)
GOTO(cleanup, rc = -ENOENT);
+ /* check if found child is regular file */
+ if (!S_ISREG(dchild->d_inode->i_mode))
+ GOTO(cleanup, rc = -EOPNOTSUPP);
+
mntget(mnt);
/* ok, mount object if found, opening it. */
@@
-175,18
+189,17
@@
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
if (IS_ERR(mntinfo_fd)) {
CERROR("can't open mount object %*s/%*s err = %d.\n",
(int)dentry->d_name.len, dentry->d_name.name,
-
(int)dchild->d_name.len, dchild->d_name.
name,
+
strlen(sbi->ll_gns_oname), sbi->ll_gns_o
name,
(int)PTR_ERR(mntinfo_fd));
- dput(dchild);
mntput(mnt);
GOTO(cleanup, rc = PTR_ERR(mntinfo_fd));
}
- cleanup_phase =
2
;
+ cleanup_phase =
3
;
if (mntinfo_fd->f_dentry->d_inode->i_size > PAGE_SIZE) {
CERROR("mount object %*s/%*s is too big (%Ld)\n",
(int)dentry->d_name.len, dentry->d_name.name,
-
(int)dchild->d_name.len, dchild->d_name.
name,
+
strlen(sbi->ll_gns_oname), sbi->ll_gns_o
name,
mntinfo_fd->f_dentry->d_inode->i_size);
GOTO(cleanup, rc = -EFBIG);
}
@@
-195,14
+208,14
@@
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
if (!datapage)
GOTO(cleanup, rc = -ENOMEM);
- cleanup_phase =
3
;
+ cleanup_phase =
4
;
/* read data from mount object. */
rc = kernel_read(mntinfo_fd, 0, datapage, PAGE_SIZE);
if (rc < 0) {
CERROR("can't read mount object %*s/%*s data, err %d\n",
(int)dentry->d_name.len, dentry->d_name.name,
-
(int)dchild->d_name.len, dchild->d_name.
name,
+
strlen(sbi->ll_gns_oname), sbi->ll_gns_o
name,
rc);
GOTO(cleanup, rc);
}
@@
-211,6
+224,7
@@
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
fput(mntinfo_fd);
mntinfo_fd = NULL;
+ dchild = NULL;
/* synchronizing with possible /proc/fs/...write */
down(&sbi->ll_gns_sem);
@@
-240,7
+254,9
@@
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
* or usermode upcall program will start mounting in backgound and
* return instantly. --umka
*/
- if (ll_gns_wait_for_mount(dentry, 1, GNS_WAIT_ATTEMPTS)) {
+ rc = ll_gns_wait_for_mount(dentry, 1, GNS_WAIT_ATTEMPTS);
+ complete_all(&sbi->ll_gns_mount_finished);
+ if (rc == 0) {
struct dentry *rdentry;
struct vfsmount *rmnt;
@@
-271,29
+287,30
@@
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
dentry->d_flags &= ~DCACHE_GNS_PENDING;
spin_unlock(&dentry->d_lock);
} else {
- CERROR("usermode upcall %s failed to mount %s\n",
- sbi->ll_gns_upcall, path);
- rc = -ETIME;
+ CERROR("usermode upcall %s failed to mount %s, err %d\n",
+ sbi->ll_gns_upcall, path, rc);
}
-
+
EXIT;
cleanup:
switch (cleanup_phase) {
- case
3
:
+ case
4
:
free_page((unsigned long)datapage);
- case
2
:
+ case
3
:
if (mntinfo_fd != NULL)
fput(mntinfo_fd);
+ case 2:
+ if (dchild != NULL)
+ dput(dchild);
case 1:
free_page((unsigned long)pathpage);
- case 0:
+
/*
* waking up all waiters after gns state is set to
* LL_GNS_MOUNTING
*/
- if (cleanup_phase > 0)
- complete_all(&sbi->ll_gns_mount_finished);
-
+ complete_all(&sbi->ll_gns_mount_finished);
+ case 0:
spin_lock(&sbi->ll_gns_lock);
sbi->ll_gns_state = LL_GNS_IDLE;
spin_unlock(&sbi->ll_gns_lock);