X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fdir.c;h=961a00ebb22d3d6ff2411b0c56b1b9b390a0a043;hb=7ce2000eb0f4e7b7ea1f362c17099881098cfef7;hp=05dfb095f5e1e4d67d1788ef1f046afbafd7bc17;hpb=c5050e412572b00cbe93d8517d2d1f767bebfa92;p=fs%2Flustre-release.git diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 05dfb09..961a00e 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -59,62 +59,20 @@ typedef struct ext2_dir_entry_2 ext2_dirent; static int ll_dir_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; - struct ll_sb_info *sbi = ll_i2sbi(inode); struct ll_fid mdc_fid; __u64 offset; - int rc = 0; struct ptlrpc_request *request; - struct lustre_handle lockh; struct mds_body *body; - struct lookup_intent it = { .it_op = IT_READDIR }; - struct mdc_op_data data; - struct obd_device *obddev = class_exp2obd(sbi->ll_mdc_exp); - struct ldlm_res_id res_id = - { .name = {inode->i_ino, (__u64)inode->i_generation} }; + int rc = 0; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); - if ((inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT <= page->index){ - /* XXX why do we need this exactly, and why do we think that - * an all-zero directory page is useful? - */ - CERROR("memsetting dir page %lu to zero (size %lld)\n", - page->index, inode->i_size); - memset(kmap(page), 0, PAGE_CACHE_SIZE); - kunmap(page); - GOTO(readpage_out, rc); - } - - rc = ldlm_lock_match(obddev->obd_namespace, LDLM_FL_BLOCK_GRANTED, - &res_id, LDLM_PLAIN, NULL, 0, LCK_PR, &lockh); - if (!rc) { - ll_prepare_mdc_op_data(&data, inode, NULL, NULL, 0, 0); - - rc = mdc_enqueue(sbi->ll_mdc_exp, LDLM_PLAIN, &it, LCK_PR, - &data, &lockh, NULL, 0, - ldlm_completion_ast, ll_mdc_blocking_ast, - inode); - request = (struct ptlrpc_request *)it.d.lustre.it_data; - if (request) - ptlrpc_req_finished(request); - if (rc < 0) { - CERROR("lock enqueue: err: %d\n", rc); - unlock_page(page); - RETURN(rc); - } - } - ldlm_lock_dump_handle(D_OTHER, &lockh); - - if (PageUptodate(page)) { - CERROR("Explain this please?\n"); - GOTO(readpage_out, rc); - } mdc_pack_fid(&mdc_fid, inode->i_ino, inode->i_generation, S_IFDIR); offset = page->index << PAGE_SHIFT; - rc = mdc_readpage(sbi->ll_mdc_exp, &mdc_fid, + rc = mdc_readpage(ll_i2sbi(inode)->ll_mdc_exp, &mdc_fid, offset, page, &request); if (!rc) { body = lustre_msg_buf(request->rq_repmsg, 0, sizeof (*body)); @@ -122,21 +80,17 @@ static int ll_dir_readpage(struct file *file, struct page *page) LASSERT_REPSWABBED (request, 0); /* swabbed by mdc_readpage() */ inode->i_size = body->size; + SetPageUptodate(page); } ptlrpc_req_finished(request); - EXIT; - - readpage_out: - if (!rc) - SetPageUptodate(page); unlock_page(page); - ldlm_lock_decref(&lockh, LCK_PR); + EXIT; return rc; } struct address_space_operations ll_dir_aops = { - readpage: ll_dir_readpage, + .readpage = ll_dir_readpage, }; /* @@ -247,17 +201,47 @@ Eend: fail: SetPageChecked(page); SetPageError(page); - LBUG(); } static struct page *ll_get_dir_page(struct inode *dir, unsigned long n) { + struct ldlm_res_id res_id = + { .name = { dir->i_ino, (__u64)dir->i_generation} }; + struct lustre_handle lockh; + struct obd_device *obddev = class_exp2obd(ll_i2sbi(dir)->ll_mdc_exp); struct address_space *mapping = dir->i_mapping; - struct page *page = read_cache_page(mapping, n, - (filler_t*)mapping->a_ops->readpage, NULL); + struct page *page; + ldlm_policy_data_t policy = { .l_inodebits = { MDS_INODELOCK_UPDATE } }; + int rc; + + rc = ldlm_lock_match(obddev->obd_namespace, LDLM_FL_BLOCK_GRANTED, + &res_id, LDLM_IBITS, &policy, LCK_PR, &lockh); + if (!rc) { + struct lookup_intent it = { .it_op = IT_READDIR }; + struct ptlrpc_request *request; + struct mdc_op_data data; + + ll_prepare_mdc_op_data(&data, dir, NULL, NULL, 0, 0); + + rc = mdc_enqueue(ll_i2sbi(dir)->ll_mdc_exp, LDLM_IBITS, &it, + LCK_PR, &data, &lockh, NULL, 0, + ldlm_completion_ast, ll_mdc_blocking_ast, dir); + + request = (struct ptlrpc_request *)it.d.lustre.it_data; + if (request) + ptlrpc_req_finished(request); + if (rc < 0) { + CERROR("lock enqueue: rc: %d\n", rc); + return ERR_PTR(rc); + } + } + ldlm_lock_dump_handle(D_OTHER, &lockh); + + page = read_cache_page(mapping, n, + (filler_t*)mapping->a_ops->readpage, NULL); if (!IS_ERR(page)) { wait_on_page(page); - kmap(page); + (void)kmap(page); if (!PageUptodate(page)) goto fail; if (!PageChecked(page)) @@ -265,14 +249,17 @@ static struct page *ll_get_dir_page(struct inode *dir, unsigned long n) if (PageError(page)) goto fail; } + +out_unlock: + ldlm_lock_decref(&lockh, LCK_PR); return page; fail: ext2_put_page(page); - return ERR_PTR(-EIO); + page = ERR_PTR(-EIO); + goto out_unlock; } - /* * p is at least 6 bytes before the end of page */ @@ -305,8 +292,8 @@ static unsigned char ext2_filetype_table[EXT2_FT_MAX] = { int ll_readdir(struct file * filp, void * dirent, filldir_t filldir) { - loff_t pos = filp->f_pos; struct inode *inode = filp->f_dentry->d_inode; + loff_t pos = filp->f_pos; // XXX struct super_block *sb = inode->i_sb; unsigned offset = pos & ~PAGE_CACHE_MASK; unsigned long n = pos >> PAGE_CACHE_SHIFT; @@ -314,12 +301,14 @@ int ll_readdir(struct file * filp, void * dirent, filldir_t filldir) unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); unsigned char *types = NULL; int need_revalidate = (filp->f_version != inode->i_version); + int rc = 0; ENTRY; - CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, - inode->i_generation, inode); + CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %llu/%llu\n", + inode->i_ino, inode->i_generation, inode, pos, inode->i_size); + if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) - GOTO(done, 0); + RETURN(0); types = ext2_filetype_table; @@ -328,15 +317,21 @@ int ll_readdir(struct file * filp, void * dirent, filldir_t filldir) ext2_dirent *de; struct page *page; - CDEBUG(D_EXT2, "reading %lu of dir %lu page %lu, size %llu\n", - PAGE_CACHE_SIZE, inode->i_ino, n, inode->i_size); + CDEBUG(D_EXT2,"read %lu of dir %lu/%u page %lu/%lu size %llu\n", + PAGE_CACHE_SIZE, inode->i_ino, inode->i_generation, + n, npages, inode->i_size); page = ll_get_dir_page(inode, n); /* size might have been updated by mdc_readpage */ npages = dir_pages(inode); - if (IS_ERR(page)) + if (IS_ERR(page)) { + rc = PTR_ERR(page); + CERROR("error reading dir %lu/%u page %lu: rc %d\n", + inode->i_ino, inode->i_generation, n, rc); continue; + } + kaddr = page_address(page); if (need_revalidate) { offset = ext2_validate_entry(kaddr, offset, chunk_mask); @@ -349,6 +344,7 @@ int ll_readdir(struct file * filp, void * dirent, filldir_t filldir) int over; unsigned char d_type = DT_UNKNOWN; + rc = 0; /* no error if we return something */ if (types && de->file_type < EXT2_FT_MAX) d_type = types[de->file_type]; @@ -358,7 +354,7 @@ int ll_readdir(struct file * filp, void * dirent, filldir_t filldir) le32_to_cpu(de->inode), d_type); if (over) { ext2_put_page(page); - GOTO(done,0); + GOTO(done, rc); } } } @@ -369,7 +365,7 @@ done: filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; filp->f_version = inode->i_version; update_atime(inode); - RETURN(0); + RETURN(rc); } static int ll_dir_ioctl(struct inode *inode, struct file *file, @@ -389,7 +385,7 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, switch(cmd) { case EXT3_IOC_GETFLAGS: case EXT3_IOC_SETFLAGS: - RETURN( ll_iocontrol(inode, file, cmd, arg) ); + RETURN(ll_iocontrol(inode, file, cmd, arg)); case IOC_MDC_LOOKUP: { struct ptlrpc_request *request = NULL; struct ll_fid fid; @@ -427,9 +423,77 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, obd_ioctl_freedata(buf, len); return rc; } - case LL_IOC_LOV_SETSTRIPE: - case LL_IOC_LOV_GETSTRIPE: - RETURN(-ENOTTY); + case LL_IOC_LOV_SETSTRIPE: { + struct ptlrpc_request *request = NULL; + struct mdc_op_data op_data; + struct iattr attr = { 0 }; + struct lov_user_md lum, *lump = (struct lov_user_md *)arg; + int rc = 0; + + ll_prepare_mdc_op_data(&op_data, inode, NULL, NULL, 0, 0); + + LASSERT(sizeof(lum) == sizeof(*lump)); + LASSERT(sizeof(lum.lmm_objects[0]) == + sizeof(lump->lmm_objects[0])); + rc = copy_from_user(&lum, lump, sizeof(lum)); + if (rc) + return(-EFAULT); + + if (lum.lmm_magic != LOV_USER_MAGIC) + RETURN(-EINVAL); + + rc = mdc_setattr(sbi->ll_mdc_exp, &op_data, + &attr, &lum, sizeof(lum), NULL, 0, &request); + if (rc) { + ptlrpc_req_finished(request); + if (rc != -EPERM && rc != -EACCES) + CERROR("mdc_setattr fails: rc = %d\n", rc); + return rc; + } + ptlrpc_req_finished(request); + + return rc; + } + case LL_IOC_LOV_GETSTRIPE: { + struct ptlrpc_request *request = NULL; + struct lov_user_md *lump = (struct lov_user_md *)arg; + struct lov_mds_md *lmm; + struct ll_fid fid; + struct mds_body *body; + unsigned long valid = 0; + int rc, lmmsize; + + valid |= OBD_MD_FLDIREA; + + ll_inode2fid(&fid, inode); + rc = mdc_getattr(sbi->ll_mdc_exp, &fid, valid, + obd_size_diskmd(sbi->ll_osc_exp, NULL), + &request); + if (rc < 0) { + CDEBUG(D_INFO, "mdc_getattr failed: rc = %d\n", rc); + RETURN(rc); + } + + body = lustre_msg_buf(request->rq_repmsg, 0, sizeof(*body)); + LASSERT(body != NULL); /* checked by mdc_getattr_name */ + LASSERT_REPSWABBED(request, 0);/* swabbed by mdc_getattr_name */ + + lmmsize = body->eadatasize; + if (lmmsize == 0) + GOTO(out_get, rc = -ENODATA); + + lmm = lustre_msg_buf(request->rq_repmsg, 1, lmmsize); + LASSERT(lmm != NULL); + LASSERT_REPSWABBED(request, 1); + rc = copy_to_user(lump, lmm, lmmsize); + if (rc) + GOTO(out_get, rc = -EFAULT); + + EXIT; + out_get: + ptlrpc_req_finished(request); + RETURN(rc); + } case IOC_MDC_GETSTRIPE: { struct ptlrpc_request *request = NULL; struct ll_fid fid; @@ -487,17 +551,17 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, int rc, len=0; struct client_obd *cli; struct obd_device *obd; - + rc = obd_ioctl_getdata(&buf, &len, (void *)arg); if (rc) RETURN(rc); data = (void *)buf; obd = class_name2obd(data->ioc_inlbuf1); - + if (!obd ) GOTO(out_ping, rc = -ENODEV); - + if (!obd->obd_attached) { CERROR("Device %d not attached\n", obd->obd_minor); GOTO(out_ping, rc = -ENODEV); @@ -516,11 +580,54 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, rc = ptlrpc_queue_wait(req); - ptlrpc_req_finished(req); + ptlrpc_req_finished(req); out_ping: obd_ioctl_freedata(buf, len); return rc; } + case OBD_IOC_LLOG_CATINFO: { + struct ptlrpc_request *req = NULL; + char *buf = NULL; + int rc, len = 0; + char *bufs[2], *str; + int lens[2], size; + + rc = obd_ioctl_getdata(&buf, &len, (void *)arg); + if (rc) + RETURN(rc); + data = (void *)buf; + + if (!data->ioc_inlbuf1) { + obd_ioctl_freedata(buf, len); + RETURN(-EINVAL); + } + + lens[0] = data->ioc_inllen1; + bufs[0] = data->ioc_inlbuf1; + if (data->ioc_inllen2) { + lens[1] = data->ioc_inllen2; + bufs[1] = data->ioc_inlbuf2; + } else { + lens[1] = 0; + bufs[1] = NULL; + } + size = data->ioc_plen1; + req = ptlrpc_prep_req(sbi2mdc(sbi)->cl_import, LLOG_CATINFO, + 2, lens, bufs); + if (!req) + GOTO(out_catinfo, rc = -ENOMEM); + req->rq_replen = lustre_msg_size(1, &size); + + rc = ptlrpc_queue_wait(req); + str = lustre_msg_string(req->rq_repmsg, 0, data->ioc_plen1); + if (!rc) + rc = copy_to_user(data->ioc_pbuf1, str, + data->ioc_plen1); + ptlrpc_req_finished(req); + out_catinfo: + obd_ioctl_freedata(buf, len); + RETURN(rc); + } default: return obd_iocontrol(cmd, sbi->ll_osc_exp,0,NULL,(void *)arg); } @@ -528,19 +635,21 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file, int ll_dir_open(struct inode *inode, struct file *file) { - return ll_file_open(inode, file); + ENTRY; + RETURN(ll_file_open(inode, file)); } int ll_dir_release(struct inode *inode, struct file *file) { - return ll_file_release(inode, file); + ENTRY; + RETURN(ll_file_release(inode, file)); } struct file_operations ll_dir_operations = { - open: ll_dir_open, - release: ll_dir_release, - read: generic_read_dir, - readdir: ll_readdir, - ioctl: ll_dir_ioctl + .open = ll_dir_open, + .release = ll_dir_release, + .read = generic_read_dir, + .readdir = ll_readdir, + .ioctl = ll_dir_ioctl };