}
return pos;
}
-static int get_fd(struct file *filp)
-{
- struct files_struct *files = current->files;
- int fd = 0;
-
- write_lock(&files->file_lock);
- for (fd = 0; fd < files->max_fds; fd++) {
- if(files->fd[fd] == filp) {
- write_unlock(&files->file_lock);
- return fd;
- }
- }
- write_unlock(&files->file_lock);
- RETURN(-1);
-}
static int close_fd(int fd)
{
struct files_struct *files = current->files;
write_unlock(&files->file_lock);
return 0;
}
-
-#define MAX_LOOP_DEVICES 256
-static char *parse_path2dev(struct super_block *sb, char *dev_path)
+static int set_loop_fd(char *dev_path, char *loop_dev)
{
+ struct loop_info loopinfo;
+ struct nameidata nd;
+ struct dentry *dentry;
+ struct block_device_operations *bd_ops;
struct file *filp;
- int i = 0, fd = 0, error = 0;
- char *name = NULL;
-
- filp = filp_open(dev_path, 0, 0);
- if (!filp)
- RETURN(NULL);
- if (S_ISREG(filp->f_dentry->d_inode->i_mode)) {
- /*here we must walk through all the snap cache to
- *find the loop device */
-
- fd = get_unused_fd();
- if (!fd) RETURN(NULL);
+ int fd = 0, error = 0;
+
+ fd = get_unused_fd();
+
+ if (!fd) RETURN(-EINVAL);
+
+ filp = filp_open(dev_path, FMODE_WRITE, 0);
+ if (!filp || !S_ISREG(filp->f_dentry->d_inode->i_mode))
+ RETURN(-EINVAL);
+
+ fd_install(fd, filp);
- fd_install(fd, filp);
- SM_ALLOC(name, strlen("/dev/loop/") + 2);
+ if (path_init(loop_dev, LOOKUP_FOLLOW, &nd)) {
+ error = path_walk(loop_dev, &nd);
+ if (error) {
+ path_release(&nd);
+ filp_close(filp, current->files);
+ RETURN(-EINVAL);
+ }
+ } else {
+ path_release(&nd);
+ filp_close(filp, current->files);
+ RETURN(-EINVAL);
+ }
+ dentry = nd.dentry;
+ bd_ops = get_blkfops(LOOP_MAJOR);
- for (i = 0; i < MAX_LOOP_DEVICES; i++) {
- fd = get_fd(filp);
- if (fd > 0) {
- struct block_device_operations *bd_ops;
- struct dentry *dentry;
- struct nameidata nd;
- /*FIXME later, the loop file should
- *be different for different system*/
-
- sprintf(name, "/dev/loop/%d", i);
-
- if (path_init(name, LOOKUP_FOLLOW, &nd)) {
- error = path_walk(name, &nd);
- if (error) {
- path_release(&nd);
- SM_FREE(name, sizeof(name) + 1);
- RETURN(NULL);
- }
- } else {
- SM_FREE(name, sizeof(name) + 1);
- RETURN(NULL);
- }
- dentry = nd.dentry;
- bd_ops = get_blkfops(LOOP_MAJOR);
- error = bd_ops->ioctl(dentry->d_inode,
- filp, LOOP_SET_FD,
- (unsigned long)fd);
- path_release(&nd);
- if (!error) {
- filp_close(filp, current->files);
- RETURN(name);
+ error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_FD,
+ (unsigned long)fd);
+ if (error) {
+ path_release(&nd);
+ filp_close(filp, current->files);
+ RETURN(-EINVAL);
+ }
+ memset(&loopinfo, 0, sizeof(struct loop_info));
+
+ error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_STATUS,
+ (unsigned long)(&loopinfo));
+ path_release(&nd);
+ RETURN(error);
+}
+
+#define SIZE(a) (sizeof(a)/sizeof(a[0]))
+static char *find_unused_and_set_loop_device(char *dev_path)
+{
+ char *loop_formats[] = { "/dev/loop/%d", "/dev/loop%d"};
+ struct loop_info loopinfo;
+ struct nameidata nd;
+ struct dentry *dentry;
+ char *dev = NULL;
+ int i, j, error;
+
+ for (j = 0; j < SIZE(loop_formats); j++) {
+ SM_ALLOC(dev, strlen(loop_formats[i]) + 1);
+ for(i = 0; i < 256; i++) {
+ struct block_device_operations *bd_ops;
+
+ sprintf(dev, loop_formats[j], i);
+
+ if (path_init(dev, LOOKUP_FOLLOW, &nd)) {
+ error = path_walk(dev, &nd);
+ if (error && error != -ENOENT) {
+ path_release(&nd);
+ SM_FREE(dev, strlen(loop_formats[i]) + 1);
+ RETURN(NULL);
}
+ } else {
+ SM_FREE(dev, strlen(loop_formats[i]) + 1);
+ RETURN(NULL);
+ }
+ dentry = nd.dentry;
+ bd_ops = get_blkfops(LOOP_MAJOR);
+ error = bd_ops->ioctl(dentry->d_inode, NULL, LOOP_GET_STATUS,
+ (unsigned long)&loopinfo);
+ path_release(&nd);
+
+ if (error == -ENXIO) {
+ /*find unused loop and set dev_path to loopdev*/
+ error = set_loop_fd(dev_path, dev);
+ if (error) {
+ SM_FREE(dev, strlen(loop_formats[i]) + 1);
+ dev = NULL;
+ }
+ return dev;/* probably free */
}
+ }
+ SM_FREE(dev, strlen(loop_formats[i]) + 1);
+ }
+ RETURN(NULL);
+}
+
+#define MAX_LOOP_DEVICES 256
+static char *parse_path2dev(struct super_block *sb, char *dev_path)
+{
+ struct dentry *dentry;
+ struct nameidata nd;
+ char *name = NULL;
+ int error = 0;
+
+ if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
+ error = path_walk(dev_path, &nd);
+ if (error) {
+ path_release(&nd);
+ RETURN(NULL);
}
+ } else {
+ RETURN(NULL);
+ }
+ dentry = nd.dentry;
+
+ if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
+ (!S_ISBLK(dentry->d_inode->i_mode) &&
+ !S_ISREG(dentry->d_inode->i_mode))){
+ path_release(&nd);
+ RETURN(NULL);
+ }
+
+ if (S_ISREG(dentry->d_inode->i_mode)) {
+ name = find_unused_and_set_loop_device(dev_path);
+ path_release(&nd);
+ RETURN(name);
}
SM_ALLOC(name, strlen(dev_path) + 1);
memcpy(name, dev_path, strlen(dev_path) + 1);
- filp_close(filp, current->files);
RETURN(name);
}
+static void duplicate_sb(struct super_block *csb,
+ struct super_block *sb)
+{
+ sb->s_blocksize = csb->s_blocksize;
+ sb->s_magic = csb->s_magic;
+ sb->s_blocksize_bits = csb->s_blocksize_bits;
+ sb->s_maxbytes = csb->s_maxbytes;
+}
extern struct super_operations smfs_super_ops;
static int sm_mount_cache(struct super_block *sb,
free_page(page);
if (IS_ERR(mnt)) {
- CERROR("do_kern_mount failed: rc = %d\n", err);
- GOTO(err_out, 0);
+ CERROR("do_kern_mount failed: rc = %d\n", PTR_ERR(mnt));
+ GOTO(err_out, err = PTR_ERR(mnt));
}
smb = S2SMI(sb);
smb->smsi_sb = mnt->mnt_sb;
smb->smsi_mnt = mnt;
+
+ duplicate_sb(mnt->mnt_sb, sb);
sm_set_sb_ops(mnt->mnt_sb, sb);
err_out:
if (dev_name)
struct smfs_super_info *smb = S2SMI(sb);
mntput(smb->smsi_mnt);
+
return 0;
}
void smfs_put_super(struct super_block *sb)
void *data,
int silent)
{
- struct smfs_inode_info *smi;
- struct dentry *bottom_root;
struct inode *root_inode = NULL;
char *devstr = NULL, *typestr = NULL;
char *cache_data;
CERROR("Can not mount %s as %s\n", devstr, typestr);
GOTO(out_err, 0);
}
- /* set up the super block */
-
- bottom_root = dget(S2SMI(sb)->smsi_sb->s_root);
- if (!bottom_root) {
- CERROR("bottom not mounted\n");
- GOTO(out_err, err=-ENOENT);
- }
-
- root_ino = bottom_root->d_inode->i_ino;
- smi = I2SMI(root_inode);
- /*FIXME Intialize smi here*/
-
+ dget(S2CSB(sb)->s_root);
+ root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
+ root_inode = iget(sb, root_ino);
+
CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
sb->s_op->read_inode, root_ino, root_inode);
- sb->s_root = d_alloc_root(bottom_root->d_inode);
+ sb->s_root = d_alloc_root(root_inode);
if (!sb->s_root) {
GOTO(out_err, err=-EINVAL);
}
-
+
CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
(ulong) sb, (ulong) &sb->u.generic_sbp);
- out_err:
+out_err:
cleanup_option();
if (err)
return NULL;