]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: basic .snap dir support
authorSage Weil <sage@newdream.net>
Mon, 11 Aug 2008 21:27:10 +0000 (14:27 -0700)
committerSage Weil <sage@newdream.net>
Mon, 11 Aug 2008 21:27:10 +0000 (14:27 -0700)
src/kernel/dir.c
src/kernel/inode.c
src/kernel/super.c
src/kernel/super.h

index 0e66b65b28be9bf94af0adc73d6fc7011f040c86..82a0f649bac7743cbdae1d1225f58bebc623928b 100644 (file)
@@ -43,11 +43,16 @@ char *ceph_build_dentry_path(struct dentry *dentry, int *plen, __u64 *base,
 retry:
        len = 0;
        for (temp = dentry; !IS_ROOT(temp);) {
+               struct inode *inode = temp->d_inode;
                if (len >= min &&
-                   temp->d_inode &&
+                   inode &&
+                   ceph_vino(inode).snap == CEPH_NOSNAP &&
                    !ceph_dentry_revalidate(temp, 0))
                        break;
-               len += 1 + temp->d_name.len;
+               if (inode && ceph_vino(inode).snap == CEPH_SNAPDIR)
+                       len++;  /* slash only */
+               else
+                       len += 1 + temp->d_name.len;
                temp = temp->d_parent;
                if (temp == NULL) {
                        derr(1, "corrupt dentry %p\n", dentry);
@@ -63,17 +68,21 @@ retry:
        pos = len;
        path[pos] = 0;  /* trailing null */
        for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) {
-               pos -= temp->d_name.len;
-               if (pos < 0) {
-                       break;
+               if (temp->d_inode &&
+                   ceph_vino(temp->d_inode).snap == CEPH_SNAPDIR) {
+                       dout(50, "build_path_dentry path+%d: %p SNAPDIR\n",
+                            pos, temp);
                } else {
+                       pos -= temp->d_name.len;
+                       if (pos < 0)
+                               break;
                        strncpy(path + pos, temp->d_name.name,
                                temp->d_name.len);
                        dout(50, "build_path_dentry path+%d: %p '%.*s'\n",
                             pos, temp, temp->d_name.len, path + pos);
-                       if (pos)
-                               path[--pos] = '/';
                }
+               if (pos)
+                       path[--pos] = '/';
                temp = temp->d_parent;
                if (temp == NULL) {
                        derr(1, "corrupt dentry\n");
@@ -136,6 +145,8 @@ nextfrag:
                char *path;
                int pathlen;
                u64 pathbase;
+               int op = ceph_vino(inode).snap == CEPH_SNAPDIR ?
+                       CEPH_MDS_OP_LSSNAP:CEPH_MDS_OP_READDIR;
 
                frag = ceph_choose_frag(ceph_inode(inode), frag, 0);
 
@@ -144,7 +155,7 @@ nextfrag:
                     ceph_vinop(inode), frag);
                path = ceph_build_dentry_path(filp->f_dentry, &pathlen,
                                              &pathbase, 1);
-               req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_READDIR,
+               req = ceph_mdsc_create_request(mdsc, op,
                                               pathbase, path, 0, 0,
                                               filp->f_dentry, USE_AUTH_MDS);
                kfree(path);
@@ -259,6 +270,17 @@ loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
 struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
                                  struct dentry *dentry, int err)
 {
+       struct ceph_client *client = ceph_client(dentry->d_sb);
+
+       /* snap dir? */
+       if (err == -ENOENT &&
+           strcmp(dentry->d_name.name, client->mount_args.snapdir_name) == 0) {
+               struct inode *parent = dentry->d_parent->d_inode;
+               struct inode *inode = ceph_get_snapdir(parent);
+               d_add(dentry, inode);
+               err = 0;
+       }
+
        if (err == -ENOENT) {
                /* no trace? */
                if (req->r_reply_info.trace_numd == 0) {
@@ -662,6 +684,13 @@ static int ceph_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *dir = dentry->d_parent->d_inode;
 
+       /* always validate snapped metadata, for now */
+       if (ceph_vino(dir).snap != CEPH_NOSNAP) {
+               dout(10, "d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry,
+                    dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
+               return 1;
+       }
+
        dout(10, "d_revalidate %p '%.*s' inode %p\n", dentry,
             dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
 
index 454e25311f479cc7c15da177b57aa93e829b77b0..0ff23030c7ce88190db5d6e59e48e74f14fcf2b9 100644 (file)
@@ -45,6 +45,23 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
        return inode;
 }
 
+struct inode *ceph_get_snapdir(struct inode *parent)
+{
+       struct ceph_vino vino = {
+               .ino = ceph_vino(parent).ino,
+               .snap = CEPH_SNAPDIR,
+       };
+       struct inode *inode = ceph_get_inode(parent->i_sb, vino);
+       if (IS_ERR(inode))
+               return ERR_PTR(PTR_ERR(inode));
+       inode->i_mode = parent->i_mode;
+       inode->i_uid = parent->i_uid;
+       inode->i_gid = parent->i_gid;
+       inode->i_op = &ceph_dir_iops;
+       inode->i_fop = &ceph_dir_fops;
+       return inode;
+}
+
 
 const struct inode_operations ceph_file_iops = {
        .setattr = ceph_setattr,
@@ -631,11 +648,9 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
                d_drop(dn);
        realdn = d_materialise_unique(dn, in);
        if (IS_ERR(realdn)) {
-               derr(0, "error splicing %p (%d) with %p (%d) "
+               derr(0, "error splicing %p (%d) "
                     "inode %p ino %llx.%llx\n",
-                    dn, atomic_read(&dn->d_count),
-                    realdn, atomic_read(&realdn->d_count),
-                    realdn->d_inode,
+                    dn, atomic_read(&dn->d_count), in,
                     ceph_vinop(realdn->d_inode));
                if (prehash)
                        *prehash = false; /* don't rehash on error */
@@ -901,6 +916,12 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 
                dput(parent);
                parent = NULL;
+
+               if (d == rinfo->trace_numi-rinfo->trace_snapdirpos-1) {
+                       struct inode *snapdir = ceph_get_snapdir(dn->d_inode);
+                       dn = d_find_alias(snapdir);
+                       dout(10, " snapdir dentry is %p\n", dn);
+               }
                continue;
 
 
index 62326dcb64ffd035b3bf28b754eb2b2309e7fc1a..baec0b7666aeb39dfcece9f47e50a6b735d13940 100644 (file)
@@ -434,6 +434,7 @@ static int parse_mount_args(int flags, char *options, const char *dev_name,
        args->flags = CEPH_MOUNT_DEFAULT;
        args->osd_timeout = 5;  /* seconds */
        args->mount_attempts = 2;  /* 2 attempts */
+       args->snapdir_name = ".snap";
 
        /* ip1[,ip2...]:/server/path */
        c = strchr(dev_name, ':');
index ac38e0b44769a42228799f15f9b1d89f4999c7bc..0e66a2fe5aade8bb50bb50e3b8dfc624be4dafa2 100644 (file)
@@ -107,6 +107,7 @@ struct ceph_mount_args {
        struct ceph_entity_addr mon_addr[5];
        int wsize;
        int osd_timeout;
+       char *snapdir_name;
 };
 
 enum {
@@ -513,6 +514,7 @@ extern const struct inode_operations ceph_file_iops;
 extern const struct inode_operations ceph_special_iops;
 extern struct inode *ceph_get_inode(struct super_block *sb,
                                    struct ceph_vino vino);
+extern struct inode *ceph_get_snapdir(struct inode *parent);
 extern int ceph_fill_inode(struct inode *inode,
                           struct ceph_mds_reply_info_in *iinfo,
                           struct ceph_mds_reply_dirfrag *dirinfo);